~apparmor-dev/apparmor/2_3

« back to all changes in this revision

Viewing changes to kernel-patches/for-mainline/apparmor-misc.diff

  • Committer: jrjohansen
  • Date: 2008-05-27 12:04:33 UTC
  • Revision ID: svn-v4:40609528-9d10-0410-9bd8-e926d5471da9:branches/2_3:1265
remove for-mainline dir from kernel patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
From: John Johansen <jjohansen@suse.de>
2
 
Subject: AppArmor: all the rest
3
 
 
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
8
 
access.
9
 
 
10
 
Signed-off-by: John Johansen <jjohansen@suse.de>
11
 
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
12
 
 
13
 
---
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(+)
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,367 @@
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
 
+/*
212
 
+ * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
213
 
+ * which is not related to profile accesses.
214
 
+ */
215
 
+
216
 
+#define AA_DEBUG(fmt, args...)                                         \
217
 
+       do {                                                            \
218
 
+               if (apparmor_debug)                                     \
219
 
+                       printk(KERN_DEBUG "AppArmor: " fmt, ##args);    \
220
 
+       } while (0)
221
 
+
222
 
+#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
223
 
+
224
 
+struct aa_profile;
225
 
+
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
234
 
+ */
235
 
+struct aa_namespace {
236
 
+       char *name;
237
 
+       struct list_head list;
238
 
+       struct list_head profiles;
239
 
+       int profile_count;
240
 
+       struct aa_profile *null_complain_profile;
241
 
+
242
 
+       struct kref count;
243
 
+       rwlock_t lock;
244
 
+};
245
 
+
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
264
 
+ *
265
 
+ * The AppArmor profile contains the basic confinement data.  Each profile
266
 
+ * has a name, and all nonstale profile are in a profile namespace.
267
 
+ *
268
 
+ * The task_contexts list and the isstale flag are protected by the
269
 
+ * profile lock.
270
 
+ *
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
273
 
+ * way.
274
 
+ */
275
 
+struct aa_profile {
276
 
+       char *name;
277
 
+       struct list_head list;
278
 
+       struct aa_namespace *ns;
279
 
+
280
 
+       int exec_table_size;
281
 
+       char **exec_table;
282
 
+       struct aa_dfa *file_rules;
283
 
+       struct {
284
 
+               int complain;
285
 
+               int audit;
286
 
+       } flags;
287
 
+       int isstale;
288
 
+
289
 
+       kernel_cap_t set_caps;
290
 
+       kernel_cap_t capabilities;
291
 
+       kernel_cap_t audit_caps;
292
 
+       kernel_cap_t quiet_caps;
293
 
+
294
 
+       struct kref count;
295
 
+       struct list_head task_contexts;
296
 
+       spinlock_t lock;
297
 
+       unsigned long int_flags;
298
 
+};
299
 
+
300
 
+extern struct list_head profile_ns_list;
301
 
+extern rwlock_t profile_ns_list_lock;
302
 
+extern struct mutex aa_interface_lock;
303
 
+
304
 
+/**
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
313
 
+ *
314
 
+ * Contains the task's current profile (which could change due to
315
 
+ * change_hat).  Plus the hat_magic needed during change_hat.
316
 
+ */
317
 
+struct aa_task_context {
318
 
+       struct aa_profile *profile;
319
 
+       struct aa_profile *previous_profile;
320
 
+       u64 cookie;
321
 
+       struct list_head list;
322
 
+       struct task_struct *task;
323
 
+       struct rcu_head rcu;
324
 
+       kernel_cap_t caps_logged;
325
 
+};
326
 
+
327
 
+extern struct aa_namespace *default_namespace;
328
 
+
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.
332
 
+ */
333
 
+
334
 
+struct aa_audit {
335
 
+       const char *operation;
336
 
+       gfp_t gfp_mask;
337
 
+       const char *info;
338
 
+       const char *name;
339
 
+       const char *name2;
340
 
+       const char *name3;
341
 
+       int request_mask, denied_mask, audit_mask;
342
 
+       struct iattr *iattr;
343
 
+       pid_t task, parent;
344
 
+       int error_code;
345
 
+};
346
 
+
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 */
350
 
+
351
 
+/* lock subtypes so lockdep does not raise false dependencies */
352
 
+enum aa_lock_class {
353
 
+       aa_lock_normal,
354
 
+       aa_lock_nested,
355
 
+       aa_lock_task_release
356
 
+};
357
 
+
358
 
+/* main.c */
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,
362
 
+                           int type);
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,
367
 
+                                 const char *);
368
 
+extern int aa_audit(struct aa_profile *profile, struct aa_audit *);
369
 
