[apparmor] AppArmor 2.8 beta2

John Johansen john.johansen at canonical.com
Wed Mar 14 23:20:56 UTC 2012


On 03/14/2012 02:14 PM, Christian Boltz wrote:
> Hello,
> 
> Am Mittwoch, 14. März 2012 schrieb John Johansen:
>> On 03/13/2012 01:39 PM, Christian Boltz wrote:
>>> Am Montag, 12. März 2012 schrieb John Johansen:
>>>> On 03/12/2012 03:42 PM, Christian Boltz wrote:
>>>>> Am Samstag, 10. März 2012 schrieb John Johansen:
>>>>>> * profiles have been defaulted to chroot relative instead of
>>>>>> namespace relative
> 
>>> My usual viewpoint is the filesystem POV. Hey, it's just a program
>>> or FTP user that is chrooted, not me ;-)
>>
>> Well yes, I can understand to pov.  I don't want to take away the
>> ability to express profiles in the form.  Just mark them up in such a
>> way that the tools can correctly interpret what needs to be done, and
>> can continue to be done with changes in the underlying
>> implementation.
>>
>> There is a mess of confusion around file system namespace, chroots and
>> profiles that needs to be made consistent.
> 
> I wouldn't call the current profiles a mess or inconsistent ;-)
> 
Well the profiles no, its the context and how/when they are being applied
that can become confusing when you are dealing with mix of chroot and
fs namespaces.  Add profile stacking into the mix and things get really
fun.

> Maybe if you look at the profile from the chroot'ed POV, then you might 
> get slightly confused. But "I'm root, I'm never chroot'ed" ;-)
> 
hehe, yes context is everything

