Modeled after the aa_change_profile(2) man page, this profile defines the libapparmor and kernel interfaces for the in-progress profile stacking feature.
Signed-off-by: Tyler Hicks <[email protected]> --- libraries/libapparmor/doc/Makefile.am | 2 +- libraries/libapparmor/doc/aa_stack_profile.pod | 229 +++++++++++++++++++++++++ 2 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 libraries/libapparmor/doc/aa_stack_profile.pod diff --git a/libraries/libapparmor/doc/Makefile.am b/libraries/libapparmor/doc/Makefile.am index 90cc149..0811e23 100644 --- a/libraries/libapparmor/doc/Makefile.am +++ b/libraries/libapparmor/doc/Makefile.am @@ -5,7 +5,7 @@ PODCHECKER = podchecker if ENABLE_MAN_PAGES -man_MANS = aa_change_hat.2 aa_change_profile.2 aa_getcon.2 aa_find_mountpoint.2 aa_splitcon.3 aa_query_label.2 aa_features.3 aa_kernel_interface.3 aa_policy_cache.3 +man_MANS = aa_change_hat.2 aa_change_profile.2 aa_stack_profile.2 aa_getcon.2 aa_find_mountpoint.2 aa_splitcon.3 aa_query_label.2 aa_features.3 aa_kernel_interface.3 aa_policy_cache.3 PODS = $(subst .2,.pod,$(man_MANS)) $(subst .3,.pod,$(man_MANS)) diff --git a/libraries/libapparmor/doc/aa_stack_profile.pod b/libraries/libapparmor/doc/aa_stack_profile.pod new file mode 100644 index 0000000..e707ce7 --- /dev/null +++ b/libraries/libapparmor/doc/aa_stack_profile.pod @@ -0,0 +1,229 @@ +# This publication is intellectual property of Canonical Ltd. Its contents +# can be duplicated, either in part or in whole, provided that a copyright +# label is visibly located on each copy. +# +# All information found in this book has been compiled with utmost +# attention to detail. However, this does not guarantee complete accuracy. +# Neither Canonical Ltd, the authors, nor the translators shall be held +# liable for possible errors or the consequences thereof. +# +# Many of the software and hardware descriptions cited in this book +# are registered trademarks. All trade names are subject to copyright +# restrictions and may be registered trade marks. Canonical Ltd. +# essentially adhere to the manufacturer's spelling. +# +# Names of products and trademarks appearing in this book (with or without +# specific notation) are likewise subject to trademark and trade protection +# laws and may thus fall under copyright restrictions. +# + + +=pod + +=head1 NAME + +aa_stack_profile, aa_stack_onexec - combine multiple profiles to confine a task + +=head1 SYNOPSIS + +B<#include E<lt>sys/apparmor.hE<gt>> + +B<int aa_stack_profile(const char *profile);> + +B<int aa_stack_onexec(const char *profile);> + +Link with B<-lapparmor> when compiling. + +=head1 DESCRIPTION + +AppArmor supports stacking two or more profiles when confining a task. The +result is an intersection of all profiles which are stacked. Stacking profiles +together is desirable when wanting to ensure that confinement will never become +more permissive. When changing between two profiles, as performed with +aa_change_profile(2), there is always the possibility that the new profile is +more permissive than the old profile but that possibility is eliminated when +using aa_stack_profile(). + +To stack a profile with the current confinement context, a task can use the +aa_stack_profile() function. The I<profile> parameter is a NUL-terminated +string indicating a profile name that should be stacked with the current +confinement. + +Calling aa_stack_profile("profile_a") while unconfined is equivalent to calling +aa_change_profile("profile_a") since the intersection of unconfined and +"profile_a" is "profile_a". Calling aa_change_profile("profile_b") while +confined by "profile_a" results in the task's confinement to be the +intersection of "profile_a" and "profile_b". The resulting confinement context +will be represented as "profile_a//&profile_b" in audit log messages, the +return value of aa_getcon(2), etc. + +Stacking another profile via aa_stack_profile() is permanent and the process is not +permitted to revert to the previous confinement context. Unlike +aa_change_profile(2), confined programs wanting to use aa_stack_profile() need +no special rules in their profile to stack a new profile since the operation +does not broaden the allowed permissions. + +Open file descriptors are not remediated after a call to aa_stack_profile() +so the calling program must close(2) open file descriptors to ensure they +are not available after calling aa_stack_profile(). + +The aa_stack_onexec() function is like the aa_stack_profile() function +except it specifies that the stacking should take place on the next exec +instead of immediately. The delayed profile change takes precedence over any +exec transition rules within the confining profile. Delaying the stacking +boundary has a couple of advantages, it removes the need for stub transition +profiles and the exec boundary is a natural security layer where potentially +sensitive memory is unmapped. + +=head1 RETURN VALUE + +On success zero is returned. On error, -1 is returned, and +errno(3) is set appropriately. + +=head1 ERRORS + +=over 4 + +=item B<EINVAL> + +The AppArmor kernel module is not loaded, neither a profile nor a namespace +was specified, or the communication via the F</proc/*/attr/current> file did +not conform to protocol. + +=item B<ENOMEM> + +Insufficient kernel memory was available. + +=item B<EPERM> + +The calling application is not confined by AppArmor, or the no_new_privs +bit is set. + +=item B<ENOENT> + +The specified profile does not exist, or is not visible from the current +namespace. + +=back + +=head1 NOTES + +Using aa_stack_profile() and related libapparmor functions are the only way to +ensure compatibility between among varying kernel versions. However, there may +be some situations where libapparmor is not available and directly interacting +with the AppArmor filesystem is required to stack a profile. + +To immediately stack a profile named "profile_a", as performed with +aa_stack_profile("profile_a"), the equivalent of this shell command can be +used: + + $ echo -n "stackprofile profile_a" > /proc/self/attr/current + +To stack a profile named "profile_a" at the next exec, as performed with +aa_stack_onexec("profile_a"), the equivalent of this shell command can be used: + + $ echo -n "stackexec profile_a" > /proc/self/attr/exec + +These raw AppArmor filesystem operations must only be used when using +libapparmor is not a viable option. + +=head1 EXAMPLE + +The following example shows a simple, if contrived, use of +aa_stack_profile(). + + #include <stdlib.h> + #include <string.h> + #include <sys/apparmor.h> + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> + #include <stdio.h> + #include <unistd.h> + + static void read_passwd() + { + int fd; + char buf[10]; + + if ((fd=open("/etc/passwd", O_RDONLY)) < 0) { + perror("Failure opening /etc/passwd"); + _exit(1); + } + + /* Verify that we can read /etc/passwd */ + memset(&buf, 0, 10); + if (read(fd, &buf, 10) == -1) { + perror("Failure reading /etc/passwd"); + _exit(1); + } + buf[9] = '\0'; + printf("/etc/passwd: %s\n", buf); + close(fd); + } + + int main(int argc, char * argv[]) + { + printf("Before aa_stack_profile():\n"); + read_passwd(); + + /* stack the "i_cant_be_trusted_anymore" profile, which + * should not have read access to /etc/passwd. */ + if (aa_stack_profile("i_cant_be_trusted_anymore") < 0) { + perror("Failure changing profile -- aborting"); + _exit(1); + } + + printf("After aa_stack_profile():\n"); + read_passwd(); + _exit(0); + } + +This code example requires a profile similar to the following to be loaded +with apparmor_parser(8): + + # Confine stack_p to be able to read /etc/passwd and aa_stack_profile() + # to the 'i_cant_be_trusted_anymore' profile. + /tmp/stack_p { + /etc/ld.so.cache mr, + /lib/ld-*.so* mrix, + /lib/libc*.so* mr, + + /etc/passwd r, + + # Needed for aa_stack_profile() + /usr/lib/libapparmor*.so* mr, + /proc/[0-9]*/attr/current w, + } + +As well as the profile to stack: + + profile i_cant_be_trusted_anymore { + /etc/ld.so.cache mr, + /lib/ld-*.so* mrix, + /lib/libc*.so* mr, + } + +The output when run: + + $ /tmp/stack_p + Before aa_stack_profile(): + /etc/passwd: root:x:0: + After aa_stack_profile(): + Failure opening /etc/passwd: Permission denied + $ + +=head1 BUGS + +None known. If you find any, please report them at +L<https://bugs.launchpad.net/apparmor/+filebug>. Note that using +aa_stack_profile(2) without execve(2) provides no memory barriers between +different areas of a program; if address space separation is required, then +separate processes should be used. + +=head1 SEE ALSO + +apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2), +aa_getcon(2) and L<http://wiki.apparmor.net>. + +=cut -- 2.5.0 -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