+
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,
378
 
+                  int check);
379
 
+extern int aa_perm_dir(struct aa_profile *profile, const char *operation,
380
 
+                      struct dentry *dentry, struct vfsmount *mnt,
381
 
+                      int mask);
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);
405
 
+
406
 
+/* lsm.c */
407
 
+extern int apparmor_initialized;
408
 
+extern void info_message(const char *str);
409
 
+extern void apparmor_disable(void);
410
 
+
411
 
+/* list.c */
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);
417
 
+
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);
429
 
+
430
 
+/* procattr.c */
431
 
+extern int aa_getprocattr(struct aa_profile *profile, char **string,
432
 
+                         unsigned *len);
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);
436
 
+
437
 
+/* apparmorfs.c */
438
 
+extern int create_apparmorfs(void);
439
 
+extern void destroy_apparmorfs(void);
440
 
+
441
 
+/* match.c */
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,
448
 
+                                     const char *str);
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);
453
 
+
454
 
+#endif  /* __APPARMOR_H */
455
 
--- /dev/null
456
 
+++ b/security/apparmor/apparmorfs.c
457
 
@@ -0,0 +1,280 @@
458
 
+/*
459
 
+ *     Copyright (C) 1998-2007 Novell/SUSE
460
 
+ *
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
464
 
+ *     License.
465
 
+ *
466
 
+ *     AppArmor filesystem (part of securityfs)
467
 
+ */
468
 
+
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>
474
 
+
475
 
+#include "apparmor.h"
476
 
+#include "inline.h"
477
 
+
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)
481
 
+{
482
 
+       struct aa_profile *profile;
483
 
+       char *data;
484
 
+
485
 
+       if (*pos != 0) {
486
 
+               /* only writes from pos 0, that is complete writes */
487
 
+               data = ERR_PTR(-ESPIPE);
488
 
+               goto out;
489
 
+       }
490
 
+
491
 
+       /*
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.
495
 
+        */
496
 
+       profile = aa_get_profile(current);
497
 
+       if (profile) {
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);
505
 
+               goto out;
506
 
+       }
507
 
+
508
 
+       data = vmalloc(alloc_size);
509
 
+       if (data == NULL) {
510
 
+               data = ERR_PTR(-ENOMEM);
511
 
+               goto out;
512
 
+       }
513
 
+
514
 
+       if (copy_from_user(data, userbuf, copy_size)) {
515
 
+               vfree(data);
516
 
+               data = ERR_PTR(-EFAULT);
517
 
+               goto out;
518
 
+       }
519
 
+
520
 
+out:
521
 
+       return data;
522
 
+}
523
 
+
524
 
+/* apparmor/profiles */
525
 
+extern struct seq_operations apparmorfs_profiles_op;
526
 
+
527
 
+static int aa_profiles_open(struct inode *inode, struct file *file)
528
 
+{
529
 
+       return seq_open(file, &apparmorfs_profiles_op);
530
 
+}
531
 
+
532
 
+
533
 
+static int aa_profiles_release(struct inode *inode, struct file *file)
534
 
+{
535
 
+       return seq_release(inode, file);
536
 
+}
537
 
+
538
 
+static struct file_operations apparmorfs_profiles_fops = {
539
 
+       .open =         aa_profiles_open,
540
 
+       .read =         seq_read,
541
 
+       .llseek =       seq_lseek,
542
 
+       .release =      aa_profiles_release,
543
 
+};
544
 
+
545
 
+/* apparmor/matching */
546
 
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
547
 
+                              size_t size, loff_t *ppos)
548
 
+{
549
 
+       const char *matching = "pattern=aadfa audit perms=rwxamlk/ user::other";
550
 
+
551
 
+       return simple_read_from_buffer(buf, size, ppos, matching,
552
 
+                                      strlen(matching));
553
 
+}
554
 
+
555
 
+static struct file_operations apparmorfs_matching_fops = {
556
 
+       .read =         aa_matching_read,
557
 
+};
558
 
+
559
 
+/* apparmor/features */
560
 
+static ssize_t aa_features_read(struct file *file, char __user *buf,
561
 
+                               size_t size, loff_t *ppos)
562
 
+{
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";
566
 
+
567
 
+       return simple_read_from_buffer(buf, size, ppos, features,
568
 
+                                      strlen(features));
569
 
+}
570
 
+
571
 
+static struct file_operations apparmorfs_features_fops = {
572
 
+       .read =         aa_features_read,
573
 
+};
574
 
+
575
 
+/* apparmor/.load */
576
 
+static ssize_t aa_profile_load(struct file *f, const char __user *buf,
577
 
+                              size_t size, loff_t *pos)
578
 
