.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man 5.0102 (Pod::Simple 3.45) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "AA_CHANGE_PROFILE 2" .TH AA_CHANGE_PROFILE 2 2024-10-14 "AppArmor 4.0.3" AppArmor .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME aa_change_profile, aa_change_onexec \- change a tasks profile .SH SYNOPSIS .IX Header "SYNOPSIS" \&\fB#include \fR .PP \&\fBint aa_change_profile(const char *profile);\fR .PP \&\fBint aa_change_onexec(const char *profile);\fR .PP Link with \fB\-lapparmor\fR when compiling. .SH DESCRIPTION .IX Header "DESCRIPTION" 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 \fBaa_change_profile()\fR function to do so. It passes in a pointer to the \fIprofile\fR to transition to. Confined programs wanting to use \fBaa_change_profile()\fR need to have rules permitting changing to the named profile. See \fBapparmor.d\fR\|(8) for details. .PP If a program wants to return out of the current profile to the original profile, it may use \fBaa_change_hat\fR\|(2). Otherwise, the two profiles must have rules permitting changing between the two profiles. .PP Open file descriptors may not be remediated after a call to \fBaa_change_profile()\fR so the calling program must \fBclose\fR\|(2) open file descriptors to ensure they are not available after calling \fBaa_change_profile()\fR. As \fBaa_change_profile()\fR is typically used just before \fBexecve\fR\|(2), you may want to use \fBopen\fR\|(2) or \&\fBfcntl\fR\|(2) with close-on-exec. .PP The \fBaa_change_onexec()\fR function is like the \fBaa_change_profile()\fR 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. .SH "RETURN VALUE" .IX Header "RETURN VALUE" On success zero is returned. On error, \-1 is returned, and \&\fBerrno\fR\|(3) is set appropriately. .SH ERRORS .IX Header "ERRORS" .IP \fBEINVAL\fR 4 .IX Item "EINVAL" The apparmor kernel module is not loaded, neither a profile nor a namespace was specified, or the communication via the \fI/proc/*/attr/current\fR file did not conform to protocol. .IP \fBENOMEM\fR 4 .IX Item "ENOMEM" Insufficient kernel memory was available. .IP \fBEPERM\fR 4 .IX Item "EPERM" The calling application is confined by apparmor and the no_new_privs bit is set. .IP \fBEACCES\fR 4 .IX Item "EACCES" The task does not have sufficient permissions to change its domain. .IP \fBENOENT\fR 4 .IX Item "ENOENT" The specified profile does not exist, or is not visible from the current Namespace. .SH EXAMPLE .IX Header "EXAMPLE" The following example shows a simple, if contrived, use of \&\fBaa_change_profile()\fR; a typical use of \fBaa_change_profile()\fR will \&\fBaa_change_profile()\fR just before an \fBexecve\fR\|(2) so that the new child process is permanently confined. .PP .Vb 8 \& #include \& #include \& #include \& #include \& #include \& #include \& #include \& #include \& \& int main(int argc, char * argv[]) \& { \& int fd; \& char buf[10]; \& char *execve_args[4]; \& \& printf("Before aa_change_profile():\en"); \& 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] = \*(Aq\e0\*(Aq; \& printf("/etc/passwd: %s\en", buf); \& close(fd); \& \& printf("After aa_change_profile():\en"); \& \& /* 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"); \& _exit(1); \& } \& \& /* 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); \& perror("execve"); \& _exit(1); \& } .Ve .PP This code example requires a profile similar to the following to be loaded with \fBapparmor_parser\fR\|(8): .PP .Vb 4 \& profile i_cant_be_trusted_anymore { \& /etc/ld.so.cache mr, \& /lib/ld\-*.so* mrix, \& /lib/libc*.so* mr, \& \& /usr/bin/head ix, \& } .Ve .PP The output when run: .PP .Vb 6 \& $ /tmp/change_p \& Before aa_change_profile(): \& /etc/passwd: root:x:0: \& After aa_change_profile(): \& /usr/bin/head: cannot open \`/etc/passwd\*(Aq for reading: Permission denied \& $ .Ve .PP 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): .PP .Vb 6 \& # Confine change_p to be able to read /etc/passwd and aa_change_profile() \& # to the \*(Aqi_cant_be_trusted_anymore\*(Aq 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, \& } .Ve .SH BUGS .IX Header "BUGS" None known. If you find any, please report them at . Note that using \&\fBaa_change_profile\fR\|(2) without \fBexecve\fR\|(2) provides no memory barriers between different areas of a program; if address space separation is required, then separate processes should be used. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fBapparmor\fR\|(7), \fBapparmor.d\fR\|(5), \fBapparmor_parser\fR\|(8), \fBaa_change_hat\fR\|(2) and .