]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.apparmor/apparmor-misc.diff
Move xen patchset to new version's subdir.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.apparmor / apparmor-misc.diff
CommitLineData
8f69975d
BS
1From: John Johansen <jjohansen@suse.de>
2Subject: AppArmor: all the rest
3
4All the things that didn't nicely fit in a category on their own: kbuild
5code, declararions and inline functions, /sys/kernel/security/apparmor
6filesystem for controlling apparmor from user space, profile list
7functions, locking documentation, /proc/$pid/task/$tid/attr/current
8access.
9
10Signed-off-by: John Johansen <jjohansen@suse.de>
11Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
12
13---
14 security/apparmor/Kconfig | 42 ++++
15 security/apparmor/Makefile | 13 +
16 security/apparmor/apparmor.h | 371 +++++++++++++++++++++++++++++++++++++++++
17 security/apparmor/apparmorfs.c | 281 +++++++++++++++++++++++++++++++
18 security/apparmor/inline.h | 250 +++++++++++++++++++++++++++
19 security/apparmor/list.c | 174 +++++++++++++++++++
20 security/apparmor/locking.txt | 68 +++++++
21 security/apparmor/procattr.c | 195 +++++++++++++++++++++
22 8 files changed, 1394 insertions(+)
23
24--- /dev/null
25+++ b/security/apparmor/Kconfig
26@@ -0,0 +1,42 @@
27+config SECURITY_APPARMOR
28+ bool "AppArmor support"
29+ depends on SECURITY
30+ select AUDIT
31+ help
32+ This enables the AppArmor security module.
33+ Required userspace tools (if they are not included in your
34+ distribution) and further information may be found at
35+ <http://forge.novell.com/modules/xfmod/project/?apparmor>
36+
37+ If you are unsure how to answer this question, answer N.
38+
39+config SECURITY_APPARMOR_BOOTPARAM_VALUE
40+ int "AppArmor boot parameter default value"
41+ depends on SECURITY_APPARMOR
42+ range 0 1
43+ default 1
44+ help
45+ This option sets the default value for the kernel parameter
46+ 'apparmor', which allows AppArmor to be enabled or disabled
47+ at boot. If this option is set to 0 (zero), the AppArmor
48+ kernel parameter will default to 0, disabling AppArmor at
49+ bootup. If this option is set to 1 (one), the AppArmor
50+ kernel parameter will default to 1, enabling AppArmor at
51+ bootup.
52+
53+ If you are unsure how to answer this question, answer 1.
54+
55+config SECURITY_APPARMOR_DISABLE
56+ bool "AppArmor runtime disable"
57+ depends on SECURITY_APPARMOR
58+ default n
59+ help
60+ This option enables writing to a apparmorfs node 'disable', which
61+ allows AppArmor to be disabled at runtime prior to the policy load.
62+ AppArmor will then remain disabled until the next boot.
63+ This option is similar to the apparmor.enabled=0 boot parameter,
64+ but is to support runtime disabling of AppArmor, e.g. from
65+ /sbin/init, for portability across platforms where boot
66+ parameters are difficult to employ.
67+
68+ If you are unsure how to answer this question, answer N.
69--- /dev/null
70+++ b/security/apparmor/Makefile
71@@ -0,0 +1,13 @@
72+# Makefile for AppArmor Linux Security Module
73+#
74+obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
75+
76+apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o \
77+ module_interface.o match.o
78+
79+quiet_cmd_make-caps = GEN $@
80+cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
81+
82+$(obj)/main.o : $(obj)/capability_names.h
83+$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
84+ $(call cmd,make-caps)
85--- /dev/null
86+++ b/security/apparmor/apparmor.h
87@@ -0,0 +1,371 @@
88+/*
89+ * Copyright (C) 1998-2007 Novell/SUSE
90+ *
91+ * This program is free software; you can redistribute it and/or
92+ * modify it under the terms of the GNU General Public License as
93+ * published by the Free Software Foundation, version 2 of the
94+ * License.
95+ *
96+ * AppArmor internal prototypes
97+ */
98+
99+#ifndef __APPARMOR_H
100+#define __APPARMOR_H
101+
102+#include <linux/sched.h>
103+#include <linux/fs.h>
104+#include <linux/binfmts.h>
105+#include <linux/rcupdate.h>
106+
107+/*
108+ * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
109+ * for profile permissions
110+ */
111+#define AA_MAY_LINK 0x0010
112+#define AA_MAY_LOCK 0x0020
113+#define AA_EXEC_MMAP 0x0040
114+#define AA_MAY_MOUNT 0x0080 /* no direct audit mapping */
115+#define AA_EXEC_UNSAFE 0x0100
116+#define AA_EXEC_INHERIT 0x0200
117+#define AA_EXEC_MOD_0 0x0400
118+#define AA_EXEC_MOD_1 0x0800
119+#define AA_EXEC_MOD_2 0x1000
120+#define AA_EXEC_MOD_3 0x2000
121+
122+#define AA_BASE_PERMS (MAY_READ | MAY_WRITE | MAY_EXEC | \
123+ MAY_APPEND | AA_MAY_LINK | \
124+ AA_MAY_LOCK | AA_EXEC_MMAP | \
125+ AA_MAY_MOUNT | AA_EXEC_UNSAFE | \
126+ AA_EXEC_INHERIT | AA_EXEC_MOD_0 | \
127+ AA_EXEC_MOD_1 | AA_EXEC_MOD_2 | \
128+ AA_EXEC_MOD_3)
129+
130+#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
131+ AA_EXEC_MOD_2 | AA_EXEC_MOD_3)
132+
133+#define AA_EXEC_TYPE (AA_EXEC_UNSAFE | AA_EXEC_INHERIT | \
134+ AA_EXEC_MODIFIERS)
135+
136+#define AA_EXEC_UNCONFINED AA_EXEC_MOD_0
137+#define AA_EXEC_PROFILE AA_EXEC_MOD_1
138+#define AA_EXEC_CHILD (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
139+/* remaining exec modes are index into profile name table */
140+#define AA_EXEC_INDEX(mode) ((mode & AA_EXEC_MODIFIERS) >> 10)
141+
142+#define AA_USER_SHIFT 0
143+#define AA_OTHER_SHIFT 14
144+
145+#define AA_USER_PERMS (AA_BASE_PERMS << AA_USER_SHIFT)
146+#define AA_OTHER_PERMS (AA_BASE_PERMS << AA_OTHER_SHIFT)
147+
148+#define AA_FILE_PERMS (AA_USER_PERMS | AA_OTHER_PERMS)
149+
150+#define AA_LINK_BITS ((AA_MAY_LINK << AA_USER_SHIFT) | \
151+ (AA_MAY_LINK << AA_OTHER_SHIFT))
152+
153+#define AA_USER_EXEC (MAY_EXEC << AA_USER_SHIFT)
154+#define AA_OTHER_EXEC (MAY_EXEC << AA_OTHER_SHIFT)
155+
156+#define AA_USER_EXEC_TYPE (AA_EXEC_TYPE << AA_USER_SHIFT)
157+#define AA_OTHER_EXEC_TYPE (AA_EXEC_TYPE << AA_OTHER_SHIFT)
158+
159+#define AA_EXEC_BITS (AA_USER_EXEC | AA_OTHER_EXEC)
160+
161+#define ALL_AA_EXEC_UNSAFE ((AA_EXEC_UNSAFE << AA_USER_SHIFT) | \
162+ (AA_EXEC_UNSAFE << AA_OTHER_SHIFT))
163+
164+#define ALL_AA_EXEC_TYPE (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE)
165+
166+/* overloaded permissions for link pairs */
167+#define AA_LINK_SUBSET_TEST 0x0020
168+
169+#define AA_USER_PTRACE 0x10000000
170+#define AA_OTHER_PTRACE 0x20000000
171+#define AA_PTRACE_PERMS (AA_USER_PTRACE | AA_OTHER_PTRACE)
172+
173+/* shared permissions that are not duplicated in user::other */
174+#define AA_CHANGE_HAT 0x40000000
175+#define AA_CHANGE_PROFILE 0x80000000
176+
177+#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
178+
179+#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_PTRACE_PERMS | \
180+ AA_SHARED_PERMS)
181+
182+/* audit bits for the second accept field */
183+#define AUDIT_FILE_MASK 0x1fc07f
184+#define AUDIT_QUIET_MASK(mask) ((mask >> 7) & AUDIT_FILE_MASK)
185+#define AA_VALID_PERM2_MASK 0x0fffffff
186+
187+#define AA_SECURE_EXEC_NEEDED 1
188+
189+/* Control parameters (0 or 1), settable thru module/boot flags or
190+ * via /sys/kernel/security/apparmor/control */
191+extern int apparmor_complain;
192+extern int apparmor_debug;
193+extern int apparmor_audit;
194+extern int apparmor_logsyscall;
195+extern unsigned int apparmor_path_max;
196+
197+#define PROFILE_COMPLAIN(_profile) \
198+ (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
199+
200+#define APPARMOR_COMPLAIN(_cxt) \
201+ (apparmor_complain == 1 || \
202+ ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.complain))
203+
204+#define PROFILE_AUDIT(_profile) \
205+ (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
206+
207+#define APPARMOR_AUDIT(_cxt) \
208+ (apparmor_audit == 1 || \
209+ ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.audit))
210+
211+#define PROFILE_IS_HAT(_profile) \
212+ ((_profile) && (_profile)->flags.hat)
213+
214+/*
215+ * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
216+ * which is not related to profile accesses.
217+ */
218+
219+#define AA_DEBUG(fmt, args...) \
220+ do { \
221+ if (apparmor_debug) \
222+ printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
223+ } while (0)
224+
225+#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
226+
227+struct aa_profile;
228+
229+/* struct aa_namespace - namespace for a set of profiles
230+ * @name: the name of the namespace
231+ * @list: list the namespace is on
232+ * @profiles: list of profile in the namespace
233+ * @profile_count: the number of profiles in the namespace
234+ * @null_complain_profile: special profile used for learning in this namespace
235+ * @count: reference count on the namespace
236+ * @lock: lock for adding/removing profile to the namespace
237+ */
238+struct aa_namespace {
239+ char *name;
240+ struct list_head list;
241+ struct list_head profiles;
242+ int profile_count;
243+ struct aa_profile *null_complain_profile;
244+
245+ struct kref count;
246+ rwlock_t lock;
247+};
248+
249+/* struct aa_profile - basic confinement data
250+ * @name: the profiles name
251+ * @list: list this profile is on
252+ * @ns: namespace the profile is in
253+ * @file_rules: dfa containing the profiles file rules
254+ * @flags: flags controlling profile behavior
255+ * @isstale: flag indicating if profile is stale
256+ * @set_caps: capabilities that are being set
257+ * @capabilities: capabilities mask
258+ * @audit_caps: caps that are to be audited
259+ * @quiet_caps: caps that should not be audited
260+ * @capabilities: capabilities granted by the process
261+ * @count: reference count of the profile
262+ * @task_contexts: list of tasks confined by profile
263+ * @lock: lock for the task_contexts list
264+ * @network_families: basic network permissions
265+ * @audit_network: which network permissions to force audit
266+ * @quiet_network: which network permissions to quiet rejects
267+ *
268+ * The AppArmor profile contains the basic confinement data. Each profile
269+ * has a name, and all nonstale profile are in a profile namespace.
270+ *
271+ * The task_contexts list and the isstale flag are protected by the
272+ * profile lock.
273+ *
274+ * If a task context is moved between two profiles, we first need to grab
275+ * both profile locks. lock_both_profiles() does that in a deadlock-safe
276+ * way.
277+ */
278+struct aa_profile {
279+ char *name;
280+ struct list_head list;
281+ struct aa_namespace *ns;
282+
283+ int exec_table_size;
284+ char **exec_table;
285+ struct aa_dfa *file_rules;
286+ struct {
287+ int hat;
288+ int complain;
289+ int audit;
290+ } flags;
291+ int isstale;
292+
293+ kernel_cap_t set_caps;
294+ kernel_cap_t capabilities;
295+ kernel_cap_t audit_caps;
296+ kernel_cap_t quiet_caps;
297+
298+ struct kref count;
299+ struct list_head task_contexts;
300+ spinlock_t lock;
301+ unsigned long int_flags;
302+};
303+
304+extern struct list_head profile_ns_list;
305+extern rwlock_t profile_ns_list_lock;
306+extern struct mutex aa_interface_lock;
307+
308+/**
309+ * struct aa_task_context - primary label for confined tasks
310+ * @profile: the current profile
311+ * @previous_profile: profile the task may return to
312+ * @cookie: magic value the task must know for returning to @previous_profile
313+ * @list: list this aa_task_context is on
314+ * @task: task that the aa_task_context confines
315+ * @rcu: rcu head used when freeing the aa_task_context
316+ * @caps_logged: caps that have previously generated log entries
317+ *
318+ * Contains the task's current profile (which could change due to
319+ * change_hat). Plus the hat_magic needed during change_hat.
320+ */
321+struct aa_task_context {
322+ struct aa_profile *profile;
323+ struct aa_profile *previous_profile;
324+ u64 cookie;
325+ struct list_head list;
326+ struct task_struct *task;
327+ struct rcu_head rcu;
328+ kernel_cap_t caps_logged;
329+};
330+
331+extern struct aa_namespace *default_namespace;
332+
333+/* aa_audit - AppArmor auditing structure
334+ * Structure is populated by access control code and passed to aa_audit which
335+ * provides for a single point of logging.
336+ */
337+
338+struct aa_audit {
339+ const char *operation;
340+ gfp_t gfp_mask;
341+ const char *info;
342+ const char *name;
343+ const char *name2;
344+ const char *name3;
345+ int request_mask, denied_mask, audit_mask;
346+ struct iattr *iattr;
347+ pid_t task, parent;
348+ int error_code;
349+};
350+
351+/* Flags for the permission check functions */
352+#define AA_CHECK_FD 1 /* coming from a file descriptor */
353+#define AA_CHECK_DIR 2 /* file type is directory */
354+
355+/* lock subtypes so lockdep does not raise false dependencies */
356+enum aa_lock_class {
357+ aa_lock_normal,
358+ aa_lock_nested,
359+ aa_lock_task_release
360+};
361+
362+/* main.c */
363+extern int alloc_default_namespace(void);
364+extern void free_default_namespace(void);
365+extern int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
366+ int type);
367+void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa);
368+void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa);
369+int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa);
370+extern int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
371+ const char *);
372+extern int aa_audit(struct aa_profile *profile, struct aa_audit *);
373+
374+extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
375+ struct vfsmount *mnt, struct iattr *iattr);
376+extern int aa_perm_xattr(struct aa_profile *profile, const char *operation,
377+ struct dentry *dentry, struct vfsmount *mnt,
378+ int mask, int check);
379+extern int aa_capability(struct aa_task_context *cxt, int cap);
380+extern int aa_perm(struct aa_profile *profile, const char *operation,
381+ struct dentry *dentry, struct vfsmount *mnt, int mask,
382+ int check);
383+extern int aa_perm_dir(struct aa_profile *profile, const char *operation,
384+ struct dentry *dentry, struct vfsmount *mnt,
385+ int mask);
386+extern int aa_perm_path(struct aa_profile *, const char *operation,
387+ const char *name, int mask, uid_t uid);
388+extern int aa_link(struct aa_profile *profile,
389+ struct dentry *link, struct vfsmount *link_mnt,
390+ struct dentry *target, struct vfsmount *target_mnt);
391+extern int aa_clone(struct task_struct *task);
392+extern int aa_register(struct linux_binprm *bprm);
393+extern void aa_release(struct task_struct *task);
394+extern int aa_change_hat(const char *id, u64 hat_magic);
395+extern int aa_change_profile(const char *ns_name, const char *name);
396+extern struct aa_profile *__aa_replace_profile(struct task_struct *task,
397+ struct aa_profile *profile);
398+extern struct aa_task_context *lock_task_and_profiles(struct task_struct *task,
399+ struct aa_profile *profile);
400+extern void unlock_task_and_profiles(struct task_struct *task,
401+ struct aa_task_context *cxt,
402+ struct aa_profile *profile);
403+extern void aa_change_task_context(struct task_struct *task,
404+ struct aa_task_context *new_cxt,
405+ struct aa_profile *profile, u64 cookie,
406+ struct aa_profile *previous_profile);
407+extern int aa_may_ptrace(struct aa_task_context *cxt,
408+ struct aa_profile *tracee);
409+
410+/* lsm.c */
411+extern int apparmor_initialized;
412+extern void info_message(const char *str);
413+extern void apparmor_disable(void);
414+
415+/* list.c */
416+extern struct aa_namespace *__aa_find_namespace(const char *name,
417+ struct list_head *list);
418+extern struct aa_profile *__aa_find_profile(const char *name,
419+ struct list_head *list);
420+extern void aa_profile_ns_list_release(void);
421+
422+/* module_interface.c */
423+extern ssize_t aa_add_profile(void *, size_t);
424+extern ssize_t aa_replace_profile(void *, size_t);
425+extern ssize_t aa_remove_profile(char *, size_t);
426+extern struct aa_namespace *alloc_aa_namespace(char *name);
427+extern void free_aa_namespace(struct aa_namespace *ns);
428+extern void free_aa_namespace_kref(struct kref *kref);
429+extern struct aa_profile *alloc_aa_profile(void);
430+extern void free_aa_profile(struct aa_profile *profile);
431+extern void free_aa_profile_kref(struct kref *kref);
432+extern void aa_unconfine_tasks(struct aa_profile *profile);
433+
434+/* procattr.c */
435+extern int aa_getprocattr(struct aa_profile *profile, char **string,
436+ unsigned *len);
437+extern int aa_setprocattr_changehat(char *args);
438+extern int aa_setprocattr_changeprofile(char *args);
439+extern int aa_setprocattr_setprofile(struct task_struct *task, char *args);
440+
441+/* apparmorfs.c */
442+extern int create_apparmorfs(void);
443+extern void destroy_apparmorfs(void);
444+
445+/* match.c */
446+extern struct aa_dfa *aa_match_alloc(void);
447+extern void aa_match_free(struct aa_dfa *dfa);
448+extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
449+extern int verify_dfa(struct aa_dfa *dfa);
450+extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *);
451+extern unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
452+ const char *str);
453+extern unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
454+ const char *str, unsigned int *final);
455+extern unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
456+ unsigned int start);
457+
458+#endif /* __APPARMOR_H */
459--- /dev/null
460+++ b/security/apparmor/apparmorfs.c
461@@ -0,0 +1,281 @@
462+/*
463+ * Copyright (C) 1998-2007 Novell/SUSE
464+ *
465+ * This program is free software; you can redistribute it and/or
466+ * modify it under the terms of the GNU General Public License as
467+ * published by the Free Software Foundation, version 2 of the
468+ * License.
469+ *
470+ * AppArmor filesystem (part of securityfs)
471+ */
472+
473+#include <linux/security.h>
474+#include <linux/vmalloc.h>
475+#include <linux/module.h>
476+#include <linux/seq_file.h>
477+#include <asm/uaccess.h>
478+#include <linux/namei.h>
479+
480+#include "apparmor.h"
481+#include "inline.h"
482+
483+static char *aa_simple_write_to_buffer(const char __user *userbuf,
484+ size_t alloc_size, size_t copy_size,
485+ loff_t *pos, const char *operation)
486+{
487+ struct aa_profile *profile;
488+ char *data;
489+
490+ if (*pos != 0) {
491+ /* only writes from pos 0, that is complete writes */
492+ data = ERR_PTR(-ESPIPE);
493+ goto out;
494+ }
495+
496+ /*
497+ * Don't allow confined processes to load/replace/remove profiles.
498+ * No sane person would add rules allowing this to a profile
499+ * but we enforce the restriction anyways.
500+ */
501+ profile = aa_get_profile(current);
502+ if (profile) {
503+ struct aa_audit sa;
504+ memset(&sa, 0, sizeof(sa));
505+ sa.operation = operation;
506+ sa.gfp_mask = GFP_KERNEL;
507+ sa.error_code = -EACCES;
508+ data = ERR_PTR(aa_audit_reject(profile, &sa));
509+ aa_put_profile(profile);
510+ goto out;
511+ }
512+
513+ data = vmalloc(alloc_size);
514+ if (data == NULL) {
515+ data = ERR_PTR(-ENOMEM);
516+ goto out;
517+ }
518+
519+ if (copy_from_user(data, userbuf, copy_size)) {
520+ vfree(data);
521+ data = ERR_PTR(-EFAULT);
522+ goto out;
523+ }
524+
525+out:
526+ return data;
527+}
528+
529+/* apparmor/profiles */
530+extern struct seq_operations apparmorfs_profiles_op;
531+
532+static int aa_profiles_open(struct inode *inode, struct file *file)
533+{
534+ return seq_open(file, &apparmorfs_profiles_op);
535+}
536+
537+
538+static int aa_profiles_release(struct inode *inode, struct file *file)
539+{
540+ return seq_release(inode, file);
541+}
542+
543+static struct file_operations apparmorfs_profiles_fops = {
544+ .open = aa_profiles_open,
545+ .read = seq_read,
546+ .llseek = seq_lseek,
547+ .release = aa_profiles_release,
548+};
549+
550+/* apparmor/matching */
551+static ssize_t aa_matching_read(struct file *file, char __user *buf,
552+ size_t size, loff_t *ppos)
553+{
554+ const char *matching = "pattern=aadfa audit perms=rwxamlk/ user::other";
555+
556+ return simple_read_from_buffer(buf, size, ppos, matching,
557+ strlen(matching));
558+}
559+
560+static struct file_operations apparmorfs_matching_fops = {
561+ .read = aa_matching_read,
562+};
563+
564+/* apparmor/features */
565+static ssize_t aa_features_read(struct file *file, char __user *buf,
566+ size_t size, loff_t *ppos)
567+{
568+ const char *features = "file=3.0 capability=2.0 network=1.0 "
569+ "change_hat=1.5 change_profile=1.0 "
570+ "aanamespaces=1.0";
571+
572+ return simple_read_from_buffer(buf, size, ppos, features,
573+ strlen(features));
574+}
575+
576+static struct file_operations apparmorfs_features_fops = {
577+ .read = aa_features_read,
578+};
579+
580+/* apparmor/.load */
581+static ssize_t aa_profile_load(struct file *f, const char __user *buf,
582+ size_t size, loff_t *pos)
583+{
584+ char *data;
585+ ssize_t error;
586+
587+ data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
588+
589+ error = PTR_ERR(data);
590+ if (!IS_ERR(data)) {
591+ error = aa_add_profile(data, size);
592+ vfree(data);
593+ }
594+
595+ return error;
596+}
597+
598+
599+static struct file_operations apparmorfs_profile_load = {
600+ .write = aa_profile_load
601+};
602+
603+/* apparmor/.replace */
604+static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
605+ size_t size, loff_t *pos)
606+{
607+ char *data;
608+ ssize_t error;
609+
610+ data = aa_simple_write_to_buffer(buf, size, size, pos,
611+ "profile_replace");
612+
613+ error = PTR_ERR(data);
614+ if (!IS_ERR(data)) {
615+ error = aa_replace_profile(data, size);
616+ vfree(data);
617+ }
618+
619+ return error;
620+}
621+
622+
623+static struct file_operations apparmorfs_profile_replace = {
624+ .write = aa_profile_replace
625+};
626+
627+/* apparmor/.remove */
628+static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
629+ size_t size, loff_t *pos)
630+{
631+ char *data;
632+ ssize_t error;
633+
634+ /*
635+ * aa_remove_profile needs a null terminated string so 1 extra
636+ * byte is allocated and the copied data is null terminated.
637+ */
638+ data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
639+ "profile_remove");
640+
641+ error = PTR_ERR(data);
642+ if (!IS_ERR(data)) {
643+ data[size] = 0;
644+ error = aa_remove_profile(data, size);
645+ vfree(data);
646+ }
647+
648+ return error;
649+}
650+
651+static struct file_operations apparmorfs_profile_remove = {
652+ .write = aa_profile_remove
653+};
654+
655+static struct dentry *apparmor_dentry;
656+
657+static void aafs_remove(const char *name)
658+{
659+ struct dentry *dentry;
660+
661+ dentry = lookup_one_len(name, apparmor_dentry, strlen(name));
662+ if (!IS_ERR(dentry)) {
663+ securityfs_remove(dentry);
664+ dput(dentry);
665+ }
666+}
667+
668+static int aafs_create(const char *name, int mask, struct file_operations *fops)
669+{
670+ struct dentry *dentry;
671+
672+ dentry = securityfs_create_file(name, S_IFREG | mask, apparmor_dentry,
673+ NULL, fops);
674+
675+ return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
676+}
677+
678+void destroy_apparmorfs(void)
679+{
680+ if (apparmor_dentry) {
681+ aafs_remove(".remove");
682+ aafs_remove(".replace");
683+ aafs_remove(".load");
684+ aafs_remove("matching");
685+ aafs_remove("features");
686+ aafs_remove("profiles");
687+ securityfs_remove(apparmor_dentry);
688+ apparmor_dentry = NULL;
689+ }
690+}
691+
692+int create_apparmorfs(void)
693+{
694+ int error;
695+
696+ if (!apparmor_initialized)
697+ return 0;
698+
699+ if (apparmor_dentry) {
700+ AA_ERROR("%s: AppArmor securityfs already exists\n",
701+ __FUNCTION__);
702+ return -EEXIST;
703+ }
704+
705+ apparmor_dentry = securityfs_create_dir("apparmor", NULL);
706+ if (IS_ERR(apparmor_dentry)) {
707+ error = PTR_ERR(apparmor_dentry);
708+ apparmor_dentry = NULL;
709+ goto error;
710+ }
711+ error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
712+ if (error)
713+ goto error;
714+ error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
715+ if (error)
716+ goto error;
717+ error = aafs_create("features", 0444, &apparmorfs_features_fops);
718+ if (error)
719+ goto error;
720+ error = aafs_create(".load", 0640, &apparmorfs_profile_load);
721+ if (error)
722+ goto error;
723+ error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
724+ if (error)
725+ goto error;
726+ error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
727+ if (error)
728+ goto error;
729+
730+ /* Report that AppArmor fs is enabled */
731+ info_message("AppArmor Filesystem Enabled");
732+ return 0;
733+
734+error:
735+ destroy_apparmorfs();
736+ AA_ERROR("Error creating AppArmor securityfs\n");
737+ apparmor_disable();
738+ return error;
739+}
740+
741+fs_initcall(create_apparmorfs);
742+
743--- /dev/null
744+++ b/security/apparmor/inline.h
745@@ -0,0 +1,250 @@
746+/*
747+ * Copyright (C) 1998-2007 Novell/SUSE
748+ *
749+ * This program is free software; you can redistribute it and/or
750+ * modify it under the terms of the GNU General Public License as
751+ * published by the Free Software Foundation, version 2 of the
752+ * License.
753+ */
754+
755+#ifndef __INLINE_H
756+#define __INLINE_H
757+
758+#include <linux/sched.h>
759+
760+#include "match.h"
761+
762+static inline int mediated_filesystem(struct inode *inode)
763+{
764+ return !(inode->i_sb->s_flags & MS_NOUSER);
765+}
766+
767+static inline struct aa_task_context *aa_task_context(struct task_struct *task)
768+{
769+ return (struct aa_task_context *) rcu_dereference(task->security);
770+}
771+
772+static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
773+{
774+ if (ns)
775+ kref_get(&(ns->count));
776+
777+ return ns;
778+}
779+
780+static inline void aa_put_namespace(struct aa_namespace *ns)
781+{
782+ if (ns)
783+ kref_put(&ns->count, free_aa_namespace_kref);
784+}
785+
786+
787+static inline struct aa_namespace *aa_find_namespace(const char *name)
788+{
789+ struct aa_namespace *ns = NULL;
790+
791+ read_lock(&profile_ns_list_lock);
792+ ns = aa_get_namespace(__aa_find_namespace(name, &profile_ns_list));
793+ read_unlock(&profile_ns_list_lock);
794+
795+ return ns;
796+}
797+
798+/**
799+ * aa_dup_profile - increment refcount on profile @p
800+ * @p: profile
801+ */
802+static inline struct aa_profile *aa_dup_profile(struct aa_profile *p)
803+{
804+ if (p)
805+ kref_get(&(p->count));
806+
807+ return p;
808+}
809+
810+/**
811+ * aa_put_profile - decrement refcount on profile @p
812+ * @p: profile
813+ */
814+static inline void aa_put_profile(struct aa_profile *p)
815+{
816+ if (p)
817+ kref_put(&p->count, free_aa_profile_kref);
818+}
819+
820+static inline struct aa_profile *aa_get_profile(struct task_struct *task)
821+{
822+ struct aa_task_context *cxt;
823+ struct aa_profile *profile = NULL;
824+
825+ rcu_read_lock();
826+ cxt = aa_task_context(task);
827+ if (cxt) {
828+ profile = cxt->profile;
829+ aa_dup_profile(profile);
830+ }
831+ rcu_read_unlock();
832+
833+ return profile;
834+}
835+
836+static inline struct aa_profile *aa_find_profile(struct aa_namespace *ns,
837+ const char *name)
838+{
839+ struct aa_profile *profile = NULL;
840+
841+ read_lock(&ns->lock);
842+ profile = aa_dup_profile(__aa_find_profile(name, &ns->profiles));
843+ read_unlock(&ns->lock);
844+
845+ return profile;
846+}
847+
848+static inline struct aa_task_context *aa_alloc_task_context(gfp_t flags)
849+{
850+ struct aa_task_context *cxt;
851+
852+ cxt = kzalloc(sizeof(*cxt), flags);
853+ if (cxt) {
854+ INIT_LIST_HEAD(&cxt->list);
855+ INIT_RCU_HEAD(&cxt->rcu);
856+ }
857+
858+ return cxt;
859+}
860+
861+static inline void aa_free_task_context(struct aa_task_context *cxt)
862+{
863+ if (cxt) {
864+ aa_put_profile(cxt->profile);
865+ aa_put_profile(cxt->previous_profile);
866+ kfree(cxt);
867+ }
868+}
869+
870+/**
871+ * lock_profile - lock a profile
872+ * @profile: the profile to lock
873+ *
874+ * While the profile is locked, local interrupts are disabled. This also
875+ * gives us RCU reader safety.
876+ */
877+static inline void lock_profile_nested(struct aa_profile *profile,
878+ enum aa_lock_class lock_class)
879+{
880+ /*
881+ * Lock the profile.
882+ *
883+ * Need to disable interrupts here because this lock is used in
884+ * the task_free_security hook, which may run in RCU context.
885+ */
886+ if (profile)
887+ spin_lock_irqsave_nested(&profile->lock, profile->int_flags,
888+ lock_class);
889+}
890+
891+static inline void lock_profile(struct aa_profile *profile)
892+{
893+ lock_profile_nested(profile, aa_lock_normal);
894+}
895+
896+/**
897+ * unlock_profile - unlock a profile
898+ * @profile: the profile to unlock
899+ */
900+static inline void unlock_profile(struct aa_profile *profile)
901+{
902+ /* Unlock the profile. */
903+ if (profile)
904+ spin_unlock_irqrestore(&profile->lock, profile->int_flags);
905+}
906+
907+/**
908+ * lock_both_profiles - lock two profiles in a deadlock-free way
909+ * @profile1: profile to lock (may be NULL)
910+ * @profile2: profile to lock (may be NULL)
911+ *
912+ * The order in which profiles are passed into lock_both_profiles() /
913+ * unlock_both_profiles() does not matter.
914+ * While the profile is locked, local interrupts are disabled. This also
915+ * gives us RCU reader safety.
916+ */
917+static inline void lock_both_profiles(struct aa_profile *profile1,
918+ struct aa_profile *profile2)
919+{
920+ /*
921+ * Lock the two profiles.
922+ *
923+ * We need to disable interrupts because the profile locks are
924+ * used in the task_free_security hook, which may run in RCU
925+ * context.
926+ *
927+ * Do not nest spin_lock_irqsave()/spin_unlock_irqresore():
928+ * interrupts only need to be turned off once.
929+ */
930+ if (!profile1 || profile1 == profile2) {
931+ if (profile2)
932+ spin_lock_irqsave_nested(&profile2->lock,
933+ profile2->int_flags,
934+ aa_lock_normal);
935+ } else if (profile1 > profile2) {
936+ /* profile1 cannot be NULL here. */
937+ spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags,
938+ aa_lock_normal);
939+ if (profile2)
940+ spin_lock_nested(&profile2->lock, aa_lock_nested);
941+
942+ } else {
943+ /* profile2 cannot be NULL here. */
944+ spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags,
945+ aa_lock_normal);
946+ spin_lock_nested(&profile1->lock, aa_lock_nested);
947+ }
948+}
949+
950+/**
951+ * unlock_both_profiles - unlock two profiles in a deadlock-free way
952+ * @profile1: profile to unlock (may be NULL)
953+ * @profile2: profile to unlock (may be NULL)
954+ *
955+ * The order in which profiles are passed into lock_both_profiles() /
956+ * unlock_both_profiles() does not matter.
957+ * While the profile is locked, local interrupts are disabled. This also
958+ * gives us RCU reader safety.
959+ */
960+static inline void unlock_both_profiles(struct aa_profile *profile1,
961+ struct aa_profile *profile2)
962+{
963+ /* Unlock the two profiles. */
964+ if (!profile1 || profile1 == profile2) {
965+ if (profile2)
966+ spin_unlock_irqrestore(&profile2->lock,
967+ profile2->int_flags);
968+ } else if (profile1 > profile2) {
969+ /* profile1 cannot be NULL here. */
970+ if (profile2)
971+ spin_unlock(&profile2->lock);
972+ spin_unlock_irqrestore(&profile1->lock, profile1->int_flags);
973+ } else {
974+ /* profile2 cannot be NULL here. */
975+ spin_unlock(&profile1->lock);
976+ spin_unlock_irqrestore(&profile2->lock, profile2->int_flags);
977+ }
978+}
979+
980+static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname,
981+ int *audit_mask)
982+{
983+ if (dfa)
984+ return aa_dfa_match(dfa, pathname, audit_mask);
985+ if (audit_mask)
986+ *audit_mask = 0;
987+ return 0;
988+}
989+
990+static inline int dfa_audit_mask(struct aa_dfa *dfa, unsigned int state)
991+{
992+ return ACCEPT_TABLE2(dfa)[state];
993+}
994+
995+#endif /* __INLINE_H__ */
996--- /dev/null
997+++ b/security/apparmor/list.c
998@@ -0,0 +1,174 @@
999+/*
1000+ * Copyright (C) 1998-2007 Novell/SUSE
1001+ *
1002+ * This program is free software; you can redistribute it and/or
1003+ * modify it under the terms of the GNU General Public License as
1004+ * published by the Free Software Foundation, version 2 of the
1005+ * License.
1006+ *
1007+ * AppArmor Profile List Management
1008+ */
1009+
1010+#include <linux/seq_file.h>
1011+#include "apparmor.h"
1012+#include "inline.h"
1013+
1014+/* list of profile namespaces and lock */
1015+LIST_HEAD(profile_ns_list);
1016+rwlock_t profile_ns_list_lock = RW_LOCK_UNLOCKED;
1017+
1018+/**
1019+ * __aa_find_namespace - look up a profile namespace on the namespace list
1020+ * @name: name of namespace to find
1021+ * @head: list to search
1022+ *
1023+ * Returns a pointer to the namespace on the list, or NULL if no namespace
1024+ * called @name exists. The caller must hold the profile_ns_list_lock.
1025+ */
1026+struct aa_namespace *__aa_find_namespace(const char *name,
1027+ struct list_head *head)
1028+{
1029+ struct aa_namespace *ns;
1030+
1031+ list_for_each_entry(ns, head, list) {
1032+ if (!strcmp(ns->name, name))
1033+ return ns;
1034+ }
1035+
1036+ return NULL;
1037+}
1038+
1039+/**
1040+ * __aa_find_profile - look up a profile on the profile list
1041+ * @name: name of profile to find
1042+ * @head: list to search
1043+ *
1044+ * Returns a pointer to the profile on the list, or NULL if no profile
1045+ * called @name exists. The caller must hold the profile_list_lock.
1046+ */
1047+struct aa_profile *__aa_find_profile(const char *name, struct list_head *head)
1048+{
1049+ struct aa_profile *profile;
1050+
1051+ list_for_each_entry(profile, head, list) {
1052+ if (!strcmp(profile->name, name))
1053+ return profile;
1054+ }
1055+
1056+ return NULL;
1057+}
1058+
1059+static void aa_profile_list_release(struct list_head *head)
1060+{
1061+ struct aa_profile *profile, *tmp;
1062+ list_for_each_entry_safe(profile, tmp, head, list) {
1063+ /* Remove the profile from each task context it is on. */
1064+ lock_profile(profile);
1065+ profile->isstale = 1;
1066+ aa_unconfine_tasks(profile);
1067+ list_del_init(&profile->list);
1068+ unlock_profile(profile);
1069+ aa_put_profile(profile);
1070+ }
1071+}
1072+
1073+/**
1074+ * aa_profilelist_release - Remove all profiles from profile_list
1075+ */
1076+void aa_profile_ns_list_release(void)
1077+{
1078+ struct aa_namespace *ns, *tmp;
1079+
1080+ /* Remove and release all the profiles on namespace profile lists. */
1081+ write_lock(&profile_ns_list_lock);
1082+ list_for_each_entry_safe(ns, tmp, &profile_ns_list, list) {
1083+ write_lock(&ns->lock);
1084+ aa_profile_list_release(&ns->profiles);
1085+ list_del_init(&ns->list);
1086+ write_unlock(&ns->lock);
1087+ aa_put_namespace(ns);
1088+ }
1089+ write_unlock(&profile_ns_list_lock);
1090+}
1091+
1092+
1093+static struct aa_profile *next_profile(struct aa_profile *profile)
1094+{
1095+ struct aa_profile *next = profile;
1096+ struct aa_namespace *ns;
1097+
1098+ list_for_each_entry_continue(next, &profile->ns->profiles, list)
1099+ return next;
1100+
1101+ ns = profile->ns;
1102+ read_unlock(&ns->lock);
1103+ list_for_each_entry_continue(ns, &profile_ns_list, list) {
1104+ read_lock(&ns->lock);
1105+ list_for_each_entry(profile, &ns->profiles, list)
1106+ return profile;
1107+ read_unlock(&ns->lock);
1108+ }
1109+ return NULL;
1110+}
1111+
1112+static void *p_start(struct seq_file *f, loff_t *pos)
1113+{
1114+ struct aa_namespace *ns;
1115+ loff_t l = *pos;
1116+
1117+ read_lock(&profile_ns_list_lock);
1118+ if (!list_empty(&profile_ns_list)) {
1119+ struct aa_profile *profile = NULL;
1120+ ns = list_first_entry(&profile_ns_list, typeof(*ns), list);
1121+ read_lock(&ns->lock);
1122+ if (!list_empty(&ns->profiles))
1123+ profile = list_first_entry(&ns->profiles,
1124+ typeof(*profile), list);
1125+ else
1126+ read_unlock(&ns->lock);
1127+ for ( ; profile && l > 0; l--)
1128+ profile = next_profile(profile);
1129+ return profile;
1130+ }
1131+ return NULL;
1132+}
1133+
1134+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
1135+{
1136+ struct aa_profile *profile = (struct aa_profile *) p;
1137+
1138+ (*pos)++;
1139+ profile = next_profile(profile);
1140+
1141+ return profile;
1142+}
1143+
1144+static void p_stop(struct seq_file *f, void *p)
1145+{
1146+ struct aa_profile *profile = (struct aa_profile *) p;
1147+
1148+ if (profile)
1149+ read_unlock(&profile->ns->lock);
1150+ read_unlock(&profile_ns_list_lock);
1151+}
1152+
1153+static int seq_show_profile(struct seq_file *f, void *p)
1154+{
1155+ struct aa_profile *profile = (struct aa_profile *)p;
1156+
1157+ if (profile->ns == default_namespace)
1158+ seq_printf(f, "%s (%s)\n", profile->name,
1159+ PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
1160+ else
1161+ seq_printf(f, ":%s:%s (%s)\n", profile->ns->name, profile->name,
1162+ PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
1163+ return 0;
1164+}
1165+
1166+/* Used in apparmorfs.c */
1167+struct seq_operations apparmorfs_profiles_op = {
1168+ .start = p_start,
1169+ .next = p_next,
1170+ .stop = p_stop,
1171+ .show = seq_show_profile,
1172+};
1173--- /dev/null
1174+++ b/security/apparmor/locking.txt
1175@@ -0,0 +1,68 @@
1176+Locking in AppArmor
1177+===================
1178+
1179+Lock hierarchy:
1180+
1181+ aa_interface_lock
1182+ profile_list_lock
1183+ aa_profile->lock
1184+ task_lock()
1185+
1186+
1187+Which lock protects what?
1188+
1189+ /-----------------------+-------------------------------\
1190+ | Variable | Lock |
1191+ >-----------------------+-------------------------------<
1192+ | profile_list | profile_list_lock |
1193+ +-----------------------+-------------------------------+
1194+ | aa_profile | (reference count) |
1195+ +-----------------------+-------------------------------+
1196+ | aa_profile-> | aa_profile->lock |
1197+ | isstale, | |
1198+ | task_contexts | |
1199+ +-----------------------+-------------------------------+
1200+ | task_struct->security | read: RCU |
1201+ | | write: task_lock() |
1202+ +-----------------------+-------------------------------+
1203+ | aa_profile->sub | handle on the profile (list |
1204+ | | is never modified) |
1205+ \-----------------------+-------------------------------/
1206+
1207+(Obviously, the list_heads embedded in data structures are always
1208+protected with the lock that also protects the list.)
1209+
1210+When moving a task context from one profile to another, we grab both
1211+profile locks with lock_both_profiles(). This ensures that both locks
1212+are always taken in the same order, and so we won't deadlock.
1213+
1214+Since task_struct->security is RCU protected the aa_task_struct it
1215+references is only guarenteed to exist for the rcu cycle. Where
1216+aa_task_context->profile is needed in blocking operations the
1217+profile's reference count is incremented and the profile reference
1218+is used.
1219+
1220+Profiles on profile_list are never stale: when a profile becomes stale,
1221+it is removed from profile_list at the same time (under profile_list_lock
1222+and aa_profile->lock).
1223+
1224+The aa_interface_lock is taken whenever user-space modifies the profile
1225+list, and can sleep. This ensures that profile loading/replacement/removal
1226+won't race with itself. We release the profile_list_lock as soon as
1227+possible to avoid stalling exec during profile loading/replacement/removal.
1228+
1229+AppArmor uses lock subtyping to avoid false positives from lockdep. The
1230+profile lock is often taken nested, but it is guaranteed to be in a lock
1231+safe order and not the same lock when done, so it is safe.
1232+
1233+A third lock type (aa_lock_task_release) is given to the profile lock
1234+when it is taken in soft irq context during task release (aa_release).
1235+This is to avoid a false positive between the task lock and the profile
1236+lock. In task context the profile lock wraps the task lock with irqs
1237+off, but the kernel takes the task lock with irqs enabled. This won't
1238+result in a deadlock because for a deadlock to occur the kernel must
1239+take dead task A's lock (irqs on), the rcu callback hook freeing
1240+dead task A must be run and AppArmor must be changing the profile on
1241+dead task A. The kernel should not be taking a dead task's task_lock
1242+at the same time the task is being freed by task rcu cleanup other wise
1243+the task would not be out of its quiescent period.
1244--- /dev/null
1245+++ b/security/apparmor/procattr.c
1246@@ -0,0 +1,195 @@
1247+/*
1248+ * Copyright (C) 1998-2007 Novell/SUSE
1249+ *
1250+ * This program is free software; you can redistribute it and/or
1251+ * modify it under the terms of the GNU General Public License as
1252+ * published by the Free Software Foundation, version 2 of the
1253+ * License.
1254+ *
1255+ * AppArmor /proc/pid/attr handling
1256+ */
1257+
1258+#include "apparmor.h"
1259+#include "inline.h"
1260+
1261+int aa_getprocattr(struct aa_profile *profile, char **string, unsigned *len)
1262+{
1263+ char *str;
1264+
1265+ if (profile) {
1266+ const char *mode_str = PROFILE_COMPLAIN(profile) ?
1267+ " (complain)" : " (enforce)";
1268+ int mode_len, name_len, ns_len = 0;
1269+
1270+ mode_len = strlen(mode_str);
1271+ name_len = strlen(profile->name);
1272+ if (profile->ns != default_namespace)
1273+ ns_len = strlen(profile->ns->name) + 2;
1274+ *len = mode_len + ns_len + name_len + 1;
1275+ str = kmalloc(*len, GFP_ATOMIC);
1276+ if (!str)
1277+ return -ENOMEM;
1278+
1279+ if (ns_len) {
1280+ *str++ = ':';
1281+ memcpy(str, profile->ns->name, ns_len - 2);
1282+ str += ns_len - 2;
1283+ *str++ = ':';
1284+ }
1285+ memcpy(str, profile->name, name_len);
1286+ str += name_len;
1287+ memcpy(str, mode_str, mode_len);
1288+ str += mode_len;
1289+ *str++ = '\n';
1290+ str -= *len;
1291+ } else {
1292+ const char *unconfined_str = "unconfined\n";
1293+
1294+ *len = strlen(unconfined_str);
1295+ str = kmalloc(*len, GFP_ATOMIC);
1296+ if (!str)
1297+ return -ENOMEM;
1298+
1299+ memcpy(str, unconfined_str, *len);
1300+ }
1301+ *string = str;
1302+
1303+ return 0;
1304+}
1305+
1306+static char *split_token_from_name(const char *op, char *args, u64 *cookie)
1307+{
1308+ char *name;
1309+
1310+ *cookie = simple_strtoull(args, &name, 16);
1311+ if ((name == args) || *name != '^') {
1312+ AA_ERROR("%s: Invalid input '%s'", op, args);
1313+ return ERR_PTR(-EINVAL);
1314+ }
1315+
1316+ name++; /* skip ^ */
1317+ if (!*name)
1318+ name = NULL;
1319+ return name;
1320+}
1321+
1322+int aa_setprocattr_changehat(char *args)
1323+{
1324+ char *hat;
1325+ u64 cookie;
1326+
1327+ hat = split_token_from_name("change_hat", args, &cookie);
1328+ if (IS_ERR(hat))
1329+ return PTR_ERR(hat);
1330+
1331+ if (!hat && !cookie) {
1332+ AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
1333+ return -EINVAL;
1334+ }
1335+
1336+ AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
1337+ __FUNCTION__, cookie, hat ? hat : NULL);
1338+
1339+ return aa_change_hat(hat, cookie);
1340+}
1341+
1342+int aa_setprocattr_changeprofile(char *args)
1343+{
1344+ char *name = args, *ns_name = NULL;
1345+
1346+ if (name[0] == ':') {
1347+ char *split = strchr(&name[1], ':');
1348+ if (split) {
1349+ *split = 0;
1350+ ns_name = &name[1];
1351+ name = split + 1;
1352+ }
1353+ }
1354+
1355+ return aa_change_profile(ns_name, name);
1356+}
1357+
1358+int aa_setprocattr_setprofile(struct task_struct *task, char *args)
1359+{
1360+ struct aa_profile *old_profile, *new_profile;
1361+ struct aa_namespace *ns;
1362+ struct aa_audit sa;
1363+ char *name, *ns_name = NULL;
1364+
1365+ memset(&sa, 0, sizeof(sa));
1366+ sa.operation = "profile_set";
1367+ sa.gfp_mask = GFP_KERNEL;
1368+ sa.task = task->pid;
1369+
1370+ AA_DEBUG("%s: current %d\n",
1371+ __FUNCTION__, current->pid);
1372+
1373+ name = args;
1374+ if (args[0] != '/') {
1375+ char *split = strchr(args, ':');
1376+ if (split) {
1377+ *split = 0;
1378+ ns_name = args;
1379+ name = split + 1;
1380+ }
1381+ }
1382+ if (ns_name)
1383+ ns = aa_find_namespace(ns_name);
1384+ else
1385+ ns = aa_get_namespace(default_namespace);
1386+ if (!ns) {
1387+ sa.name = ns_name;
1388+ sa.info = "unknown namespace";
1389+ aa_audit_reject(NULL, &sa);
1390+ aa_put_namespace(ns);
1391+ return -EINVAL;
1392+ }
1393+
1394+repeat:
1395+ if (strcmp(name, "unconfined") == 0)
1396+ new_profile = NULL;
1397+ else {
1398+ new_profile = aa_find_profile(ns, name);
1399+ if (!new_profile) {
1400+ sa.name = ns_name;
1401+ sa.name2 = name;
1402+ sa.info = "unknown profile";
1403+ aa_audit_reject(NULL, &sa);
1404+ aa_put_namespace(ns);
1405+ return -EINVAL;
1406+ }
1407+ }
1408+
1409+ old_profile = __aa_replace_profile(task, new_profile);
1410+ if (IS_ERR(old_profile)) {
1411+ int error;
1412+
1413+ aa_put_profile(new_profile);
1414+ error = PTR_ERR(old_profile);
1415+ if (error == -ESTALE)
1416+ goto repeat;
1417+ aa_put_namespace(ns);
1418+ return error;
1419+ }
1420+
1421+ if (new_profile) {
1422+ sa.name = ns_name;
1423+ sa.name2 = name;
1424+ sa.name3 = old_profile ? old_profile->name :
1425+ "unconfined";
1426+ aa_audit_status(NULL, &sa);
1427+ } else {
1428+ if (old_profile) {
1429+ sa.name = "unconfined";
1430+ sa.name2 = old_profile->name;
1431+ aa_audit_status(NULL, &sa);
1432+ } else {
1433+ sa.info = "task is unconfined";
1434+ aa_audit_status(NULL, &sa);
1435+ }
1436+ }
1437+ aa_put_namespace(ns);
1438+ aa_put_profile(old_profile);
1439+ aa_put_profile(new_profile);
1440+ return 0;
1441+}