]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.apparmor/apparmor-main.diff
Add a patch to fix Intel E100 wake-on-lan problems.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.apparmor / apparmor-main.diff
1 From: John Johansen <jjohansen@suse.de>
2 Subject: AppArmor: Main Part
3
4 The underlying functions by which the AppArmor LSM hooks are implemented.
5
6 Signed-off-by: John Johansen <jjohansen@suse.de>
7 Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
8
9 ---
10 security/apparmor/main.c | 1478 +++++++++++++++++++++++++++++++++++++++++++++++
11 1 file changed, 1478 insertions(+)
12
13 --- /dev/null
14 +++ b/security/apparmor/main.c
15 @@ -0,0 +1,1478 @@
16 +/*
17 + * Copyright (C) 2002-2007 Novell/SUSE
18 + *
19 + * This program is free software; you can redistribute it and/or
20 + * modify it under the terms of the GNU General Public License as
21 + * published by the Free Software Foundation, version 2 of the
22 + * License.
23 + *
24 + * AppArmor Core
25 + */
26 +
27 +#include <linux/security.h>
28 +#include <linux/namei.h>
29 +#include <linux/audit.h>
30 +#include <linux/mount.h>
31 +#include <linux/ptrace.h>
32 +
33 +#include "apparmor.h"
34 +
35 +#include "inline.h"
36 +
37 +/*
38 + * Table of capability names: we generate it from capabilities.h.
39 + */
40 +static const char *capability_names[] = {
41 +#include "capability_names.h"
42 +};
43 +
44 +struct aa_namespace *default_namespace;
45 +
46 +static int aa_inode_mode(struct inode *inode)
47 +{
48 + /* if the inode doesn't exist the user is creating it */
49 + if (!inode || current->fsuid == inode->i_uid)
50 + return AA_USER_SHIFT;
51 + return AA_OTHER_SHIFT;
52 +}
53 +
54 +int alloc_default_namespace(void)
55 +{
56 + struct aa_namespace *ns;
57 + char *name = kstrdup("default", GFP_KERNEL);
58 + if (!name)
59 + return -ENOMEM;
60 + ns = alloc_aa_namespace(name);
61 + if (!ns) {
62 + kfree(name);
63 + return -ENOMEM;
64 + }
65 +
66 + write_lock(&profile_ns_list_lock);
67 + default_namespace = ns;
68 + aa_get_namespace(ns);
69 + list_add(&ns->list, &profile_ns_list);
70 + write_unlock(&profile_ns_list_lock);
71 +
72 + return 0;
73 +}
74 +
75 +void free_default_namespace(void)
76 +{
77 + write_lock(&profile_ns_list_lock);
78 + list_del_init(&default_namespace->list);
79 + write_unlock(&profile_ns_list_lock);
80 + aa_put_namespace(default_namespace);
81 + default_namespace = NULL;
82 +}
83 +
84 +static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
85 + int mask)
86 +{
87 + const char unsafex[] = "upcn";
88 + const char safex[] = "UPCN";
89 + char *m = buffer;
90 +
91 + if (mask & AA_EXEC_MMAP)
92 + *m++ = 'm';
93 + if (mask & MAY_READ)
94 + *m++ = 'r';
95 + if (mask & MAY_WRITE)
96 + *m++ = 'w';
97 + else if (mask & MAY_APPEND)
98 + *m++ = 'a';
99 + if (mask & MAY_EXEC) {
100 + int index = AA_EXEC_INDEX(mask);
101 + /* all indexes > 4 are also named transitions */
102 + if (index > 4)
103 + index = 4;
104 + if (index > 0) {
105 + if (mask & AA_EXEC_UNSAFE)
106 + *m++ = unsafex[index - 1];
107 + else
108 + *m++ = safex[index - 1];
109 + }
110 + if (mask & AA_EXEC_INHERIT)
111 + *m++ = 'i';
112 + *m++ = 'x';
113 + }
114 + if (mask & AA_MAY_LINK)
115 + *m++ = 'l';
116 + if (mask & AA_MAY_LOCK)
117 + *m++ = 'k';
118 + *m++ = '\0';
119 +}
120 +
121 +static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
122 + int mask)
123 +{
124 + char user[10], other[10];
125 +
126 + aa_audit_file_sub_mask(ab, user,
127 + (mask & AA_USER_PERMS) >> AA_USER_SHIFT);
128 + aa_audit_file_sub_mask(ab, other,
129 + (mask & AA_OTHER_PERMS) >> AA_OTHER_SHIFT);
130 +
131 + audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
132 +}
133 +
134 +/**
135 + * aa_audit - Log an audit event to the audit subsystem
136 + * @profile: profile to check against
137 + * @sa: audit event
138 + * @audit_cxt: audit context to log message to
139 + * @type: audit event number
140 + */
141 +static int aa_audit_base(struct aa_profile *profile, struct aa_audit *sa,
142 + struct audit_context *audit_cxt, int type)
143 +{
144 + struct audit_buffer *ab = NULL;
145 +
146 + ab = audit_log_start(audit_cxt, sa->gfp_mask, type);
147 +
148 + if (!ab) {
149 + AA_ERROR("Unable to log event (%d) to audit subsys\n",
150 + type);
151 + /* don't fail operations in complain mode even if logging
152 + * fails */
153 + return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
154 + }
155 +
156 + if (sa->operation)
157 + audit_log_format(ab, "operation=\"%s\"", sa->operation);
158 +
159 + if (sa->info) {
160 + audit_log_format(ab, " info=\"%s\"", sa->info);
161 + if (sa->error_code)
162 + audit_log_format(ab, " error=%d", sa->error_code);
163 + }
164 +
165 + if (sa->request_mask)
166 + aa_audit_file_mask(ab, "requested_mask", sa->request_mask);
167 +
168 + if (sa->denied_mask)
169 + aa_audit_file_mask(ab, "denied_mask", sa->denied_mask);
170 +
171 + if (sa->request_mask)
172 + audit_log_format(ab, " fsuid=%d", current->fsuid);
173 +
174 + if (sa->iattr) {
175 + struct iattr *iattr = sa->iattr;
176 +
177 + audit_log_format(ab, " attribute=\"%s%s%s%s%s%s%s\"",
178 + iattr->ia_valid & ATTR_MODE ? "mode," : "",
179 + iattr->ia_valid & ATTR_UID ? "uid," : "",
180 + iattr->ia_valid & ATTR_GID ? "gid," : "",
181 + iattr->ia_valid & ATTR_SIZE ? "size," : "",
182 + iattr->ia_valid & (ATTR_ATIME | ATTR_ATIME_SET) ?
183 + "atime," : "",
184 + iattr->ia_valid & (ATTR_MTIME | ATTR_MTIME_SET) ?
185 + "mtime," : "",
186 + iattr->ia_valid & ATTR_CTIME ? "ctime," : "");
187 + }
188 +
189 + if (sa->task)
190 + audit_log_format(ab, " task=%d", sa->task);
191 +
192 + if (sa->parent)
193 + audit_log_format(ab, " parent=%d", sa->parent);
194 +
195 + if (sa->name) {
196 + audit_log_format(ab, " name=");
197 + audit_log_untrustedstring(ab, sa->name);
198 + }
199 +
200 + if (sa->name2) {
201 + audit_log_format(ab, " name2=");
202 + audit_log_untrustedstring(ab, sa->name2);
203 + }
204 +
205 + audit_log_format(ab, " pid=%d", current->pid);
206 +
207 + if (profile) {
208 + audit_log_format(ab, " profile=");
209 + audit_log_untrustedstring(ab, profile->name);
210 +
211 + if (profile->ns != default_namespace) {
212 + audit_log_format(ab, " namespace=");
213 + audit_log_untrustedstring(ab, profile->ns->name);
214 + }
215 + }
216 +
217 + audit_log_end(ab);
218 +
219 + return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error_code;
220 +}
221 +
222 +/**
223 + * aa_audit_syscallreject - Log a syscall rejection to the audit subsystem
224 + * @profile: profile to check against
225 + * @gfp: memory allocation flags
226 + * @msg: string describing syscall being rejected
227 + */
228 +int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
229 + const char *msg)
230 +{
231 + struct aa_audit sa;
232 + memset(&sa, 0, sizeof(sa));
233 + sa.operation = "syscall";
234 + sa.name = msg;
235 + sa.gfp_mask = gfp;
236 + sa.error_code = -EPERM;
237 +
238 + return aa_audit_base(profile, &sa, current->audit_context,
239 + AUDIT_APPARMOR_DENIED);
240 +}
241 +
242 +int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
243 + int type)
244 +{
245 + struct audit_context *audit_cxt;
246 +
247 + audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
248 + return aa_audit_base(profile, sa, audit_cxt, type);
249 +}
250 +
251 +void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa)
252 +{
253 + aa_audit_message(profile, sa, AUDIT_APPARMOR_HINT);
254 +}
255 +
256 +void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa)
257 +{
258 + aa_audit_message(profile, sa, AUDIT_APPARMOR_STATUS);
259 +}
260 +
261 +int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa)
262 +{
263 + return aa_audit_message(profile, sa, AUDIT_APPARMOR_DENIED);
264 +}
265 +
266 +/**
267 + * aa_audit - Log an audit event to the audit subsystem
268 + * @profile: profile to check against
269 + * @sa: audit event
270 + */
271 +int aa_audit(struct aa_profile *profile, struct aa_audit *sa)
272 +{
273 + int type = AUDIT_APPARMOR_DENIED;
274 + struct audit_context *audit_cxt;
275 +
276 + if (likely(!sa->error_code))
277 + type = AUDIT_APPARMOR_AUDIT;
278 + else if (PROFILE_COMPLAIN(profile))
279 + type = AUDIT_APPARMOR_ALLOWED;
280 +
281 + audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
282 + return aa_audit_base(profile, sa, audit_cxt, type);
283 +}
284 +
285 +static int aa_audit_file(struct aa_profile *profile, struct aa_audit *sa)
286 +{
287 + if (likely(!sa->error_code)) {
288 + int mask = sa->audit_mask & AUDIT_FILE_MASK;
289 +
290 + if (unlikely(PROFILE_AUDIT(profile)))
291 + mask |= AUDIT_FILE_MASK;
292 +
293 + if (likely(!(sa->request_mask & mask)))
294 + return 0;
295 +
296 + /* mask off perms that are not being force audited */
297 + sa->request_mask &= mask | ALL_AA_EXEC_TYPE;
298 + } else {
299 + int mask = AUDIT_QUIET_MASK(sa->audit_mask);
300 +
301 + if (!(sa->denied_mask & ~mask))
302 + return sa->error_code;
303 +
304 + /* mask off perms whose denial is being silenced */
305 + sa->denied_mask &= (~mask) | ALL_AA_EXEC_TYPE;
306 + }
307 +
308 + return aa_audit(profile, sa);
309 +}
310 +
311 +static int aa_audit_caps(struct aa_profile *profile, struct aa_audit *sa,
312 + int cap)
313 +{
314 + if (likely(!sa->error_code)) {
315 + if (likely(!PROFILE_AUDIT(profile) &&
316 + !cap_raised(profile->audit_caps, cap)))
317 + return 0;
318 + }
319 +
320 + /* quieting of capabilities is handled the caps_logged cache */
321 + return aa_audit(profile, sa);
322 +}
323 +
324 +/**
325 + * aa_file_denied - check for @mask access on a file
326 + * @profile: profile to check against
327 + * @name: pathname of file
328 + * @mask: permission mask requested for file
329 + * @audit_mask: return audit mask for the match
330 + *
331 + * Return %0 on success, or else the permissions in @mask that the
332 + * profile denies.
333 + */
334 +static int aa_file_denied(struct aa_profile *profile, const char *name,
335 + int mask, int *audit_mask)
336 +{
337 + return (mask & ~aa_match(profile->file_rules, name, audit_mask));
338 +}
339 +
340 +/**
341 + * aa_link_denied - check for permission to link a file
342 + * @profile: profile to check against
343 + * @link: pathname of link being created
344 + * @target: pathname of target to be linked to
345 + * @target_mode: UGO shift for target inode
346 + * @request_mask: the permissions subset valid only if link succeeds
347 + * @audit_mask: return the audit_mask for the link permission
348 + * Return %0 on success, or else the permissions that the profile denies.
349 + */
350 +static int aa_link_denied(struct aa_profile *profile, const char *link,
351 + const char *target, int target_mode,
352 + int *request_mask, int *audit_mask)
353 +{
354 + unsigned int state;
355 + int l_mode, t_mode, l_x, t_x, denied_mask = 0;
356 + int link_mask = AA_MAY_LINK << target_mode;
357 +
358 + *request_mask = link_mask;
359 +
360 + l_mode = aa_match_state(profile->file_rules, DFA_START, link, &state);
361 +
362 + if (l_mode & link_mask) {
363 + int mode;
364 + /* test to see if target can be paired with link */
365 + state = aa_dfa_null_transition(profile->file_rules, state);
366 + mode = aa_match_state(profile->file_rules, state, target,
367 + &state);
368 +
369 + if (!(mode & link_mask))
370 + denied_mask |= link_mask;
371 +
372 + *audit_mask = dfa_audit_mask(profile->file_rules, state);
373 +
374 + /* return if link subset test is not required */
375 + if (!(mode & (AA_LINK_SUBSET_TEST << target_mode)))
376 + return denied_mask;
377 + }
378 +
379 + /* Do link perm subset test requiring permission on link are a
380 + * subset of the permissions on target.
381 + * If a subset test is required a permission subset test of the
382 + * perms for the link are done against the user::other of the
383 + * target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
384 + *
385 + * If the link has 'x', an exact match of all the execute flags
386 + * must match.
387 + */
388 + denied_mask |= ~l_mode & link_mask;
389 +
390 + t_mode = aa_match(profile->file_rules, target, NULL);
391 +
392 + l_x = l_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
393 + t_x = t_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
394 +
395 + /* For actual subset test ignore valid-profile-transition flags,
396 + * and link bits
397 + */
398 + l_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
399 + t_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
400 +
401 + *request_mask = l_mode | link_mask;
402 +
403 + if (l_mode) {
404 + int x = l_x | (t_x & ALL_AA_EXEC_UNSAFE);
405 + denied_mask |= l_mode & ~t_mode;
406 + /* mask off x modes not used by link */
407 +
408 + /* handle exec subset
409 + * - link safe exec issubset of unsafe exec
410 + * - no link x perm is subset of target having x perm
411 + */
412 + if ((l_mode & AA_USER_EXEC) &&
413 + (x & AA_USER_EXEC_TYPE) != (t_x & AA_USER_EXEC_TYPE))
414 + denied_mask = AA_USER_EXEC | (l_x & AA_USER_EXEC_TYPE);
415 + if ((l_mode & AA_OTHER_EXEC) &&
416 + (x & AA_OTHER_EXEC_TYPE) != (t_x & AA_OTHER_EXEC_TYPE))
417 + denied_mask = AA_OTHER_EXEC | (l_x & AA_OTHER_EXEC_TYPE);
418 + }
419 +
420 + return denied_mask;
421 +}
422 +
423 +/**
424 + * aa_get_name - compute the pathname of a file
425 + * @dentry: dentry of the file
426 + * @mnt: vfsmount of the file
427 + * @buffer: buffer that aa_get_name() allocated
428 + * @check: AA_CHECK_DIR is set if the file is a directory
429 + *
430 + * Returns a pointer to the beginning of the pathname (which usually differs
431 + * from the beginning of the buffer), or an error code.
432 + *
433 + * We need @check to indicate whether the file is a directory or not because
434 + * the file may not yet exist, and so we cannot check the inode's file type.
435 + */
436 +static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
437 + char **buffer, int check)
438 +{
439 + char *name;
440 + int is_dir, size = 256;
441 +
442 + is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
443 +
444 + for (;;) {
445 + char *buf = kmalloc(size, GFP_KERNEL);
446 + if (!buf)
447 + return ERR_PTR(-ENOMEM);
448 +
449 + name = d_namespace_path(dentry, mnt, buf, size - is_dir);
450 + if (!IS_ERR(name)) {
451 + if (name[0] != '/') {
452 + /*
453 + * This dentry is not connected to the
454 + * namespace root -- reject access.
455 + */
456 + kfree(buf);
457 + return ERR_PTR(-ENOENT);
458 + }
459 + if (is_dir && name[1] != '\0') {
460 + /*
461 + * Append "/" to the pathname. The root
462 + * directory is a special case; it already
463 + * ends in slash.
464 + */
465 + buf[size - 2] = '/';
466 + buf[size - 1] = '\0';
467 + }
468 +
469 + *buffer = buf;
470 + return name;
471 + }
472 + if (PTR_ERR(name) != -ENAMETOOLONG)
473 + return name;
474 +
475 + kfree(buf);
476 + size <<= 1;
477 + if (size > apparmor_path_max)
478 + return ERR_PTR(-ENAMETOOLONG);
479 + }
480 +}
481 +
482 +static char *new_compound_name(const char *n1, const char *n2)
483 +{
484 + char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
485 + if (name)
486 + sprintf(name, "%s//%s", n1, n2);
487 + return name;
488 +}
489 +static inline void aa_put_name_buffer(char *buffer)
490 +{
491 + kfree(buffer);
492 +}
493 +
494 +/**
495 + * aa_perm_dentry - check if @profile allows @mask for a file
496 + * @profile: profile to check against
497 + * @dentry: dentry of the file
498 + * @mnt: vfsmount o the file
499 + * @sa: audit context
500 + * @mask: requested profile permissions
501 + * @check: kind of check to perform
502 + *
503 + * Returns 0 upon success, or else an error code.
504 + *
505 + * @check indicates the file type, and whether the file was accessed through
506 + * an open file descriptor (AA_CHECK_FD) or not.
507 + */
508 +static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry,
509 + struct vfsmount *mnt, struct aa_audit *sa, int check)
510 +{
511 + int error;
512 + char *buffer = NULL;
513 +
514 + sa->name = aa_get_name(dentry, mnt, &buffer, check);
515 + sa->request_mask <<= aa_inode_mode(dentry->d_inode);
516 + if (IS_ERR(sa->name)) {
517 + /*
518 + * deleted files are given a pass on permission checks when
519 + * accessed through a file descriptor.
520 + */
521 + if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
522 + sa->denied_mask = 0;
523 + else {
524 + sa->denied_mask = sa->request_mask;
525 + sa->error_code = PTR_ERR(sa->name);
526 + if (sa->error_code == -ENOENT)
527 + sa->info = "Failed name resolution - object not a valid entry";
528 + else if (sa->error_code == -ENAMETOOLONG)
529 + sa->info = "Failed name resolution - name too long";
530 + else
531 + sa->info = "Failed name resolution";
532 + }
533 + sa->name = NULL;
534 + } else
535 + sa->denied_mask = aa_file_denied(profile, sa->name,
536 + sa->request_mask,
537 + &sa->audit_mask);
538 +
539 + if (!sa->denied_mask)
540 + sa->error_code = 0;
541 +
542 + error = aa_audit_file(profile, sa);
543 + aa_put_name_buffer(buffer);
544 +
545 + return error;
546 +}
547 +
548 +/**
549 + * aa_attr - check if attribute change is allowed
550 + * @profile: profile to check against
551 + * @dentry: dentry of the file to check
552 + * @mnt: vfsmount of the file to check
553 + * @iattr: attribute changes requested
554 + */
555 +int aa_attr(struct aa_profile *profile, struct dentry *dentry,
556 + struct vfsmount *mnt, struct iattr *iattr)
557 +{
558 + struct inode *inode = dentry->d_inode;
559 + int error, check;
560 + struct aa_audit sa;
561 +
562 + memset(&sa, 0, sizeof(sa));
563 + sa.operation = "setattr";
564 + sa.gfp_mask = GFP_KERNEL;
565 + sa.iattr = iattr;
566 + sa.request_mask = MAY_WRITE;
567 + sa.error_code = -EACCES;
568 +
569 + check = 0;
570 + if (inode && S_ISDIR(inode->i_mode))
571 + check |= AA_CHECK_DIR;
572 + if (iattr->ia_valid & ATTR_FILE)
573 + check |= AA_CHECK_FD;
574 +
575 + error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
576 +
577 + return error;
578 +}
579 +
580 +/**
581 + * aa_perm_xattr - check if xattr attribute change is allowed
582 + * @profile: profile to check against
583 + * @dentry: dentry of the file to check
584 + * @mnt: vfsmount of the file to check
585 + * @operation: xattr operation being done
586 + * @mask: access mode requested
587 + * @check: kind of check to perform
588 + */
589 +int aa_perm_xattr(struct aa_profile *profile, const char *operation,
590 + struct dentry *dentry, struct vfsmount *mnt, int mask,
591 + int check)
592 +{
593 + struct inode *inode = dentry->d_inode;
594 + int error;
595 + struct aa_audit sa;
596 +
597 + memset(&sa, 0, sizeof(sa));
598 + sa.operation = operation;
599 + sa.gfp_mask = GFP_KERNEL;
600 + sa.request_mask = mask;
601 + sa.error_code = -EACCES;
602 +
603 + if (inode && S_ISDIR(inode->i_mode))
604 + check |= AA_CHECK_DIR;
605 +
606 + error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
607 +
608 + return error;
609 +}
610 +
611 +/**
612 + * aa_perm - basic apparmor permissions check
613 + * @profile: profile to check against
614 + * @dentry: dentry of the file to check
615 + * @mnt: vfsmount of the file to check
616 + * @mask: access mode requested
617 + * @check: kind of check to perform
618 + *
619 + * Determine if access @mask for the file is authorized by @profile.
620 + * Returns 0 on success, or else an error code.
621 + */
622 +int aa_perm(struct aa_profile *profile, const char *operation,
623 + struct dentry *dentry, struct vfsmount *mnt, int mask, int check)
624 +{
625 + struct aa_audit sa;
626 + int error = 0;
627 +
628 + if (mask == 0)
629 + goto out;
630 +
631 + memset(&sa, 0, sizeof(sa));
632 + sa.operation = operation;
633 + sa.gfp_mask = GFP_KERNEL;
634 + sa.request_mask = mask;
635 + sa.error_code = -EACCES;
636 +
637 + error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
638 +
639 +out:
640 + return error;
641 +}
642 +
643 +/**
644 + * aa_perm_dir
645 + * @profile: profile to check against
646 + * @dentry: dentry of directory to check
647 + * @mnt: vfsmount of directory to check
648 + * @operation: directory operation being performed
649 + * @mask: access mode requested
650 + *
651 + * Determine if directory operation (make/remove) for dentry is authorized
652 + * by @profile.
653 + * Returns 0 on success, or else an error code.
654 + */
655 +int aa_perm_dir(struct aa_profile *profile, const char *operation,
656 + struct dentry *dentry, struct vfsmount *mnt, int mask)
657 +{
658 + struct aa_audit sa;
659 +
660 + memset(&sa, 0, sizeof(sa));
661 + sa.operation = operation;
662 + sa.gfp_mask = GFP_KERNEL;
663 + sa.request_mask = mask;
664 + sa.error_code = -EACCES;
665 +
666 + return aa_perm_dentry(profile, dentry, mnt, &sa, AA_CHECK_DIR);
667 +}
668 +
669 +int aa_perm_path(struct aa_profile *profile, const char *operation,
670 + const char *name, int mask, uid_t uid)
671 +{
672 + struct aa_audit sa;
673 +
674 + memset(&sa, 0, sizeof(sa));
675 + sa.operation = operation;
676 + sa.gfp_mask = GFP_KERNEL;
677 + sa.request_mask = mask;
678 + sa.name = name;
679 + if (current->fsuid == uid)
680 + sa.request_mask = mask << AA_USER_SHIFT;
681 + else
682 + sa.request_mask = mask << AA_OTHER_SHIFT;
683 +
684 + sa.denied_mask = aa_file_denied(profile, name, sa.request_mask,
685 + &sa.audit_mask) ;
686 + sa.error_code = sa.denied_mask ? -EACCES : 0;
687 +
688 + return aa_audit_file(profile, &sa);
689 +}
690 +
691 +/**
692 + * aa_capability - test permission to use capability
693 + * @cxt: aa_task_context with profile to check against
694 + * @cap: capability to be tested
695 + *
696 + * Look up capability in profile capability set.
697 + * Returns 0 on success, or else an error code.
698 + */
699 +int aa_capability(struct aa_task_context *cxt, int cap)
700 +{
701 + int error = cap_raised(cxt->profile->capabilities, cap) ? 0 : -EPERM;
702 + struct aa_audit sa;
703 +
704 + /* test if cap has alread been logged */
705 + if (cap_raised(cxt->caps_logged, cap)) {
706 + if (PROFILE_COMPLAIN(cxt->profile))
707 + error = 0;
708 + return error;
709 + } else
710 + /* don't worry about rcu replacement of the cxt here.
711 + * caps_logged is a cache to reduce the occurence of
712 + * duplicate messages in the log. The worst that can
713 + * happen is duplicate capability messages shows up in
714 + * the audit log
715 + */
716 + cap_raise(cxt->caps_logged, cap);
717 +
718 + memset(&sa, 0, sizeof(sa));
719 + sa.operation = "capable";
720 + sa.gfp_mask = GFP_ATOMIC;
721 + sa.name = capability_names[cap];
722 + sa.error_code = error;
723 +
724 + error = aa_audit_caps(cxt->profile, &sa, cap);
725 +
726 + return error;
727 +}
728 +
729 +/* must be used inside rcu_read_lock or task_lock */
730 +int aa_may_ptrace(struct aa_task_context *cxt, struct aa_profile *tracee)
731 +{
732 + if (!cxt || cxt->profile == tracee)
733 + return 0;
734 + return aa_capability(cxt, CAP_SYS_PTRACE);
735 +}
736 +
737 +/**
738 + * aa_link - hard link check
739 + * @profile: profile to check against
740 + * @link: dentry of link being created
741 + * @link_mnt: vfsmount of link being created
742 + * @target: dentry of link target
743 + * @target_mnt: vfsmunt of link target
744 + *
745 + * Returns 0 on success, or else an error code.
746 + */
747 +int aa_link(struct aa_profile *profile,
748 + struct dentry *link, struct vfsmount *link_mnt,
749 + struct dentry *target, struct vfsmount *target_mnt)
750 +{
751 + int error;
752 + struct aa_audit sa;
753 + char *buffer = NULL, *buffer2 = NULL;
754 +
755 + memset(&sa, 0, sizeof(sa));
756 + sa.operation = "inode_link";
757 + sa.gfp_mask = GFP_KERNEL;
758 + sa.name = aa_get_name(link, link_mnt, &buffer, 0);
759 + sa.name2 = aa_get_name(target, target_mnt, &buffer2, 0);
760 +
761 + if (IS_ERR(sa.name)) {
762 + sa.error_code = PTR_ERR(sa.name);
763 + sa.name = NULL;
764 + }
765 + if (IS_ERR(sa.name2)) {
766 + sa.error_code = PTR_ERR(sa.name2);
767 + sa.name2 = NULL;
768 + }
769 +
770 + if (sa.name && sa.name2) {
771 + sa.denied_mask = aa_link_denied(profile, sa.name, sa.name2,
772 + aa_inode_mode(target->d_inode),
773 + &sa.request_mask,
774 + &sa.audit_mask);
775 + sa.error_code = sa.denied_mask ? -EACCES : 0;
776 + }
777 +
778 + error = aa_audit_file(profile, &sa);
779 +
780 + aa_put_name_buffer(buffer);
781 + aa_put_name_buffer(buffer2);
782 +
783 + return error;
784 +}
785 +
786 +/*******************************
787 + * Global task related functions
788 + *******************************/
789 +
790 +/**
791 + * aa_clone - initialize the task context for a new task
792 + * @child: task that is being created
793 + *
794 + * Returns 0 on success, or else an error code.
795 + */
796 +int aa_clone(struct task_struct *child)
797 +{
798 + struct aa_task_context *cxt, *child_cxt;
799 + struct aa_profile *profile;
800 +
801 + if (!aa_task_context(current))
802 + return 0;
803 + child_cxt = aa_alloc_task_context(GFP_KERNEL);
804 + if (!child_cxt)
805 + return -ENOMEM;
806 +
807 +repeat:
808 + profile = aa_get_profile(current);
809 + if (profile) {
810 + lock_profile(profile);
811 + cxt = aa_task_context(current);
812 + if (unlikely(profile->isstale || !cxt ||
813 + cxt->profile != profile)) {
814 + /**
815 + * Race with profile replacement or removal, or with
816 + * task context removal.
817 + */
818 + unlock_profile(profile);
819 + aa_put_profile(profile);
820 + goto repeat;
821 + }
822 +
823 + /* No need to grab the child's task lock here. */
824 + aa_change_task_context(child, child_cxt, profile,
825 + cxt->cookie, cxt->previous_profile);
826 + unlock_profile(profile);
827 +
828 + if (APPARMOR_COMPLAIN(child_cxt) &&
829 + profile == profile->ns->null_complain_profile) {
830 + struct aa_audit sa;
831 + memset(&sa, 0, sizeof(sa));
832 + sa.operation = "clone";
833 + sa.gfp_mask = GFP_KERNEL;
834 + sa.task = child->pid;
835 + aa_audit_hint(profile, &sa);
836 + }
837 + aa_put_profile(profile);
838 + } else
839 + aa_free_task_context(child_cxt);
840 +
841 + return 0;
842 +}
843 +
844 +static struct aa_profile *
845 +aa_register_find(struct aa_profile *profile, const char* ns_name,
846 + const char *name, int mandatory, int complain,
847 + struct aa_audit *sa)
848 +{
849 + struct aa_namespace *ns;
850 + struct aa_profile *new_profile;
851 + int ns_ref = 0;
852 +
853 + if (profile)
854 + ns = profile->ns;
855 + else
856 + ns = default_namespace;
857 +
858 + if (ns_name) {
859 + /* locate the profile namespace */
860 + ns = aa_find_namespace(ns_name);
861 + if (!ns) {
862 + if (mandatory) {
863 + sa->info = "profile namespace not found";
864 + sa->denied_mask = sa->request_mask;
865 + sa->error_code = -ENOENT;
866 + return ERR_PTR(-ENOENT);
867 + } else {
868 + return NULL;
869 + }
870 + }
871 + ns_ref++;
872 + }
873 +
874 + /* Locate new profile */
875 + new_profile = aa_find_profile(ns, name);
876 +
877 + if (new_profile) {
878 + AA_DEBUG("%s: setting profile %s\n",
879 + __FUNCTION__, new_profile->name);
880 + } else if (mandatory && profile) {
881 + sa->info = "mandatory profile missing";
882 + sa->denied_mask = sa->request_mask; /* shifted MAY_EXEC */
883 + if (complain) {
884 + aa_audit_hint(profile, sa);
885 + new_profile =
886 + aa_dup_profile(profile->ns->null_complain_profile);
887 + } else {
888 + sa->error_code = -EACCES;
889 + if (ns_ref)
890 + aa_put_namespace(ns);
891 + return ERR_PTR(-EACCES);
892 + }
893 + } else {
894 + /* Only way we can get into this code is if task
895 + * is unconfined, pix, nix.
896 + */
897 + AA_DEBUG("%s: No profile found for exec image '%s'\n",
898 + __FUNCTION__,
899 + name);
900 + }
901 + if (ns_ref)
902 + aa_put_namespace(ns);
903 + return new_profile;
904 +}
905 +
906 +static struct aa_profile *
907 +aa_x_to_profile(struct aa_profile *profile, const char *filename, int xmode,
908 + struct aa_audit *sa, char **child)
909 +{
910 + struct aa_profile *new_profile = NULL;
911 + int ix = xmode & AA_EXEC_INHERIT;
912 + int complain = PROFILE_COMPLAIN(profile);
913 + int index;
914 +
915 + *child = NULL;
916 + switch (xmode & AA_EXEC_MODIFIERS) {
917 + case 0:
918 + /* only valid with ix flag */
919 + ix = 1;
920 + break;
921 + case AA_EXEC_UNCONFINED:
922 + /* only valid without ix flag */
923 + ix = 0;
924 + break;
925 + case AA_EXEC_PROFILE:
926 + new_profile = aa_register_find(profile, NULL, filename, !ix,
927 + complain, sa);
928 + break;
929 + case AA_EXEC_CHILD:
930 + *child = new_compound_name(profile->name, filename);
931 + sa->name2 = *child;
932 + if (!*child) {
933 + sa->info = "Failed name resolution - exec failed";
934 + sa->error_code = -ENOMEM;
935 + new_profile = ERR_PTR(-ENOMEM);
936 + } else {
937 + new_profile = aa_register_find(profile, NULL, *child,
938 + !ix, complain, sa);
939 + }
940 + break;
941 + default:
942 + /* all other indexes are named transitions */
943 + index = AA_EXEC_INDEX(xmode);
944 + if (index - 4 > profile->exec_table_size) {
945 + sa->info = "invalid named transition - exec failed";
946 + sa->error_code = -EACCES;
947 + new_profile = ERR_PTR(-EACCES);
948 + } else {
949 + char *ns_name = NULL;
950 + char *name = profile->exec_table[index - 4];
951 + if (*name == ':') {
952 + ns_name = name + 1;
953 + name = ns_name + strlen(ns_name) + 1;
954 + }
955 + sa->name2 = name;
956 + sa->name3 = ns_name;
957 + new_profile =
958 + aa_register_find(profile, ns_name, name,
959 + !ix, complain, sa);
960 + }
961 + }
962 + if (IS_ERR(new_profile))
963 + /* all these failures must be audited - no quieting */
964 + return ERR_PTR(aa_audit_reject(profile, sa));
965 + return new_profile;
966 +}
967 +
968 +/**
969 + * aa_register - register a new program
970 + * @bprm: binprm of program being registered
971 + *
972 + * Try to register a new program during execve(). This should give the
973 + * new program a valid aa_task_context if confined.
974 + */
975 +int aa_register(struct linux_binprm *bprm)
976 +{
977 + const char *filename;
978 + char *buffer = NULL, *child = NULL;
979 + struct file *filp = bprm->file;
980 + struct aa_profile *profile, *old_profile, *new_profile = NULL;
981 + int exec_mode, complain = 0, shift;
982 + struct aa_audit sa;
983 +
984 + AA_DEBUG("%s\n", __FUNCTION__);
985 +
986 + profile = aa_get_profile(current);
987 +
988 + shift = aa_inode_mode(filp->f_dentry->d_inode);
989 + memset(&sa, 0, sizeof(sa));
990 + sa.operation = "exec";
991 + sa.gfp_mask = GFP_KERNEL;
992 + sa.request_mask = MAY_EXEC << shift;
993 +
994 + filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt, &buffer, 0);
995 + if (IS_ERR(filename)) {
996 + if (profile) {
997 + sa.info = "Failed name resolution - exec failed";
998 + sa.error_code = PTR_ERR(filename);
999 + aa_audit_file(profile, &sa);
1000 + return sa.error_code;
1001 + } else
1002 + return 0;
1003 + }
1004 + sa.name = filename;
1005 +
1006 + exec_mode = AA_EXEC_UNSAFE << shift;
1007 +
1008 +repeat:
1009 + if (profile) {
1010 + complain = PROFILE_COMPLAIN(profile);
1011 +
1012 + /* Confined task, determine what mode inherit, unconfined or
1013 + * mandatory to load new profile
1014 + */
1015 + exec_mode = aa_match(profile->file_rules, filename,
1016 + &sa.audit_mask);
1017 +
1018 +
1019 + if (exec_mode & sa.request_mask) {
1020 + int xm = exec_mode >> shift;
1021 + new_profile = aa_x_to_profile(profile, filename,
1022 + xm, &sa, &child);
1023 +
1024 + if (!new_profile && (xm & AA_EXEC_INHERIT))
1025 + /* (p|c|n|)ix - don't change profile */
1026 + goto cleanup;
1027 + /* error case caught below */
1028 +
1029 + } else if (sa.request_mask & AUDIT_QUIET_MASK(sa.audit_mask)) {
1030 + /* quiet failed exit */
1031 + new_profile = ERR_PTR(-EACCES);
1032 + } else if (complain) {
1033 + /* There was no entry in calling profile
1034 + * describing mode to execute image in.
1035 + * Drop into null-profile (disabling secure exec).
1036 + */
1037 + new_profile =
1038 + aa_dup_profile(profile->ns->null_complain_profile);
1039 + exec_mode |= AA_EXEC_UNSAFE << shift;
1040 + } else {
1041 + sa.denied_mask = sa.request_mask;
1042 + sa.error_code = -EACCES;
1043 + new_profile = ERR_PTR(aa_audit_file(profile, &sa));
1044 + }
1045 + } else {
1046 + /* Unconfined task, load profile if it exists */
1047 + new_profile = aa_register_find(NULL, NULL, filename, 0, 0, &sa);
1048 + if (new_profile == NULL)
1049 + goto cleanup;
1050 + }
1051 +
1052 + if (IS_ERR(new_profile))
1053 + goto cleanup;
1054 +
1055 + old_profile = __aa_replace_profile(current, new_profile);
1056 + if (IS_ERR(old_profile)) {
1057 + aa_put_profile(new_profile);
1058 + aa_put_profile(profile);
1059 + if (PTR_ERR(old_profile) == -ESTALE) {
1060 + profile = aa_get_profile(current);
1061 + goto repeat;
1062 + }
1063 + if (PTR_ERR(old_profile) == -EPERM) {
1064 + sa.denied_mask = sa.request_mask;
1065 + sa.info = "unable to set profile due to ptrace";
1066 + sa.task = current->parent->pid;
1067 + aa_audit_reject(profile, &sa);
1068 + }
1069 + new_profile = old_profile;
1070 + goto cleanup;
1071 + }
1072 + aa_put_profile(old_profile);
1073 + aa_put_profile(profile);
1074 +
1075 + /* Handle confined exec.
1076 + * Can be at this point for the following reasons:
1077 + * 1. unconfined switching to confined
1078 + * 2. confined switching to different confinement
1079 + * 3. confined switching to unconfined
1080 + *
1081 + * Cases 2 and 3 are marked as requiring secure exec
1082 + * (unless policy specified "unsafe exec")
1083 + */
1084 + if (!(exec_mode & (AA_EXEC_UNSAFE << shift))) {
1085 + unsigned long bprm_flags;
1086 +
1087 + bprm_flags = AA_SECURE_EXEC_NEEDED;
1088 + bprm->security = (void*)
1089 + ((unsigned long)bprm->security | bprm_flags);
1090 + }
1091 +
1092 + if (complain && new_profile &&
1093 + new_profile == new_profile->ns->null_complain_profile) {
1094 + sa.request_mask = 0;
1095 + sa.name = NULL;
1096 + sa.info = "set profile";
1097 + aa_audit_hint(new_profile, &sa);
1098 + }
1099 +
1100 +cleanup:
1101 + aa_put_name_buffer(child);
1102 + aa_put_name_buffer(buffer);
1103 + if (IS_ERR(new_profile))
1104 + return PTR_ERR(new_profile);
1105 + aa_put_profile(new_profile);
1106 + return 0;
1107 +}
1108 +
1109 +/**
1110 + * aa_release - release a task context
1111 + * @task: task being released
1112 + *
1113 + * This is called after a task has exited and the parent has reaped it.
1114 + */
1115 +void aa_release(struct task_struct *task)
1116 +{
1117 + struct aa_task_context *cxt;
1118 + struct aa_profile *profile;
1119 + /*
1120 + * While the task context is still on a profile's task context
1121 + * list, another process could replace the profile under us,
1122 + * leaving us with a locked profile that is no longer attached
1123 + * to this task. So after locking the profile, we check that
1124 + * the profile is still attached. The profile lock is
1125 + * sufficient to prevent the replacement race so we do not lock
1126 + * the task.
1127 + *
1128 + * Use lock subtyping to avoid lockdep reporting a false irq
1129 + * possible inversion between the task_lock and profile_lock
1130 + *
1131 + * We also avoid taking the task_lock here because lock_dep
1132 + * would report another false {softirq-on-W} potential irq_lock
1133 + * inversion.
1134 + *
1135 + * If the task does not have a profile attached we are safe;
1136 + * nothing can race with us at this point.
1137 + */
1138 +
1139 +repeat:
1140 + profile = aa_get_profile(task);
1141 + if (profile) {
1142 + lock_profile_nested(profile, aa_lock_task_release);
1143 + cxt = aa_task_context(task);
1144 + if (unlikely(!cxt || cxt->profile != profile)) {
1145 + unlock_profile(profile);
1146 + aa_put_profile(profile);
1147 + goto repeat;
1148 + }
1149 + aa_change_task_context(task, NULL, NULL, 0, NULL);
1150 + unlock_profile(profile);
1151 + aa_put_profile(profile);
1152 + }
1153 +}
1154 +
1155 +static int do_change_profile(struct aa_profile *expected,
1156 + struct aa_namespace *ns, const char *name,
1157 + u64 cookie, int restore, int hat,
1158 + struct aa_audit *sa)
1159 +{
1160 + struct aa_profile *new_profile = NULL, *old_profile = NULL,
1161 + *previous_profile = NULL;
1162 + struct aa_task_context *new_cxt, *cxt;
1163 + int error = 0;
1164 +
1165 + sa->name = name;
1166 +
1167 + new_cxt = aa_alloc_task_context(GFP_KERNEL);
1168 + if (!new_cxt)
1169 + return -ENOMEM;
1170 +
1171 + new_profile = aa_find_profile(ns, name);
1172 + if (!new_profile && !restore) {
1173 + if (!PROFILE_COMPLAIN(expected)) {
1174 + aa_free_task_context(new_cxt);
1175 + return -ENOENT;
1176 + }
1177 + new_profile = aa_dup_profile(ns->null_complain_profile);
1178 + } else if (new_profile && hat && !PROFILE_IS_HAT(new_profile)) {
1179 + aa_free_task_context(new_cxt);
1180 + aa_put_profile(new_profile);
1181 + return error;
1182 + }
1183 +
1184 + cxt = lock_task_and_profiles(current, new_profile);
1185 + if (!cxt) {
1186 + error = -EPERM;
1187 + goto out;
1188 + }
1189 + old_profile = cxt->profile;
1190 +
1191 + if (cxt->profile != expected || (new_profile && new_profile->isstale)) {
1192 + error = -ESTALE;
1193 + goto out;
1194 + }
1195 +
1196 + if (cxt->previous_profile) {
1197 + if (cxt->cookie != cookie) {
1198 + error = -EACCES;
1199 + sa->info = "killing process";
1200 + aa_audit_reject(cxt->profile, sa);
1201 + /* terminate process */
1202 + (void)send_sig_info(SIGKILL, NULL, current);
1203 + goto out;
1204 + }
1205 +
1206 + if (!restore)
1207 + previous_profile = cxt->previous_profile;
1208 + } else
1209 + previous_profile = cxt->profile;
1210 +
1211 + if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, new_profile)) {
1212 + error = -EACCES;
1213 + goto out;
1214 + }
1215 +
1216 + if (new_profile == ns->null_complain_profile)
1217 + aa_audit_hint(cxt->profile, sa);
1218 +
1219 + if (APPARMOR_AUDIT(cxt))
1220 + aa_audit_message(cxt->profile, sa, AUDIT_APPARMOR_AUDIT);
1221 +
1222 + if (!restore && cookie)
1223 + aa_change_task_context(current, new_cxt, new_profile, cookie,
1224 + previous_profile);
1225 + else
1226 + /* either return to previous_profile, or a permanent change */
1227 + aa_change_task_context(current, new_cxt, new_profile, 0, NULL);
1228 +
1229 +out:
1230 + if (aa_task_context(current) != new_cxt)
1231 + aa_free_task_context(new_cxt);
1232 + task_unlock(current);
1233 + unlock_both_profiles(old_profile, new_profile);
1234 + aa_put_profile(new_profile);
1235 + return error;
1236 +}
1237 +
1238 +/**
1239 + * aa_change_profile - perform a one-way profile transition
1240 + * @ns_name: name of the profile namespace to change to
1241 + * @name: name of profile to change to
1242 + * Change to new profile @name. Unlike with hats, there is no way
1243 + * to change back.
1244 + *
1245 + * Returns %0 on success, error otherwise.
1246 + */
1247 +int aa_change_profile(const char *ns_name, const char *name)
1248 +{
1249 + struct aa_task_context *cxt;
1250 + struct aa_profile *profile = NULL;
1251 + struct aa_namespace *ns = NULL;
1252 + struct aa_audit sa;
1253 + unsigned int state;
1254 + int error = -EINVAL;
1255 +
1256 + if (!name)
1257 + return -EINVAL;
1258 +
1259 + memset(&sa, 0, sizeof(sa));
1260 + sa.gfp_mask = GFP_ATOMIC;
1261 + sa.operation = "change_profile";
1262 +
1263 +repeat:
1264 + task_lock(current);
1265 + cxt = aa_task_context(current);
1266 + if (cxt)
1267 + profile = aa_dup_profile(cxt->profile);
1268 + task_unlock(current);
1269 +
1270 + if (ns_name)
1271 + ns = aa_find_namespace(ns_name);
1272 + else if (profile)
1273 + ns = aa_get_namespace(profile->ns);
1274 + else
1275 + ns = aa_get_namespace(default_namespace);
1276 +
1277 + if (!ns) {
1278 + aa_put_profile(profile);
1279 + return -ENOENT;
1280 + }
1281 +
1282 + if (!profile || PROFILE_COMPLAIN(profile) ||
1283 + (ns == profile->ns &&
1284 + (aa_match(profile->file_rules, name, NULL) & AA_CHANGE_PROFILE)))
1285 + error = do_change_profile(profile, ns, name, 0, 0, 0, &sa);
1286 + else {
1287 + /* check for a rule with a namespace prepended */
1288 + aa_match_state(profile->file_rules, DFA_START, ns->name,
1289 + &state);
1290 + state = aa_dfa_null_transition(profile->file_rules, state);
1291 + if ((aa_match_state(profile->file_rules, state, name, NULL) &
1292 + AA_CHANGE_PROFILE))
1293 + error = do_change_profile(profile, ns, name, 0, 0, 0,
1294 + &sa);
1295 + else
1296 + /* no permission to transition to profile @name */
1297 + error = -EACCES;
1298 + }
1299 +
1300 + aa_put_namespace(ns);
1301 + aa_put_profile(profile);
1302 + if (error == -ESTALE)
1303 + goto repeat;
1304 +
1305 + return error;
1306 +}
1307 +
1308 +/**
1309 + * aa_change_hat - change hat to/from subprofile
1310 + * @hat_name: hat to change to
1311 + * @cookie: magic value to validate the hat change
1312 + *
1313 + * Change to new @hat_name, and store the @hat_magic in the current task
1314 + * context. If the new @hat_name is %NULL and the @cookie matches that
1315 + * stored in the current task context and is not 0, return to the top level
1316 + * profile.
1317 + * Returns %0 on success, error otherwise.
1318 + */
1319 +int aa_change_hat(const char *hat_name, u64 cookie)
1320 +{
1321 + struct aa_task_context *cxt;
1322 + struct aa_profile *profile, *previous_profile;
1323 + struct aa_audit sa;
1324 + int error = 0;
1325 +
1326 + memset(&sa, 0, sizeof(sa));
1327 + sa.gfp_mask = GFP_ATOMIC;
1328 + sa.operation = "change_hat";
1329 +
1330 +repeat:
1331 + task_lock(current);
1332 + cxt = aa_task_context(current);
1333 + if (!cxt) {
1334 + task_unlock(current);
1335 + return -EPERM;
1336 + }
1337 + profile = aa_dup_profile(cxt->profile);
1338 + previous_profile = aa_dup_profile(cxt->previous_profile);
1339 + task_unlock(current);
1340 +
1341 + if (hat_name) {
1342 + char *name, *profile_name;
1343 +
1344 + if (previous_profile)
1345 + profile_name = previous_profile->name;
1346 + else
1347 + profile_name = profile->name;
1348 +
1349 + name = new_compound_name(profile_name, hat_name);
1350 + if (!name) {
1351 + error = -ENOMEM;
1352 + goto out;
1353 + }
1354 + error = do_change_profile(profile, profile->ns, name, cookie,
1355 + 0, 1, &sa);
1356 + aa_put_name_buffer(name);
1357 + } else if (previous_profile)
1358 + error = do_change_profile(profile, profile->ns,
1359 + previous_profile->name, cookie, 1, 0,
1360 + &sa);
1361 + /* else ignore restores when there is no saved profile */
1362 +
1363 +out:
1364 + aa_put_profile(previous_profile);
1365 + aa_put_profile(profile);
1366 + if (error == -ESTALE)
1367 + goto repeat;
1368 +
1369 + return error;
1370 +}
1371 +
1372 +/**
1373 + * __aa_replace_profile - replace a task's profile
1374 + * @task: task to switch the profile of
1375 + * @profile: profile to switch to
1376 + *
1377 + * Returns a handle to the previous profile upon success, or else an
1378 + * error code.
1379 + */
1380 +struct aa_profile *__aa_replace_profile(struct task_struct *task,
1381 + struct aa_profile *profile)
1382 +{
1383 + struct aa_task_context *cxt, *new_cxt = NULL;
1384 + struct aa_profile *old_profile = NULL;
1385 +
1386 + if (profile) {
1387 + new_cxt = aa_alloc_task_context(GFP_KERNEL);
1388 + if (!new_cxt)
1389 + return ERR_PTR(-ENOMEM);
1390 + }
1391 +
1392 + cxt = lock_task_and_profiles(task, profile);
1393 + if (unlikely(profile && profile->isstale)) {
1394 + task_unlock(task);
1395 + unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
1396 + aa_free_task_context(new_cxt);
1397 + return ERR_PTR(-ESTALE);
1398 + }
1399 +
1400 + if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
1401 + task_unlock(task);
1402 + unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
1403 + aa_free_task_context(new_cxt);
1404 + return ERR_PTR(-EPERM);
1405 + }
1406 +
1407 + if (cxt)
1408 + old_profile = aa_dup_profile(cxt->profile);
1409 + aa_change_task_context(task, new_cxt, profile, 0, NULL);
1410 +
1411 + task_unlock(task);
1412 + unlock_both_profiles(profile, old_profile);
1413 + return old_profile;
1414 +}
1415 +
1416 +/**
1417 + * lock_task_and_profiles - lock the task and confining profiles and @profile
1418 + * @task: task to lock
1419 + * @profile: extra profile to lock in addition to the current profile
1420 + *
1421 + * Handle the spinning on locking to make sure the task context and
1422 + * profile are consistent once all locks are aquired.
1423 + *
1424 + * return the aa_task_context currently confining the task. The task lock
1425 + * will be held whether or not the task is confined.
1426 + */
1427 +struct aa_task_context *
1428 +lock_task_and_profiles(struct task_struct *task, struct aa_profile *profile)
1429 +{
1430 + struct aa_task_context *cxt;
1431 + struct aa_profile *old_profile = NULL;
1432 +
1433 + rcu_read_lock();
1434 +repeat:
1435 + cxt = aa_task_context(task);
1436 + if (cxt)
1437 + old_profile = cxt->profile;
1438 +
1439 + lock_both_profiles(profile, old_profile);
1440 + task_lock(task);
1441 +
1442 + /* check for race with profile transition, replacement or removal */
1443 + if (unlikely(cxt != aa_task_context(task))) {
1444 + task_unlock(task);
1445 + unlock_both_profiles(profile, old_profile);
1446 + old_profile = NULL;
1447 + goto repeat;
1448 + }
1449 + rcu_read_unlock();
1450 + return cxt;
1451 +}
1452 +
1453 +static void free_aa_task_context_rcu_callback(struct rcu_head *head)
1454 +{
1455 + struct aa_task_context *cxt;
1456 +
1457 + cxt = container_of(head, struct aa_task_context, rcu);
1458 + aa_free_task_context(cxt);
1459 +}
1460 +
1461 +/**
1462 + * aa_change_task_context - switch a task to use a new context and profile
1463 + * @task: task that is having its task context changed
1464 + * @new_cxt: new task context to use after the switch
1465 + * @profile: new profile to use after the switch
1466 + * @cookie: magic value to switch to
1467 + * @previous_profile: profile the task can return to
1468 + */
1469 +void aa_change_task_context(struct task_struct *task,
1470 + struct aa_task_context *new_cxt,
1471 + struct aa_profile *profile, u64 cookie,
1472 + struct aa_profile *previous_profile)
1473 +{
1474 + struct aa_task_context *old_cxt = aa_task_context(task);
1475 +
1476 + if (old_cxt) {
1477 + list_del_init(&old_cxt->list);
1478 + call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
1479 + }
1480 + if (new_cxt) {
1481 + /* set the caps_logged cache to the quiet_caps mask
1482 + * this has the effect of quieting caps that are not
1483 + * supposed to be logged
1484 + */
1485 + new_cxt->caps_logged = profile->quiet_caps;
1486 + new_cxt->cookie = cookie;
1487 + new_cxt->task = task;
1488 + new_cxt->profile = aa_dup_profile(profile);
1489 + new_cxt->previous_profile = aa_dup_profile(previous_profile);
1490 + list_move(&new_cxt->list, &profile->task_contexts);
1491 + }
1492 + rcu_assign_pointer(task->security, new_cxt);
1493 +}