[apparmor] Making AppArmor work with new mount context API
David Howells
dhowells at redhat.com
Tue Jan 9 16:37:54 UTC 2018
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).
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).
(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);
(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).
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? 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).
Thanks,
David
More information about the AppArmor
mailing list