[apparmor] Handling chroot, pivotroot, and file system namespaces

John Johansen john.johansen at canonical.com
Wed Dec 7 23:54:51 UTC 2011


On 12/07/2011 02:36 PM, Ángel González wrote:
> I think the profile change on chroot is the way to go, although it may
> be interesting to make rules explicit for both pre and post chroot. Eg.
> 
>>
>>         profile foo {
>>           
>>            /etc/shells r # Applies to both but the chroot uses the full path, so only affects prechroot
>>           @{root}/etc/nsswitch.conf r # The file with path /etc/nsswitch.conf can be read both outside and inside the chroot
>>
>>           chroot none {
>>             # pre chroot rules
>>             @{root}/etc/passwd r # Can only be read before chrooting
>>           }
>>
>>           chroot /var/lib/foo-chroot {
>>             # post chroot rules
>>             @{root}/etc/foo-users.conf r # Equivalent to /var/lib/foo-chroot/etc/foo-users.conf r
>>           }
>>         }
> 
> I'm assuming a variable @{root} which would be automatically set to the
> process root folder, either by the kernel or by apparmor_parser.
> 
> 

That is a possibility, The syntax is something we need to work out.  One
thing we would like to do is maintain backwards compatibility as much
as possible and also make it as close as possible to what we do for pivotroot.

While appreciate wanting to share rules I question having the base profile
rules being shared, ie.
>>            /etc/shells r # Applies to both but the chroot uses the full path, so only affects prechroot
>>           @{root}/etc/nsswitch.conf r # The file with path /etc/nsswitch.conf can be read both outside and inside the chroot

and then having a separate section for chroot none.  As the base profile
rules are already in the chroot none situation.  I think I would rather
have the ability to define a block of rules that can be referenced.
And expect to be reminded at this point that includes do just that, though
they don't currently allow defining it within the profile file.

Supposing that we can share rules with @{root} for a moment what I was
thinking is more a long the lines of

profile foo {
        include <chroot-shared>

	# pre chroot rules
	@{root}/etc/passwd r # Can only be read before chrooting

        chroot /var/lib/foo-chroot -> ^/var/lib/foo-chroot,

        profile /var/lib/foo-chroot {
                include <chroot-shared>
		# post chroot rules
		@{root}/etc/foo-users.conf r # Equivalent to /var/lib/foo-chroot/etc/foo-users.conf r
	}
}

The syntax you propose could be supported by having the option to embedded
the profile right after the chroot match (btw this has been an optional
proposed syntax for exec to child profiles as well).


so you would get
	chroot /var/lib/foo-chroot {
                include <chroot-shared>
		# post chroot rules
		@{root}/etc/foo-users.conf r # Equivalent to /var/lib/foo-chroot/etc/foo-users.conf r
	}

This would then show up as a child profile just similar to the first example.


To remove the need for another file we could extend apparmor syntax with a
block (or something similar command).

block chroot-shared {
	/etc/shells r # Applies to both but the chroot uses the full path, so only affects prechroot
	@{root}/etc/nsswitch.conf r # The file with path /etc/nsswitch.conf can be read both outside and inside the chroot
}

and then let includes reference that block, by using say { } as the quoting.
This would give us

block chroot {
	/etc/shells r # Applies to both but the chroot uses the full path, so only affects prechroot
	@{root}/etc/nsswitch.conf r # The file with path /etc/nsswitch.conf can be read both outside and inside the chroot
}

profile foo {
        include {chroot-shared}

	# pre chroot rules
	@{root}/etc/passwd r # Can only be read before chrooting

	chroot /var/lib/foo-chroot {
                include {chroot-shared}
		# post chroot rules
		@{root}/etc/foo-users.conf r # Equivalent to /var/lib/foo-chroot/etc/foo-users.conf r
	}
}

which is fairly close to what you proposed.


However,
The variable is going to be a bit more problematic.  If we use a
userspace variable then @{root} would be currently doable.  But
may not give you the value you want when you do

chroot /** {

}

as it wouldn't be able to pickup the dynamic value of where you
actually chroot.  It possible we could add a kernel var that would
get updated, but that presupposes having kernel vars (which we don't
yet.

Also part of the point of this switch is that using the namespace
root in the chroot is problematic at best so using @{root} within
the chroot would not get you what you want as the paths are actually
relative to the new root. Nor would you be able to open new files
outside the scope of the chroot, though you could inherit access
from an already open fd.

I suppose it would be possible to add something to say that the rules
should be relative to @{root}, but then all your file rules would
have to be prefixed with @{root}, and I not sure that is what you want.


Part of this comes from chroots and namespaces being allowed to
load their own profile sets (eg they are being used as a light vm).
And you want the profiles they load to have rules relative to their
own root.  And accessing files outside of that root makes no sense,
except maybe in the case of stacking, where the earlier profiles in
the stack may want to access something that was opened before the
transition.

To handle that we are going to need use labeling or delegation.



More information about the AppArmor mailing list