+{
579
 
+       char *data;
580
 
+       ssize_t error;
581
 
+
582
 
+       data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
583
 
+
584
 
+       error = PTR_ERR(data);
585
 
+       if (!IS_ERR(data)) {
586
 
+               error = aa_add_profile(data, size);
587
 
+               vfree(data);
588
 
+       }
589
 
+
590
 
+       return error;
591
 
+}
592
 
+
593
 
+
594
 
+static struct file_operations apparmorfs_profile_load = {
595
 
+       .write = aa_profile_load
596
 
+};
597
 
+
598
 
+/* apparmor/.replace */
599
 
+static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
600
 
+                                 size_t size, loff_t *pos)
601
 
+{
602
 
+       char *data;
603
 
+       ssize_t error;
604
 
+
605
 
+       data = aa_simple_write_to_buffer(buf, size, size, pos,
606
 
+                                        "profile_replace");
607
 
+
608
 
+       error = PTR_ERR(data);
609
 
+       if (!IS_ERR(data)) {
610
 
+               error = aa_replace_profile(data, size);
611
 
+               vfree(data);
612
 
+       }
613
 
+
614
 
+       return error;
615
 
+}
616
 
+
617
 
+
618
 
+static struct file_operations apparmorfs_profile_replace = {
619
 
+       .write = aa_profile_replace
620
 
+};
621
 
+
622
 
+/* apparmor/.remove */
623
 
+static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
624
 
+                                 size_t size, loff_t *pos)
625
 
+{
626
 
+       char *data;
627
 
+       ssize_t error;
628
 
+
629
 
+       /*
630
 
+        * aa_remove_profile needs a null terminated string so 1 extra
631
 
+        * byte is allocated and the copied data is null terminated.
632
 
+        */
633
 
+       data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
634
 
+                                        "profile_remove");
635
 
+
636
 
+       error = PTR_ERR(data);
637
 
+       if (!IS_ERR(data)) {
638
 
+               data[size] = 0;
639
 
+               error = aa_remove_profile(data, size);
640
 
+               vfree(data);
641
 
+       }
642
 
+
643
 
+       return error;
644
 
+}
645
 
+
646
 
+static struct file_operations apparmorfs_profile_remove = {
647
 
+       .write = aa_profile_remove
648
 
+};
649
 
+
650
 
+static struct dentry *apparmor_dentry;
651
 
+
652
 
+static void aafs_remove(const char *name)
653
 
+{
654
 
+       struct dentry *dentry;
655
 
+
656
 
+       dentry = lookup_one_len(name, apparmor_dentry, strlen(name));
657
 
+       if (!IS_ERR(dentry)) {
658
 
+               securityfs_remove(dentry);
659
 
+               dput(dentry);
660
 
+       }
661
 
+}
662
 
+
663
 
+static int aafs_create(const char *name, int mask, struct file_operations *fops)
664
 
+{
665
 
+       struct dentry *dentry;
666
 
+
667
 
+       dentry = securityfs_create_file(name, S_IFREG | mask, apparmor_dentry,
668
 
+                                       NULL, fops);
669
 
+
670
 
+       return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
671
 
+}
672
 
+
673
 
+void destroy_apparmorfs(void)
674
 
+{
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;
684
 
+       }
685
 
+}
686
 
+
687
 
+int create_apparmorfs(void)
688
 
+{
689
 
+       int error;
690
 
+
691
 
+       if (!apparmor_initialized)
692
 
+               return 0;
693
 
+
694
 
+       if (apparmor_dentry) {
695
 
+               AA_ERROR("%s: AppArmor securityfs already exists\n",
696
 
+                       __FUNCTION__);
697
 
+               return -EEXIST;
698
 
+       }
699
 
+
700
 
+       apparmor_dentry = securityfs_create_dir("apparmor", NULL);
701
 
+       if (IS_ERR(apparmor_dentry)) {
702
 
+               error = PTR_ERR(apparmor_dentry);
703
 
+               apparmor_dentry = NULL;
704
 
+               goto error;
705
 
+       }
706
 
+       error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
707
 
+       if (error)
708
 
+               goto error;
709
 
+       error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
710
 
+       if (error)
711
 
+               goto error;
712
 
+       error = aafs_create("features", 0444, &apparmorfs_features_fops);
713
 
+       if (error)
714
 
+               goto error;
715
 
+       error = aafs_create(".load", 0640, &apparmorfs_profile_load);
716
 
+       if (error)
717
 
+               goto error;
718
 
+       error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
719
 
+       if (error)
720
 
+               goto error;
721
 
+       error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
722
 
+       if (error)
723
 
+               goto error;
724
 
+
725
 
+       /* Report that AppArmor fs is enabled */
726
 
+       info_message("AppArmor Filesystem Enabled");
727
 
+       return 0;
728
 
+
729
 
+error:
730
 
+       destroy_apparmorfs();
731
 
+       AA_ERROR("Error creating AppArmor securityfs\n");
732
 
+       apparmor_disable();
733
 
+       return error;
734
 
+}
735
 
