aa_change_profile, aa_change_onexec − change a tasks profile


#include <sys/apparmor.h>

int aa_change_profile(const char *profile);

int aa_change_onexec(const char *profile);

Link with −lapparmor when compiling.


An AppArmor profile applies to an executable program; if a portion of the program needs different access permissions than other portions, the program can "change profile" to a different profile. To change into a new profile, it can use the aa_change_profile() function to do so. It passes in a pointer to the profile to transition to. Transitioning to another profile via aa_change_profile() is permanent and the process is not permitted to transition back to the original profile. Confined programs wanting to use aa_change_profile() need to have rules permitting changing to the named profile. See apparmor.d(8) for details.

If a program wants to return out of the current profile to the original profile, it should use aa_change_hat(2) instead.

Open file descriptors are not remediated after a call to aa_change_profile() so the calling program must close(2) open file descriptors to ensure they are not available after calling aa_change_profile(). As aa_change_profile() is typically used just before execve(2), you may want to use open(2) or fcntl(2) with close-on-exec.

The aa_change_onexec() function is like the aa_change_profile() function except it specifies that the profile transition 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 profile 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.


On success zero is returned. On error, −1 is returned, and errno(3) is set appropriately.



The apparmor kernel module is not loaded, neither a profile nor a namespace was specified, or the communication via the /proc/*/attr/current file did not conform to protocol.


Insufficient kernel memory was available.


The calling application is not confined by apparmor, or the no_new_privs bit is set.


The task does not have sufficient permissions to change its domain.


The specified profile does not exist, or is not visible from the current Namespace.


The following example shows a simple, if contrived, use of aa_change_profile(); a typical use of aa_change_profile() will aa_change_profile() just before an execve(2) so that the new child process is permanently confined.

 #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;
         char buf[10];
         char *execve_args[4];
                  printf("Before aa_change_profile():\n");
                  if ((fd=open("/etc/passwd", O_RDONLY)) < 0) {
                                perror("Failure opening /etc/passwd");
                return 1;
         /* 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");
                 return 1;
         buf[9] = '\0';
                  printf("/etc/passwd: %s\n", buf);
                  printf("After aa_change_profile():\n");
         /* change profile to the "i_cant_be_trusted_anymore" profile, which
          * should not have read access to /etc/passwd. */
                  if (aa_change_profile("i_cant_be_trusted_anymore") < 0) {
                          perror("Failure changing profile −− aborting");
         /* confirm that we cannot read /etc/passwd */
         execve_args[0] = "/usr/bin/head";
         execve_args[1] = "−1";
         execve_args[2] = "/etc/passwd";
         execve_args[3] = NULL;
                  execve("/usr/bin/head", execve_args, NULL);

This code example requires a profile similar to the following to be loaded with apparmor_parser(8):

 profile i_cant_be_trusted_anymore {
     /etc/ld.so.cache      mr,
     /lib/ld−*.so*         mrix,
     /lib/libc*.so*        mr,
     /usr/bin/head ix,

The output when run:

 $ /tmp/change_p
  Before aa_change_profile():
 /etc/passwd: root:x:0:
  After aa_change_profile():
 /usr/bin/head: cannot open `/etc/passwd' for reading: Permission denied

If /tmp/change_p is to be confined as well, then the following profile can be used (in addition to the one for ’i_cant_be_trusted_anymore’, above):

 # Confine change_p to be able to read /etc/passwd and aa_change_profile()
 # to the 'i_cant_be_trusted_anymore' profile.
 /tmp/change_p {
     /etc/ld.so.cache          mr,
     /lib/ld−*.so*             mrix,
     /lib/libc*.so*            mr,
     /etc/passwd               r,
          # Needed for aa_change_profile()
     /usr/lib/libapparmor*.so* mr,
     /proc/[0−9]*/attr/current w,
     change_profile −> i_cant_be_trusted_anymore,


None known. If you find any, please report them at <https://bugs.launchpad.net/apparmor/+filebug>. Note that using aa_change_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.


apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_hat(2) and <http://wiki.apparmor.net>.

More Linux Commands

XDrawPoint(3) - draw points and points structure (Man Page)
The XDrawPoint function uses the foreground pixel and function components of the GC to draw a single point into the specified drawable; XDrawPoints draws multip

nlmconv(1) - converts object code into an NLM. (Man Page)...
nlmconv converts the relocatable i386 object file infile into the NetWare Loadable Module outfile, optionally reading headerfile for NLM header information. For

getrpcbynumber_r(3) - get RPC entry (reentrant) (Man Page)
The getrpcent_r(), getrpcbyname_r(), and getrpcbynumber_r() functions are the reentrant equivalents of, respectively, getrpcent(3), getrpcbyname(3), and getrpcb

systemd-timedated(8) Time and date bus mechanism (Man Page)
systemd-timedated is a system service that may be used as a mechanism to change the system clock and timezone, as well as to enable/disable NTP time synchroniza

autotrace(1) converts bitmap image data into vector graphics
The autotrace program accepts bitmap graphics from the file inputfile specified on the command line, and as output produces a collection of splines approximatin

XGetModifierMapping(3) - manipulate keyboard encoding and ke
The XChangeKeyboardMapping function defines the symbols for the specified number of KeyCodes starting with first_keycode. The symbols for KeyCodes outside this

Tcl_CreateEncoding(3) - procedures for creating and using en
Tcl_GetEncoding finds an encoding given its name. The name may refer to a built-in Tcl encoding, a user-defined encoding registered by calling Tcl_CreateEncodin

ppmtoppm(1) - copy PPM image (Commands - Linux man page)....
This program is part of Netpbm(1) ppmtoppm simply copies a PPM image from Standard Input to Standard Output. This may seem an unnecessary duplication of cat, bu

btrfs-balance(8) balance btrfs filesystem - Linux man page
btrfs balance is used to balance chunks in a btrfs filesystem across multiple or even single device. See btrfs-device(8) for more details about the effect on de

Tcl_SignalId(3) - Convert signal codes - Linux manual page
Tcl_SignalId and Tcl_SignalMsg return a string representation of the provided signal number (sig). Tcl_SignalId returns a machine-readable textual identifier su

ldap_value_free(3) - LDAP attribute value handling routines
These routines are used to retrieve and manipulate attribute values from an LDAP entry as returned by ldap_first_entry(3) or ldap_next_entry(3). ldap_get_values

DMXGetDesktopAttributes(3) - determine global bounding box
DMXGetDesktopAttributes() returns information about the desktop in DMXDesktopAttributes: typedef struct { unsigned int width; unsigned int height; int shiftX; i

We can't live, work or learn in freedom unless the software we use is free.