1
# $Id: change_hat.pod 224 2006-11-10 12:10:30Z seth_arnold $
2
# This publication is intellectual property of Novell Inc. Its contents
3
# can be duplicated, either in part or in whole, provided that a copyright
4
# label is visibly located on each copy.
6
# All information found in this book has been compiled with utmost
7
# attention to detail. However, this does not guarantee complete accuracy.
8
# Neither SUSE LINUX GmbH, the authors, nor the translators shall be held
9
# liable for possible errors or the consequences thereof.
11
# Many of the software and hardware descriptions cited in this book
12
# are registered trademarks. All trade names are subject to copyright
13
# restrictions and may be registered trade marks. SUSE LINUX GmbH
14
# essentially adheres to the manufacturer's spelling.
16
# Names of products and trademarks appearing in this book (with or without
17
# specific notation) are likewise subject to trademark and trade protection
18
# laws and may thus fall under copyright restrictions.
20
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
27
change_hat - change to or from a "hat" within a AppArmor profile
31
B<#include E<lt>sys/apparmor.hE<gt>>
33
B<int change_hat (char *subprofile, unsigned int magic_token);>
35
Link with B<-lapparmor> when compiling.
39
An AppArmor profile applies to an executable program; if a portion of
40
the program needs different access permissions than other portions,
41
the program can "change hats" to a different role, also known as a
42
subprofile. To change into a new hat, it calls the change_hat() function
43
to do so. It passes in a pointer to the I<subprofile> which it wants to
44
change into, and a 32bit I<magic_token>. The I<magic_token> is used to
45
return out of the subprofile at a later time.
47
If a program wants to return out of the current subprofile to the
48
original profile, it calls change_hat() with a pointer to NULL as
49
the I<subprofile>, and the original I<magic_token> value. If the
50
I<magic_token> does not match the original I<magic_token> passed into the
51
kernel when the program entered the subprofile, the change back to the
52
original profile will not happen, and the current task will be killed.
53
If the I<magic_token> matches the original token, then the process will
54
change back to the original profile.
56
If the program wants to change to a subprofile that it can never
57
change back out of, the application should call change_hat() with a
58
I<magic_token> of I<0>.
60
As both read(2) and write(2) are mediated, a file must be listed in a
61
subprofile definition if the file is to be accessed while the process
66
On success zero is returned. On error, -1 is returned, and
67
errno(3) is set appropriately.
75
The apparmor kernel module is not loaded or the communication via the
76
F</proc/*/attr/current> file did not conform to protocol.
80
Insufficient kernel memory was available.
84
The calling application is not confined by apparmor.
88
The application's profile has no hats defined for it.
92
The specified I<subprofile> does not exist in this profile or the
93
process tried to change another process's domain.
99
The following code examples shows simple, if contrived, uses of
100
change_hat(); a typical use of change_hat() will separate privileged
101
portions of a process from unprivileged portions of a process, such as
102
keeping unauthenticated network traffic handling separate from
103
authenticated network traffic handling in OpenSSH or executing
104
user-supplied CGI scripts in apache.
106
The use of random(3) is simply illustrative. Use of F</dev/urandom> is
109
First, a simple high-level overview of change_hat() use:
114
/* get a random magic token value
115
from our huge entropy pool */
116
magic_token = random_function();
118
/* change into the subprofile while
119
* we do stuff we don't trust */
120
change_hat ("stuff_we_dont_trust", magic_token);
122
/* Go do stuff we don't trust -- this is all
123
* done in *this* process space, no separate
124
* fork()/exec()'s are done. */
125
interpret_perl_stuff(stuff_from_user);
127
/* now change back to our original profile */
128
change_hat (NULL, magic_token);
131
Second, an example to show that files not listed in a subprofile
132
("hat") aren't accessible after a change_hat() call:
136
#include <sys/apparmor.h>
137
#include <sys/types.h>
138
#include <sys/stat.h>
144
int main(int argc, char *argv[]) {
149
/* random() is a poor choice */
152
/* open /etc/passwd outside of any hat */
153
if ((fd=open("/etc/passwd", O_RDONLY)) < 0)
154
perror("Failure opening /etc/passwd");
156
/* confirm for ourselves that we can really read /etc/passwd */
158
if (read(fd, &buf, 10) == -1) {
159
perror("Failure reading /etc/passwd pre-hat");
163
printf("/etc/passwd: %s\n", buf);
165
/* change hat to the "hat" subprofile, which should not have
166
* read access to /etc/passwd -- even though we have a valid
167
* file descriptor at the time of the change_hat() call. */
168
if (change_hat("hat", tok)) {
169
perror("Failure changing hat -- aborting");
173
/* confirm that we cannot read /etc/passwd */
174
lseek(fd,0,SEEK_SET);
176
if (read(fd, &buf, 10) == -1)
177
perror("Failure reading /etc/passwd post-hat");
179
printf("/etc/passwd: %s\n", buf);
185
This code example requires the following profile to be loaded with
192
/usr/share/locale/** r,
193
/usr/share/zoneinfo/** r,
194
/usr/lib/locale/** mr,
195
/usr/lib/gconv/*.so mr,
196
/usr/lib/gconv/gconv-modules* mr,
200
/lib/libapparmor*.so* mr,
215
/etc/passwd: root:x:0:
216
Failure reading /etc/passwd post-hat: Permission denied
223
None known. If you find any, please report them to bugzilla at
224
L<http://bugzilla.novell.com>. Note that change_hat(2) provides no
225
memory barriers between different areas of a program; if address space
226
separation is required, then separate processes should be used.
230
apparmor(7), apparmor.d(5), apparmor_parser(8), and
231
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.