+
736
 
+fs_initcall(create_apparmorfs);
737
 
+
738
 
--- /dev/null
739
 
+++ b/security/apparmor/inline.h
740
 
@@ -0,0 +1,250 @@
741
 
+/*
742
 
+ *     Copyright (C) 1998-2007 Novell/SUSE
743
 
+ *
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
747
 
+ *     License.
748
 
+ */
749
 
+
750
 
+#ifndef __INLINE_H
751
 
+#define __INLINE_H
752
 
+
753
 
+#include <linux/sched.h>
754
 
+
755
 
+#include "match.h"
756
 
+
757
 
+static inline int mediated_filesystem(struct inode *inode)
758
 
+{
759
 
+       return !(inode->i_sb->s_flags & MS_NOUSER);
760
 
+}
761
 
+
762
 
+static inline struct aa_task_context *aa_task_context(struct task_struct *task)
763
 
+{
764
 
+       return (struct aa_task_context *) rcu_dereference(task->security);
765
 
+}
766
 
+
767
 
+static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
768
 
+{
769
 
+       if (ns)
770
 
+               kref_get(&(ns->count));
771
 
+
772
 
+       return ns;
773
 
+}
774
 
+
775
 
+static inline void aa_put_namespace(struct aa_namespace *ns)
776
 
+{
777
 
+       if (ns)
778
 
+               kref_put(&ns->count, free_aa_namespace_kref);
779
 
+}
780
 
+
781
 
+
782
 
+static inline struct aa_namespace *aa_find_namespace(const char *name)
783
 
+{
784
 
+       struct aa_namespace *ns = NULL;
785
 
+
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);
789
 
+
790
 
+       return ns;
791
 
+}
792
 
+
793
 
+/**
794
 
+ * aa_dup_profile - increment refcount on profile @p
795
 
+ * @p: profile
796
 
+ */
797
 
+static inline struct aa_profile *aa_dup_profile(struct aa_profile *p)
798
 
+{
799
 
+       if (p)
800
 
+               kref_get(&(p->count));
801
 
+
802
 
+       return p;
803
 
+}
804
 
+
805
 
+/**
806
 
+ * aa_put_profile - decrement refcount on profile @p
807
 
+ * @p: profile
808
 
+ */
809
 
+static inline void aa_put_profile(struct aa_profile *p)
810
 
+{
811
 
+       if (p)
812
 
+               kref_put(&p->count, free_aa_profile_kref);
813
 
+}
814
 
+
815
 
+static inline struct aa_profile *aa_get_profile(struct task_struct *task)
816
 
+{
817
 
+       struct aa_task_context *cxt;
818
 
+       struct aa_profile *profile = NULL;
819
 
+
820
 
+       rcu_read_lock();
821
 
+       cxt = aa_task_context(task);
822
 
+       if (cxt) {
823
 
+               profile = cxt->profile;
824
 
+               aa_dup_profile(profile);
825
 
+       }
826
 
+       rcu_read_unlock();
827
 
+
828
 
+       return profile;
829
 
+}
830
 
+
831
 
+static inline struct aa_profile *aa_find_profile(struct aa_namespace *ns,
832
 
+                                                const char *name)
833
 
+{
834
 
+       struct aa_profile *profile = NULL;
835
 
+
836
 
+       read_lock(&ns->lock);
837
 
+       profile = aa_dup_profile(__aa_find_profile(name, &ns->profiles));
838
 
+       read_unlock(&ns->lock);
839
 
+
840
 
+       return profile;
841
 
+}
842
 
+
843
 
+static inline struct aa_task_context *aa_alloc_task_context(gfp_t flags)
844
 
+{
845
 
+       struct aa_task_context *cxt;
846
 
+
847
 
+       cxt = kzalloc(sizeof(*cxt), flags);
848
 
+       if (cxt) {
849
 
+               INIT_LIST_HEAD(&cxt->list);
850
 
+               INIT_RCU_HEAD(&cxt->rcu);
851
 
+       }
852
 
+
853
 
+       return cxt;
854
 
+}
855
 
+
856
 
+static inline void aa_free_task_context(struct aa_task_context *cxt)
857
 
