~ubuntu-branches/ubuntu/wily/apparmor/wily

« back to all changes in this revision

Viewing changes to docs/change_hat.pod

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2011-04-27 10:38:07 UTC
  • mfrom: (5.1.118 natty)
  • Revision ID: james.westby@ubuntu.com-20110427103807-ym3rhwys6o84ith0
Tags: 2.6.1-2
debian/copyright: clarify for some full organization names.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.
5
 
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.
10
 
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.
15
 
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.
19
 
20
 
# Please direct suggestions and comments to apparmor-general@forge.novell.com.
21
 
 
22
 
 
23
 
=pod
24
 
 
25
 
=head1 NAME
26
 
 
27
 
change_hat  - change to or from a "hat" within a AppArmor profile
28
 
 
29
 
=head1 SYNOPSIS
30
 
 
31
 
B<#include E<lt>sys/apparmor.hE<gt>>
32
 
 
33
 
B<int change_hat (char *subprofile, unsigned int magic_token);>
34
 
 
35
 
Link with B<-lapparmor> when compiling.
36
 
 
37
 
=head1 DESCRIPTION
38
 
 
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.
46
 
 
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.
55
 
 
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>.
59
 
 
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
62
 
is in a "hat".
63
 
 
64
 
=head1 RETURN VALUE
65
 
 
66
 
On success zero is returned. On error, -1 is returned, and
67
 
errno(3) is set appropriately.
68
 
 
69
 
=head1 ERRORS
70
 
 
71
 
=over 4
72
 
 
73
 
=item B<EINVAL>
74
 
 
75
 
The apparmor kernel module is not loaded or the communication via the
76
 
F</proc/*/attr/current> file did not conform to protocol.
77
 
 
78
 
=item B<ENOMEM>
79
 
 
80
 
Insufficient kernel memory was available.
81
 
 
82
 
=item B<EPERM>
83
 
 
84
 
The calling application is not confined by apparmor.
85
 
 
86
 
=item B<ECHILD>
87
 
 
88
 
The application's profile has no hats defined for it.
89
 
 
90
 
=item B<EACCES>
91
 
 
92
 
The specified I<subprofile> does not exist in this profile or the
93
 
process tried to change another process's domain.
94
 
 
95
 
=back 
96
 
 
97
 
=head1 EXAMPLE
98
 
 
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.
105
 
 
106
 
The use of random(3) is simply illustrative. Use of F</dev/urandom> is
107
 
recommended.
108
 
 
109
 
First, a simple high-level overview of change_hat() use:
110
 
 
111
 
 void foo (void) {
112
 
        int magic_token;
113
 
  
114
 
        /* get a random magic token value
115
 
        from our huge entropy pool */
116
 
        magic_token = random_function();
117
 
 
118
 
        /* change into the subprofile while
119
 
         * we do stuff we don't trust */
120
 
        change_hat ("stuff_we_dont_trust", magic_token);
121
 
 
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);
126
 
 
127
 
        /* now change back to our original profile */
128
 
        change_hat (NULL, magic_token);
129
 
 }
130
 
 
131
 
Second, an example to show that files not listed in a subprofile
132
 
("hat") aren't accessible after a change_hat() call:
133
 
 
134
 
 #include <stdlib.h>
135
 
 #include <string.h>
136
 
 #include <sys/apparmor.h>
137
 
 #include <sys/types.h>
138
 
 #include <sys/stat.h>
139
 
 #include <fcntl.h>
140
 
 #include <stdio.h>
141
 
 #include <unistd.h>
142
 
 
143
 
 
144
 
 int main(int argc, char *argv[]) {
145
 
        int fd;
146
 
        int tok;
147
 
        char buf[10];
148
 
 
149
 
        /* random() is a poor choice */
150
 
        tok = random();
151
 
 
152
 
        /* open /etc/passwd outside of any hat */
153
 
        if ((fd=open("/etc/passwd", O_RDONLY)) < 0)
154
 
                perror("Failure opening /etc/passwd");
155
 
 
156
 
        /* confirm for ourselves that we can really read /etc/passwd */
157
 
        memset(&buf, 0, 10);
158
 
        if (read(fd, &buf, 10) == -1) {
159
 
                perror("Failure reading /etc/passwd pre-hat");
160
 
                _exit(1);
161
 
        }
162
 
        buf[9] = '\0';
163
 
        printf("/etc/passwd: %s\n", buf);
164
 
 
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");
170
 
                _exit(1);
171
 
        }
172
 
 
173
 
        /* confirm that we cannot read /etc/passwd */
174
 
        lseek(fd,0,SEEK_SET);
175
 
        memset(&buf, 0, 10);
176
 
        if (read(fd, &buf, 10) == -1)
177
 
                perror("Failure reading /etc/passwd post-hat");
178
 
        buf[9] = '\0';
179
 
        printf("/etc/passwd: %s\n", buf);
180
 
 
181
 
        return 0;
182
 
 }
183
 
 
184
 
 
185
 
This code example requires the following profile to be loaded with
186
 
apparmor_parser(8):
187
 
 
188
 
 /tmp/ch {
189
 
   /etc/ld.so.cache               mr,
190
 
   /etc/locale/**                 r,
191
 
   /etc/localtime                 r,
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,
197
 
 
198
 
   /lib/ld-*.so*         mrix,
199
 
   /lib/libc*.so*        mr,
200
 
   /lib/libapparmor*.so* mr,
201
 
   /dev/pts/*            rw,
202
 
   /tmp/ch               mr,
203
 
 
204
 
   /etc/passwd           r,
205
 
 
206
 
   ^hat {
207
 
     /dev/pts/*     rw,
208
 
   }
209
 
 }
210
 
 
211
 
 
212
 
The output when run:
213
 
 
214
 
 $ /tmp/ch
215
 
 /etc/passwd: root:x:0:
216
 
 Failure reading /etc/passwd post-hat: Permission denied
217
 
 /etc/passwd:
218
 
 $
219
 
 
220
 
 
221
 
=head1 BUGS
222
 
 
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.
227
 
 
228
 
=head1 SEE ALSO
229
 
 
230
 
apparmor(7), apparmor.d(5), apparmor_parser(8), and
231
 
L<http://forge.novell.com/modules/xfmod/project/?apparmor>.
232
 
 
233
 
=cut