SEARCH
NEW RPMS
DIRECTORIES
ABOUT
FAQ
VARIOUS
BLOG
DONATE




YUM REPOSITORY

 
 

AA_CHANGE_HAT

Section: AppArmor (2)
Updated: 2007-07-27
Index 

NAME

aa_change_hat - change to or from a "hat" within a AppArmor profile 

SYNOPSIS

#include <sys/apparmor.h>

int aa_change_hat (char *subprofile, unsigned long magic_token);

Link with -lapparmor when compiling. 

DESCRIPTION

An AppArmor profile applies to an executable program; if a portion ofthe program needs different access permissions than other portions,the program can ``change hats'' to a different role, also known as asubprofile. To change into a new hat, it calls the aa_change_hat()function to do so. It passes in a pointer to the subprofile which itwants to change into, and a 64bit magic_token. The magic_tokenis used to return out of the subprofile at a later time.

If a program wants to return out of the current subprofile to theoriginal profile, it calls aa_change_hat() with a pointer to NULL asthe subprofile, and the original magic_token value. If themagic_token does not match the original magic_token passed into thekernel when the program entered the subprofile, the change back to theoriginal profile will not happen, and the current task will be killed.If the magic_token matches the original token, then the process willchange back to the original profile.

If the program wants to change to a subprofile that it can neverchange back out of, the application should call aa_change_hat() with amagic_token of 0.

As both read(2) and write(2) are mediated, a file must be listed in asubprofile definition if the file is to be accessed while the processis in a ``hat''. 

RETURN VALUE

On success zero is returned. On error, -1 is returned, anderrno(3) is set appropriately. 

ERRORS

EINVAL
The apparmor kernel module is not loaded or the communication via the/proc/*/attr/current file did not conform to protocol.
ENOMEM
Insufficient kernel memory was available.
EPERM
The calling application is not confined by apparmor.
ECHILD
The application's profile has no hats defined for it.
EACCES
The specified subprofile does not exist in this profile or theprocess tried to change another process's domain.
 

EXAMPLE

The following code examples shows simple, if contrived, uses ofaa_change_hat(); a typical use of aa_change_hat() will separateprivileged portions of a process from unprivileged portions of a process,such as keeping unauthenticated network traffic handling separatefrom authenticated network traffic handling in OpenSSH or executinguser-supplied CGI scripts in apache.

The use of random(3) is simply illustrative. Use of /dev/urandom isrecommended.

First, a simple high-level overview of aa_change_hat() use:

 void foo (void) {        unsigned long magic_token;          /* get a random magic token value        from our huge entropy pool */        magic_token = random_function();         /* change into the subprofile while         * we do stuff we don't trust */        aa_change_hat("stuff_we_dont_trust", magic_token);        /* Go do stuff we don't trust -- this is all         * done in *this* process space, no separate         * fork()/exec()'s are done. */        interpret_perl_stuff(stuff_from_user);        /* now change back to our original profile */        aa_change_hat(NULL, magic_token); }

Second, an example to show that files not listed in a subprofile (``hat'')aren't accessible after an aa_change_hat() call:

 #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>   int main(int argc, char *argv[]) {        int fd;        unsigned long tok;        char buf[10];         /* random() is a poor choice */        tok = random();         /* open /etc/passwd outside of any hat */        if ((fd=open("/etc/passwd", O_RDONLY)) < 0)                perror("Failure opening /etc/passwd");         /* confirm for ourselves that we can really read /etc/passwd */        memset(&buf, 0, 10);        if (read(fd, &buf, 10) == -1) {                perror("Failure reading /etc/passwd pre-hat");                _exit(1);        }        buf[9] = '\0';        printf("/etc/passwd: %s\n", buf);         /* change hat to the "hat" subprofile, which should not have         * read access to /etc/passwd -- even though we have a valid         * file descriptor at the time of the aa_change_hat() call. */        if (aa_change_hat("hat", tok)) {                perror("Failure changing hat -- aborting");                _exit(1);        }         /* confirm that we cannot read /etc/passwd */        lseek(fd,0,SEEK_SET);        memset(&buf, 0, 10);        if (read(fd, &buf, 10) == -1)                perror("Failure reading /etc/passwd post-hat");        buf[9] = '\0';        printf("/etc/passwd: %s\n", buf);         return 0; }

This code example requires the following profile to be loaded withapparmor_parser(8):

 /tmp/ch {   /etc/ld.so.cache               mr,   /etc/locale/**                 r,   /etc/localtime                 r,   /usr/share/locale/**           r,   /usr/share/zoneinfo/**         r,   /usr/lib/locale/**             mr,   /usr/lib/gconv/*.so            mr,   /usr/lib/gconv/gconv-modules*  mr,   /lib/ld-*.so*         mrix,   /lib/libc*.so*        mr,   /lib/libapparmor*.so* mr,   /dev/pts/*            rw,   /tmp/ch               mr,   /etc/passwd           r,   ^hat {     /dev/pts/*     rw,   } }

The output when run:

 $ /tmp/ch /etc/passwd: root:x:0: Failure reading /etc/passwd post-hat: Permission denied /etc/passwd: $
 

BUGS

None known. If you find any, please report them to bugzilla at<http://bugzilla.novell.com>. Note that aa_change_hat(2) provides nomemory barriers between different areas of a program; if address spaceseparation is required, then separate processes should be used. 

SEE ALSO

apparmor(7), apparmor.d(5), apparmor_parser(8), and<http://forge.novell.com/modules/xfmod/project/?apparmor>.


 

Index

NAME
SYNOPSIS
DESCRIPTION
RETURN VALUE
ERRORS
EXAMPLE
BUGS
SEE ALSO

This document was created byman2html,using the manual pages.