+{
858
 
+       if (cxt) {
859
 
+               aa_put_profile(cxt->profile);
860
 
+               aa_put_profile(cxt->previous_profile);
861
 
+               kfree(cxt);
862
 
+       }
863
 
+}
864
 
+
865
 
+/**
866
 
+ * lock_profile - lock a profile
867
 
+ * @profile: the profile to lock
868
 
+ *
869
 
+ * While the profile is locked, local interrupts are disabled. This also
870
 
+ * gives us RCU reader safety.
871
 
+ */
872
 
+static inline void lock_profile_nested(struct aa_profile *profile,
873
 
+                                      enum aa_lock_class lock_class)
874
 
+{
875
 
+       /*
876
 
+        * Lock the profile.
877
 
+        *
878
 
+        * Need to disable interrupts here because this lock is used in
879
 
+        * the task_free_security hook, which may run in RCU context.
880
 
+        */
881
 
+       if (profile)
882
 
+               spin_lock_irqsave_nested(&profile->lock, profile->int_flags,
883
 
+                                        lock_class);
884
 
+}
885
 
+
886
 
+static inline void lock_profile(struct aa_profile *profile)
887
 
+{
888
 
+       lock_profile_nested(profile, aa_lock_normal);
889
 
+}
890
 
+
891
 
+/**
892
 
+ * unlock_profile - unlock a profile
893
 
+ * @profile: the profile to unlock
894
 
+ */
895
 
+static inline void unlock_profile(struct aa_profile *profile)
896
 
+{
897
 
+       /* Unlock the profile. */
898
 
+       if (profile)
899
 
+               spin_unlock_irqrestore(&profile->lock, profile->int_flags);
900
 
+}
901
 
+
902
 
+/**
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)
906
 
+ *
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.
911
 
+ */
912
 
+static inline void lock_both_profiles(struct aa_profile *profile1,
913
 
+                                     struct aa_profile *profile2)
914
 
+{
915
 
+       /*
916
 
+        * Lock the two profiles.
917
 
+        *
918
 
+        * We need to disable interrupts because the profile locks are
919
 
+        * used in the task_free_security hook, which may run in RCU
920
 
+        * context.
921
 
+        *
922
 
+        * Do not nest spin_lock_irqsave()/spin_unlock_irqresore():
923
 
+        * interrupts only need to be turned off once.
924
 
+        */
925
 
+       if (!profile1 || profile1 == profile2) {
926
 
+               if (profile2)
927
 
+                       spin_lock_irqsave_nested(&profile2->lock,
928
 
+                                                profile2->int_flags,
929
 
+                                                aa_lock_normal);
930
 
+       } else if (profile1 > profile2) {
931
 
+               /* profile1 cannot be NULL here. */
932
 
+               spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags,
933
 
+                                        aa_lock_normal);
934
 
+               if (profile2)
935
 
+                       spin_lock_nested(&profile2->lock, aa_lock_nested);
936
 
+
937
 
+       } else {
938
 
+               /* profile2 cannot be NULL here. */
939
 
+               spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags,
940
 
+                                        aa_lock_normal);
941
 
+               spin_lock_nested(&profile1->lock, aa_lock_nested);
942
 
+       }
943
 
+}
944
 
+
945
 
+/**
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)
949
 
+ *
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.
954
 
+ */
955
 
+static inline void unlock_both_profiles(struct aa_profile *profile1,
956
 
+                                       struct aa_profile *profile2)
957
 
+{
958
 
+       /* Unlock the two profiles. */
959
 
+       if (!profile1 || profile1 == profile2) {
960
 
+               if (profile2)
961
 
+                       spin_unlock_irqrestore(&profile2->lock,
962
 
+                                              profile2->int_flags);
963
 
+       } else if (profile1 > profile2) {
964
 
+               /* profile1 cannot be NULL here. */
965
 
+               if (profile2)
966
 
+                       spin_unlock(&profile2->lock);
967
 
+               spin_unlock_irqrestore(&profile1->lock, profile1->int_flags);
968
 
+       } else {
969
 
+               /* profile2 cannot be NULL here. */
970
 
+               spin_unlock(&profile1->lock);
971
 
+               spin_unlock_irqrestore(&profile2->lock, profile2->int_flags);
972
 
+       }
973
 
+}
974
 
+
975
 
+static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname,
976
 
+                                   int *audit_mask)
977
 
+{
978
 
+       if (dfa)
979
 
+               return aa_dfa_match(dfa, pathname, audit_mask);
980
 
+       if (audit_mask)
981
 
+               *audit_mask = 0;
982
 
+       return 0;
983
 
+}
984
 
+
985
 
+static inline int dfa_audit_mask(struct aa_dfa *dfa, unsigned int state)
986
 