>>> Additionally, there might be overlaps inside and outside the chroot
>>> - and I'd like to avoid that a program gets too much permissions in
>>> the "real" filesystem. Just think of
>>>
>>>     /** rw,
>>>
>>> which is quite common for a chrooted FTP user in chroot_relative
>>> notation. You don't want to (accidently) apply this rule for the
>>> real filesystem ;-)
>>
>> I would NEVER propose overlaping pre and post chroot paths, that is
>> just broken. And indeed its one of the failure points that is
>> encountered with fs namespaces atm, 
> 
> Well, at the moment I don't see a real problem because all profiles are 
> always filesystem relative. 
> 
But they aren't because there can be multiple filesystem roots with fs
namespaces, if you ignore them ...

> Oh, there's another possible problem - sharing profiles between two 
> apparmor versions. If chroot_relative becomes the default, then you will 
> get a "/** rw" rule for FTP uploads (chroot relative), but older 
> versions will interpret it as filesystem relative.
> 
Right, this has to fail closed.  That is old profiles have to fail/deny
this would achieved by requiring a chroot rule, which the old profile
does not have so it can't get that far.

>> and will be until full implicit labeling comes on line.
> 
> What about enforcing _explicit_ labeling in the profile everything that 
> is meant chroot relative?
> 
hehe, a miscommunication :)  Implicit labeling is an implementation detail
that will allow us to handle disconnected path and fds out of namespaces
in a sane maner

>> Because fs namespaces don't have root requirements that are the same
>> as chroots, there is no way to get back to the pre namespace change
>> path, and the attach_disconnected flag must be used, which effectively
>> causes the overlap you just pointed out above.
> 
> attach_disconnected is another technical detail I don't really 
> understand yet. Do you have an explanation at hand that the average 
> winegrower (like me) can understand? ;-)
> 
Sure we will use chroots with chroot_relative profiles as an example
(just so you can say don't do that), but it becomes a real problem with
fs namespaces in which there is no way to construct an "fs relative" path.

say your application, accesses

  /var/socket

and chroots to
  /var/chroot/

so that when its in the chroot it can only see everything under /var/chroot/
Now say the application is written using privilege separation so that it
has two components, one in the chroot and one out and they communicate via
/var/socket.  It does this by opening /var/socket before the chroot and
then then half of the application doing the chroot keeps the fd open
and chroots.  It can now communicate with the other half over the socket
even though the socket is not visible from within the chroot.

>From the chroots pov the fd is disconnected.  With chroots we currently
have two ways of dealing with this.  By makeing chroot profiles fs namespace
relative (so they have the same view as outside the chroot).  And by a simple
caching of profile labeling on the open file.

The caching allows us to avoid having to a path name reconstruction on every
file access as long as the profile doesn't change.  But even if that fails
with chroots we can reconstruct a path back to either the chroot root or
the fs root.

if we are only reconstructing paths back to the chroot root, then /var/sockets
path is disconnected, we end up getting
  var/socket

and then we detect that its root is not the same as the chroot.  What the
attach disconnected flag does is a HORRIBLE hack where it then attaches
var/socket the chroot root so from in the chroot you end up with

  /var/socket

as its path name, which is just wrong because it does not exit with in the
chroot and may alias to a file that actually exists in the chroot.  So of
course attach_disconnected should NEVER be used.  However if the profile
is enforcing and you encounter denials due to disconnected paths you
may not have any choice, and having a profile enforcing even with it
using attach_disconnected is generally better that not having a profile.
Especially when you consider that there are a limited set of files that
will actually have this applied because they either have to be opened before
and passed in, passed in over ipc, or be do to lazy unmount.

Alright so at this point you say well just use fs relative, problem solved.
And it would be for chroots from a system profile pov.  But it is not
solved for profiles that are supposed to be relative to the chroot,
fs namespaces, nor lazily unmounted filesystems, and maybe not for chroots
in the future.

So what are fs namespaces? They are another mechanism in the kernel that
are similar to chroots, but they are more flexible and it is not possible
to compute a pre namespace path like it is with chroots.

Lazy unmounts really don't have anything to do with fs relative, or
chroot relative paths, and only get a cursory mention because they are
another source of disconnected paths that we need to deal with better.

Now for chroots, it is possible that our ability to compute the fs relative
path from a chroot within the linux kernel will disappear in the future.
This was discussed a little earlier this year with Linus being in favor
of removing it.

I can't say whether that will ever actually happen but after looking at it,
and the problems we currently have with fs namespaces, a better solution,
and that we needed to prepare before something like that.

Unifying chroots and fs namespace handling is appealing considering their
similarities, and that containers like lxc may use one or the other
solution interchangeably depending on some set of options.

That and chroot based profiles are in the minority, and so if we have to
break something then it makes sense to consider them.

>>> Anyway, we seem to agree that the main profile should always use the
>>> full path.
>>
>> It would be easier, but there is going to need to be some magic,
>> especially around fs namespaces, which are being used interchangeably
>> in some places.
> 
> What type of "magic"?
> 
There is NO full path in the sense of chroot with fs namespaces.  Its just
not possible to do, you could come up with something similar for a subset
of cases, but it would be hideous and I doubt I could get it upstream, and
it would completely fail in a whole bunch of cases.

So yes fs namespaces and the drive to make chroot more like them are in
some sense the problem.

>>> OK, if we have something like
>>>
>>>     chroot /home/www/*/ -> ^subprofile
>>>
>>> then it can make sense to make this subprofile chroot_relative.
>>> However I don't see why we can't just explicitely specify the
>>> chroot_relative flag on the ^subprofile to make it clear. The parser
>>> could even warn if a chroot target profile is not flagged as
>>> chroot_relative or namespace_relative.
>>
>> Hehe but you be able to.
>>
>>> Another idea would be (to enable using existing profiles or
>>> subprofiles> 
>>> without the need to add a chroot_relative flag on them):
>>>     chroot /home/www/*/ -> ^subprofile (chroot_relative)
>>
>> I am open to ideas, since we are reverting all of it from 2.8 there is
>> more time to kick around the design and requirements
> 
> OK, then just save my ideas from above somewhere ;-)
> 
of course, and of course be prepared for the next round of discussions

>>> Everything else should stay namespace_relative because of
>>> - backward compability (never change the meaning of a profile!)
>>
>> I understand this pov, but this may not even be possible in the future
>> or at least not in the current form.  This is one of the reasons to
>> begin pushing for the change.  The other being consistency between
>> chroot and fs namespaces.
>>
>> If we break things I promise it will be a fail closed situation.
> 
> Can you rephrase that to
>     If we break things I promise we will implement profile versioning 
>     first.
> please? ;-)
> 
No. We can discuss it again, the version discussion as I remember it last
time died out last time with a sense of its not worth it.

>> We need to mark up one or the other case, and the chroot case for
>> profiles is much less common, so its the one we should be targeting.
> 
> Yes, chroot is indeed less common. Nevertheless, if the change can be 
> done in a non-breaking way, I'd really prefer that.
> 
Of course

>> There are things we can do to auto detect, like chroot rules with no
>> transition means the profile is being mixed and should be using
>> namespace relative.
> 
> Agreed, even if I'd propose another style of autodetection:
> "If there is no chroot_relative flag, the profile is namespace relative"
> 
But that could be seen as forcing the requirement on the majority of
profiles.  Instead of those that are actually written for the system
profile confining a chroot case.

And it really is the majority case, because soon we need to deal with
all our profiles being loaded inside of containers, with the container
providing the virtualization of the OS instead of the full virtualization
solutions.

We got to punt that requirement this release, but I think I will have to
deal with it in the next.

>> Even in namespace relative profiles I would like to see moving to a
>> variable root, for chroot paths
>>
>> Eg.
>>
>>   chroot /home/www/*,
>>
>>   @{root}/foo rw,
>>
>> its not required but it would aid in analysis and make it easier to
>> get a tighter dynamic profile.
> 
> Yes, looks like a good idea.
> 
>>> - principle of least surprise (just think you know nothing about
>>>
>>>   AppArmor and your first contact is by reading a profile) - which
>>>   behaviour would you expect in the main profile?
>>
>> well again define main profile?
> 
> With "main profile" I mean the part outside the chroot. In case of 
> vsftpd, it would be something like:
> 
hehe yeah, I know.  What I was getting at is this is getting more and
more blurred.  Soon we will be offering stacking which will allow
a containerized OS to load its own profiles while the host OS is also
applying its own profiles to the container.

That is the host profiles are protecting the host from the container and
the container is using profiles to protect its self from its apps.  To
the host it is the main profile, but to the container its profiles are
the main profile.  From a policy authoring pov the container is unaware
of the hosts profiles.

<< snip >>

> 
> (and yes, this is my profile for vsftpd - if someone wants to grab it, 
> feel free to do so. Needless to say the /home/www/* paths are specific 
> to my setup.)
> 
heh I might look into using as a reference/example profile :)

>>> If we really want to do such a change, we should finally implement
>>> versioning in the profiles - there were lots of discussions about
>>> this, but until now nobody implemented it ;-)
>>
>> Well, we can always bring that discussion up again
> 
> IMHO we _must_ use versioning if we change the meaning of existing 
> profiles. (Or, even better, avoid changes that change the meaning of 
> existing profiles ;-)
> 
I do understand that pov

>>> BTW: I remember that a very old version of AppArmor (2.3?) was
>>> indeed
>>> chroot_relative. I always thought of that as a bug (which might even
>>> introduce security issues if chroot and the real filesystem overlap)
>>> and was very happy when it was fixed^Wchanged.
>>
>> 2.0 I think, maybe 2.1 but I doubt it
> 
> IIRC it was one of the first versions in openSUSE that didn't have the 
> restriction to some hardcoded programs to confine. (Not sure if that 
> helps to answer the question.)
> 
> (Digging that up might become an interesting history lesson, similar to 
> the question which update applet was used in which openSUSE version ;-)
> 
> Oh, BTW, there's https://bugzilla.novell.com/show_bug.cgi?id=740327 for 
> a named profile that still contains traces from those days. (The bind 
> changelog contains "added apparmor profile" from May 2007.)
> 
oh yuk, maybe it was 2.3 that changed that.  I know it was talked about
before 2.3, I thought it was changed in 2.1 but now I am not sure.

Anyways we won't be going back to that.  I can promise more discussion
going forward and we will try to keep things sane and not break things
as much as is reasonable.

The push for changes this cycle was premature, and didn't get the discussion
it deserved.  I think we can do better and improve on what will be
eventually done.

thanks Christian, its been good to get some actual discussion on this and
has given me some ideas to poke at.



More information about the AppArmor mailing list