1
From: John Johansen <jjohansen@suse.de>
2
Subject: AppArmor: all the rest
4
All the things that didn't nicely fit in a category on their own: kbuild
5
code, declararions and inline functions, /sys/kernel/security/apparmor
6
filesystem for controlling apparmor from user space, profile list
7
functions, locking documentation, /proc/$pid/task/$tid/attr/current
10
Signed-off-by: John Johansen <jjohansen@suse.de>
11
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
14
security/apparmor/Kconfig | 42 ++++
15
security/apparmor/Makefile | 13 +
16
security/apparmor/apparmor.h | 367 +++++++++++++++++++++++++++++++++++++++++
17
security/apparmor/apparmorfs.c | 280 +++++++++++++++++++++++++++++++
18
security/apparmor/inline.h | 250 +++++++++++++++++++++++++++
19
security/apparmor/list.c | 156 +++++++++++++++++
20
security/apparmor/locking.txt | 68 +++++++
21
security/apparmor/procattr.c | 195 +++++++++++++++++++++
22
8 files changed, 1371 insertions(+)
25
+++ b/security/apparmor/Kconfig
27
+config SECURITY_APPARMOR
28
+ bool "AppArmor support"
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>
37
+ If you are unsure how to answer this question, answer N.
39
+config SECURITY_APPARMOR_BOOTPARAM_VALUE
40
+ int "AppArmor boot parameter default value"
41
+ depends on SECURITY_APPARMOR
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
53
+ If you are unsure how to answer this question, answer 1.
55
+config SECURITY_APPARMOR_DISABLE
56
+ bool "AppArmor runtime disable"
57
+ depends on SECURITY_APPARMOR
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.
68
+ If you are unsure how to answer this question, answer N.
70
+++ b/security/apparmor/Makefile
72
+# Makefile for AppArmor Linux Security Module
74
+obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
76
+apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o \
77
+ module_interface.o match.o
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 > $@
82
+$(obj)/main.o : $(obj)/capability_names.h
83
+$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
84
+ $(call cmd,make-caps)
86
+++ b/security/apparmor/apparmor.h
89
+ * Copyright (C) 1998-2007 Novell/SUSE
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
96
+ * AppArmor internal prototypes
100
+#define __APPARMOR_H
102
+#include <linux/sched.h>
103
+#include <linux/fs.h>
104
+#include <linux/binfmts.h>
105
+#include <linux/rcupdate.h>
108
+ * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
109
+ * for profile permissions
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
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 | \
130
+#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
131
+ AA_EXEC_MOD_2 | AA_EXEC_MOD_3)
133
+#define AA_EXEC_TYPE (AA_EXEC_UNSAFE | AA_EXEC_INHERIT | \
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)
142
+#define AA_USER_SHIFT 0
143
+#define AA_OTHER_SHIFT 14
145
+#define AA_USER_PERMS (AA_BASE_PERMS << AA_USER_SHIFT)
146
+#define AA_OTHER_PERMS (AA_BASE_PERMS << AA_OTHER_SHIFT)
148
+#define AA_FILE_PERMS (AA_USER_PERMS | AA_OTHER_PERMS)
150
+#define AA_LINK_BITS ((AA_MAY_LINK << AA_USER_SHIFT) | \
151
+ (AA_MAY_LINK << AA_OTHER_SHIFT))
153
+#define AA_USER_EXEC (MAY_EXEC << AA_USER_SHIFT)
154
+#define AA_OTHER_EXEC (MAY_EXEC << AA_OTHER_SHIFT)
156
+#define AA_USER_EXEC_TYPE (AA_EXEC_TYPE << AA_USER_SHIFT)
157
+#define AA_OTHER_EXEC_TYPE (AA_EXEC_TYPE << AA_OTHER_SHIFT)
159
+#define AA_EXEC_BITS (AA_USER_EXEC | AA_OTHER_EXEC)
161
+#define ALL_AA_EXEC_UNSAFE ((AA_EXEC_UNSAFE << AA_USER_SHIFT) | \
162
+ (AA_EXEC_UNSAFE << AA_OTHER_SHIFT))
164
+#define ALL_AA_EXEC_TYPE (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE)
166
+/* overloaded permissions for link pairs */
167
+#define AA_LINK_SUBSET_TEST 0x0020
169
+#define AA_USER_PTRACE 0x10000000
170
+#define AA_OTHER_PTRACE 0x20000000
171
+#define AA_PTRACE_PERMS (AA_USER_PTRACE | AA_OTHER_PTRACE)
173
+/* shared permissions that are not duplicated in user::other */
174
+#define AA_CHANGE_HAT 0x40000000
175
+#define AA_CHANGE_PROFILE 0x80000000
177
+#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
179
+#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_PTRACE_PERMS | \
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
187
+#define AA_SECURE_EXEC_NEEDED 1
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;
197
+#define PROFILE_COMPLAIN(_profile) \
198
+ (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
200
+#define APPARMOR_COMPLAIN(_cxt) \
201
+ (apparmor_complain == 1 || \
202
+ ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.complain))
204
+#define PROFILE_AUDIT(_profile) \
205
+ (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
207
+#define APPARMOR_AUDIT(_cxt) \
208
+ (apparmor_audit == 1 || \
209
+ ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.audit))
212
+ * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
213
+ * which is not related to profile accesses.
216
+#define AA_DEBUG(fmt, args...) \
218
+ if (apparmor_debug) \
219
+ printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
222
+#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
226
+/* struct aa_namespace - namespace for a set of profiles
227
+ * @name: the name of the namespace
228
+ * @list: list the namespace is on
229
+ * @profiles: list of profile in the namespace
230
+ * @profile_count: the number of profiles in the namespace
231
+ * @null_complain_profile: special profile used for learning in this namespace
232
+ * @count: reference count on the namespace
233
+ * @lock: lock for adding/removing profile to the namespace
235
+struct aa_namespace {
237
+ struct list_head list;
238
+ struct list_head profiles;
240
+ struct aa_profile *null_complain_profile;
246
+/* struct aa_profile - basic confinement data
247
+ * @name: the profiles name
248
+ * @list: list this profile is on
249
+ * @ns: namespace the profile is in
250
+ * @file_rules: dfa containing the profiles file rules
251
+ * @flags: flags controlling profile behavior
252
+ * @isstale: flag indicating if profile is stale
253
+ * @set_caps: capabilities that are being set
254
+ * @capabilities: capabilities mask
255
+ * @audit_caps: caps that are to be audited
256
+ * @quiet_caps: caps that should not be audited
257
+ * @capabilities: capabilities granted by the process
258
+ * @count: reference count of the profile
259
+ * @task_contexts: list of tasks confined by profile
260
+ * @lock: lock for the task_contexts list
261
+ * @network_families: basic network permissions
262
+ * @audit_network: which network permissions to force audit
263
+ * @quiet_network: which network permissions to quiet rejects
265
+ * The AppArmor profile contains the basic confinement data. Each profile
266
+ * has a name, and all nonstale profile are in a profile namespace.
268
+ * The task_contexts list and the isstale flag are protected by the
271
+ * If a task context is moved between two profiles, we first need to grab
272
+ * both profile locks. lock_both_profiles() does that in a deadlock-safe
277
+ struct list_head list;
278
+ struct aa_namespace *ns;
280
+ int exec_table_size;
282
+ struct aa_dfa *file_rules;
289
+ kernel_cap_t set_caps;
290
+ kernel_cap_t capabilities;
291
+ kernel_cap_t audit_caps;
292
+ kernel_cap_t quiet_caps;
295
+ struct list_head task_contexts;
297
+ unsigned long int_flags;
300
+extern struct list_head profile_ns_list;
301
+extern rwlock_t profile_ns_list_lock;
302
+extern struct mutex aa_interface_lock;
305
+ * struct aa_task_context - primary label for confined tasks
306
+ * @profile: the current profile
307
+ * @previous_profile: profile the task may return to
308
+ * @cookie: magic value the task must know for returning to @previous_profile
309
+ * @list: list this aa_task_context is on
310
+ * @task: task that the aa_task_context confines
311
+ * @rcu: rcu head used when freeing the aa_task_context
312
+ * @caps_logged: caps that have previously generated log entries
314
+ * Contains the task's current profile (which could change due to
315
+ * change_hat). Plus the hat_magic needed during change_hat.
317
+struct aa_task_context {
318
+ struct aa_profile *profile;
319
+ struct aa_profile *previous_profile;
321
+ struct list_head list;
322
+ struct task_struct *task;
323
+ struct rcu_head rcu;
324
+ kernel_cap_t caps_logged;
327
+extern struct aa_namespace *default_namespace;
329
+/* aa_audit - AppArmor auditing structure
330
+ * Structure is populated by access control code and passed to aa_audit which
331
+ * provides for a single point of logging.
335
+ const char *operation;
341
+ int request_mask, denied_mask, audit_mask;
342
+ struct iattr *iattr;
343
+ pid_t task, parent;
347
+/* Flags for the permission check functions */
348
+#define AA_CHECK_FD 1 /* coming from a file descriptor */
349
+#define AA_CHECK_DIR 2 /* file type is directory */
351
+/* lock subtypes so lockdep does not raise false dependencies */
352
+enum aa_lock_class {
355
+ aa_lock_task_release
359
+extern int alloc_default_namespace(void);
360
+extern void free_default_namespace(void);
361
+extern int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
363
+void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa);
364
+void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa);
365
+int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa);
366
+extern int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
368
+extern int aa_audit(struct aa_profile *profile, struct aa_audit *);
370
+extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
371
+ struct vfsmount *mnt, struct iattr *iattr);
372
+extern int aa_perm_xattr(struct aa_profile *profile, const char *operation,
373
+ struct dentry *dentry, struct vfsmount *mnt,
374
+ int mask, int check);
375
+extern int aa_capability(struct aa_task_context *cxt, int cap);
376
+extern int aa_perm(struct aa_profile *profile, const char *operation,
377
+ struct dentry *dentry, struct vfsmount *mnt, int mask,
379
+extern int aa_perm_dir(struct aa_profile *profile, const char *operation,
380
+ struct dentry *dentry, struct vfsmount *mnt,
382
+extern int aa_perm_path(struct aa_profile *, const char *operation,
383
+ const char *name, int mask, uid_t uid);
384
+extern int aa_link(struct aa_profile *profile,
385
+ struct dentry *link, struct vfsmount *link_mnt,
386
+ struct dentry *target, struct vfsmount *target_mnt);
387
+extern int aa_clone(struct task_struct *task);
388
+extern int aa_register(struct linux_binprm *bprm);
389
+extern void aa_release(struct task_struct *task);
390
+extern int aa_change_hat(const char *id, u64 hat_magic);
391
+extern int aa_change_profile(const char *ns_name, const char *name);
392
+extern struct aa_profile *__aa_replace_profile(struct task_struct *task,
393
+ struct aa_profile *profile);
394
+extern struct aa_task_context *lock_task_and_profiles(struct task_struct *task,
395
+ struct aa_profile *profile);
396
+extern void unlock_task_and_profiles(struct task_struct *task,
397
+ struct aa_task_context *cxt,
398
+ struct aa_profile *profile);
399
+extern void aa_change_task_context(struct task_struct *task,
400
+ struct aa_task_context *new_cxt,
401
+ struct aa_profile *profile, u64 cookie,
402
+ struct aa_profile *previous_profile);
403
+extern int aa_may_ptrace(struct aa_task_context *cxt,
404
+ struct aa_profile *tracee);
407
+extern int apparmor_initialized;
408
+extern void info_message(const char *str);
409
+extern void apparmor_disable(void);
412
+extern struct aa_namespace *__aa_find_namespace(const char *name,
413
+ struct list_head *list);
414
+extern struct aa_profile *__aa_find_profile(const char *name,
415
+ struct list_head *list);
416
+extern void aa_profile_ns_list_release(void);
418
+/* module_interface.c */
419
+extern ssize_t aa_add_profile(void *, size_t);
420
+extern ssize_t aa_replace_profile(void *, size_t);
421
+extern ssize_t aa_remove_profile(char *, size_t);
422
+extern struct aa_namespace *alloc_aa_namespace(char *name);
423
+extern void free_aa_namespace(struct aa_namespace *ns);
424
+extern void free_aa_namespace_kref(struct kref *kref);
425
+extern struct aa_profile *alloc_aa_profile(void);
426
+extern void free_aa_profile(struct aa_profile *profile);
427
+extern void free_aa_profile_kref(struct kref *kref);
428
+extern void aa_unconfine_tasks(struct aa_profile *profile);
431
+extern int aa_getprocattr(struct aa_profile *profile, char **string,
433
+extern int aa_setprocattr_changehat(char *args);
434
+extern int aa_setprocattr_changeprofile(char *args);
435
+extern int aa_setprocattr_setprofile(struct task_struct *task, char *args);
438
+extern int create_apparmorfs(void);
439
+extern void destroy_apparmorfs(void);
442
+extern struct aa_dfa *aa_match_alloc(void);
443
+extern void aa_match_free(struct aa_dfa *dfa);
444
+extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
445
+extern int verify_dfa(struct aa_dfa *dfa);
446
+extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *);
447
+extern unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
449
+extern unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
450
+ const char *str, unsigned int *final);
451
+extern unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
452
+ unsigned int start);
454
+#endif /* __APPARMOR_H */
456
+++ b/security/apparmor/apparmorfs.c
459
+ * Copyright (C) 1998-2007 Novell/SUSE
461
+ * This program is free software; you can redistribute it and/or
462
+ * modify it under the terms of the GNU General Public License as
463
+ * published by the Free Software Foundation, version 2 of the
466
+ * AppArmor filesystem (part of securityfs)
469
+#include <linux/security.h>
470
+#include <linux/vmalloc.h>
471
+#include <linux/module.h>
472
+#include <linux/seq_file.h>
473
+#include <asm/uaccess.h>
475
+#include "apparmor.h"
478
+static char *aa_simple_write_to_buffer(const char __user *userbuf,
479
+ size_t alloc_size, size_t copy_size,
480
+ loff_t *pos, const char *operation)
482
+ struct aa_profile *profile;
486
+ /* only writes from pos 0, that is complete writes */
487
+ data = ERR_PTR(-ESPIPE);
492
+ * Don't allow confined processes to load/replace/remove profiles.
493
+ * No sane person would add rules allowing this to a profile
494
+ * but we enforce the restriction anyways.
496
+ profile = aa_get_profile(current);
498
+ struct aa_audit sa;
499
+ memset(&sa, 0, sizeof(sa));
500
+ sa.operation = operation;
501
+ sa.gfp_mask = GFP_KERNEL;
502
+ sa.error_code = -EACCES;
503
+ data = ERR_PTR(aa_audit_reject(profile, &sa));
504
+ aa_put_profile(profile);
508
+ data = vmalloc(alloc_size);
509
+ if (data == NULL) {
510
+ data = ERR_PTR(-ENOMEM);
514
+ if (copy_from_user(data, userbuf, copy_size)) {
516
+ data = ERR_PTR(-EFAULT);
524
+/* apparmor/profiles */
525
+extern struct seq_operations apparmorfs_profiles_op;
527
+static int aa_profiles_open(struct inode *inode, struct file *file)
529
+ return seq_open(file, &apparmorfs_profiles_op);
533
+static int aa_profiles_release(struct inode *inode, struct file *file)
535
+ return seq_release(inode, file);
538
+static struct file_operations apparmorfs_profiles_fops = {
539
+ .open = aa_profiles_open,
541
+ .llseek = seq_lseek,
542
+ .release = aa_profiles_release,
545
+/* apparmor/matching */
546
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
547
+ size_t size, loff_t *ppos)
549
+ const char *matching = "pattern=aadfa audit perms=rwxamlk/ user::other";
551
+ return simple_read_from_buffer(buf, size, ppos, matching,
555
+static struct file_operations apparmorfs_matching_fops = {
556
+ .read = aa_matching_read,
559
+/* apparmor/features */
560
+static ssize_t aa_features_read(struct file *file, char __user *buf,
561
+ size_t size, loff_t *ppos)
563
+ const char *features = "file=3.0 capability=2.0 network=1.0 "
564
+ "change_hat=1.4 change_profile=1.0 "
565
+ "aanamespaces=1.0";
567
+ return simple_read_from_buffer(buf, size, ppos, features,
571
+static struct file_operations apparmorfs_features_fops = {
572
+ .read = aa_features_read,
575
+/* apparmor/.load */
576
+static ssize_t aa_profile_load(struct file *f, const char __user *buf,
577
+ size_t size, loff_t *pos)
582
+ data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
584
+ error = PTR_ERR(data);
585
+ if (!IS_ERR(data)) {
586
+ error = aa_add_profile(data, size);
594
+static struct file_operations apparmorfs_profile_load = {
595
+ .write = aa_profile_load
598
+/* apparmor/.replace */
599
+static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
600
+ size_t size, loff_t *pos)
605
+ data = aa_simple_write_to_buffer(buf, size, size, pos,
606
+ "profile_replace");
608
+ error = PTR_ERR(data);
609
+ if (!IS_ERR(data)) {
610
+ error = aa_replace_profile(data, size);
618
+static struct file_operations apparmorfs_profile_replace = {
619
+ .write = aa_profile_replace
622
+/* apparmor/.remove */
623
+static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
624
+ size_t size, loff_t *pos)
630
+ * aa_remove_profile needs a null terminated string so 1 extra
631
+ * byte is allocated and the copied data is null terminated.
633
+ data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
636
+ error = PTR_ERR(data);
637
+ if (!IS_ERR(data)) {
639
+ error = aa_remove_profile(data, size);
646
+static struct file_operations apparmorfs_profile_remove = {
647
+ .write = aa_profile_remove
650
+static struct dentry *apparmor_dentry;
652
+static void aafs_remove(const char *name)
654
+ struct dentry *dentry;
656
+ dentry = lookup_one_len(name, apparmor_dentry, strlen(name));
657
+ if (!IS_ERR(dentry)) {
658
+ securityfs_remove(dentry);
663
+static int aafs_create(const char *name, int mask, struct file_operations *fops)
665
+ struct dentry *dentry;
667
+ dentry = securityfs_create_file(name, S_IFREG | mask, apparmor_dentry,
670
+ return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
673
+void destroy_apparmorfs(void)
675
+ if (apparmor_dentry) {
676
+ aafs_remove(".remove");
677
+ aafs_remove(".replace");
678
+ aafs_remove(".load");
679
+ aafs_remove("matching");
680
+ aafs_remove("features");
681
+ aafs_remove("profiles");
682
+ securityfs_remove(apparmor_dentry);
683
+ apparmor_dentry = NULL;
687
+int create_apparmorfs(void)
691
+ if (!apparmor_initialized)
694
+ if (apparmor_dentry) {
695
+ AA_ERROR("%s: AppArmor securityfs already exists\n",
700
+ apparmor_dentry = securityfs_create_dir("apparmor", NULL);
701
+ if (IS_ERR(apparmor_dentry)) {
702
+ error = PTR_ERR(apparmor_dentry);
703
+ apparmor_dentry = NULL;
706
+ error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
709
+ error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
712
+ error = aafs_create("features", 0444, &apparmorfs_features_fops);
715
+ error = aafs_create(".load", 0640, &apparmorfs_profile_load);
718
+ error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
721
+ error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
725
+ /* Report that AppArmor fs is enabled */
726
+ info_message("AppArmor Filesystem Enabled");
730
+ destroy_apparmorfs();
731
+ AA_ERROR("Error creating AppArmor securityfs\n");
732
+ apparmor_disable();
736
+fs_initcall(create_apparmorfs);
739
+++ b/security/apparmor/inline.h
742
+ * Copyright (C) 1998-2007 Novell/SUSE
744
+ * This program is free software; you can redistribute it and/or
745
+ * modify it under the terms of the GNU General Public License as
746
+ * published by the Free Software Foundation, version 2 of the
753
+#include <linux/sched.h>
757
+static inline int mediated_filesystem(struct inode *inode)
759
+ return !(inode->i_sb->s_flags & MS_NOUSER);
762
+static inline struct aa_task_context *aa_task_context(struct task_struct *task)
764
+ return (struct aa_task_context *) rcu_dereference(task->security);
767
+static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
770
+ kref_get(&(ns->count));
775
+static inline void aa_put_namespace(struct aa_namespace *ns)
778
+ kref_put(&ns->count, free_aa_namespace_kref);
782
+static inline struct aa_namespace *aa_find_namespace(const char *name)
784
+ struct aa_namespace *ns = NULL;
786
+ read_lock(&profile_ns_list_lock);
787
+ ns = aa_get_namespace(__aa_find_namespace(name, &profile_ns_list));
788
+ read_unlock(&profile_ns_list_lock);
794
+ * aa_dup_profile - increment refcount on profile @p
797
+static inline struct aa_profile *aa_dup_profile(struct aa_profile *p)
800
+ kref_get(&(p->count));
806
+ * aa_put_profile - decrement refcount on profile @p
809
+static inline void aa_put_profile(struct aa_profile *p)
812
+ kref_put(&p->count, free_aa_profile_kref);
815
+static inline struct aa_profile *aa_get_profile(struct task_struct *task)
817
+ struct aa_task_context *cxt;
818
+ struct aa_profile *profile = NULL;
821
+ cxt = aa_task_context(task);
823
+ profile = cxt->profile;
824
+ aa_dup_profile(profile);
831
+static inline struct aa_profile *aa_find_profile(struct aa_namespace *ns,
834
+ struct aa_profile *profile = NULL;
836
+ read_lock(&ns->lock);
837
+ profile = aa_dup_profile(__aa_find_profile(name, &ns->profiles));
838
+ read_unlock(&ns->lock);
843
+static inline struct aa_task_context *aa_alloc_task_context(gfp_t flags)
845
+ struct aa_task_context *cxt;
847
+ cxt = kzalloc(sizeof(*cxt), flags);
849
+ INIT_LIST_HEAD(&cxt->list);
850
+ INIT_RCU_HEAD(&cxt->rcu);
856
+static inline void aa_free_task_context(struct aa_task_context *cxt)
859
+ aa_put_profile(cxt->profile);
860
+ aa_put_profile(cxt->previous_profile);
866
+ * lock_profile - lock a profile
867
+ * @profile: the profile to lock
869
+ * While the profile is locked, local interrupts are disabled. This also
870
+ * gives us RCU reader safety.
872
+static inline void lock_profile_nested(struct aa_profile *profile,
873
+ enum aa_lock_class lock_class)
876
+ * Lock the profile.
878
+ * Need to disable interrupts here because this lock is used in
879
+ * the task_free_security hook, which may run in RCU context.
882
+ spin_lock_irqsave_nested(&profile->lock, profile->int_flags,
886
+static inline void lock_profile(struct aa_profile *profile)
888
+ lock_profile_nested(profile, aa_lock_normal);
892
+ * unlock_profile - unlock a profile
893
+ * @profile: the profile to unlock
895
+static inline void unlock_profile(struct aa_profile *profile)
897
+ /* Unlock the profile. */
899
+ spin_unlock_irqrestore(&profile->lock, profile->int_flags);
903
+ * lock_both_profiles - lock two profiles in a deadlock-free way
904
+ * @profile1: profile to lock (may be NULL)
905
+ * @profile2: profile to lock (may be NULL)
907
+ * The order in which profiles are passed into lock_both_profiles() /
908
+ * unlock_both_profiles() does not matter.
909
+ * While the profile is locked, local interrupts are disabled. This also
910
+ * gives us RCU reader safety.
912
+static inline void lock_both_profiles(struct aa_profile *profile1,
913
+ struct aa_profile *profile2)
916
+ * Lock the two profiles.
918
+ * We need to disable interrupts because the profile locks are
919
+ * used in the task_free_security hook, which may run in RCU
922
+ * Do not nest spin_lock_irqsave()/spin_unlock_irqresore():
923
+ * interrupts only need to be turned off once.
925
+ if (!profile1 || profile1 == profile2) {
927
+ spin_lock_irqsave_nested(&profile2->lock,
928
+ profile2->int_flags,
930
+ } else if (profile1 > profile2) {
931
+ /* profile1 cannot be NULL here. */
932
+ spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags,
935
+ spin_lock_nested(&profile2->lock, aa_lock_nested);
938
+ /* profile2 cannot be NULL here. */
939
+ spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags,
941
+ spin_lock_nested(&profile1->lock, aa_lock_nested);
946
+ * unlock_both_profiles - unlock two profiles in a deadlock-free way
947
+ * @profile1: profile to unlock (may be NULL)
948
+ * @profile2: profile to unlock (may be NULL)
950
+ * The order in which profiles are passed into lock_both_profiles() /
951
+ * unlock_both_profiles() does not matter.
952
+ * While the profile is locked, local interrupts are disabled. This also
953
+ * gives us RCU reader safety.
955
+static inline void unlock_both_profiles(struct aa_profile *profile1,
956
+ struct aa_profile *profile2)
958
+ /* Unlock the two profiles. */
959
+ if (!profile1 || profile1 == profile2) {
961
+ spin_unlock_irqrestore(&profile2->lock,
962
+ profile2->int_flags);
963
+ } else if (profile1 > profile2) {
964
+ /* profile1 cannot be NULL here. */
966
+ spin_unlock(&profile2->lock);
967
+ spin_unlock_irqrestore(&profile1->lock, profile1->int_flags);
969
+ /* profile2 cannot be NULL here. */
970
+ spin_unlock(&profile1->lock);
971
+ spin_unlock_irqrestore(&profile2->lock, profile2->int_flags);
975
+static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname,
979
+ return aa_dfa_match(dfa, pathname, audit_mask);
985
+static inline int dfa_audit_mask(struct aa_dfa *dfa, unsigned int state)
987
+ return ACCEPT_TABLE2(dfa)[state];
990
+#endif /* __INLINE_H__ */
992
+++ b/security/apparmor/list.c
995
+ * Copyright (C) 1998-2007 Novell/SUSE
997
+ * This program is free software; you can redistribute it and/or
998
+ * modify it under the terms of the GNU General Public License as
999
+ * published by the Free Software Foundation, version 2 of the
1002
+ * AppArmor Profile List Management
1005
+#include <linux/seq_file.h>
1006
+#include "apparmor.h"
1007
+#include "inline.h"
1009
+/* list of profile namespaces and lock */
1010
+LIST_HEAD(profile_ns_list);
1011
+rwlock_t profile_ns_list_lock = RW_LOCK_UNLOCKED;
1014
+ * __aa_find_namespace - look up a profile namespace on the namespace list
1015
+ * @name: name of namespace to find
1016
+ * @head: list to search
1018
+ * Returns a pointer to the namespace on the list, or NULL if no namespace
1019
+ * called @name exists. The caller must hold the profile_ns_list_lock.
1021
+struct aa_namespace *__aa_find_namespace(const char *name,
1022
+ struct list_head *head)
1024
+ struct aa_namespace *ns;
1026
+ list_for_each_entry(ns, head, list) {
1027
+ if (!strcmp(ns->name, name))
1035
+ * __aa_find_profile - look up a profile on the profile list
1036
+ * @name: name of profile to find
1037
+ * @head: list to search
1039
+ * Returns a pointer to the profile on the list, or NULL if no profile
1040
+ * called @name exists. The caller must hold the profile_list_lock.
1042
+struct aa_profile *__aa_find_profile(const char *name, struct list_head *head)
1044
+ struct aa_profile *profile;
1046
+ list_for_each_entry(profile, head, list) {
1047
+ if (!strcmp(profile->name, name))
1054
+static void aa_profile_list_release(struct list_head *head)
1056
+ struct aa_profile *profile, *tmp;
1057
+ list_for_each_entry_safe(profile, tmp, head, list) {
1058
+ /* Remove the profile from each task context it is on. */
1059
+ lock_profile(profile);
1060
+ profile->isstale = 1;
1061
+ aa_unconfine_tasks(profile);
1062
+ list_del_init(&profile->list);
1063
+ unlock_profile(profile);
1064
+ aa_put_profile(profile);
1069
+ * aa_profilelist_release - Remove all profiles from profile_list
1071
+void aa_profile_ns_list_release(void)
1073
+ struct aa_namespace *ns, *tmp;
1075
+ /* Remove and release all the profiles on namespace profile lists. */
1076
+ write_lock(&profile_ns_list_lock);
1077
+ list_for_each_entry_safe(ns, tmp, &profile_ns_list, list) {
1078
+ write_lock(&ns->lock);
1079
+ aa_profile_list_release(&ns->profiles);
1080
+ list_del_init(&ns->list);
1081
+ write_unlock(&ns->lock);
1082
+ aa_put_namespace(ns);
1084
+ write_unlock(&profile_ns_list_lock);
1087
+static void *p_start(struct seq_file *f, loff_t *pos)
1089
+ struct aa_namespace *ns;
1090
+ struct aa_profile *profile;
1092
+ read_lock(&profile_ns_list_lock);
1095
+ list_for_each_entry(ns, &profile_ns_list, list) {
1096
+ read_lock(&ns->lock);
1097
+ list_for_each_entry(profile, &ns->profiles, list)
1099
+ read_unlock(&ns->lock);
1104
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
1106
+ struct aa_profile *profile = (struct aa_profile *) p;
1107
+ struct list_head *lh = profile->list.next;
1108
+ struct aa_namespace *ns;
1110
+ if (lh != &profile->ns->profiles)
1111
+ return list_entry(lh, struct aa_profile, list);
1113
+ lh = profile->ns->list.next;
1114
+ read_unlock(&profile->ns->lock);
1115
+ while (lh != &profile_ns_list) {
1116
+ ns = list_entry(lh, struct aa_namespace, list);
1117
+ read_lock(&ns->lock);
1118
+ list_for_each_entry(profile, &ns->profiles, list)
1120
+ read_unlock(&ns->lock);
1121
+ lh = ns->list.next;
1126
+static void p_stop(struct seq_file *f, void *v)
1128
+ read_unlock(&profile_ns_list_lock);
1131
+static int seq_show_profile(struct seq_file *f, void *v)
1133
+ struct aa_profile *profile = (struct aa_profile *)v;
1134
+ if (profile->ns == default_namespace)
1135
+ seq_printf(f, "%s (%s)\n", profile->name,
1136
+ PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
1138
+ seq_printf(f, ":%s:%s (%s)\n", profile->ns->name, profile->name,
1139
+ PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
1143
+/* Used in apparmorfs.c */
1144
+struct seq_operations apparmorfs_profiles_op = {
1148
+ .show = seq_show_profile,
1151
+++ b/security/apparmor/locking.txt
1153
+Locking in AppArmor
1154
+===================
1164
+Which lock protects what?
1166
+ /-----------------------+-------------------------------\
1167
+ | Variable | Lock |
1168
+ >-----------------------+-------------------------------<
1169
+ | profile_list | profile_list_lock |
1170
+ +-----------------------+-------------------------------+
1171
+ | aa_profile | (reference count) |
1172
+ +-----------------------+-------------------------------+
1173
+ | aa_profile-> | aa_profile->lock |
1175
+ | task_contexts | |
1176
+ +-----------------------+-------------------------------+
1177
+ | task_struct->security | read: RCU |
1178
+ | | write: task_lock() |
1179
+ +-----------------------+-------------------------------+
1180
+ | aa_profile->sub | handle on the profile (list |
1181
+ | | is never modified) |
1182
+ \-----------------------+-------------------------------/
1184
+(Obviously, the list_heads embedded in data structures are always
1185
+protected with the lock that also protects the list.)
1187
+When moving a task context from one profile to another, we grab both
1188
+profile locks with lock_both_profiles(). This ensures that both locks
1189
+are always taken in the same order, and so we won't deadlock.
1191
+Since task_struct->security is RCU protected the aa_task_struct it
1192
+references is only guarenteed to exist for the rcu cycle. Where
1193
+aa_task_context->profile is needed in blocking operations the
1194
+profile's reference count is incremented and the profile reference
1197
+Profiles on profile_list are never stale: when a profile becomes stale,
1198
+it is removed from profile_list at the same time (under profile_list_lock
1199
+and aa_profile->lock).
1201
+The aa_interface_lock is taken whenever user-space modifies the profile
1202
+list, and can sleep. This ensures that profile loading/replacement/removal
1203
+won't race with itself. We release the profile_list_lock as soon as
1204
+possible to avoid stalling exec during profile loading/replacement/removal.
1206
+AppArmor uses lock subtyping to avoid false positives from lockdep. The
1207
+profile lock is often taken nested, but it is guaranteed to be in a lock
1208
+safe order and not the same lock when done, so it is safe.
1210
+A third lock type (aa_lock_task_release) is given to the profile lock
1211
+when it is taken in soft irq context during task release (aa_release).
1212
+This is to avoid a false positive between the task lock and the profile
1213
+lock. In task context the profile lock wraps the task lock with irqs
1214
+off, but the kernel takes the task lock with irqs enabled. This won't
1215
+result in a deadlock because for a deadlock to occur the kernel must
1216
+take dead task A's lock (irqs on), the rcu callback hook freeing
1217
+dead task A must be run and AppArmor must be changing the profile on
1218
+dead task A. The kernel should not be taking a dead task's task_lock
1219
+at the same time the task is being freed by task rcu cleanup other wise
1220
+the task would not be out of its quiescent period.
1222
+++ b/security/apparmor/procattr.c
1225
+ * Copyright (C) 1998-2007 Novell/SUSE
1227
+ * This program is free software; you can redistribute it and/or
1228
+ * modify it under the terms of the GNU General Public License as
1229
+ * published by the Free Software Foundation, version 2 of the
1232
+ * AppArmor /proc/pid/attr handling
1235
+#include "apparmor.h"
1236
+#include "inline.h"
1238
+int aa_getprocattr(struct aa_profile *profile, char **string, unsigned *len)
1243
+ const char *mode_str = PROFILE_COMPLAIN(profile) ?
1244
+ " (complain)" : " (enforce)";
1245
+ int mode_len, name_len, ns_len = 0;
1247
+ mode_len = strlen(mode_str);
1248
+ name_len = strlen(profile->name);
1249
+ if (profile->ns != default_namespace)
1250
+ ns_len = strlen(profile->ns->name) + 2;
1251
+ *len = mode_len + ns_len + name_len + 1;
1252
+ str = kmalloc(*len, GFP_ATOMIC);
1258
+ memcpy(str, profile->ns->name, ns_len - 2);
1259
+ str += ns_len - 2;
1262
+ memcpy(str, profile->name, name_len);
1264
+ memcpy(str, mode_str, mode_len);
1269
+ const char *unconfined_str = "unconfined\n";
1271
+ *len = strlen(unconfined_str);
1272
+ str = kmalloc(*len, GFP_ATOMIC);
1276
+ memcpy(str, unconfined_str, *len);
1283
+static char *split_token_from_name(const char *op, char *args, u64 *cookie)
1287
+ *cookie = simple_strtoull(args, &name, 16);
1288
+ if ((name == args) || *name != '^') {
1289
+ AA_ERROR("%s: Invalid input '%s'", op, args);
1290
+ return ERR_PTR(-EINVAL);
1293
+ name++; /* skip ^ */
1299
+int aa_setprocattr_changehat(char *args)
1304
+ hat = split_token_from_name("change_hat", args, &cookie);
1306
+ return PTR_ERR(hat);
1308
+ if (!hat && !cookie) {
1309
+ AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
1313
+ AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
1314
+ __FUNCTION__, cookie, hat ? hat : NULL);
1316
+ return aa_change_hat(hat, cookie);
1319
+int aa_setprocattr_changeprofile(char *args)
1321
+ char *name = args, *ns_name = NULL;
1323
+ if (name[0] == ':') {
1324
+ char *split = strchr(&name[1], ':');
1327
+ ns_name = &name[1];
1332
+ return aa_change_profile(ns_name, name);
1335
+int aa_setprocattr_setprofile(struct task_struct *task, char *args)
1337
+ struct aa_profile *old_profile, *new_profile;
1338
+ struct aa_namespace *ns;
1339
+ struct aa_audit sa;
1340
+ char *name, *ns_name = NULL;
1342
+ memset(&sa, 0, sizeof(sa));
1343
+ sa.operation = "profile_set";
1344
+ sa.gfp_mask = GFP_KERNEL;
1345
+ sa.task = task->pid;
1347
+ AA_DEBUG("%s: current %d\n",
1348
+ __FUNCTION__, current->pid);
1351
+ if (args[0] != '/') {
1352
+ char *split = strchr(args, ':');
1360
+ ns = aa_find_namespace(ns_name);
1362
+ ns = aa_get_namespace(default_namespace);
1364
+ sa.name = ns_name;
1365
+ sa.info = "unknown namespace";
1366
+ aa_audit_reject(NULL, &sa);
1367
+ aa_put_namespace(ns);
1372
+ if (strcmp(name, "unconfined") == 0)
1373
+ new_profile = NULL;
1375
+ new_profile = aa_find_profile(ns, name);
1376
+ if (!new_profile) {
1377
+ sa.name = ns_name;
1379
+ sa.info = "unknown profile";
1380
+ aa_audit_reject(NULL, &sa);
1381
+ aa_put_namespace(ns);
1386
+ old_profile = __aa_replace_profile(task, new_profile);
1387
+ if (IS_ERR(old_profile)) {
1390
+ aa_put_profile(new_profile);
1391
+ error = PTR_ERR(old_profile);
1392
+ if (error == -ESTALE)
1394
+ aa_put_namespace(ns);
1398
+ if (new_profile) {
1399
+ sa.name = ns_name;
1401
+ sa.name3 = old_profile ? old_profile->name :
1403
+ aa_audit_status(NULL, &sa);
1405
+ if (old_profile) {
1406
+ sa.name = "unconfined";
1407
+ sa.name2 = old_profile->name;
1408
+ aa_audit_status(NULL, &sa);
1410
+ sa.info = "task is unconfined";
1411
+ aa_audit_status(NULL, &sa);
1414
+ aa_put_namespace(ns);
1415
+ aa_put_profile(old_profile);
1416
+ aa_put_profile(new_profile);