+{
987
 
+       return  ACCEPT_TABLE2(dfa)[state];
988
 
+}
989
 
+
990
 
+#endif /* __INLINE_H__ */
991
 
--- /dev/null
992
 
+++ b/security/apparmor/list.c
993
 
@@ -0,0 +1,156 @@
994
 
+/*
995
 
+ *     Copyright (C) 1998-2007 Novell/SUSE
996
 
+ *
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
1000
 
+ *     License.
1001
 
+ *
1002
 
+ *     AppArmor Profile List Management
1003
 
+ */
1004
 
+
1005
 
+#include <linux/seq_file.h>
1006
 
+#include "apparmor.h"
1007
 
+#include "inline.h"
1008
 
+
1009
 
+/* list of profile namespaces and lock */
1010
 
+LIST_HEAD(profile_ns_list);
1011
 
+rwlock_t profile_ns_list_lock = RW_LOCK_UNLOCKED;
1012
 
+
1013
 
+/**
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
1017
 
+ *
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.
1020
 
+ */
1021
 
+struct aa_namespace *__aa_find_namespace(const char *name,
1022
 
+                                      struct list_head *head)
1023
 
+{
1024
 
+       struct aa_namespace *ns;
1025
 
+
1026
 
+       list_for_each_entry(ns, head, list) {
1027
 
+               if (!strcmp(ns->name, name))
1028
 
+                       return ns;
1029
 
+       }
1030
 
+
1031
 
+       return NULL;
1032
 
+}
1033
 
+
1034
 
+/**
1035
 
+ * __aa_find_profile  -  look up a profile on the profile list
1036
 
+ * @name: name of profile to find
1037
 
+ * @head: list to search
1038
 
+ *
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.
1041
 
+ */
1042
 
+struct aa_profile *__aa_find_profile(const char *name, struct list_head *head)
1043
 
+{
1044
 
+       struct aa_profile *profile;
1045
 
+
1046
 
+       list_for_each_entry(profile, head, list) {
1047
 
+               if (!strcmp(profile->name, name))
1048
 
+                       return profile;
1049
 
+       }
1050
 
+
1051
 
+       return NULL;
1052
 
+}
1053
 
+
1054
 
+static void aa_profile_list_release(struct list_head *head)
1055
 
+{
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);
1065
 
+       }
1066
 
+}
1067
 
+
1068
 
+/**
1069
 
+ * aa_profilelist_release - Remove all profiles from profile_list
1070
 
+ */
1071
 
+void aa_profile_ns_list_release(void)
1072
 
+{
1073
 
+       struct aa_namespace *ns, *tmp;
1074
 
+
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);
1083
 
+       }
1084
 
+       write_unlock(&profile_ns_list_lock);
1085
 
+}
1086
 
+
1087
 
+static void *p_start(struct seq_file *f, loff_t *pos)
1088
 
+{
1089
 
+       struct aa_namespace *ns;
1090
 
+       struct aa_profile *profile;
1091
 
+       loff_t l = *pos;
1092
 
+       read_lock(&profile_ns_list_lock);
1093
 
+       if (l--)
1094
 
+               return NULL;
1095
 
+       list_for_each_entry(ns, &profile_ns_list, list) {
1096
 
+               read_lock(&ns->lock);
1097
 
+               list_for_each_entry(profile, &ns->profiles, list)
1098
 
+                       return profile;
1099
 
+               read_unlock(&ns->lock);
1100
 
+       }
1101
 
+       return NULL;
1102
 
+}
1103
 
+
1104
 
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
1105
 
+{
1106
 
+       struct aa_profile *profile = (struct aa_profile *) p;
1107
 
+       struct list_head *lh = profile->list.next;
1108
 
+       struct aa_namespace *ns;
1109
 
+       (*pos)++;
1110
 
+       if (lh != &profile->ns->profiles)
1111
 
+               return list_entry(lh, struct aa_profile, list);
1112
 
+
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)
1119
 
+                       return profile;
1120
 
+               read_unlock(&ns->lock);
1121
 
+               lh = ns->list.next;
1122
 
+       }
1123
 
+       return NULL;
1124
 
+}
1125
 
+
1126
 
+static void p_stop(struct seq_file *f, void *v)
1127
 
+{
1128
 
+       read_unlock(&profile_ns_list_lock);
1129
 
+}
1130
 
+
1131
 
+static int seq_show_profile(struct seq_file *f, void *v)
1132
 
