[apparmor] Making AppArmor work with new mount context API

John Johansen john.johansen at canonical.com
Wed Jan 10 12:05:10 UTC 2018


On 01/09/2018 08:37 AM, David Howells wrote:
> Hi John,
> 
> I've been having a look at making AppArmor work with the new mount API, the
> basic infrastructure for which can be found here:
> 
> 	https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=mount-context
> 
> but this doesn't work for AppArmor.  Unfortunately, I've come across a tricky
> problem that I'm not sure how to solve, but maybe you can help with.
> 
> The issue involves how apparmor evaluates a DFA in do_match_mnt().  The DFA is
> fed the following things in the order:
> 
>  (1) Mountpoint path.
> 
>  (2) Device name.
> 
>  (3) File system type.
> 
>  (4) MS_* flags.
> 
>  (5) Non-binary mount data string (ie. mount options).
> 

yep

> However, what I want to do is make it so that:
> 
>  (1) MNT_* flags are differentiated from SB_* flags (ie. MS_* flags don't get
>      past the syscall interface).
> 
makes sense

>  (2) The superblock is set up as a separate step from the mounting step, prior
>      to the mounting step and then the mounting step may be repeated multiple
>      times for a given context, eg.;
> 
> 	fd = fsopen("ext4");
> 	write(fd, "d /dev/sda2");
> 	write(fd, "o user_xattr");
> 	write(fd, "o acl");
> 	write(fd, "o data=ordered");
> 	write(fd, "x create");
> 	// We now have a superblock and we can now query fs data
> 	write(fd, "q block_size");
> 	read(fd, query_buffer);
> 	// Mount three times
> 	fsmount(fd, "/mnt/a", MNT_NODEV | MNT_NOEXEC);
> 	fsmount(fd, "/mnt/b", 0);
> 	fsmount(fd, "/mnt/c", 0);
> 	close(fd);
> 
okay

>  (3) We can pick an existing object and then create a bind mount by something
>      like:
> 
> 	fd = fspick("/mnt/a");
> 	fsmount(fd, "/mnt/d");
> 	close(fd);
> 
>  (4) We can reconfigure (~= remount) a superblock by picking it, setting
>      parameters and then executing the reconfigure, eg.:
> 
> 	fd = fspick("/mnt/a");
> 	write(fd, "o ro");
> 	write(fd, "x reconfigure");
> 	close(fd);
> 
>      (Note that I want to use this opportunity to make reconfiguration atomic
>       with all the parameter error checking being done first).
> >  (5) Any particular option value may exceed a page in size and the total set
>      of options may exceed a page in size.  We can do this because the options
>      are delivered with write() and then parsed immediately.
> 
>  (6) Any particular option could be binary rather than text.  write() is given
>      the size of the blob, so we don't need to guess.  This feature could be
>      used to pass authentication data, say, for a network fs.
> 
> So the order in which Apparmor evaluates its DFA is really inconvenient.
> Ideally it would be:
> 
>  (1) Filesystem type.
> 
>  (2) Device name.
> 
>  (3) SB_* flags.
> 
>  (4) Options, passed one at a time (it doesn't look like it would be a problem
>      to save the intermediate DFA state).
> 

right, there are a couple places where we store and restart based off
of a saved state

> save this DFA state, then for each mount attempt, begin with the saved state
> and add:
> 
>  (5) Mount path.
> 
>  (6) MNT_* flags.
> 
> I don't suppose the DFA is created such that it doesn't matter what the order
> is?

it isn't atm, but the ability reorder and change the parameters set is
planned for to provide extended conditional support. So once that
lands a reordering would be possible.

Basically instead of hard coding the match order, policy will get a
vector that will be used to determine the set of conditionals and the
order to match them in.

> I would really like to avoid having to buffer the entire option set as a
> text string just so that Apparmor can parse it for each mount (though this
> could be done inside Apparmor code as the fs_context struct gives the active
> LSM somewhere to save state).
> 

that would be ugly but acceptable as an intermediate solution until I
can land the extended conditionals support.

I am not sure which is the quickest approach to get apparmor out of
the way for the new mount API. I can accelerate the extended
conditional work some by making mount mediation the first to use it,
but my guess is buffering the option set will still be a little
quicker as the extended conditional rework will require both kernel
and policy compiler work.




More information about the AppArmor mailing list