+{
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");
1137
 
+       else
1138
 
+           seq_printf(f, ":%s:%s (%s)\n", profile->ns->name, profile->name,
1139
 
+                      PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
1140
 
+       return 0;
1141
 
+}
1142
 
+
1143
 
+/* Used in apparmorfs.c */
1144
 
+struct seq_operations apparmorfs_profiles_op = {
1145
 
+       .start =        p_start,
1146
 
+       .next =         p_next,
1147
 
+       .stop =         p_stop,
1148
 
+       .show =         seq_show_profile,
1149
 
+};
1150
 
--- /dev/null
1151
 
+++ b/security/apparmor/locking.txt
1152
 
@@ -0,0 +1,68 @@
1153
 
+Locking in AppArmor
1154
 
+===================
1155
 
+
1156
 
+Lock hierarchy:
1157
 
+
1158
 
+       aa_interface_lock
1159
 
+         profile_list_lock
1160
 
+           aa_profile->lock
1161
 
+             task_lock()
1162
 
+
1163
 
+
1164
 
+Which lock protects what?
1165
 
+
1166
 
+       /-----------------------+-------------------------------\
1167
 
+       | Variable              | Lock                          |
1168
 
+       >-----------------------+-------------------------------<
1169
 
+       | profile_list          | profile_list_lock             |
1170
 
+       +-----------------------+-------------------------------+
1171
 
+       | aa_profile            | (reference count)             |
1172
 
+       +-----------------------+-------------------------------+
1173
 
+       | aa_profile->          | aa_profile->lock              |
1174
 
+       |   isstale,            |                               |
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
 
+       \-----------------------+-------------------------------/
1183
 
+
1184
 
+(Obviously, the list_heads embedded in data structures are always
1185
 
+protected with the lock that also protects the list.)
1186
 
+
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.
1190
 
+
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
1195
 
+is used.
1196
 
+
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).
1200
 
+
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.
1205
 
+
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.
1209
 
+
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.
1221
 
--- /dev/null
1222
 
+++ b/security/apparmor/procattr.c
1223
 
@@ -0,0 +1,195 @@
1224
 
+/*
1225
 
+ *     Copyright (C) 1998-2007 Novell/SUSE
1226
 
+ *
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
1230
 
+ *     License.
1231
 
+ *
1232
 
+ *     AppArmor /proc/pid/attr handling
1233
 
+ */
1234
 
+
1235
 
+#include "apparmor.h"
1236
 
+#include "inline.h"
1237
 
+
1238
 
+int aa_getprocattr(struct aa_profile *profile, char **string, unsigned *len)
1239
 
+{
1240
 
+       char *str;
1241
 
+
1242
 
+       if (profile) {
1243
 
+               const char *mode_str = PROFILE_COMPLAIN(profile) ?
1244
 
+                       " (complain)" : " (enforce)";
1245
 
+               int mode_len, name_len, ns_len = 0;
1246
 
+
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);
1253
 
+               if (!str)
1254
 
+                       return -ENOMEM;
1255
 
+
1256
 
+               if (ns_len) {
1257
 
+                       *str++ = ':';
1258
 
+                       memcpy(str, profile->ns->name, ns_len - 2);
1259
 
+                       str += ns_len - 2;
1260
 
+                       *str++ = ':';
1261
 
+               }
1262
 
+               memcpy(str, profile->name, name_len);
1263
 
+               str += name_len;
1264
 
+               memcpy(str, mode_str, mode_len);
1265
 
+               str += mode_len;
1266
 
+               *str++ = '\n';
1267
 
+               str -= *len;
1268
 
+       } else {
1269
 
+               const char *unconfined_str = "unconfined\n";
1270
 
+
1271
 
+               *len = strlen(unconfined_str);
1272
 
+               str = kmalloc(*len, GFP_ATOMIC);
1273
 
+               if (!str)
1274
 
+                       return -ENOMEM;
1275
 
+
1276
 
+               memcpy(str, unconfined_str, *len);
1277
 
+       }
1278
 
+       *string = str;
1279
 
+
1280
 
+       return 0;
1281
 
+}
1282
 
+
1283
 
+static char *split_token_from_name(const char *op, char *args, u64 *cookie)
1284
 
+{
1285
 
+       char *name;
1286
 
+
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);
1291
 
+       }
1292
 
+
1293
 
+       name++;  /* skip ^ */
1294
 
+       if (!*name)
1295
 
+               name = NULL;
1296
 
+       return name;
1297
 
+}
1298
 
+
1299
 
+int aa_setprocattr_changehat(char *args)
1300
 
+{
1301
 
+       char *hat;
1302
 
+       u64 cookie;
1303
 
+
1304
 
+       hat = split_token_from_name("change_hat", args, &cookie);
1305
 
+       if (IS_ERR(hat))
1306
 
+               return PTR_ERR(hat);
1307
 
+
1308
 
+       if (!hat && !cookie) {
1309
 
+               AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
1310
 
+               return -EINVAL;
1311
 
+       }
1312
 
+
1313
 
+       AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
1314
 
+                __FUNCTION__, cookie, hat ? hat : NULL);
1315
 
+
1316
 
+       return aa_change_hat(hat, cookie);
1317
 
+}
1318
 
+
1319
 
+int aa_setprocattr_changeprofile(char *args)
1320
 
+{
1321
 
+       char *name = args, *ns_name = NULL;
1322
 
+
1323
 
+       if (name[0] == ':') {
1324
 
+               char *split = strchr(&name[1], ':');
1325
 
+               if (split) {
1326
 
+                       *split = 0;
1327
 
+                       ns_name = &name[1];
1328
 
+                       name = split + 1;
1329
 
+               }
1330
 
+       }
1331
 
+
1332
 
+       return aa_change_profile(ns_name, name);
1333
 
+}
1334
 
+
1335
 
+int aa_setprocattr_setprofile(struct task_struct *task, char *args)
1336
 
+{
1337
 
+       struct aa_profile *old_profile, *new_profile;
1338
 
+       struct aa_namespace *ns;
1339
 
+       struct aa_audit sa;
1340
 
+       char *name, *ns_name = NULL;
1341
 
+
1342
 
+       memset(&sa, 0, sizeof(sa));
1343
 
+       sa.operation = "profile_set";
1344
 
+       sa.gfp_mask = GFP_KERNEL;
1345
 
+       sa.task = task->pid;
1346
 
+
1347
 
+       AA_DEBUG("%s: current %d\n",
1348
 
+                __FUNCTION__, current->pid);
1349
 
+
1350
 
+       name = args;
1351
 
+       if (args[0] != '/') {
1352
 
+               char *split = strchr(args, ':');
1353
 
+               if (split) {
1354
 
+                       *split = 0;
1355
 
+                       ns_name = args;
1356
 
+                       name = split + 1;
1357
 
+               }
1358
 
+       }
1359
 
+       if (ns_name)
1360
 
+               ns = aa_find_namespace(ns_name);
1361
 
+       else
1362
 
+               ns = aa_get_namespace(default_namespace);
1363
 
+       if (!ns) {
1364
 
+               sa.name = ns_name;
1365
 
+               sa.info = "unknown namespace";
1366
 
+               aa_audit_reject(NULL, &sa);
1367
 
+               aa_put_namespace(ns);
1368
 
+               return -EINVAL;
1369
 
+       }
1370
 
+
1371
 
+repeat:
1372
 
+       if (strcmp(name, "unconfined") == 0)
1373
 
+               new_profile = NULL;
1374
 
+       else {
1375
 
+               new_profile = aa_find_profile(ns, name);
1376
 
+               if (!new_profile) {
1377
 
+                       sa.name = ns_name;
1378
 
+                       sa.name2 = name;
1379
 
+                       sa.info = "unknown profile";
1380
 
+                       aa_audit_reject(NULL, &sa);
1381
 
+                       aa_put_namespace(ns);
1382
 
+                       return -EINVAL;
1383
 
+               }
1384
 
+       }
1385
 
+
1386
 
+       old_profile = __aa_replace_profile(task, new_profile);
1387
 
+       if (IS_ERR(old_profile)) {
1388
 
+               int error;
1389
 
+
1390
 
+               aa_put_profile(new_profile);
1391
 
+               error = PTR_ERR(old_profile);
1392
 
+               if (error == -ESTALE)
1393
 
+                       goto repeat;
1394
 
+               aa_put_namespace(ns);
1395
 
+               return error;
1396
 
+       }
1397
 
+
1398
 
+       if (new_profile) {
1399
 
+               sa.name = ns_name;
1400
 
+               sa.name2 = name;
1401
 
+               sa.name3 = old_profile ? old_profile->name :
1402
 
+                       "unconfined";
1403
 
+               aa_audit_status(NULL, &sa);
1404
 
+       } else {
1405
 
+               if (old_profile) {
1406
 
+                       sa.name = "unconfined";
1407
 
+                       sa.name2 = old_profile->name;
1408
 
+                       aa_audit_status(NULL, &sa);
1409
 
+               } else {
1410
 
+                       sa.info = "task is unconfined";
1411
 
+                       aa_audit_status(NULL, &sa);
1412
 
+               }
1413
 
+       }
1414
 
+       aa_put_namespace(ns);
1415
 
+       aa_put_profile(old_profile);
1416
 
+       aa_put_profile(new_profile);
1417
 
+       return 0;
1418
 
+}