]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-apparmor.patch
-started update to 2.6.30; patches apply when using --without grsecurity
[packages/kernel.git] / kernel-apparmor.patch
1 diff --git a/include/linux/audit.h b/include/linux/audit.h
2 index 4fa2810..9f87073 100644
3 --- a/include/linux/audit.h
4 +++ b/include/linux/audit.h
5 @@ -33,7 +33,7 @@
6   * 1200 - 1299 messages internal to the audit daemon
7   * 1300 - 1399 audit event messages
8   * 1400 - 1499 SE Linux use
9 - * 1500 - 1599 kernel LSPP events
10 + * 1500 - 1599 AppArmor use
11   * 1600 - 1699 kernel crypto events
12   * 1700 - 1799 kernel anomaly records
13   * 1800 - 1899 kernel integrity events
14 @@ -122,6 +122,14 @@
15  #define AUDIT_MAC_UNLBL_STCADD 1416    /* NetLabel: add a static label */
16  #define AUDIT_MAC_UNLBL_STCDEL 1417    /* NetLabel: del a static label */
17  
18 +#define AUDIT_APPARMOR_AUDIT   1501    /* AppArmor audited grants */
19 +#define AUDIT_APPARMOR_ALLOWED 1502    /* Allowed Access for learning */
20 +#define AUDIT_APPARMOR_DENIED  1503
21 +#define AUDIT_APPARMOR_HINT    1504    /* Process Tracking information */
22 +#define AUDIT_APPARMOR_STATUS  1505    /* Changes in config */
23 +#define AUDIT_APPARMOR_ERROR   1506    /* Internal AppArmor Errors */
24 +#define AUDIT_APPARMOR_KILL    1507    /* AppArmor killing processes */
25 +
26  #define AUDIT_FIRST_KERN_ANOM_MSG   1700
27  #define AUDIT_LAST_KERN_ANOM_MSG    1799
28  #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
29 diff --git a/security/Kconfig b/security/Kconfig
30 index bb24477..f3db74c 100644
31 --- a/security/Kconfig
32 +++ b/security/Kconfig
33 @@ -136,6 +136,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
34  source security/selinux/Kconfig
35  source security/smack/Kconfig
36  source security/tomoyo/Kconfig
37 +source security/apparmor/Kconfig
38  
39  source security/integrity/ima/Kconfig
40  
41 diff --git a/security/Makefile b/security/Makefile
42 index fa77021..60aa7c5 100644
43 --- a/security/Makefile
44 +++ b/security/Makefile
45 @@ -6,6 +6,7 @@ obj-$(CONFIG_KEYS)                      += keys/
46  subdir-$(CONFIG_SECURITY_SELINUX)      += selinux
47  subdir-$(CONFIG_SECURITY_SMACK)                += smack
48  subdir-$(CONFIG_SECURITY_TOMOYO)        += tomoyo
49 +subdir-$(CONFIG_SECURITY_APPARMOR)        += apparmor
50  
51  # always enable default capabilities
52  obj-y          += commoncap.o
53 @@ -17,6 +18,7 @@ obj-$(CONFIG_SECURITYFS)              += inode.o
54  obj-$(CONFIG_SECURITY_SELINUX)         += selinux/built-in.o
55  obj-$(CONFIG_SECURITY_SMACK)           += smack/built-in.o
56  obj-$(CONFIG_SECURITY_TOMOYO)          += tomoyo/built-in.o
57 +obj-$(CONFIG_SECURITY_APPARMOR)         += apparmor/built-in.o
58  obj-$(CONFIG_SECURITY_ROOTPLUG)                += root_plug.o
59  obj-$(CONFIG_CGROUP_DEVICE)            += device_cgroup.o
60  
61 diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
62 new file mode 100644
63 index 0000000..0f7ba5e
64 --- /dev/null
65 +++ b/security/apparmor/Kconfig
66 @@ -0,0 +1,53 @@
67 +config SECURITY_APPARMOR
68 +       bool "AppArmor support"
69 +       depends on SECURITY && SECURITY_NETWORK && NET && INET
70 +       select AUDIT
71 +       select SECURITY_PATH
72 +       select SECURITYFS
73 +       default n
74 +       help
75 +         This enables the AppArmor security module.
76 +         Required userspace tools (if they are not included in your
77 +         distribution) and further information may be found at
78 +         <http://forge.novell.com/modules/xfmod/project/?apparmor>
79 +
80 +         If you are unsure how to answer this question, answer N.
81 +
82 +config SECURITY_APPARMOR_NETWORK
83 +       bool "AppArmor network support"
84 +       depends on SECURITY_APPARMOR
85 +       default n
86 +       help
87 +        This enables AppArmor to mediate applications network use.
88 +        This will enable the SECURITY_NETWORK hooks.
89 +
90 +config SECURITY_APPARMOR_BOOTPARAM_VALUE
91 +       int "AppArmor boot parameter default value"
92 +       depends on SECURITY_APPARMOR
93 +       range 0 1
94 +       default 1
95 +       help
96 +         This option sets the default value for the kernel parameter
97 +         'apparmor', which allows AppArmor to be enabled or disabled
98 +          at boot.  If this option is set to 0 (zero), the AppArmor
99 +         kernel parameter will default to 0, disabling AppArmor at
100 +         bootup.  If this option is set to 1 (one), the AppArmor
101 +         kernel parameter will default to 1, enabling AppArmor at
102 +         bootup.
103 +
104 +         If you are unsure how to answer this question, answer 1.
105 +
106 +config SECURITY_APPARMOR_DISABLE
107 +       bool "AppArmor runtime disable"
108 +       depends on SECURITY_APPARMOR
109 +       default n
110 +       help
111 +         This option enables writing to a apparmorfs node 'disable', which
112 +         allows AppArmor to be disabled at runtime prior to the policy load.
113 +         AppArmor will then remain disabled until the next boot.
114 +         This option is similar to the apparmor.enabled=0 boot parameter,
115 +         but is to support runtime disabling of AppArmor, e.g. from
116 +         /sbin/init, for portability across platforms where boot
117 +         parameters are difficult to employ.
118 +
119 +         If you are unsure how to answer this question, answer N.
120 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
121 new file mode 100644
122 index 0000000..6e186ce
123 --- /dev/null
124 +++ b/security/apparmor/Makefile
125 @@ -0,0 +1,24 @@
126 +# Makefile for AppArmor Linux Security Module
127 +#
128 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
129 +
130 +apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
131 +              path.o domain.o policy.o policy_interface.o procattr.o lsm.o \
132 +              resource.o sid.o file.o
133 +
134 +apparmor-$(CONFIG_SECURITY_APPARMOR_NETWORK) += net.o
135 +
136 +clean-files: capability_names.h af_names.h
137 +
138 +quiet_cmd_make-caps = GEN     $@
139 +cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; 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 >> $@ ; echo "};" >> $@
140 +
141 +quiet_cmd_make-af = GEN     $@
142 +cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
143 +
144 +$(obj)/capability.o : $(obj)/capability_names.h
145 +$(obj)/net.o : $(obj)/af_names.h
146 +$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
147 +       $(call cmd,make-caps)
148 +$(obj)/af_names.h : $(srctree)/include/linux/socket.h
149 +       $(call cmd,make-af)
150 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
151 new file mode 100644
152 index 0000000..02ba36f
153 --- /dev/null
154 +++ b/security/apparmor/apparmorfs.c
155 @@ -0,0 +1,395 @@
156 +/*
157 + * AppArmor security module
158 + *
159 + * This file contains AppArmor /proc/<pid>/attr interface functions
160 + *
161 + * Copyright (C) 1998-2008 Novell/SUSE
162 + * Copyright 2009 Canonical Ltd.
163 + *
164 + * This program is free software; you can redistribute it and/or
165 + * modify it under the terms of the GNU General Public License as
166 + * published by the Free Software Foundation, version 2 of the
167 + * License.
168 + */
169 +
170 +#include <linux/security.h>
171 +#include <linux/vmalloc.h>
172 +#include <linux/module.h>
173 +#include <linux/seq_file.h>
174 +#include <linux/uaccess.h>
175 +#include <linux/namei.h>
176 +
177 +#include "include/apparmor.h"
178 +#include "include/audit.h"
179 +#include "include/context.h"
180 +#include "include/policy.h"
181 +#include "include/policy_interface.h"
182 +
183 +static char *aa_simple_write_to_buffer(const char __user *userbuf,
184 +                                      size_t alloc_size, size_t copy_size,
185 +                                      loff_t *pos, const char *operation)
186 +{
187 +       const struct cred *cred;
188 +       struct aa_profile *profile;
189 +       char *data;
190 +
191 +       if (*pos != 0) {
192 +               /* only writes from pos 0, that is complete writes */
193 +               data = ERR_PTR(-ESPIPE);
194 +               goto out;
195 +       }
196 +
197 +       /*
198 +        * Don't allow confined processes to load/replace/remove profiles.
199 +        * No sane person would add rules allowing this to a profile
200 +        * but we enforce the restriction anyways.
201 +        */
202 +       cred = aa_current_policy(&profile);
203 +       if (profile) {
204 +               struct aa_audit sa;
205 +               memset(&sa, 0, sizeof(sa));
206 +               sa.operation = operation;
207 +               sa.gfp_mask = GFP_KERNEL;
208 +               sa.error = -EACCES;
209 +               data = ERR_PTR(aa_audit(AUDIT_APPARMOR_DENIED, profile, &sa,
210 +                                       NULL));
211 +               goto out;
212 +       }
213 +
214 +       data = vmalloc(alloc_size);
215 +       if (data == NULL) {
216 +               data = ERR_PTR(-ENOMEM);
217 +               goto out;
218 +       }
219 +
220 +       if (copy_from_user(data, userbuf, copy_size)) {
221 +               vfree(data);
222 +               data = ERR_PTR(-EFAULT);
223 +               goto out;
224 +       }
225 +
226 +out:
227 +       return data;
228 +}
229 +
230 +static struct aa_profile *next_profile(struct aa_profile *profile)
231 +{
232 +       struct aa_profile *next = profile;
233 +       struct aa_namespace *ns;
234 +
235 +       if (!list_empty(&profile->base.profiles)) {
236 +               list_for_each_entry(next, &profile->base.profiles, base.list)
237 +                       return next;
238 +       }
239 +
240 +       while (profile->parent) {
241 +               next = profile->parent;
242 +               list_for_each_entry_continue(next,
243 +                                            &profile->parent->base.profiles,
244 +                                            base.list)
245 +                       return next;
246 +               profile = profile->parent;
247 +       }
248 +
249 +       next = profile;
250 +       list_for_each_entry_continue(next, &profile->ns->base.profiles,
251 +                                    base.list)
252 +               return next;
253 +
254 +       ns = profile->ns;
255 +       read_unlock(&ns->base.lock);
256 +       list_for_each_entry_continue(ns, &ns_list, base.list) {
257 +               read_lock(&ns->base.lock);
258 +               list_for_each_entry(profile, &ns->base.profiles, base.list)
259 +                       return profile;
260 +               read_unlock(&ns->base.lock);
261 +       }
262 +       return NULL;
263 +}
264 +
265 +static void *p_start(struct seq_file *f, loff_t *pos)
266 +       __acquires(ns_list_lock)
267 +{
268 +       struct aa_namespace *ns;
269 +       loff_t l = *pos;
270 +
271 +       read_lock(&ns_list_lock);
272 +       if (!list_empty(&ns_list)) {
273 +               struct aa_profile *profile = NULL;
274 +               ns = list_first_entry(&ns_list, typeof(*ns), base.list);
275 +               read_lock(&ns->base.lock);
276 +               if (!list_empty(&ns->base.profiles)) {
277 +                       profile = list_first_entry(&ns->base.profiles,
278 +                                                  typeof(*profile), base.list);
279 +                       for ( ; profile && l > 0; l--)
280 +                               profile = next_profile(profile);
281 +                       return profile;
282 +               } else
283 +                       read_unlock(&ns->base.lock);
284 +       }
285 +       return NULL;
286 +}
287 +
288 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
289 +{
290 +       struct aa_profile *profile = (struct aa_profile *) p;
291 +
292 +       (*pos)++;
293 +       profile = next_profile(profile);
294 +
295 +       return profile;
296 +}
297 +
298 +static void p_stop(struct seq_file *f, void *p)
299 +       __releases(ns_list_lock)
300 +{
301 +       struct aa_profile *profile = (struct aa_profile *) p;
302 +
303 +       if (profile)
304 +               read_unlock(&profile->ns->base.lock);
305 +       read_unlock(&ns_list_lock);
306 +}
307 +
308 +static void print_name(struct seq_file *f, struct aa_profile *profile)
309 +{
310 +       if (profile->parent) {
311 +               print_name(f, profile->parent);
312 +               seq_printf(f, "//");
313 +       }
314 +       seq_printf(f, "%s", profile->base.name);
315 +}
316 +
317 +static int seq_show_profile(struct seq_file *f, void *p)
318 +{
319 +       struct aa_profile *profile = (struct aa_profile *)p;
320 +
321 +       if (profile->ns != default_namespace)
322 +               seq_printf(f, ":%s:", profile->ns->base.name);
323 +       print_name(f, profile);
324 +       seq_printf(f, " (%s)\n",
325 +                  PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
326 +
327 +       return 0;
328 +}
329 +
330 +/* Used in apparmorfs.c */
331 +static struct seq_operations apparmorfs_profiles_op = {
332 +       .start =        p_start,
333 +       .next =         p_next,
334 +       .stop =         p_stop,
335 +       .show =         seq_show_profile,
336 +};
337 +
338 +static int aa_profiles_open(struct inode *inode, struct file *file)
339 +{
340 +       return seq_open(file, &apparmorfs_profiles_op);
341 +}
342 +
343 +
344 +static int aa_profiles_release(struct inode *inode, struct file *file)
345 +{
346 +       return seq_release(inode, file);
347 +}
348 +
349 +static struct file_operations apparmorfs_profiles_fops = {
350 +       .open =         aa_profiles_open,
351 +       .read =         seq_read,
352 +       .llseek =       seq_lseek,
353 +       .release =      aa_profiles_release,
354 +};
355 +
356 +/* apparmor/matching */
357 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
358 +                              size_t size, loff_t *ppos)
359 +{
360 +       const char *matching = "pattern=aadfa audit perms=crwxamlk/ user::other";
361 +
362 +       return simple_read_from_buffer(buf, size, ppos, matching,
363 +                                      strlen(matching));
364 +}
365 +
366 +static struct file_operations apparmorfs_matching_fops = {
367 +       .read =         aa_matching_read,
368 +};
369 +
370 +/* apparmor/features */
371 +static ssize_t aa_features_read(struct file *file, char __user *buf,
372 +                               size_t size, loff_t *ppos)
373 +{
374 +       const char *features = "file=3.1 capability=2.0 network=1.0 "
375 +                              "change_hat=1.5 change_profile=1.1 "
376 +                              "aanamespaces=1.1 rlimit=1.1";
377 +
378 +       return simple_read_from_buffer(buf, size, ppos, features,
379 +                                      strlen(features));
380 +}
381 +
382 +static struct file_operations apparmorfs_features_fops = {
383 +       .read =         aa_features_read,
384 +};
385 +
386 +/* apparmor/.load */
387 +static ssize_t aa_profile_load(struct file *f, const char __user *buf,
388 +                              size_t size, loff_t *pos)
389 +{
390 +       char *data;
391 +       ssize_t error;
392 +
393 +       data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
394 +
395 +       error = PTR_ERR(data);
396 +       if (!IS_ERR(data)) {
397 +               error = aa_interface_add_profiles(data, size);
398 +               vfree(data);
399 +       }
400 +
401 +       return error;
402 +}
403 +
404 +
405 +static struct file_operations apparmorfs_profile_load = {
406 +       .write = aa_profile_load
407 +};
408 +
409 +/* apparmor/.replace */
410 +static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
411 +                                 size_t size, loff_t *pos)
412 +{
413 +       char *data;
414 +       ssize_t error;
415 +
416 +       data = aa_simple_write_to_buffer(buf, size, size, pos,
417 +                                        "profile_replace");
418 +       error = PTR_ERR(data);
419 +       if (!IS_ERR(data)) {
420 +               error = aa_interface_replace_profiles(data, size);
421 +               vfree(data);
422 +       }
423 +
424 +       return error;
425 +}
426 +
427 +
428 +static struct file_operations apparmorfs_profile_replace = {
429 +       .write = aa_profile_replace
430 +};
431 +
432 +/* apparmor/.remove */
433 +static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
434 +                                 size_t size, loff_t *pos)
435 +{
436 +       char *data;
437 +       ssize_t error;
438 +
439 +       /*
440 +        * aa_remove_profile needs a null terminated string so 1 extra
441 +        * byte is allocated and the copied data is null terminated.
442 +        */
443 +       data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
444 +                                        "profile_remove");
445 +
446 +       error = PTR_ERR(data);
447 +       if (!IS_ERR(data)) {
448 +               data[size] = 0;
449 +               error = aa_interface_remove_profiles(data, size);
450 +               vfree(data);
451 +       }
452 +
453 +       return error;
454 +}
455 +
456 +static struct file_operations apparmorfs_profile_remove = {
457 +       .write = aa_profile_remove
458 +};
459 +
460 +static struct dentry *apparmorfs_dentry;
461 +struct dentry *apparmorfs_null;
462 +struct vfsmount *apparmorfs_mnt;
463 +
464 +static void aafs_remove(const char *name)
465 +{
466 +       struct dentry *dentry;
467 +
468 +       dentry = lookup_one_len(name, apparmorfs_dentry, strlen(name));
469 +       if (!IS_ERR(dentry)) {
470 +               securityfs_remove(dentry);
471 +               dput(dentry);
472 +       }
473 +}
474 +
475 +static int aafs_create(const char *name, int mask, struct file_operations *fops)
476 +{
477 +       struct dentry *dentry;
478 +
479 +       dentry = securityfs_create_file(name, S_IFREG | mask, apparmorfs_dentry,
480 +                                       NULL, fops);
481 +
482 +       return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
483 +}
484 +
485 +void destroy_apparmorfs(void)
486 +{
487 +       if (apparmorfs_dentry) {
488 +               aafs_remove(".remove");
489 +               aafs_remove(".replace");
490 +               aafs_remove(".load");
491 +               aafs_remove("matching");
492 +               aafs_remove("features");
493 +               aafs_remove("profiles");
494 +               securityfs_remove(apparmorfs_dentry);
495 +               apparmorfs_dentry = NULL;
496 +       }
497 +}
498 +
499 +int create_apparmorfs(void)
500 +{
501 +       int error;
502 +
503 +       if (!apparmor_initialized)
504 +               return 0;
505 +
506 +       if (apparmorfs_dentry) {
507 +               AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
508 +               return -EEXIST;
509 +       }
510 +
511 +       apparmorfs_dentry = securityfs_create_dir("apparmor", NULL);
512 +       if (IS_ERR(apparmorfs_dentry)) {
513 +               error = PTR_ERR(apparmorfs_dentry);
514 +               apparmorfs_dentry = NULL;
515 +               goto error;
516 +       }
517 +       error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
518 +       if (error)
519 +               goto error;
520 +       error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
521 +       if (error)
522 +               goto error;
523 +       error = aafs_create("features", 0444, &apparmorfs_features_fops);
524 +       if (error)
525 +               goto error;
526 +       error = aafs_create(".load", 0640, &apparmorfs_profile_load);
527 +       if (error)
528 +               goto error;
529 +       error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
530 +       if (error)
531 +               goto error;
532 +       error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
533 +       if (error)
534 +               goto error;
535 +
536 +       /* TODO: add support for apparmorfs_null and apparmorfs_mnt */
537 +
538 +       /* Report that AppArmor fs is enabled */
539 +       info_message("AppArmor Filesystem Enabled");
540 +       return 0;
541 +
542 +error:
543 +       destroy_apparmorfs();
544 +       AA_ERROR("Error creating AppArmor securityfs\n");
545 +       apparmor_disable();
546 +       return error;
547 +}
548 +
549 +fs_initcall(create_apparmorfs);
550 +
551 diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
552 new file mode 100644
553 index 0000000..834a4f5
554 --- /dev/null
555 +++ b/security/apparmor/audit.c
556 @@ -0,0 +1,151 @@
557 +/*
558 + * AppArmor security module
559 + *
560 + * This file contains AppArmor auditing functions
561 + *
562 + * Copyright (C) 1998-2008 Novell/SUSE
563 + * Copyright 2009 Canonical Ltd.
564 + *
565 + * This program is free software; you can redistribute it and/or
566 + * modify it under the terms of the GNU General Public License as
567 + * published by the Free Software Foundation, version 2 of the
568 + * License.
569 + */
570 +
571 +#include <linux/audit.h>
572 +#include <linux/socket.h>
573 +
574 +#include "include/apparmor.h"
575 +#include "include/audit.h"
576 +#include "include/policy.h"
577 +
578 +const char *audit_mode_names[] = {
579 +       "normal",
580 +       "quiet_denied",
581 +       "quiet"
582 +       "noquiet",
583 +       "all"
584 +};
585 +
586 +static char* aa_audit_type[] = {
587 +       "APPARMOR_AUDIT",
588 +       "APPARMOR_ALLOWED",
589 +       "APPARMOR_DENIED",
590 +       "APPARMOR_HINT",
591 +       "APPARMOR_STATUS",
592 +       "APPARMOR_ERROR",
593 +       "APPARMOR_KILLED"
594 +};
595 +
596 +/*
597 + * TODO:
598 + * user auditing - netlink interface
599 + * system control of whether user audit messages go to system log
600 + */
601 +static int aa_audit_base(int type, struct aa_profile *profile,
602 +                        struct aa_audit *sa, struct audit_context *audit_cxt,
603 +                        void(*cb)(struct audit_buffer *, void *))
604 +{
605 +       struct audit_buffer *ab = NULL;
606 +
607 +       if (profile && PROFILE_KILL(profile) && type == AUDIT_APPARMOR_DENIED)
608 +               type = AUDIT_APPARMOR_KILL;
609 +
610 +       ab = audit_log_start(audit_cxt, sa->gfp_mask, type);
611 +
612 +       if (!ab) {
613 +               AA_ERROR("(%d) Unable to log event of type (%d)\n",
614 +                        -ENOMEM, type);
615 +                /* don't fail operations in complain mode even if logging
616 +                 * fails */
617 +               return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
618 +       }
619 +
620 +       if (g_apparmor_audit_header)
621 +               audit_log_format(ab, "type=%s ",
622 +                                aa_audit_type[type - AUDIT_APPARMOR_AUDIT]);
623 +
624 +       if (sa->operation)
625 +               audit_log_format(ab, "operation=\"%s\"", sa->operation);
626 +
627 +       if (sa->info) {
628 +               audit_log_format(ab, " info=\"%s\"", sa->info);
629 +               if (sa->error)
630 +                       audit_log_format(ab, " error=%d", sa->error);
631 +       }
632 +
633 +       audit_log_format(ab, " pid=%d", sa->task ?sa->task->pid : current->pid);
634 +
635 +       if (profile) {
636 +               pid_t pid = sa->task ? sa->task->real_parent->pid :
637 +                                      current->real_parent->pid;
638 +               audit_log_format(ab, " parent=%d", pid);
639 +               audit_log_format(ab, " profile=");
640 +               audit_log_untrustedstring(ab, profile->fqname);
641 +
642 +               if (profile->ns != default_namespace) {
643 +                       audit_log_format(ab, " namespace=");
644 +                       audit_log_untrustedstring(ab, profile->ns->base.name);
645 +               }
646 +       }
647 +
648 +       if (cb)
649 +               cb(ab, sa);
650 +
651 +       audit_log_end(ab);
652 +
653 +       if (type == AUDIT_APPARMOR_KILL)
654 +               (void)send_sig_info(SIGKILL, NULL,
655 +                                   sa->task ? sa->task : current);
656 +
657 +       return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error;
658 +}
659 +
660 +/**
661 + * aa_audit - Log an audit event to the audit subsystem
662 + * @type: audit type for the message
663 + * @profile: profile to check against
664 + * @sa: audit event
665 + */
666 +int aa_audit(int type, struct aa_profile *profile, struct aa_audit *sa,
667 +            void(*cb)(struct audit_buffer *, void *))
668 +{
669 +       struct audit_context *audit_cxt;
670 +       audit_cxt = g_apparmor_logsyscall ? current->audit_context : NULL;
671 +
672 +       if (type == AUDIT_APPARMOR_AUTO) {
673 +               if (likely(!sa->error))
674 +                       type = AUDIT_APPARMOR_AUDIT;
675 +               else if (PROFILE_COMPLAIN(profile))
676 +                       type = AUDIT_APPARMOR_ALLOWED;
677 +               else
678 +                       type = AUDIT_APPARMOR_DENIED;
679 +       }
680 +       if (PROFILE_AUDIT_MODE(profile) == AUDIT_QUIET ||
681 +           (type == AUDIT_APPARMOR_DENIED &&
682 +            PROFILE_AUDIT_MODE(profile) == AUDIT_QUIET))
683 +               return sa->error;
684 +
685 +       return aa_audit_base(type, profile, sa, audit_cxt, cb);
686 +}
687 +
688 +/**
689 + * aa_audit_syscallreject - Log a syscall rejection to the audit subsystem
690 + * @profile: profile to check against
691 + * @gfp: memory allocation flags
692 + * @msg: string describing syscall being rejected
693 + */
694 +int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
695 +                          const char *msg,
696 +                          void(*cb)(struct audit_buffer *, void *))
697 +{
698 +       struct aa_audit sa;
699 +       memset(&sa, 0, sizeof(sa));
700 +       sa.operation = "syscall";
701 +       sa.info = msg;
702 +       sa.gfp_mask = gfp;
703 +       sa.error = -EACCES;
704 +
705 +       return aa_audit_base(AUDIT_APPARMOR_DENIED, profile, &sa,
706 +                            current->audit_context, NULL);
707 +}
708 diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
709 new file mode 100644
710 index 0000000..79097e8
711 --- /dev/null
712 +++ b/security/apparmor/capability.c
713 @@ -0,0 +1,121 @@
714 +/*
715 + * AppArmor security module
716 + *
717 + * This file contains AppArmor capability mediation functions
718 + *
719 + * Copyright (C) 1998-2008 Novell/SUSE
720 + * Copyright 2009 Canonical Ltd.
721 + *
722 + * This program is free software; you can redistribute it and/or
723 + * modify it under the terms of the GNU General Public License as
724 + * published by the Free Software Foundation, version 2 of the
725 + * License.
726 + */
727 +
728 +#include <linux/capability.h>
729 +#include <linux/errno.h>
730 +#include <linux/gfp.h>
731 +
732 +#include "include/apparmor.h"
733 +#include "include/capability.h"
734 +#include "include/context.h"
735 +#include "include/policy.h"
736 +#include "include/audit.h"
737 +
738 +/*
739 + * Table of capability names: we generate it from capabilities.h.
740 + */
741 +#include "capability_names.h"
742 +
743 +struct audit_cache {
744 +       struct task_struct *task;
745 +       kernel_cap_t caps;
746 +};
747 +
748 +static DEFINE_PER_CPU(struct audit_cache, audit_cache);
749 +
750 +struct aa_audit_caps {
751 +       struct aa_audit base;
752 +
753 +       int cap;
754 +};
755 +
756 +static void audit_cb(struct audit_buffer *ab, void *va)
757 +{
758 +       struct aa_audit_caps *sa = va;
759 +
760 +       audit_log_format(ab, " name=");
761 +       audit_log_untrustedstring(ab, capability_names[sa->cap]);
762 +}
763 +
764 +static int aa_audit_caps(struct aa_profile *profile, struct aa_audit_caps *sa)
765 +{
766 +       struct audit_cache *ent;
767 +       int type = AUDIT_APPARMOR_AUTO;
768 +
769 +       if (likely(!sa->base.error)) {
770 +               /* test if auditing is being forced */
771 +               if (likely((PROFILE_AUDIT_MODE(profile) != AUDIT_ALL) &&
772 +                          !cap_raised(profile->caps.audit, sa->cap)))
773 +                       return 0;
774 +       } else if (PROFILE_KILL(profile) ||
775 +                  cap_raised(profile->caps.kill, sa->cap)) {
776 +               type = AUDIT_APPARMOR_KILL;
777 +       } else if (cap_raised(profile->caps.quiet, sa->cap) &&
778 +                  PROFILE_AUDIT_MODE(profile) != AUDIT_NOQUIET &&
779 +                  PROFILE_AUDIT_MODE(profile) != AUDIT_ALL) {
780 +               /* quiet auditing */
781 +               return sa->base.error;
782 +       }
783 +
784 +       /* Do simple duplicate message elimination */
785 +       ent = &get_cpu_var(audit_cache);
786 +       if (sa->base.task == ent->task && cap_raised(ent->caps, sa->cap)) {
787 +               if (PROFILE_COMPLAIN(profile))
788 +                       return 0;
789 +               return sa->base.error;
790 +       } else {
791 +               ent->task = sa->base.task;
792 +               cap_raise(ent->caps, sa->cap);
793 +       }
794 +       put_cpu_var(audit_cache);
795 +
796 +       return aa_audit(type, profile, &sa->base, audit_cb);
797 +}
798 +
799 +int aa_profile_capable(struct aa_profile *profile, int cap)
800 +{
801 +       return cap_raised(profile->caps.allowed, cap) ? 0 : -EPERM;
802 +}
803 +
804 +/**
805 + * aa_capable - test permission to use capability
806 + * @task: task doing capability test against
807 + * @profile: profile confining @task
808 + * @cap: capability to be tested
809 + * @audit: whether an audit record should be generated
810 + *
811 + * Look up capability in profile capability set.
812 + * Returns 0 on success, or else an error code.
813 + */
814 +int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
815 +              int audit)
816 +{
817 +       int error = aa_profile_capable(profile, cap);
818 +       struct aa_audit_caps sa;
819 +
820 +       if (!audit) {
821 +               if (PROFILE_COMPLAIN(profile))
822 +                       return 0;
823 +               return error;
824 +       }
825 +
826 +       memset(&sa, 0, sizeof(sa));
827 +       sa.base.operation = "capable";
828 +       sa.base.task = task;
829 +       sa.base.gfp_mask = GFP_ATOMIC;
830 +       sa.base.error = error;
831 +       sa.cap = cap;
832 +
833 +       return aa_audit_caps(profile, &sa);
834 +}
835 diff --git a/security/apparmor/context.c b/security/apparmor/context.c
836 new file mode 100644
837 index 0000000..02e0b70
838 --- /dev/null
839 +++ b/security/apparmor/context.c
840 @@ -0,0 +1,209 @@
841 +/*
842 + * AppArmor security module
843 + *
844 + * This file contains AppArmor functions used to manipulate object security
845 + * contexts.
846 + *
847 + * Copyright (C) 1998-2008 Novell/SUSE
848 + * Copyright 2009 Canonical Ltd.
849 + *
850 + * This program is free software; you can redistribute it and/or
851 + * modify it under the terms of the GNU General Public License as
852 + * published by the Free Software Foundation, version 2 of the
853 + * License.
854 + */
855 +
856 +#include "include/context.h"
857 +#include "include/policy.h"
858 +
859 +
860 +
861 +struct aa_task_context *aa_alloc_task_context(gfp_t flags)
862 +{
863 +       return kzalloc(sizeof(struct aa_task_context), flags);
864 +}
865 +
866 +void aa_free_task_context(struct aa_task_context *cxt)
867 +{
868 +       if (cxt) {
869 +               aa_put_profile(cxt->sys.profile);
870 +               aa_put_profile(cxt->sys.previous);
871 +               aa_put_profile(cxt->sys.onexec);
872 +
873 +               memset(cxt, 0, sizeof(*cxt));
874 +               kfree(cxt);
875 +       }
876 +}
877 +
878 +/*
879 + * duplicate a task context, incrementing reference counts
880 + */
881 +struct aa_task_context *aa_dup_task_context(struct aa_task_context *old_cxt,
882 +                                           gfp_t gfp)
883 +{
884 +       struct aa_task_context *cxt;
885 +
886 +       cxt = kmemdup(old_cxt, sizeof(*cxt), gfp);
887 +       if (!cxt)
888 +               return NULL;
889 +
890 +       aa_get_profile(cxt->sys.profile);
891 +       aa_get_profile(cxt->sys.previous);
892 +       aa_get_profile(cxt->sys.onexec);
893 +
894 +       return cxt;
895 +}
896 +
897 +/**
898 + * aa_cred_policy - obtain cred's profiles
899 + * @cred: cred to obtain profiles from
900 + * @sys: return system profile
901 + * does NOT increment reference count
902 + */
903 +void aa_cred_policy(const struct cred *cred, struct aa_profile **sys)
904 +{
905 +       struct aa_task_context *cxt = cred->security;
906 +       BUG_ON(!cxt);
907 +       *sys = aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
908 +}
909 +
910 +/**
911 + * aa_get_task_policy - get the cred with the task policy, and current profiles
912 + * @task: task to get policy of
913 + * @sys: return - pointer to system profile
914 + *
915 + * Only gets the cred ref count which has ref counts on the profiles returned
916 + */
917 +struct cred *aa_get_task_policy(const struct task_struct *task,
918 +                               struct aa_profile **sys)
919 +{
920 +       struct cred *cred = get_task_cred(task);
921 +       aa_cred_policy(cred, sys);
922 +       return cred;
923 +}
924 +
925 +void aa_put_task_policy(struct cred *cred)
926 +{
927 +       put_cred(cred);
928 +}
929 +
930 +static void replace_group(struct aa_task_cxt_group *cgrp,
931 +                         struct aa_profile *profile)
932 +{
933 +       if (cgrp->profile == profile)
934 +               return;
935 +
936 +       if (!profile || (profile->flags & PFLAG_UNCONFINED) ||
937 +           (cgrp->profile && cgrp->profile->ns != profile->ns)) {
938 +               aa_put_profile(cgrp->previous);
939 +               aa_put_profile(cgrp->onexec);
940 +               cgrp->previous = NULL;
941 +               cgrp->onexec = NULL;
942 +               cgrp->token = 0;
943 +       }
944 +       aa_put_profile(cgrp->profile);
945 +       cgrp->profile = aa_get_profile(profile);
946 +}
947 +
948 +/**
949 + * aa_replace_current_profiles - replace the current tasks profiles
950 + * @sys: new system profile
951 + *
952 + * Returns: error on failure
953 + */
954 +int aa_replace_current_profiles(struct aa_profile *sys)
955 +{
956 +       struct aa_task_context *cxt;
957 +       struct cred *new = prepare_creds();
958 +       if (!new)
959 +               return -ENOMEM;
960 +
961 +       cxt = new->security;
962 +       replace_group(&cxt->sys, sys);
963 +
964 +       commit_creds(new);
965 +       return 0;
966 +}
967 +
968 +int aa_set_current_onexec(struct aa_profile *sys)
969 +{
970 +       struct aa_task_context *cxt;
971 +       struct cred *new = prepare_creds();
972 +       if (!new)
973 +               return -ENOMEM;
974 +
975 +       cxt = new->security;
976 +       aa_put_profile(cxt->sys.onexec);
977 +       cxt->sys.onexec = aa_get_profile(sys);
978 +
979 +       commit_creds(new);
980 +       return 0;
981 +}
982 +
983 +/*
984 + * Do the actual cred switching of a changehat
985 + * profile must be valid
986 + */
987 +int aa_set_current_hat(struct aa_profile *profile, u64 token)
988 +{
989 +       struct aa_task_context *cxt;
990 +       struct cred *new = prepare_creds();
991 +       if (!new)
992 +               return -ENOMEM;
993 +
994 +       cxt = new->security;
995 +       if (!cxt->sys.previous) {
996 +               cxt->sys.previous = cxt->sys.profile;
997 +               cxt->sys.token = token;
998 +       } else if (cxt->sys.token == token) {
999 +               aa_put_profile(cxt->sys.profile);
1000 +       } else {
1001 +               /* previous_profile && cxt->token != token */
1002 +               abort_creds(new);
1003 +               return -EACCES;
1004 +       }
1005 +       cxt->sys.profile = aa_get_profile(profile);
1006 +       /* clear exec on switching context */
1007 +       aa_put_profile(cxt->sys.onexec);
1008 +       cxt->sys.onexec = NULL;
1009 +
1010 +       commit_creds(new);
1011 +       return 0;
1012 +}
1013 +
1014 +/*
1015 + * Attempt to return out of a hat to the previous profile
1016 + */
1017 +int aa_restore_previous_profile(u64 token)
1018 +{
1019 +       struct aa_task_context *cxt;
1020 +       struct cred *new = prepare_creds();
1021 +       if (!new)
1022 +               return -ENOMEM;
1023 +
1024 +       cxt = new->security;
1025 +       if (cxt->sys.token != token) {
1026 +               abort_creds(new);
1027 +               return -EACCES;
1028 +       }
1029 +       /* ignore restores when there is no saved profile */
1030 +       if (!cxt->sys.previous) {
1031 +               abort_creds(new);
1032 +               return 0;
1033 +       }
1034 +
1035 +       aa_put_profile(cxt->sys.profile);
1036 +       cxt->sys.profile = aa_profile_newest(cxt->sys.previous);
1037 +       if (unlikely(cxt->sys.profile != cxt->sys.previous)) {
1038 +               aa_get_profile(cxt->sys.profile);
1039 +               aa_put_profile(cxt->sys.previous);
1040 +       }
1041 +       /* clear exec && prev information when restoring to previous context */
1042 +       cxt->sys.previous = NULL;
1043 +       cxt->sys.token = 0;
1044 +       aa_put_profile(cxt->sys.onexec);
1045 +       cxt->sys.onexec = NULL;
1046 +
1047 +       commit_creds(new);
1048 +       return 0;
1049 +}
1050 diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
1051 new file mode 100644
1052 index 0000000..34f337c
1053 --- /dev/null
1054 +++ b/security/apparmor/domain.c
1055 @@ -0,0 +1,699 @@
1056 +/*
1057 + * AppArmor security module
1058 + *
1059 + * This file contains AppArmor policy attachment and domain transitions
1060 + *
1061 + * Copyright (C) 2002-2008 Novell/SUSE
1062 + * Copyright 2009 Canonical Ltd.
1063 + *
1064 + * This program is free software; you can redistribute it and/or
1065 + * modify it under the terms of the GNU General Public License as
1066 + * published by the Free Software Foundation, version 2 of the
1067 + * License.
1068 + */
1069 +
1070 +#include <linux/errno.h>
1071 +#include <linux/fdtable.h>
1072 +#include <linux/file.h>
1073 +#include <linux/mount.h>
1074 +#include <linux/personality.h>
1075 +#include <linux/syscalls.h>
1076 +#include <linux/tracehook.h>
1077 +
1078 +#include "include/audit.h"
1079 +#include "include/apparmorfs.h"
1080 +#include "include/context.h"
1081 +#include "include/domain.h"
1082 +#include "include/file.h"
1083 +#include "include/ipc.h"
1084 +#include "include/match.h"
1085 +#include "include/path.h"
1086 +#include "include/policy.h"
1087 +
1088 +/**
1089 + * aa_free_domain_entries - free entries in a domain table
1090 + * @domain: the domain table to free
1091 + */
1092 +void aa_free_domain_entries(struct aa_domain *domain)
1093 +{
1094 +       int i;
1095 +
1096 +       if (!domain->table)
1097 +               return;
1098 +
1099 +       for (i = 0; i < domain->size; i++)
1100 +               kfree(domain->table[i]);
1101 +       kfree(domain->table);
1102 +}
1103 +
1104 +/*
1105 + * check if the task is ptraced and if so if the tracing task is allowed
1106 + * to trace the new domain
1107 + */
1108 +static int aa_may_change_ptraced_domain(struct task_struct *task,
1109 +                                       struct aa_profile *to_profile)
1110 +{
1111 +       struct task_struct *tracer;
1112 +       struct cred *cred = NULL;
1113 +       struct aa_profile *tracerp = NULL;
1114 +       int error = 0;
1115 +
1116 +       rcu_read_lock();
1117 +       tracer = tracehook_tracer_task(task);
1118 +       if (tracer)
1119 +               cred = aa_get_task_policy(tracer, &tracerp);
1120 +       rcu_read_unlock();
1121 +
1122 +       if (!tracerp)
1123 +               return error;
1124 +
1125 +       error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
1126 +       put_cred(cred);
1127 +
1128 +       return error;
1129 +}
1130 +
1131 +/**
1132 + * change_profile_perms
1133 + */
1134 +static struct file_perms change_profile_perms(struct aa_profile *profile,
1135 +                                             struct aa_namespace *ns,
1136 +                                             const char *name,
1137 +                                             unsigned int *rstate)
1138 +{
1139 +       struct file_perms perms;
1140 +       struct path_cond cond = { 0, 0 };
1141 +       unsigned int state;
1142 +
1143 +       if (!profile) {
1144 +               /* unconfined */
1145 +               perms.allowed = AA_MAY_CHANGE_PROFILE;
1146 +               perms.xindex = perms.dindex = 0;
1147 +               perms.audit = perms.quiet = perms.kill = 0;
1148 +               *rstate = 0;
1149 +               return perms;
1150 +       } else if ((ns == profile->ns)) {
1151 +               /* try matching against rules with out namespace prependend */
1152 +               perms = aa_str_perms(profile->file.dfa, DFA_START, name, &cond,
1153 +                                    rstate);
1154 +               if (COMBINED_PERM_MASK(perms) & AA_MAY_CHANGE_PROFILE)
1155 +                       return perms;
1156 +       }
1157 +
1158 +       /* try matching with namespace name and then profile */
1159 +       if (!profile->file.dfa)
1160 +               return nullperms;
1161 +
1162 +       state = aa_dfa_match(profile->file.dfa, DFA_START, ns->base.name);
1163 +       state = aa_dfa_null_transition(profile->file.dfa, state);
1164 +       return aa_str_perms(profile->file.dfa, state, name, &cond, rstate);
1165 +}
1166 +
1167 +/*
1168 + * TODO: fix parser to detect unconfined, inherit,
1169 + * check for next name in list of names that is double null terminated
1170 + * The names list is a set of strings that \0 seperated with a double
1171 + * \0 terminating the list
1172 + * names that belong to namespaces begin with a :
1173 + * and are followed by a name a \0 seperated name.  If the name is
1174 + * unspecified it is 0 length.  This double \0\0 does not count as
1175 + * the end of the list
1176 + *
1177 + * profile\0\0                 # single profile
1178 + * profile\0profile\0\0                # 2 profiles in list
1179 + * :namespace\0profile\0\0     # profile & namespace
1180 + * :namespace\0\0\0            # namespace without profile
1181 + * :namespace\0\0profile\0\0   # namespace without profile followed by profile
1182 +*/
1183 +static const char *next_name(int xtype, const char *name)
1184 +{
1185 +/* TODO: fix parser and enable
1186 +       if (xtype == AA_X_TABLE) {
1187 +               name = name + strlen(name) + 1;
1188 +               if (*name != 0)
1189 +                       return name;
1190 +       }
1191 +*/
1192 +       return NULL;
1193 +}
1194 +
1195 +/*
1196 + * get target profile for xindex
1197 + */
1198 +static struct aa_profile *x_to_profile(struct aa_namespace *ns,
1199 +                                      struct aa_profile *profile,
1200 +                                      const char *name, u16 xindex)
1201 +
1202 +{
1203 +       struct aa_profile *new_profile = NULL;
1204 +       u16 xtype = xindex & AA_X_TYPE_MASK;
1205 +       int index = xindex & AA_X_INDEX_MASK;
1206 +
1207 +       if (!profile)
1208 +               profile = ns->unconfined;
1209 +
1210 +       switch(xtype) {
1211 +       case AA_X_NONE:
1212 +               /* fail exec unless ix || ux fallback - handled by caller */
1213 +               return ERR_PTR(-EACCES);
1214 +       case AA_X_NAME:
1215 +               break;
1216 +       case AA_X_TABLE:
1217 +               if (index > profile->file.trans.size) {
1218 +                       AA_ERROR("Invalid named transition\n");
1219 +                       return ERR_PTR(-EACCES);
1220 +               }
1221 +               name = profile->file.trans.table[index];
1222 +               break;
1223 +       }
1224 +
1225 +       for (; !new_profile && name; name = next_name(xtype, name)) {
1226 +               struct aa_namespace *new_ns;
1227 +               const char *xname = NULL;
1228 +
1229 +               new_ns = NULL;
1230 +               if (xindex & AA_X_CHILD) {
1231 +                       new_profile = aa_find_child(profile, name);
1232 +                       if (new_profile)
1233 +                               return new_profile;
1234 +                       continue;
1235 +               } else if (*name == ':') {
1236 +                       /* switching namespace */
1237 +                       const char *ns_name = name + 1;
1238 +                       name = xname = ns_name + strlen(ns_name) + 1;
1239 +                       if (!*xname)
1240 +                               /* no name so use profile name */
1241 +                               xname = profile->fqname;
1242 +                       if (*ns_name == '@') {
1243 +                               /* TODO: variable support */
1244 +                               ;
1245 +                       }
1246 +                       new_ns = aa_find_namespace(ns_name);
1247 +                       if (!new_ns)
1248 +                               continue;
1249 +               } else if (*name == '@') {
1250 +                       /* TODO: variable support */
1251 +
1252 +               } else {
1253 +                       xname = name;
1254 +               }
1255 +
1256 +               new_profile = aa_find_profile_by_fqname(new_ns ? new_ns : ns,
1257 +                                                       xname);
1258 +               aa_put_namespace(new_ns);
1259 +       }
1260 +
1261 +       if (!new_profile)
1262 +               return ERR_PTR(-ENOENT);
1263 +
1264 +       return new_profile;
1265 +}
1266 +
1267 +int apparmor_bprm_set_creds(struct linux_binprm *bprm)
1268 +{
1269 +       struct aa_task_context *cxt;
1270 +       struct aa_profile *profile, *new_profile = NULL;
1271 +       struct aa_namespace *ns;
1272 +       char *buffer = NULL;
1273 +       unsigned int state = DFA_START;
1274 +       struct aa_audit_file sa;
1275 +       struct path_cond cond = { bprm->file->f_path.dentry->d_inode->i_uid,
1276 +                                 bprm->file->f_path.dentry->d_inode->i_mode }; 
1277 +
1278 +       sa.base.error = cap_bprm_set_creds(bprm);
1279 +       if (sa.base.error)
1280 +               return sa.base.error;
1281 +
1282 +       if (bprm->cred_prepared)
1283 +               return 0;
1284 +
1285 +       memset(&sa, 0, sizeof(sa));
1286 +       sa.base.operation = "exec";
1287 +       sa.base.gfp_mask = GFP_KERNEL;
1288 +       sa.request = MAY_EXEC;
1289 +       sa.cond = &cond;
1290 +
1291 +       cxt = bprm->cred->security;
1292 +       BUG_ON(!cxt);
1293 +
1294 +       profile = aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
1295 +       ns = cxt->sys.profile->ns;
1296 +
1297 +       sa.base.error = aa_get_name(&bprm->file->f_path, 0, &buffer,
1298 +                                   (char **) &sa.name);
1299 +       if (sa.base.error) {
1300 +               if (profile || profile->flags & PFLAG_IX_ON_NAME_ERROR)
1301 +                       sa.base.error = 0;
1302 +               sa.base.info = "Exec failed name resolution";
1303 +               sa.name = bprm->filename;
1304 +               goto audit;
1305 +       }
1306 +
1307 +       if (!profile) {
1308 +               /* unconfined task - attach profile if one matches */
1309 +               new_profile = aa_sys_find_attach(ns, sa.name);
1310 +               if (!new_profile)
1311 +                       goto cleanup;
1312 +               goto apply;
1313 +       } else if (cxt->sys.onexec) {
1314 +               /*
1315 +                * onexec permissions are stored in a pair, rewalk the
1316 +                * dfa to get start of the exec path match.
1317 +                */
1318 +               sa.perms = change_profile_perms(profile, cxt->sys.onexec->ns,
1319 +                                               sa.name, &state);
1320 +               state = aa_dfa_null_transition(profile->file.dfa, state);
1321 +       }
1322 +       sa.perms = aa_str_perms(profile->file.dfa, state, sa.name, &cond,
1323 +                               NULL);
1324 +       if (cxt->sys.onexec && sa.perms.allowed & AA_MAY_ONEXEC) {
1325 +               new_profile = cxt->sys.onexec;
1326 +               cxt->sys.onexec = NULL;
1327 +               sa.base.info = "change_profile onexec";
1328 +       } else if (sa.perms.allowed & MAY_EXEC) {
1329 +               new_profile = x_to_profile(ns, profile, sa.name,
1330 +                                          sa.perms.xindex);
1331 +               if (IS_ERR(new_profile)) {
1332 +                       if (sa.perms.xindex & AA_X_INHERIT) {
1333 +                               /* (p|c|n)ix - don't change profile */
1334 +                               sa.base.info = "ix fallback";
1335 +                               goto x_clear;
1336 +                       } else if (sa.perms.xindex & AA_X_UNCONFINED) {
1337 +                               new_profile = aa_get_profile(ns->unconfined);
1338 +                               sa.base.info = "ux fallback";
1339 +                       } else {
1340 +                               sa.base.error = PTR_ERR(new_profile);
1341 +                               if (sa.base.error == -ENOENT)
1342 +                                       sa.base.info = "profile not found";
1343 +                               new_profile = NULL;
1344 +                       }
1345 +               }
1346 +       } else if (PROFILE_COMPLAIN(profile)) {
1347 +               new_profile = aa_alloc_null_profile(profile, 0);
1348 +               sa.base.error = -EACCES;
1349 +               if (!new_profile)
1350 +                       sa.base.error = -ENOMEM;
1351 +               sa.name2 = new_profile->fqname;
1352 +               sa.perms.xindex |= AA_X_UNSAFE;
1353 +       } else {
1354 +               sa.base.error = -EACCES;
1355 +       }
1356 +
1357 +       if (!new_profile)
1358 +               goto audit;
1359 +
1360 +       if (profile == new_profile) {
1361 +               aa_put_profile(new_profile);
1362 +               goto audit;
1363 +       }
1364 +
1365 +       if (bprm->unsafe & LSM_UNSAFE_SHARE) {
1366 +               /* FIXME: currently don't mediate shared state */
1367 +               ;
1368 +       }
1369 +
1370 +       if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
1371 +               sa.base.error = aa_may_change_ptraced_domain(current,
1372 +                                                            new_profile);
1373 +               if (sa.base.error)
1374 +                       goto audit;
1375 +       }
1376 +
1377 +       /* Determine if secure exec is needed.
1378 +        * Can be at this point for the following reasons:
1379 +        * 1. unconfined switching to confined
1380 +        * 2. confined switching to different confinement
1381 +        * 3. confined switching to unconfined
1382 +        *
1383 +        * Cases 2 and 3 are marked as requiring secure exec
1384 +        * (unless policy specified "unsafe exec")
1385 +        *
1386 +        * bprm->unsafe is used to cache the AA_X_UNSAFE permission
1387 +        * to avoid having to recompute in secureexec
1388 +        */
1389 +       if (!(sa.perms.xindex & AA_X_UNSAFE))
1390 +               bprm->unsafe |= AA_SECURE_X_NEEDED;
1391 +
1392 +apply:
1393 +       sa.name2 = new_profile->fqname;
1394 +       /* When switching namespace ensure its part of audit message */
1395 +       if (new_profile->ns != profile->ns)
1396 +               sa.name3 = new_profile->ns->base.name;
1397 +
1398 +       /* when transitioning profiles clear unsafe personality bits */
1399 +       bprm->per_clear |= PER_CLEAR_ON_SETID;
1400 +
1401 +       aa_put_profile(cxt->sys.profile);
1402 +       cxt->sys.profile = new_profile;
1403 +
1404 +x_clear:
1405 +       aa_put_profile(cxt->sys.previous);
1406 +       aa_put_profile(cxt->sys.onexec);
1407 +       cxt->sys.previous = NULL;
1408 +       cxt->sys.onexec = NULL;
1409 +       cxt->sys.token = 0;
1410 +
1411 +audit:
1412 +       sa.base.error = aa_audit_file(profile, &sa);
1413 +
1414 +cleanup:
1415 +       kfree(buffer);
1416 +
1417 +       return sa.base.error;
1418 +}
1419 +
1420 +int apparmor_bprm_secureexec(struct linux_binprm *bprm)
1421 +{
1422 +       int ret = cap_bprm_secureexec(bprm);
1423 +
1424 +       /* the decision to use secure exec is computed in set_creds
1425 +        * and stored in bprm->unsafe.  The AppArmor X_UNSAFE flag is
1426 +        * indicates don't 
1427 +        */
1428 +       if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
1429 +               ret = 1;
1430 +
1431 +       return ret;
1432 +}
1433 +
1434 +
1435 +static int aa_revalidate_perm(struct aa_profile *profile, struct file *file,
1436 +                             char *buffer, int size)
1437 +{
1438 +       umode_t mode = file->f_path.dentry->d_inode->i_mode;
1439 +       char *name;
1440 +       int error;
1441 +
1442 +       error = aa_get_name_to_buffer(&file->f_path, S_ISDIR(mode), buffer,
1443 +                                     size, &name);
1444 +       return aa_file_common_perm(profile, "file_inherit", file,
1445 +                                  aa_map_file_to_perms(file), name,
1446 +                                  error);
1447 +}
1448 +
1449 +static void revalidate_file(struct aa_profile *profile, struct file *file,
1450 +                           unsigned long i, char *buffer, int size,
1451 +                           struct cred *cred)
1452 +{
1453 +       if (aa_revalidate_perm(profile, file, buffer, size)) {
1454 +               struct file *devnull = NULL;
1455 +               int fd = get_unused_fd();
1456 +               sys_close(i);
1457 +               if (fd != i) {
1458 +                       if (fd >= 0)
1459 +                               put_unused_fd(fd);
1460 +                       return;
1461 +               }
1462 +               if (devnull) {
1463 +                       get_file(devnull);
1464 +               } else if (apparmorfs_null) {
1465 +                       devnull = dentry_open(dget(apparmorfs_null),
1466 +                                             mntget(apparmorfs_mnt),
1467 +                                             O_RDWR, cred);
1468 +                       if (IS_ERR(devnull)) {
1469 +                               devnull = NULL;
1470 +                               put_unused_fd(fd);
1471 +                               return;
1472 +                       }
1473 +               } else {
1474 +                       /* apparmorfs_null not setup */
1475 +                       put_unused_fd(fd);
1476 +                       return;
1477 +               }
1478 +               fd_install(fd, devnull);
1479 +       }
1480 +}
1481 +
1482 +/* 
1483 + * derived from security/selinux/hooks.c: flush_unauthorized_files &&
1484 + * fs/exec.c:flush_old_files
1485 + */
1486 +static int revalidate_files(struct aa_profile *profile,
1487 +                           struct files_struct *files, gfp_t gfp,
1488 +                           struct cred *cred)
1489 +{
1490 +       struct file *file;
1491 +       struct fdtable *fdt;
1492 +       long j = -1;
1493 +       char *buffer = kmalloc(g_apparmor_path_max, gfp);
1494 +       if (!buffer)
1495 +               return -ENOMEM;
1496 +
1497 +       spin_lock(&files->file_lock);
1498 +       for (;;) {
1499 +               unsigned long set, i;
1500 +
1501 +               j++;
1502 +               i = j * __NFDBITS;
1503 +               fdt = files_fdtable(files);
1504 +               if (i >= fdt->max_fds)
1505 +                       break;
1506 +               set = fdt->open_fds->fds_bits[j];
1507 +               if (!set)
1508 +                       continue;
1509 +               spin_unlock(&files->file_lock);
1510 +               for ( ; set ; i++,set >>= 1) {
1511 +                       if (set & 1) {
1512 +                               file = fget(i);
1513 +                               if (!file)
1514 +                                       continue;
1515 +                               revalidate_file(profile, file, i, buffer,
1516 +                                               g_apparmor_path_max, cred);
1517 +                               fput(file);
1518 +                       }
1519 +               }
1520 +               spin_lock(&files->file_lock);
1521 +       }
1522 +       spin_unlock(&files->file_lock); 
1523 +       kfree(buffer);
1524 +       return 0;
1525 +}
1526 +
1527 +int apparmor_bprm_committing_creds(struct linux_binprm *bprm)
1528 +{
1529 +       struct aa_profile *profile;
1530 +       struct cred *cred = aa_get_task_policy(current, &profile);
1531 +       struct aa_task_context *new_cxt = bprm->cred->security;
1532 +       int error;
1533 +
1534 +       if ((new_cxt->sys.profile == profile) ||
1535 +           (new_cxt->sys.profile->flags & PFLAG_UNCONFINED)) {
1536 +               put_cred(cred);
1537 +               return 0;
1538 +       }
1539 +       put_cred(cred);
1540 +
1541 +       error = revalidate_files(new_cxt->sys.profile, current->files,
1542 +                                GFP_KERNEL, bprm->cred);
1543 +       if (error)
1544 +               return error;
1545 +
1546 +       current->pdeath_signal = 0;
1547 +
1548 +       /* reset soft limits and set hard limits for the new profile */
1549 +       __aa_transition_rlimits(profile, new_cxt->sys.profile);
1550 +       return 0;
1551 +}
1552 +
1553 +void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
1554 +{
1555 +       /* TODO: cleanup signals - ipc mediation */
1556 +       return;
1557 +}
1558 +
1559 +/**
1560 + * aa_change_hat - change hat to/from subprofile
1561 + * @hat_name: hat to change to
1562 + * @token: magic value to validate the hat change
1563 + * @permtest: true if this is just a permission test
1564 + *
1565 + * Change to new @hat_name, and store the @hat_magic in the current task
1566 + * context.  If the new @hat_name is %NULL and the @token matches that
1567 + * stored in the current task context and is not 0, return to the top level
1568 + * profile.
1569 + * Returns %0 on success, error otherwise.
1570 + */
1571 +int aa_change_hat(const char *hat_name, u64 token, int permtest)
1572 +{
1573 +       const struct cred *cred;
1574 +       struct aa_task_context *cxt;
1575 +       struct aa_profile *profile, *previous_profile, *hat = NULL;
1576 +       struct aa_audit_file sa;
1577 +
1578 +       memset(&sa, 0, sizeof(sa));
1579 +       sa.base.gfp_mask = GFP_KERNEL;
1580 +       sa.base.operation = "change_hat";
1581 +
1582 +       cred = aa_current_policy(&profile);
1583 +       cxt = cred->security;
1584 +       previous_profile = cxt->sys.previous;
1585 +       token = cxt->sys.token;
1586 +
1587 +       if (!profile) {
1588 +               sa.base.info = "unconfined";
1589 +               sa.base.error = -EPERM;
1590 +               goto audit;
1591 +       }
1592 +
1593 +       if (hat_name) {
1594 +               if (previous_profile)
1595 +                       sa.name = previous_profile->fqname;
1596 +               else
1597 +                       sa.name = profile->fqname;
1598 +
1599 +               sa.name2 = profile->ns->base.name;
1600 +
1601 +               if (PROFILE_IS_HAT(profile))
1602 +                       hat = aa_find_child(profile->parent, hat_name);
1603 +               else
1604 +                       hat = aa_find_child(profile, hat_name);
1605 +               if (!hat) {
1606 +                       sa.base.info = "hat not found";
1607 +                       sa.base.error = -ENOENT;
1608 +                       if (permtest || !PROFILE_COMPLAIN(profile))
1609 +                               goto audit;
1610 +                       hat = aa_alloc_null_profile(profile, 1);
1611 +                       if (!hat) {
1612 +                               sa.base.info = "failed null profile create";
1613 +                               sa.base.error = -ENOMEM;
1614 +                               goto audit;
1615 +                       }
1616 +               } else if (!PROFILE_IS_HAT(hat)) {
1617 +                       sa.base.info = "target not hat";
1618 +                       sa.base.error = -EPERM;
1619 +                       goto audit;
1620 +               }
1621 +
1622 +               sa.base.error = aa_may_change_ptraced_domain(current, hat);
1623 +               if (sa.base.error) {
1624 +                       sa.base.info = "ptraced";
1625 +                       sa.base.error = -EPERM;
1626 +                       goto audit;
1627 +               }
1628 +
1629 +               if (!permtest) {
1630 +                       sa.base.error = aa_set_current_hat(hat, token);
1631 +                       if (sa.base.error == -EACCES) {
1632 +                               (void)send_sig_info(SIGKILL, NULL, current);
1633 +                               sa.base.error = aa_audit(AUDIT_APPARMOR_KILL,
1634 +                                                        profile, &sa.base,
1635 +                                                        file_audit_cb);
1636 +                               goto out;
1637 +                       }
1638 +               }
1639 +       } else if (previous_profile)
1640 +               sa.base.error = aa_restore_previous_profile(token);
1641 +       /* else
1642 +                ignore restores when there is no saved profile
1643 +       */
1644 +
1645 +audit:
1646 +       if (!permtest)
1647 +               sa.base.error = aa_audit_file(profile, &sa);
1648 +
1649 +
1650 +out:
1651 +       aa_put_profile(hat);
1652 +
1653 +       return sa.base.error;
1654 +}
1655 +
1656 +/**
1657 + * aa_change_profile - perform a one-way profile transition
1658 + * @ns_name: name of the profile namespace to change to
1659 + * @fqname: name of profile to change to
1660 + * @onexec: whether this transition is to take place immediately or at exec
1661 + * @permtest: true if this is just a permission test
1662 + *
1663 + * Change to new profile @name.  Unlike with hats, there is no way
1664 + * to change back.  If @onexec then the transition is delayed until
1665 + * the next exec.
1666 + *
1667 + * Returns %0 on success, error otherwise.
1668 + */
1669 +int aa_change_profile(const char *ns_name, const char *fqname, int onexec,
1670 +                     int permtest)
1671 +{
1672 +       const struct cred *cred;
1673 +       struct aa_task_context *cxt;
1674 +       struct aa_profile *profile, *target = NULL;
1675 +       struct aa_namespace *ns = NULL;
1676 +       struct aa_audit_file sa;
1677 +       char *name = NULL;
1678 +
1679 +       if (!name && !ns_name)
1680 +               return -EINVAL;
1681 +
1682 +       memset(&sa, 0, sizeof(sa));
1683 +       sa.base.gfp_mask = GFP_KERNEL;
1684 +       if (onexec)
1685 +               sa.base.operation = "change_onexec";
1686 +       else
1687 +               sa.base.operation = "change_profile";
1688 +
1689 +       cred = aa_current_policy(&profile);
1690 +       cxt = cred->security;
1691 +       ns = aa_get_namespace(cxt->sys.profile->ns);
1692 +
1693 +       if (ns_name) {
1694 +               sa.name2 = ns_name;
1695 +               aa_put_namespace(ns);
1696 +               ns = aa_find_namespace(ns_name);
1697 +               if (!ns) {
1698 +                       /* we don't create new namespace in complain mode */
1699 +                       sa.base.info = "namespace not found";
1700 +                       sa.base.error = -ENOENT;
1701 +                       goto audit;
1702 +               }
1703 +       } else
1704 +               sa.name2 = ns->base.name;
1705 +
1706 +       /* if the name was not specified, use the name of the current profile */
1707 +       if (!fqname) {
1708 +               if (!profile)
1709 +                       fqname = ns->unconfined->fqname;
1710 +               else
1711 +                       fqname = profile->fqname;
1712 +       }
1713 +       sa.name = fqname;
1714 +
1715 +       sa.perms = change_profile_perms(profile, ns, fqname, NULL);
1716 +
1717 +       if (!(sa.perms.allowed & AA_MAY_CHANGE_PROFILE)) {
1718 +               sa.base.error = -EACCES;
1719 +               goto audit;
1720 +       }
1721 +
1722 +       target = aa_find_profile_by_fqname(ns, fqname);
1723 +       if (!target) {
1724 +               sa.base.info = "profile not found";
1725 +               sa.base.error = -ENOENT;
1726 +               if (permtest || !PROFILE_COMPLAIN(profile))
1727 +                       goto audit;
1728 +               target = aa_alloc_null_profile(profile, 0);
1729 +       }
1730 +       
1731 +       /* check if tracing task is allowed to trace target domain */
1732 +       sa.base.error = aa_may_change_ptraced_domain(current, target);
1733 +       if (sa.base.error) {
1734 +               sa.base.info = "ptrace prevents transition";
1735 +               goto audit;
1736 +       }
1737 +
1738 +       if (permtest)
1739 +               goto audit;
1740 +
1741 +       if (onexec)
1742 +               sa.base.error = aa_set_current_onexec(target);
1743 +       else
1744 +               sa.base.error = aa_replace_current_profiles(target);
1745 +
1746 +audit:
1747 +       if (!permtest)
1748 +               sa.base.error = aa_audit_file(profile, &sa);
1749 +
1750 +       aa_put_namespace(ns);
1751 +       aa_put_profile(target);
1752 +
1753 +       return sa.base.error;
1754 +}
1755 diff --git a/security/apparmor/file.c b/security/apparmor/file.c
1756 new file mode 100644
1757 index 0000000..fdade01
1758 --- /dev/null
1759 +++ b/security/apparmor/file.c
1760 @@ -0,0 +1,425 @@
1761 +/*
1762 + * AppArmor security module
1763 + *
1764 + * This file contains AppArmor mediation of files
1765 + *
1766 + * Copyright (C) 1998-2008 Novell/SUSE
1767 + * Copyright 2009 Canonical Ltd.
1768 + *
1769 + * This program is free software; you can redistribute it and/or
1770 + * modify it under the terms of the GNU General Public License as
1771 + * published by the Free Software Foundation, version 2 of the
1772 + * License.
1773 + */
1774 +
1775 +#include "include/apparmor.h"
1776 +#include "include/audit.h"
1777 +#include "include/file.h"
1778 +#include "include/match.h"
1779 +#include "include/path.h"
1780 +#include "include/policy.h"
1781 +
1782 +struct file_perms nullperms;
1783 +
1784 +static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
1785 +                                  u16 mask, u16 xindex)
1786 +{
1787 +
1788 +  /*   const char xchar[] = "PpCc";*/
1789 +
1790 +       char *m = buffer;
1791 +
1792 +       if (mask & AA_EXEC_MMAP)
1793 +               *m++ = 'm';
1794 +       if (mask & MAY_READ)
1795 +               *m++ = 'r';
1796 +       if (mask & (MAY_WRITE | AA_MAY_CREATE))
1797 +               *m++ = 'w';
1798 +       else if (mask & MAY_APPEND)
1799 +               *m++ = 'a';
1800 +       if (mask & AA_MAY_LINK)
1801 +               *m++ = 'l';
1802 +       if (mask & AA_MAY_LOCK)
1803 +               *m++ = 'k';
1804 +       if (mask & MAY_EXEC) {
1805 +               *m++ = 'x';
1806 +
1807 +/* FIXME: only want more advanced auditing of x if in audit/hint mode
1808 +               u16 index = xindex & AA_X_INDEX_MASK;
1809 +               u16 xtype = xindex & AA_X_TYPE_MASK;
1810 +               if (xtype > AA_X_NONE)
1811 +                       *m++ = xchar[(xindex >> 12) & 0x3];
1812 +               if (xindex & AA_X_INHERIT) {
1813 +                       *m++ = 'i';
1814 +               } else if (xindex & AA_X_UNCONFINED) {
1815 +                       if (xindex & AA_X_UNSAFE)
1816 +                               *m++ = 'u';
1817 +                       else
1818 +                               *m++ = 'U';
1819 +               }
1820 +               *m++ = 'x';
1821 +               / * at most 7 character including trailing \0 * /
1822 +               if (xtype == AA_X_VARIABLE) {
1823 +                       m += sprintf(m, "->v%x", index);
1824 +               } else if (xtype == AA_X_TABLE) {
1825 +                       m += sprintf(m, "->n%x", index);
1826 +               }
1827 +*/
1828 +       }
1829 +       *m++ = '\0';
1830 +}
1831 +
1832 +static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
1833 +                              u16 mask, int xindex, int owner)
1834 +{
1835 +/*     char str[18]; */
1836 +       char str[10];
1837 +
1838 +       aa_audit_file_sub_mask(ab, str, mask, xindex);
1839 +       if (owner)
1840 +               audit_log_format(ab, " %s=\"%s::\"", name, str);
1841 +       else
1842 +               audit_log_format(ab, " %s=\"::%s\"", name, str);
1843 +}
1844 +
1845 +void file_audit_cb(struct audit_buffer *ab, void *va)
1846 +{
1847 +       struct aa_audit_file *sa = va;
1848 +       u16 denied = sa->request & ~sa->perms.allowed;
1849 +       uid_t fsuid;
1850 +
1851 +       if (sa->base.task)
1852 +               fsuid = task_uid(sa->base.task);
1853 +       else
1854 +               fsuid = current_fsuid();
1855 +
1856 +       if (sa->request & AA_AUDIT_FILE_MASK)
1857 +               aa_audit_file_mask(ab, "requested_mask", sa->request,
1858 +                                  AA_X_NONE, fsuid == sa->cond->uid);
1859 +
1860 +       if (denied & AA_AUDIT_FILE_MASK)
1861 +               aa_audit_file_mask(ab, "denied_mask", denied, sa->perms.xindex,
1862 +                       fsuid == sa->cond->uid);
1863 +
1864 +       if (sa->request & AA_AUDIT_FILE_MASK) {
1865 +               audit_log_format(ab, " fsuid=%d", fsuid);
1866 +               audit_log_format(ab, " ouid=%d", sa->cond->uid);
1867 +       }
1868 +
1869 +       if (sa->name) {
1870 +               audit_log_format(ab, " name=");
1871 +               audit_log_untrustedstring(ab, sa->name);
1872 +       }
1873 +
1874 +       if (sa->name2) {
1875 +               audit_log_format(ab, " name2=");
1876 +               audit_log_untrustedstring(ab, sa->name2);
1877 +       }
1878 +
1879 +       if (sa->name3) {
1880 +               audit_log_format(ab, " name3=");
1881 +               audit_log_untrustedstring(ab, sa->name3);
1882 +       }
1883 +}
1884 +
1885 +int aa_audit_file(struct aa_profile *profile, struct aa_audit_file *sa)
1886 +{
1887 +       int type = AUDIT_APPARMOR_AUTO;
1888 +
1889 +       if (likely(!sa->base.error)) {
1890 +               u16 mask = sa->perms.audit;
1891 +
1892 +               if (unlikely(PROFILE_AUDIT_MODE(profile) == AUDIT_ALL))
1893 +                       mask = 0xffff;
1894 +
1895 +               /* mask off perms that are not being force audited */
1896 +               sa->request &= mask;
1897 +
1898 +               if (likely(!sa->request))
1899 +                       return 0;
1900 +       } else {
1901 +               /* quiet auditing of specific known rejects */
1902 +               u16 mask = sa->perms.quiet;
1903 +               u16 denied = sa->request & ~sa->perms.allowed;
1904 +
1905 +               if (denied & sa->perms.kill)
1906 +                       type = AUDIT_APPARMOR_KILL;
1907 +
1908 +               /* assumes quiet and kill do not overlap */
1909 +               if ((denied & mask) &&
1910 +                   PROFILE_AUDIT_MODE(profile) != AUDIT_NOQUIET &&
1911 +                   PROFILE_AUDIT_MODE(profile) != AUDIT_ALL)
1912 +                       sa->request &= ~mask;
1913 +
1914 +               if (!sa->request)
1915 +                       return PROFILE_COMPLAIN(profile) ? 0 : sa->base.error;
1916 +       }
1917 +       return aa_audit(type, profile, (struct aa_audit *)sa, file_audit_cb);
1918 +}
1919 +
1920 +/* FIXME: convert from dfa + state to permission entry */
1921 +struct file_perms aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
1922 +                                  struct path_cond *cond)
1923 +{
1924 +       struct file_perms perms;
1925 +
1926 +       /* FIXME: change over to new dfa format */
1927 +       /* currently file perms are encoded in the dfa */
1928 +       perms.kill = 0;
1929 +       perms.dindex = 0;
1930 +
1931 +       if (current_fsuid() == cond->uid) {
1932 +               perms.allowed = dfa_user_allow(dfa, state);
1933 +               perms.audit = dfa_user_audit(dfa, state);
1934 +               perms.quiet = dfa_user_quiet(dfa, state);
1935 +               perms.xindex = dfa_user_xindex(dfa, state);
1936 +       } else {
1937 +               perms.allowed = dfa_other_allow(dfa, state);
1938 +               perms.audit = dfa_other_audit(dfa, state);
1939 +               perms.quiet = dfa_other_quiet(dfa, state);
1940 +               perms.xindex = dfa_other_xindex(dfa, state);
1941 +       }
1942 +       /* in the old mapping MAY_WRITE implies AA_MAY_CREATE */
1943 +       perms.allowed |= (perms.allowed & MAY_WRITE) << 6;
1944 +       perms.audit |= (perms.audit & MAY_WRITE) << 6;
1945 +       perms.quiet |= (perms.quiet & MAY_WRITE) << 6;
1946 +
1947 +       /* in the old mapping AA_MAY_LOCK and link subset are overlayed
1948 +        * and only determined by which part of a pair they are  in
1949 +        */
1950 +       if (perms.allowed & AA_MAY_LOCK)
1951 +               perms.allowed |= AA_LINK_SUBSET;
1952 +
1953 +       /* change_profile wasn't determined by ownership in old mapping */
1954 +       if (ACCEPT_TABLE2(dfa)[state] & 0x80000000)
1955 +               perms.allowed |= AA_MAY_CHANGE_PROFILE;
1956 +
1957 +       return perms;
1958 +}
1959 +
1960 +struct file_perms aa_str_perms(struct aa_dfa *dfa, unsigned int start,
1961 +                              const char *name, struct path_cond *cond,
1962 +                              unsigned int *rstate)
1963 +{
1964 +       unsigned int state;
1965 +       if (!dfa)
1966 +               return nullperms;
1967 +
1968 +       state = aa_dfa_match(dfa, start, name);
1969 +
1970 +       if (rstate)
1971 +               *rstate = state;
1972 +
1973 +       /* TODO: convert to new dfa format */
1974 +
1975 +       return aa_compute_perms(dfa, state, cond);
1976 +}
1977 +
1978 +int aa_pathstr_perm(struct aa_profile *profile, const char *op,
1979 +                   const char *name, u16 request, struct path_cond *cond)
1980 +{
1981 +       struct aa_audit_file sa;
1982 +
1983 +       memset(&sa, 0, sizeof(sa));
1984 +       sa.base.operation = op;
1985 +       sa.base.gfp_mask = GFP_KERNEL;
1986 +       sa.request = request;
1987 +       sa.name = name;
1988 +       sa.cond = cond;
1989 +
1990 +       sa.perms = aa_str_perms(profile->file.dfa, DFA_START, sa.name, cond,
1991 +                               NULL);
1992 +       if (request & ~sa.perms.allowed)
1993 +               sa.base.error = -EACCES;
1994 +       return aa_audit_file(profile, &sa);
1995 +}
1996 +
1997 +int aa_path_perm(struct aa_profile *profile, const char *operation,
1998 +                struct path *path, u16 request, struct path_cond *cond)
1999 +{
2000 +       struct aa_audit_file sa;
2001 +       char *buffer, *name;
2002 +
2003 +       memset(&sa, 0, sizeof(sa));
2004 +       sa.base.operation = operation;
2005 +       sa.base.gfp_mask = GFP_KERNEL;
2006 +       sa.request = request;
2007 +       sa.cond = cond;
2008 +
2009 +       sa.base.error = aa_get_name(path, S_ISDIR(cond->mode), &buffer,
2010 +                                   &name);
2011 +       sa.name = name;
2012 +       if (sa.base.error) {
2013 +               sa.perms = nullperms;
2014 +               if (sa.base.error == -ENOENT)
2015 +                       sa.base.info = "Failed name lookup - deleted entry";
2016 +               else if (sa.base.error == -ESTALE)
2017 +                       sa.base.info = "Failed name lookup - disconnected path";
2018 +               else if (sa.base.error == -ENAMETOOLONG)
2019 +                       sa.base.info = "Failed name lookup - name too long";
2020 +               else
2021 +                       sa.base.info = "Failed name lookup";
2022 +       } else {
2023 +               sa.perms = aa_str_perms(profile->file.dfa, DFA_START, sa.name,
2024 +                                       cond, NULL);
2025 +               if (request & ~sa.perms.allowed)
2026 +                       sa.base.error = -EACCES;
2027 +       }
2028 +       sa.base.error = aa_audit_file(profile, &sa);
2029 +       kfree(buffer);
2030 +
2031 +       return sa.base.error;
2032 +}
2033 +
2034 +int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
2035 +                struct path *new_dir, struct dentry *new_dentry)
2036 +{
2037 +       struct path link = { new_dir->mnt, new_dentry };
2038 +       struct path target = { new_dir->mnt, old_dentry };
2039 +       struct path_cond cond = { old_dentry->d_inode->i_uid,
2040 +                                 old_dentry->d_inode->i_mode };
2041 +       char *buffer = NULL, *buffer2 = NULL;
2042 +       char *lname, *tname;
2043 +       struct file_perms perms;
2044 +       unsigned int state;
2045 +
2046 +       struct aa_audit_file sa;
2047 +       memset(&sa, 0, sizeof(sa));
2048 +       sa.base.operation = "link";
2049 +       sa.base.gfp_mask = GFP_KERNEL;
2050 +       sa.request = AA_MAY_LINK;
2051 +       sa.cond = &cond;
2052 +       sa.perms = nullperms;
2053 +
2054 +       sa.base.error = aa_get_name(&link, 0, &buffer, &lname);
2055 +       sa.name = lname;
2056 +       if (sa.base.error)
2057 +               goto audit;
2058 +
2059 +       sa.base.error = aa_get_name(&target, 0, &buffer2, &tname);
2060 +       sa.name2 = tname;
2061 +       if (sa.base.error)
2062 +               goto audit;
2063 +
2064 +
2065 +       sa.perms = aa_str_perms(profile->file.dfa, DFA_START, sa.name, &cond,
2066 +                            &state);
2067 +       sa.perms.audit &= AA_MAY_LINK;
2068 +       sa.perms.quiet &= AA_MAY_LINK;
2069 +       sa.perms.kill &= AA_MAY_LINK;
2070 +
2071 +       if (!(sa.perms.allowed & AA_MAY_LINK)) {
2072 +               sa.base.error = -EACCES;
2073 +               goto audit;
2074 +       }
2075 +
2076 +       /* test to see if target can be paired with link */
2077 +       state = aa_dfa_null_transition(profile->file.dfa, state);
2078 +       perms = aa_str_perms(profile->file.dfa, state, sa.name2, &cond, NULL);
2079 +       if (!(perms.allowed & AA_MAY_LINK)) {
2080 +               sa.base.error = -EACCES;
2081 +               sa.base.info = "target restricted";
2082 +               goto audit;
2083 +       }
2084 +
2085 +       /* done if link subset test is not required */
2086 +       if (!(perms.allowed & AA_LINK_SUBSET))
2087 +               goto audit;
2088 +
2089 +       /* Do link perm subset test requiring allowed permission on link are a
2090 +        * subset of the allowed permissions on target.
2091 +        */
2092 +       perms = aa_str_perms(profile->file.dfa, DFA_START, sa.name2, &cond,
2093 +                            NULL);
2094 +
2095 +       /* AA_MAY_LINK is not considered in the subset test */
2096 +       sa.request = sa.perms.allowed & ~AA_MAY_LINK;
2097 +       sa.perms.allowed &= perms.allowed | AA_MAY_LINK;
2098 +
2099 +       sa.request |= AA_AUDIT_FILE_MASK & (sa.perms.allowed & ~perms.allowed);
2100 +       if (sa.request & ~sa.perms.allowed)
2101 +               sa.base.error = -EACCES;
2102 +       else if (sa.perms.allowed & MAY_EXEC) {
2103 +               if (((sa.perms.xindex & ~AA_X_UNSAFE) !=
2104 +                    (perms.xindex &~AA_X_UNSAFE)) ||
2105 +                   ((sa.perms.xindex & AA_X_UNSAFE) &&
2106 +                    !(perms.xindex & AA_X_UNSAFE))) {
2107 +                       sa.perms.allowed &= ~MAY_EXEC;
2108 +                       sa.request |= MAY_EXEC;
2109 +                       sa.base.error = -EACCES;
2110 +                       sa.base.info = "link not subset of target";
2111 +               }
2112 +       }
2113 +
2114 +audit:
2115 +       sa.base.error = aa_audit_file(profile, &sa);
2116 +       kfree(buffer);
2117 +       kfree(buffer2);
2118 +
2119 +       return sa.base.error;
2120 +}
2121 +
2122 +
2123 +static inline int aa_is_deleted_file(struct dentry *dentry)
2124 +{
2125 +       if (d_unhashed(dentry) && dentry->d_inode->i_nlink == 0)
2126 +               return 1;
2127 +       return 0;
2128 +}
2129 +
2130 +int aa_file_common_perm(struct aa_profile *profile, const char *operation,
2131 +                       struct file *file, u16 request, const char *name,
2132 +                       int error)
2133 +{
2134 +       struct path_cond cond = { .uid = file->f_path.dentry->d_inode->i_uid,
2135 +                                .mode = file->f_path.dentry->d_inode->i_mode };
2136 +       struct aa_audit_file sa;
2137 +
2138 +       memset(&sa, 0, sizeof(sa));
2139 +       sa.base.operation = operation;
2140 +       sa.base.gfp_mask = GFP_KERNEL;
2141 +       sa.request = request;
2142 +       sa.base.error = error;
2143 +       sa.name = name;
2144 +       sa.cond = &cond;
2145 +
2146 +       if (sa.base.error) {
2147 +               sa.perms = nullperms;
2148 +               if (sa.base.error == -ENOENT &&
2149 +                   aa_is_deleted_file(file->f_path.dentry)) {
2150 +                       /* Access to open files that are deleted are
2151 +                        * give a pass (implicit delegation
2152 +                        */
2153 +                       sa.base.error = 0;
2154 +                       sa.perms.allowed = sa.request;
2155 +               } else if (sa.base.error == -ENOENT)
2156 +                       sa.base.info = "Failed name lookup - deleted entry";
2157 +               else if (sa.base.error == -ESTALE)
2158 +                       sa.base.info = "Failed name lookup - disconnected path";
2159 +               else if (sa.base.error == -ENAMETOOLONG)
2160 +                       sa.base.info = "Failed name lookup - name too long";
2161 +               else
2162 +                       sa.base.info = "Failed name lookup";
2163 +       } else {
2164 +               sa.perms = aa_str_perms(profile->file.dfa, DFA_START, sa.name,
2165 +                                       &cond, NULL);
2166 +               if (request & ~sa.perms.allowed)
2167 +                       sa.base.error = -EACCES;
2168 +       }
2169 +       sa.base.error = aa_audit_file(profile, &sa);
2170 +
2171 +       return sa.base.error;
2172 +}
2173 +
2174 +int aa_file_perm(struct aa_profile *profile, const char *operation,
2175 +                struct file *file, u16 request)
2176 +{
2177 +       char *buffer, *name;
2178 +       umode_t mode = file->f_path.dentry->d_inode->i_mode;
2179 +       int error = aa_get_name(&file->f_path, S_ISDIR(mode), &buffer, &name);
2180 +
2181 +       error = aa_file_common_perm(profile, operation, file, request, name,
2182 +                                   error);
2183 +       kfree(buffer);
2184 +       return error;
2185 +}
2186 diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
2187 new file mode 100644
2188 index 0000000..fbbc961
2189 --- /dev/null
2190 +++ b/security/apparmor/include/apparmor.h
2191 @@ -0,0 +1,65 @@
2192 +/*
2193 + * AppArmor security module
2194 + *
2195 + * This file contains AppArmor basic global and lib definitions
2196 + *
2197 + * Copyright (C) 1998-2008 Novell/SUSE
2198 + * Copyright 2009 Canonical Ltd.
2199 + *
2200 + * This program is free software; you can redistribute it and/or
2201 + * modify it under the terms of the GNU General Public License as
2202 + * published by the Free Software Foundation, version 2 of the
2203 + * License.
2204 + */
2205 +
2206 +#ifndef __APPARMOR_H
2207 +#define __APPARMOR_H
2208 +
2209 +#include <linux/fs.h>
2210 +
2211 +/* Control parameters settable thru module/boot flags or
2212 + * via /sys/kernel/security/apparmor/control */
2213 +extern enum audit_mode g_apparmor_audit;
2214 +extern int g_apparmor_audit_header;
2215 +extern int g_apparmor_debug;
2216 +extern int g_apparmor_lock_policy;
2217 +extern int g_apparmor_logsyscall;
2218 +extern unsigned int g_apparmor_path_max;
2219 +
2220 +
2221 +/*
2222 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
2223 + * which is not related to profile accesses.
2224 + */
2225 +
2226 +#define AA_DEBUG(fmt, args...)                                         \
2227 +       do {                                                            \
2228 +               if (g_apparmor_debug && printk_ratelimit())             \
2229 +                       printk(KERN_DEBUG "AppArmor: " fmt, ##args);    \
2230 +       } while (0)
2231 +
2232 +#define AA_ERROR(fmt, args...)                                         \
2233 +       do {                                                            \
2234 +               if (printk_ratelimit())                                 \
2235 +                       printk(KERN_ERR "AppArmor: " fmt, ##args);      \
2236 +       } while (0)
2237 +
2238 +/* Flag indicating whether initialization completed */
2239 +extern int apparmor_initialized;
2240 +void apparmor_disable(void);
2241 +
2242 +/* fn's in lib */
2243 +void info_message(const char *str);
2244 +char *aa_split_name_from_ns(char *args, char **ns_name);
2245 +char *new_compound_name(const char *n1, const char *n2);
2246 +int aa_strneq(const char *str, const char *sub, int len);
2247 +char *strchrnul(const char *s, int c);
2248 +const char *fqname_subname(const char *name);
2249 +
2250 +static inline int mediated_filesystem(struct inode *inode)
2251 +{
2252 +       return !(inode->i_sb->s_flags & MS_NOUSER);
2253 +}
2254 +
2255 +#endif /* __APPARMOR_H */
2256 +
2257 diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
2258 new file mode 100644
2259 index 0000000..1af7723
2260 --- /dev/null
2261 +++ b/security/apparmor/include/apparmorfs.h
2262 @@ -0,0 +1,24 @@
2263 +/*
2264 + * AppArmor security module
2265 + *
2266 + * This file contains AppArmor filesystem definitions.
2267 + *
2268 + * Copyright (C) 1998-2008 Novell/SUSE
2269 + * Copyright 2009 Canonical Ltd.
2270 + *
2271 + * This program is free software; you can redistribute it and/or
2272 + * modify it under the terms of the GNU General Public License as
2273 + * published by the Free Software Foundation, version 2 of the
2274 + * License.
2275 + */
2276 +
2277 +#ifndef __AA_APPARMORFS_H
2278 +#define __AA_APPARMORFS_H
2279 +
2280 +extern struct dentry *apparmorfs_null;
2281 +extern struct vfsmount *apparmorfs_mnt;
2282 +
2283 +extern int create_apparmorfs(void);
2284 +extern void destroy_apparmorfs(void);
2285 +
2286 +#endif /* __AA_APPARMORFS_H */
2287 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
2288 new file mode 100644
2289 index 0000000..2180dd7
2290 --- /dev/null
2291 +++ b/security/apparmor/include/audit.h
2292 @@ -0,0 +1,59 @@
2293 +/*
2294 + * AppArmor security module
2295 + *
2296 + * This file contains AppArmor auditing function definitions.
2297 + *
2298 + * Copyright (C) 1998-2008 Novell/SUSE
2299 + * Copyright 2009 Canonical Ltd.
2300 + *
2301 + * This program is free software; you can redistribute it and/or
2302 + * modify it under the terms of the GNU General Public License as
2303 + * published by the Free Software Foundation, version 2 of the
2304 + * License.
2305 + */
2306 +
2307 +#ifndef __AA_AUDIT_H
2308 +#define __AA_AUDIT_H
2309 +
2310 +#include <linux/audit.h>
2311 +#include <linux/fs.h>
2312 +#include <linux/sched.h>
2313 +#include <linux/slab.h>
2314 +
2315 +struct aa_profile;
2316 +
2317 +
2318 +extern const char *audit_mode_names[];
2319 +#define AUDIT_MAX_INDEX 5
2320 +
2321 +#define AUDIT_APPARMOR_AUTO 0  /* auto choose audit message type */
2322 +
2323 +enum audit_mode {
2324 +       AUDIT_NORMAL,           /* follow normal auditing of accesses */
2325 +       AUDIT_QUIET_DENIED,     /* quiet all denied access messages */
2326 +       AUDIT_QUIET,            /* quiet all messages */
2327 +       AUDIT_NOQUIET,          /* do not quiet audit messages */
2328 +       AUDIT_ALL               /* audit all accesses */
2329 +};
2330 +
2331 +/*
2332 + * aa_audit - AppArmor auditing structure
2333 + * Structure is populated by access control code and passed to aa_audit which
2334 + * provides for a single point of logging.
2335 + */
2336 +struct aa_audit {
2337 +       struct task_struct *task;
2338 +       gfp_t gfp_mask;
2339 +       int error;
2340 +       const char *operation;
2341 +       const char *info;
2342 +};
2343 +
2344 +int aa_audit(int type, struct aa_profile *profile, struct aa_audit *sa,
2345 +            void(*cb)(struct audit_buffer *, void *));
2346 +
2347 +int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp, const char *,
2348 +                          void(*cb)(struct audit_buffer *, void *));
2349 +
2350 +
2351 +#endif /* __AA_AUDIT_H */
2352 diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
2353 new file mode 100644
2354 index 0000000..43bb7eb
2355 --- /dev/null
2356 +++ b/security/apparmor/include/capability.h
2357 @@ -0,0 +1,45 @@
2358 +/*
2359 + * AppArmor security module
2360 + *
2361 + * This file contains AppArmor capability mediation definitions.
2362 + *
2363 + * Copyright (C) 1998-2008 Novell/SUSE
2364 + * Copyright 2009 Canonical Ltd.
2365 + *
2366 + * This program is free software; you can redistribute it and/or
2367 + * modify it under the terms of the GNU General Public License as
2368 + * published by the Free Software Foundation, version 2 of the
2369 + * License.
2370 + */
2371 +
2372 +#ifndef __AA_CAPABILITY_H
2373 +#define __AA_CAPABILITY_H
2374 +
2375 +#include <linux/sched.h>
2376 +
2377 +struct aa_profile;
2378 +
2379 +/* aa_caps - confinement data for capabilities
2380 + * @set_caps: capabilities that are being set
2381 + * @capabilities: capabilities mask
2382 + * @audit_caps: caps that are to be audited
2383 + * @quiet_caps: caps that should not be audited
2384 + */
2385 +struct aa_caps {
2386 +       kernel_cap_t set;
2387 +       kernel_cap_t allowed;
2388 +       kernel_cap_t audit;
2389 +       kernel_cap_t quiet;
2390 +       kernel_cap_t kill;
2391 +};
2392 +
2393 +int aa_profile_capable(struct aa_profile *profile, int cap);
2394 +int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
2395 +              int audit);
2396 +
2397 +static inline void aa_free_cap_rules(struct aa_caps *caps)
2398 +{
2399 +       /* NOP */
2400 +}
2401 +
2402 +#endif /* __AA_CAPBILITY_H */
2403 diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h
2404 new file mode 100644
2405 index 0000000..202a66a
2406 --- /dev/null
2407 +++ b/security/apparmor/include/context.h
2408 @@ -0,0 +1,153 @@
2409 +/*
2410 + * AppArmor security module
2411 + *
2412 + * This file contains AppArmor contexts used to associate "labels" to objects.
2413 + *
2414 + * Copyright (C) 1998-2008 Novell/SUSE
2415 + * Copyright 2009 Canonical Ltd.
2416 + *
2417 + * This program is free software; you can redistribute it and/or
2418 + * modify it under the terms of the GNU General Public License as
2419 + * published by the Free Software Foundation, version 2 of the
2420 + * License.
2421 + */
2422 +
2423 +#ifndef __AA_CONTEXT_H
2424 +#define __AA_CONTEXT_H
2425 +
2426 +#include <linux/cred.h>
2427 +#include <linux/slab.h>
2428 +#include <linux/sched.h>
2429 +
2430 +#include "policy.h"
2431 +
2432 +
2433 +/* struct aa_file_cxt - the AppArmor context the file was opened in
2434 + * @profile: the profile the file was opened under
2435 + * @perms: the permission the file was opened with
2436 + */
2437 +struct aa_file_cxt {
2438 +       struct aa_profile *profile;
2439 +       u16 allowed;
2440 +};
2441 +
2442 +static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp)
2443 +{
2444 +       return kzalloc(sizeof(struct aa_file_cxt), gfp);
2445 +}
2446 +
2447 +static inline void aa_free_file_context(struct aa_file_cxt *cxt)
2448 +{
2449 +       aa_put_profile(cxt->profile);
2450 +       memset(cxt, 0, sizeof(struct aa_file_cxt));
2451 +       kfree(cxt);
2452 +}
2453 +
2454 +
2455 +
2456 +
2457 +
2458 +/* struct aa_task_cxt_group - a grouping label data for confined tasks
2459 + * @profile: the current profile
2460 + * @exec: profile to transition to on next exec
2461 + * @previous: profile the task may return to
2462 + * @token: magic value the task must know for returning to @previous_profile
2463 + *
2464 + * Contains the task's current profile (which could change due to
2465 + * change_hat).  Plus the hat_magic needed during change_hat.
2466 + */
2467 +struct aa_task_cxt_group {
2468 +       struct aa_profile *profile;
2469 +       struct aa_profile *onexec;
2470 +       struct aa_profile *previous;
2471 +       u64 token;
2472 +};
2473 +
2474 +/**
2475 + * struct aa_task_context - primary label for confined tasks
2476 + * @sys: the system labeling for the task
2477 + *
2478 + * A task is confined by the intersection of its system and user profiles
2479 + */
2480 +struct aa_task_context {
2481 +       struct aa_task_cxt_group sys;
2482 +};
2483 +
2484 +struct aa_task_context *aa_alloc_task_context(gfp_t flags);
2485 +void aa_free_task_context(struct aa_task_context *cxt);
2486 +struct aa_task_context *aa_dup_task_context(struct aa_task_context *old_cxt,
2487 +                                           gfp_t gfp);
2488 +void aa_cred_policy(const struct cred *cred, struct aa_profile **sys);
2489 +struct cred *aa_get_task_policy(const struct task_struct *task,
2490 +                               struct aa_profile **sys);
2491 +int aa_replace_current_profiles(struct aa_profile *sys);
2492 +void aa_put_task_policy(struct cred *cred);
2493 +int aa_set_current_onexec(struct aa_profile *sys);
2494 +int aa_set_current_hat(struct aa_profile *profile, u64 token);
2495 +int aa_restore_previous_profile(u64 cookie);
2496 +
2497 +
2498 +static inline struct aa_task_context *__aa_task_cxt(struct task_struct *task)
2499 +{
2500 +       return __task_cred(task)->security;
2501 +}
2502 +
2503 +/**
2504 + * __aa_task_is_confined - determine if @task has any confinement
2505 + * @task: task to check confinement of
2506 + *
2507 + * If @task != current needs to be in RCU safe critical section
2508 + */
2509 +static inline int __aa_task_is_confined(struct task_struct *task)
2510 +{
2511 +       struct aa_task_context *cxt;
2512 +       int rc = 1;
2513 +
2514 +       cxt = __aa_task_cxt(task);
2515 +       if (!cxt || (cxt->sys.profile->flags & PFLAG_UNCONFINED))
2516 +               rc = 0;
2517 +
2518 +       return rc;
2519 +}
2520 +
2521 +static inline const struct cred *aa_current_policy(struct aa_profile **sys)
2522 +{
2523 +       const struct cred *cred = current_cred();
2524 +       struct aa_task_context *cxt = cred->security;
2525 +       BUG_ON(!cxt);
2526 +       *sys = aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
2527 +
2528 +       return cred;
2529 +}
2530 +
2531 +static inline const struct cred *aa_current_policy_wupd(struct aa_profile **sys)
2532 +{
2533 +       const struct cred *cred = current_cred();
2534 +       struct aa_task_context *cxt = cred->security;
2535 +       BUG_ON(!cxt);
2536 +
2537 +       *sys = aa_profile_newest(cxt->sys.profile);
2538 +       if (unlikely((cxt->sys.profile != *sys)))
2539 +               aa_replace_current_profiles(*sys);
2540 +       *sys = aa_filtered_profile(*sys);
2541 +
2542 +       return cred;
2543 +}
2544 +
2545 +static inline struct aa_profile *aa_current_profile(void)
2546 +{
2547 +       const struct cred *cred = current_cred();
2548 +       struct aa_task_context *cxt = cred->security;
2549 +       BUG_ON(!cxt);
2550 +       return aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
2551 +}
2552 +
2553 +static inline struct aa_profile *aa_current_profile_wupd(void)
2554 +{
2555 +       struct aa_profile *p;
2556 +       aa_current_policy_wupd(&p);
2557 +       return p;
2558 +}
2559 +
2560 +
2561 +#endif /* __AA_CONTEXT_H */
2562 diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
2563 new file mode 100644
2564 index 0000000..a340e62
2565 --- /dev/null
2566 +++ b/security/apparmor/include/domain.h
2567 @@ -0,0 +1,37 @@
2568 +/*
2569 + * AppArmor security module
2570 + *
2571 + * This file contains AppArmor security domain transition function definitions.
2572 + *
2573 + * Copyright (C) 1998-2008 Novell/SUSE
2574 + * Copyright 2009 Canonical Ltd.
2575 + *
2576 + * This program is free software; you can redistribute it and/or
2577 + * modify it under the terms of the GNU General Public License as
2578 + * published by the Free Software Foundation, version 2 of the
2579 + * License.
2580 + */
2581 +
2582 +#include <linux/binfmts.h>
2583 +#include <linux/types.h>
2584 +
2585 +#ifndef __AA_DOMAIN_H
2586 +#define __AA_DOMAIN_H
2587 +
2588 +struct aa_domain {
2589 +       int size;
2590 +       char **table;
2591 +};
2592 +
2593 +int apparmor_bprm_set_creds(struct linux_binprm *bprm);
2594 +int apparmor_bprm_secureexec(struct linux_binprm *bprm);
2595 +int apparmor_bprm_committing_creds(struct linux_binprm *bprm);
2596 +void apparmor_bprm_committed_creds(struct linux_binprm *bprm);
2597 +
2598 +void aa_free_domain_entries(struct aa_domain *domain);
2599 +int aa_change_hat(const char *hat_name, u64 token, int permtest);
2600 +int aa_change_profile(const char *ns_name, const char *name, int onexec,
2601 +                     int permtest);
2602 +
2603 +
2604 +#endif /* __AA_DOMAIN_H */
2605 diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
2606 new file mode 100644
2607 index 0000000..e99e6fe
2608 --- /dev/null
2609 +++ b/security/apparmor/include/file.h
2610 @@ -0,0 +1,227 @@
2611 +/*
2612 + * AppArmor security module
2613 + *
2614 + * This file contains AppArmor file mediation function definitions.
2615 + *
2616 + * Copyright (C) 1998-2008 Novell/SUSE
2617 + * Copyright 2009 Canonical Ltd.
2618 + *
2619 + * This program is free software; you can redistribute it and/or
2620 + * modify it under the terms of the GNU General Public License as
2621 + * published by the Free Software Foundation, version 2 of the
2622 + * License.
2623 + */
2624 +
2625 +#ifndef __AA_FILE_H
2626 +#define __AA_FILE_H
2627 +
2628 +#include <linux/path.h>
2629 +
2630 +#include "audit.h"
2631 +#include "domain.h"
2632 +#include "match.h"
2633 +
2634 +struct aa_profile;
2635 +
2636 +/*
2637 + * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags
2638 + * for profile permissions
2639 + */
2640 +#define AA_MAY_LINK                    0x0010
2641 +#define AA_MAY_LOCK                    0x0020
2642 +#define AA_EXEC_MMAP                   0x0040
2643 +
2644 +#define AA_MAY_CREATE                  0x0080
2645 +#define AA_LINK_SUBSET                 0x0100
2646 +#define AA_MAY_DELEGATE                        0x0200
2647 +#define AA_EXEC_DELEGATE               0x0400          /*exec allows delegate*/
2648 +
2649 +#define AA_MAY_CHANGEHAT               0x2000          /* ctrl auditing only */
2650 +#define AA_MAY_ONEXEC                  0x4000          /* exec allows onexec */
2651 +#define AA_MAY_CHANGE_PROFILE          0x8000
2652 +
2653 +
2654 +#define AA_AUDIT_FILE_MASK     (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\
2655 +                                AA_MAY_LINK | AA_MAY_LOCK | AA_EXEC_MMAP | \
2656 +                                AA_MAY_CREATE)
2657 +
2658 +/*
2659 + * The xindex is broken into 3 parts
2660 + * - index - an index into either the exec name table or the variable table
2661 + * - exec type - which determines how the executable name and index are used
2662 + * - flags - which modify how the destination name is applied
2663 + */
2664 +#define AA_X_INDEX_MASK                0x03ff
2665 +
2666 +#define AA_X_TYPE_MASK         0x0c00
2667 +#define AA_X_TYPE_SHIFT                10              
2668 +#define AA_X_NONE              0x0000
2669 +#define AA_X_NAME              0x0400  /* use executable name px */
2670 +#define AA_X_TABLE             0x0800  /* use a specified name ->n# */
2671 +
2672 +#define AA_X_UNSAFE            0x1000
2673 +#define AA_X_CHILD             0x2000  /* make >AA_X_NONE apply to children */
2674 +#define AA_X_INHERIT           0x4000
2675 +#define AA_X_UNCONFINED                0x8000
2676 +
2677 +
2678 +/* AA_SECURE_X_NEEDED - is passed in the bprm->unsafe field */
2679 +#define AA_SECURE_X_NEEDED     0x8000
2680 +
2681 +/* need to conditionalize which ones are being set */
2682 +struct path_cond {
2683 +       uid_t uid;
2684 +       umode_t mode;
2685 +};
2686 +
2687 +/* struct file_perms - file permission fo
2688 + * @allowed: mask of permissions that are allowed
2689 + * @audit: mask of permissions to force an audit message for
2690 + * @quiet: mask of permissions to quiet audit messages for
2691 + * @kill: mask of permissions that when matched will kill the task
2692 + * @xindex: exec transition index if @allowed contains MAY_EXEC
2693 + * @dindex: delegate table index if @allowed contain AA_MAY_DELEGATE
2694 + *
2695 + * The @audit and @queit mask should be mutually exclusive.
2696 + */
2697 +struct file_perms {
2698 +       u16 allowed;
2699 +       u16 audit;
2700 +       u16 quiet;
2701 +       u16 kill;
2702 +       u16 xindex;
2703 +       u16 dindex;
2704 +};
2705 +
2706 +extern struct file_perms nullperms;
2707 +
2708 +#define COMBINED_PERM_MASK(X) ((X).allowed | (X).audit | (X).quiet | (X).kill)
2709 +
2710 +/* FIXME: split perms from dfa and match this to description
2711 + *        also add delegation info.
2712 + */
2713 +static inline u16 dfa_map_xindex(u16 mask)
2714 +{
2715 +       u16 old_index = (mask >> 10) & 0xf;
2716 +       u16 index = 0;
2717 +
2718 +//printk("mask x%x\n", mask);
2719 +       if (mask & 0x100)
2720 +               index |= AA_X_UNSAFE;
2721 +       if (mask & 0x200)
2722 +               index |= AA_X_INHERIT;
2723 +
2724 +       if (old_index == 1) {
2725 +               index |= AA_X_UNCONFINED;
2726 +       } else if (old_index == 2) {
2727 +               index |= AA_X_NAME;
2728 +       } else if (old_index == 3) {
2729 +               index |= AA_X_NAME | AA_X_CHILD;
2730 +       } else {
2731 +               index |= AA_X_TABLE;
2732 +               index |= old_index - 4;
2733 +       }
2734 +
2735 +       return index;
2736 +}
2737 +
2738 +/*
2739 + * map old dfa inline permissions to new format
2740 + */
2741 +#define dfa_user_allow(dfa, state)     ((ACCEPT_TABLE(dfa)[state]) & 0x7f)
2742 +#define dfa_user_audit(dfa, state)     ((ACCEPT_TABLE2(dfa)[state]) & 0x7f)
2743 +#define dfa_user_quiet(dfa, state)     (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f)
2744 +#define dfa_user_xindex(dfa, state) \
2745 +       (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff))
2746 +
2747 +#define dfa_other_allow(dfa, state)    (((ACCEPT_TABLE(dfa)[state]) >> 14) & 0x7f)
2748 +#define dfa_other_audit(dfa, state)    (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f)
2749 +#define dfa_other_quiet(dfa, state)    ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f)
2750 +#define dfa_other_xindex(dfa, state) \
2751 +       dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
2752 +
2753 +
2754 +struct aa_audit_file {
2755 +       struct aa_audit base;
2756 +
2757 +       const char *name;
2758 +       const char *name2;
2759 +       const char *name3;
2760 +       struct file_perms perms;
2761 +       u16 request;
2762 +       struct path_cond *cond;
2763 +};
2764 +
2765 +int aa_audit_file(struct aa_profile *profile, struct aa_audit_file *sa);
2766 +void file_audit_cb(struct audit_buffer *ab, void *va);
2767 +
2768 +/**
2769 + * struct aa_file_rules - components used for file rule permissions
2770 + * @dfa: dfa to match path names and conditionals against
2771 + * @perms: permission table indexed by the matched state accept entry of @dfa
2772 + * @trans: transition table for indexed by named x transitions
2773 + *
2774 + * File permission are determined by matching a path against @dfa and then
2775 + * then using the value of the accept entry for the matching state as
2776 + * an index into @perms.  If a named exec transition is required it is
2777 + * looked up in the transition table.
2778 + */
2779 +struct aa_file_rules {
2780 +       struct aa_dfa *dfa;
2781 +       /* struct perms perms; */
2782 +       struct aa_domain trans;
2783 +       /* TODO: add delegate table */
2784 +};
2785 +
2786 +struct file_perms aa_str_perms(struct aa_dfa *dfa, unsigned int start,
2787 +                              const char *name, struct path_cond *cond,
2788 +                              unsigned int *rstate);
2789 +
2790 +int aa_pathstr_perm(struct aa_profile *profile, const char *op,
2791 +                   const char *name, u16 request, struct path_cond *cond);
2792 +
2793 +int aa_path_perm(struct aa_profile *profile, const char *operation,
2794 +                struct path *path, u16 request, struct path_cond *cond);
2795 +
2796 +int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
2797 +                struct path *new_dir, struct dentry *new_dentry);
2798 +
2799 +int aa_file_common_perm(struct aa_profile *profile, const char *operation,
2800 +                       struct file *file, u16 request, const char *name,
2801 +                       int error);
2802 +
2803 +int aa_file_perm(struct aa_profile *profile, const char *operation,
2804 +                struct file *file, u16 request);
2805 +
2806 +
2807 +static inline void aa_free_file_rules(struct aa_file_rules *rules)
2808 +{
2809 +       aa_match_free(rules->dfa);
2810 +       aa_free_domain_entries(&rules->trans);
2811 +}
2812 +
2813 +#define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40))
2814 +
2815 +/* from namei.c */
2816 +#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
2817 +#define MAP_OPEN_FLAGS(x) ((((x) + 1) & O_ACCMODE) ? (x) + 1 : (x))
2818 +/*
2819 + * map file flags to AppArmor permissions
2820 + */
2821 +static inline u16 aa_map_file_to_perms(struct file *file)
2822 +{
2823 +       int flags = MAP_OPEN_FLAGS(file->f_flags);
2824 +       u16 perms = ACC_FMODE(file->f_mode);
2825 +
2826 +       if ((flags & O_APPEND) && (perms & MAY_WRITE))
2827 +               perms = (perms & ~MAY_WRITE) | MAY_APPEND;
2828 +       /* trunc implies write permission */
2829 +       if (flags & O_TRUNC)
2830 +               perms |= MAY_WRITE;
2831 +       if (flags & O_CREAT)
2832 +               perms |= AA_MAY_CREATE;
2833 +
2834 +       return perms;
2835 +}
2836 +
2837 +#endif /* __AA_FILE_H */
2838 diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h
2839 new file mode 100644
2840 index 0000000..e80a95e
2841 --- /dev/null
2842 +++ b/security/apparmor/include/ipc.h
2843 @@ -0,0 +1,28 @@
2844 +/*
2845 + * AppArmor security module
2846 + *
2847 + * This file contains AppArmor ipc mediation function definitions.
2848 + *
2849 + * Copyright (C) 1998-2008 Novell/SUSE
2850 + * Copyright 2009 Canonical Ltd.
2851 + *
2852 + * This program is free software; you can redistribute it and/or
2853 + * modify it under the terms of the GNU General Public License as
2854 + * published by the Free Software Foundation, version 2 of the
2855 + * License.
2856 + */
2857 +
2858 +#ifndef __AA_IPC_H
2859 +#define __AA_IPC_H
2860 +
2861 +#include <linux/sched.h>
2862 +
2863 +struct aa_profile;
2864 +
2865 +int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
2866 +                 struct aa_profile *tracee, unsigned int mode);
2867 +
2868 +int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
2869 +             unsigned int mode);
2870 +
2871 +#endif /* __AA_IPC_H */
2872 diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
2873 new file mode 100644
2874 index 0000000..8a0f59c
2875 --- /dev/null
2876 +++ b/security/apparmor/include/match.h
2877 @@ -0,0 +1,105 @@
2878 +/*
2879 + * AppArmor security module
2880 + *
2881 + * This file contains AppArmor policy dfa matching engine definitions.
2882 + *
2883 + * Copyright (C) 1998-2008 Novell/SUSE
2884 + * Copyright 2009 Canonical Ltd.
2885 + *
2886 + * This program is free software; you can redistribute it and/or
2887 + * modify it under the terms of the GNU General Public License as
2888 + * published by the Free Software Foundation, version 2 of the
2889 + * License.
2890 + */
2891 +
2892 +#ifndef __AA_MATCH_H
2893 +#define __AA_MATCH_H
2894 +
2895 +#define DFA_NOMATCH                    0
2896 +#define DFA_START                      1
2897 +
2898 +#define DFA_VALID_PERM_MASK            0xffffffff
2899 +#define DFA_VALID_PERM2_MASK           0xffffffff
2900 +
2901 +
2902 +/**
2903 + * The format used for transition tables is based on the GNU flex table
2904 + * file format (--tables-file option; see Table File Format in the flex
2905 + * info pages and the flex sources for documentation). The magic number
2906 + * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
2907 + * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
2908 + * slightly differently (see the apparmor-parser package).
2909 + */
2910 +
2911 +#define YYTH_MAGIC     0x1B5E783D
2912 +
2913 +struct table_set_header {
2914 +       u32             th_magic;       /* YYTH_MAGIC */
2915 +       u32             th_hsize;
2916 +       u32             th_ssize;
2917 +       u16             th_flags;
2918 +       char            th_version[];
2919 +};
2920 +
2921 +#define        YYTD_ID_ACCEPT  1
2922 +#define YYTD_ID_BASE   2
2923 +#define YYTD_ID_CHK    3
2924 +#define YYTD_ID_DEF    4
2925 +#define YYTD_ID_EC     5
2926 +#define YYTD_ID_META   6
2927 +#define YYTD_ID_ACCEPT2 7
2928 +#define YYTD_ID_NXT    8
2929 +
2930 +
2931 +#define YYTD_DATA8     1
2932 +#define YYTD_DATA16    2
2933 +#define YYTD_DATA32    4
2934 +
2935 +struct table_header {
2936 +       u16             td_id;
2937 +       u16             td_flags;
2938 +       u32             td_hilen;
2939 +       u32             td_lolen;
2940 +       char            td_data[];
2941 +};
2942 +
2943 +#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF - 1]->td_data))
2944 +#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE - 1]->td_data))
2945 +#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT - 1]->td_data))
2946 +#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
2947 +#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
2948 +#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
2949 +#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2 - 1]->td_data))
2950 +
2951 +struct aa_dfa {
2952 +       struct table_header *tables[YYTD_ID_NXT];
2953 +};
2954 +
2955 +#define byte_to_byte(X) (X)
2956 +
2957 +#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
2958 +       do { \
2959 +               typeof(LEN) __i; \
2960 +               TYPE *__t = (TYPE *) TABLE; \
2961 +               TYPE *__b = (TYPE *) BLOB; \
2962 +               for (__i = 0; __i < LEN; __i++) { \
2963 +                       __t[__i] = NTOHX(__b[__i]); \
2964 +               } \
2965 +       } while (0)
2966 +
2967 +static inline size_t table_size(size_t len, size_t el_size)
2968 +{
2969 +       return ALIGN(sizeof(struct table_header) + len * el_size, 8);
2970 +}
2971 +
2972 +struct aa_dfa *aa_match_alloc(void);
2973 +void aa_match_free(struct aa_dfa *dfa);
2974 +int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
2975 +int verify_dfa(struct aa_dfa *dfa);
2976 +unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
2977 +                             const char *str, int len);
2978 +unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
2979 +                         const char *str);
2980 +unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start);
2981 +
2982 +#endif /* __AA_MATCH_H */
2983 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
2984 new file mode 100644
2985 index 0000000..ece94b2
2986 --- /dev/null
2987 +++ b/security/apparmor/include/net.h
2988 @@ -0,0 +1,40 @@
2989 +/*
2990 + * AppArmor security module
2991 + *
2992 + * This file contains AppArmor network mediation definitions.
2993 + *
2994 + * Copyright (C) 1998-2008 Novell/SUSE
2995 + * Copyright 2009 Canonical Ltd.
2996 + *
2997 + * This program is free software; you can redistribute it and/or
2998 + * modify it under the terms of the GNU General Public License as
2999 + * published by the Free Software Foundation, version 2 of the
3000 + * License.
3001 + */
3002 +
3003 +#ifndef __AA_NET_H
3004 +#define __AA_NET_H
3005 +
3006 +#include <net/sock.h>
3007 +
3008 +/* struct aa_net - network confinement data
3009 + * @allowed: basic network families permissions
3010 + * @audit_network: which network permissions to force audit
3011 + * @quiet_network: which network permissions to quiet rejects
3012 + */
3013 +struct aa_net {
3014 +       u16 allowed[AF_MAX];
3015 +       u16 audit[AF_MAX];
3016 +       u16 quiet[AF_MAX];
3017 +};
3018 +
3019 +extern int aa_net_perm(struct aa_profile *profile, char *operation,
3020 +                       int family, int type, int protocol);
3021 +extern int aa_revalidate_sk(struct sock *sk, char *operation);
3022 +
3023 +static inline void aa_free_net_rules(struct aa_net *new)
3024 +{
3025 +       /* NOP */
3026 +}
3027 +
3028 +#endif /* __AA_NET_H */
3029 diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
3030 new file mode 100644
3031 index 0000000..d238e42
3032 --- /dev/null
3033 +++ b/security/apparmor/include/path.h
3034 @@ -0,0 +1,24 @@
3035 +/*
3036 + * AppArmor security module
3037 + *
3038 + * This file contains AppArmor basic path manipulation function definitions.
3039 + *
3040 + * Copyright (C) 1998-2008 Novell/SUSE
3041 + * Copyright 2009 Canonical Ltd.
3042 + *
3043 + * This program is free software; you can redistribute it and/or
3044 + * modify it under the terms of the GNU General Public License as
3045 + * published by the Free Software Foundation, version 2 of the
3046 + * License.
3047 + */
3048 +
3049 +#ifndef __AA_PATH_H
3050 +#define __AA_PATH_H
3051 +
3052 +int aa_get_name_to_buffer(struct path *path, int is_dir, char *buffer, int size,
3053 +                         char **name);
3054 +int aa_get_name(struct path *path, int is_dir, char **buffer, char **name);
3055 +int d_namespace_path(struct path *path, char *buf, int buflen, char **name);
3056 +char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen);
3057 +
3058 +#endif /* __AA_PATH_H */
3059 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
3060 new file mode 100644
3061 index 0000000..98cd0d9
3062 --- /dev/null
3063 +++ b/security/apparmor/include/policy.h
3064 @@ -0,0 +1,301 @@
3065 +/*
3066 + * AppArmor security module
3067 + *
3068 + * This file contains AppArmor policy definitions.
3069 + *
3070 + * Copyright (C) 1998-2008 Novell/SUSE
3071 + * Copyright 2009 Canonical Ltd.
3072 + *
3073 + * This program is free software; you can redistribute it and/or
3074 + * modify it under the terms of the GNU General Public License as
3075 + * published by the Free Software Foundation, version 2 of the
3076 + * License.
3077 + */
3078 +
3079 +#ifndef __AA_POLICY_H
3080 +#define __AA_POLICY_H
3081 +
3082 +#include <linux/capability.h>
3083 +#include <linux/cred.h>
3084 +#include <linux/kref.h>
3085 +#include <linux/sched.h>
3086 +#include <linux/slab.h>
3087 +#include <linux/socket.h>
3088 +
3089 +#include "apparmor.h"
3090 +#include "audit.h"
3091 +#include "capability.h"
3092 +#include "domain.h"
3093 +#include "file.h"
3094 +#include "net.h"
3095 +#include "resource.h"
3096 +
3097 +extern const char *profile_mode_names[];
3098 +#define APPARMOR_NAMES_MAX_INDEX 3
3099 +
3100 +#define PROFILE_COMPLAIN(_profile)                             \
3101 +       ((g_profile_mode == APPARMOR_COMPLAIN) || ((_profile) &&        \
3102 +                                       (_profile)->mode == APPARMOR_COMPLAIN))
3103 +
3104 +#define PROFILE_KILL(_profile)                                 \
3105 +       ((g_profile_mode == APPARMOR_KILL) || ((_profile) &&    \
3106 +                                       (_profile)->mode == APPARMOR_KILL))
3107 +
3108 +#define PROFILE_IS_HAT(_profile) \
3109 +       ((_profile) && (_profile)->flags & PFLAG_HAT)
3110 +
3111 +
3112 +/*
3113 + * FIXME: currently need a clean way to replace and remove profiles as a
3114 + * set.  It should be done at the namespace level.
3115 + * Either, with a set of profiles loaded at the namespace level or via
3116 + * a mark and remove marked interface.
3117 + */
3118 +enum profile_mode {
3119 +       APPARMOR_ENFORCE,               /* enforce access rules */
3120 +       APPARMOR_COMPLAIN,              /* allow and log access violations */
3121 +       APPARMOR_KILL,                  /* kill task on access violation */
3122 +};
3123 +
3124 +enum profile_flags {
3125 +       PFLAG_HAT = 1,                  /* profile is a hat */
3126 +       PFLAG_UNCONFINED = 2,           /* profile is the unconfined profile */
3127 +       PFLAG_NULL = 4,                 /* profile is null learning profile */
3128 +       PFLAG_IX_ON_NAME_ERROR = 8,     /* fallback to ix on name lookup fail */
3129 +       PFLAG_IMMUTABLE = 0x10,         /* don't allow changes/replacement */
3130 +       PFLAG_USER_DEFINED = 0x20,      /* user based profile */
3131 +       PFLAG_NO_LIST_REF = 0x40,       /* list doesn't keep profile ref */
3132 +};
3133 +
3134 +#define AA_NEW_SID 0
3135 +
3136 +struct aa_profile;
3137 +
3138 +/* struct aa_policy_common - common part of both namespaces and profiles
3139 + * @name: name of the object
3140 + * @count: reference count of the obj
3141 + * lock: lock for modifying the object
3142 + * @list: list object is on
3143 + * @profiles: head of the profiles list contained in the object
3144 + */
3145 +struct aa_policy_common {
3146 +       char *name;
3147 +       struct kref count;
3148 +       rwlock_t lock;
3149 +       struct list_head list;
3150 +       struct list_head profiles;
3151 +};
3152 +
3153 +/* struct aa_ns_acct - accounting of profiles in namespace
3154 + * @max_size: maximum space allowed for all profiles in namespace
3155 + * @max_count: maximum number of profiles that can be in this namespace
3156 + * @size: current size of profiles
3157 + * @count: current count of profiles (includes null profiles)
3158 + */
3159 +struct aa_ns_acct {
3160 +       int max_size;
3161 +       int max_count;
3162 +       int size;
3163 +       int count;
3164 +};
3165 +
3166 +/* struct aa_namespace - namespace for a set of profiles
3167 + * @name: the name of the namespace
3168 + * @list: list the namespace is on
3169 + * @profiles: list of profile in the namespace
3170 + * @acct: accounting for the namespace
3171 + * @profile_count: count of profiles on @profiles list
3172 + * @size: accounting of how much memory is consumed by the contained profiles
3173 + * @unconfined: special unconfined profile for the namespace
3174 + * @count: reference count on the namespace
3175 + * @lock: lock for adding/removing profile to the namespace
3176 + *
3177 + * An aa_namespace defines the set profiles that are searched to determine
3178 + * which profile to attach to a task.  Profiles can not be shared between
3179 + * aa_namespaces and profile names within a namespace are guarenteed to be
3180 + * unique.  When profiles in seperate namespaces have the same name they
3181 + * are NOT considered to be equivalent.
3182 + *
3183 + * Namespace names must be unique and can not contain the characters :/\0
3184 + *
3185 + * FIXME TODO: add vserver support so a vserer gets a default namespace
3186 + */
3187 +struct aa_namespace {
3188 +       struct aa_policy_common base;
3189 +       struct aa_ns_acct acct;
3190 +       int is_stale;
3191 +       struct aa_profile *unconfined;
3192 +};
3193 +
3194 +
3195 +/* struct aa_profile - basic confinement data
3196 + * @base - base componets of the profile (name, refcount, lists, lock ...)
3197 + * @fqname - The fully qualified profile name, less the namespace name
3198 + * @ns: namespace the profile is in
3199 + * @parent: parent profile of this profile, if one exists
3200 + * @replacedby: is set profile that replaced this profile
3201 + * @xmatch: optional extended matching for unconfined executables names
3202 + * @xmatch_plen: xmatch prefix len, used to determine xmatch priority
3203 + * @sid: the unique security id number of this profile
3204 + * @audit: the auditing mode of the profile
3205 + * @mode: the enforcement mode of the profile
3206 + * @flags: flags controlling profile behavior
3207 + * @size: the memory consumed by this profiles rules
3208 + * @file: The set of rules governing basic file access and domain transitions
3209 + * @caps: capabilities for the profile
3210 + * @net: network controls for the profile
3211 + * @rlimits: rlimits for the profile
3212 + *
3213 + * The AppArmor profile contains the basic confinement data.  Each profile
3214 + * has a name, and exist in a namespace.  The @name and @exec_match are
3215 + * used to determine profile attachment against unconfined tasks.  All other
3216 + * attachments are determined by in profile X transition rules.
3217 + *
3218 + * The @replacedby field is write protected by the profile lock.  Reads
3219 + * are assumed to be atomic, and are done without locking.
3220 + *
3221 + * Profiles have a hierachy where hats and children profiles keep
3222 + * a reference to their parent.
3223 + *
3224 + * Profile names can not begin with a : and can not contain the \0
3225 + * character.  If a profile name begins with / it will be considered when
3226 + * determining profile attachment on "unconfined" tasks.
3227 + */
3228 +struct aa_profile {
3229 +       struct aa_policy_common base;
3230 +       char *fqname;
3231 +
3232 +       struct aa_namespace *ns;
3233 +       struct aa_profile *parent;
3234 +       struct aa_profile *replacedby;
3235 +
3236 +       struct aa_dfa *xmatch;
3237 +       int xmatch_len;
3238 +       u32 sid;
3239 +       enum audit_mode audit;
3240 +       enum profile_mode mode;
3241 +       u32 flags;
3242 +       int size;
3243 +
3244 +       struct aa_file_rules file;
3245 +       struct aa_caps caps;
3246 +       struct aa_net net;
3247 +       struct aa_rlimit rlimits;
3248 +};
3249 +
3250 +
3251 +extern struct list_head ns_list;
3252 +extern rwlock_t ns_list_lock;
3253 +
3254 +extern struct aa_namespace *default_namespace;
3255 +extern enum profile_mode g_profile_mode;
3256
3257 +
3258 +void aa_add_profile(struct aa_policy_common *common,
3259 +                   struct aa_profile *profile);
3260 +
3261 +int alloc_default_namespace(void);
3262 +void free_default_namespace(void);
3263 +struct aa_namespace *alloc_aa_namespace(const char *name);
3264 +void free_aa_namespace_kref(struct kref *kref);
3265 +void free_aa_namespace(struct aa_namespace *ns);
3266 +struct aa_namespace *__aa_find_namespace(struct list_head *head,
3267 +                                        const char *name);
3268 +                                        
3269 +struct aa_namespace *aa_find_namespace(const char *name);
3270 +struct aa_namespace *aa_prepare_namespace(const char *name);
3271 +void aa_remove_namespace(struct aa_namespace *ns);
3272 +struct aa_namespace *aa_prepare_namespace(const char *name);
3273 +void aa_profile_list_release(struct list_head *head);
3274 +void aa_profile_ns_list_release(void);
3275 +void __aa_remove_namespace(struct aa_namespace *ns);
3276 +
3277 +
3278 +static inline struct aa_policy_common *aa_get_common(struct aa_policy_common *c)
3279 +{
3280 +       if (c)
3281 +               kref_get(&c->count);
3282 +
3283 +       return c;
3284 +}
3285 +
3286 +static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
3287 +{
3288 +       if (ns)
3289 +               kref_get(&(ns->base.count));
3290 +
3291 +       return ns;
3292 +}
3293 +
3294 +static inline void aa_put_namespace(struct aa_namespace *ns)
3295 +{
3296 +       if (ns)
3297 +               kref_put(&ns->base.count, free_aa_namespace_kref);
3298 +}
3299 +
3300 +
3301 +
3302 +struct aa_profile *alloc_aa_profile(const char *name);
3303 +struct aa_profile *aa_alloc_null_profile(struct aa_profile *parent, int hat);
3304 +void free_aa_profile_kref(struct kref *kref);
3305 +void free_aa_profile(struct aa_profile *profile);
3306 +struct aa_profile *__aa_find_profile(struct list_head *head, const char *name);
3307 +struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
3308 +struct aa_policy_common *__aa_find_parent_by_fqname(struct aa_namespace *ns,
3309 +                                                   const char *fqname);
3310 +struct aa_profile *__aa_find_profile_by_fqname(struct aa_namespace *ns,
3311 +                                              const char *fqname);
3312 +struct aa_profile *aa_find_profile_by_fqname(struct aa_namespace *ns,
3313 +                                            const char *name);
3314 +struct aa_profile *aa_match_profile(struct aa_namespace *ns, const char *name);
3315 +struct aa_profile *aa_profile_newest(struct aa_profile *profile);
3316 +struct aa_profile *aa_sys_find_attach(struct aa_namespace *ns,
3317 +                                     const char *name);
3318 +void __aa_add_profile(struct aa_policy_common *common,
3319 +                     struct aa_profile *profile);
3320 +void __aa_remove_profile(struct aa_profile *profile,
3321 +                        struct aa_profile *replacement);
3322 +void __aa_replace_profile(struct aa_profile *profile,
3323 +                         struct aa_profile *replacement);
3324 +void __aa_profile_list_release(struct list_head *head);
3325 +
3326 +static inline struct aa_profile *aa_filtered_profile(struct aa_profile *profile)
3327 +{
3328 +       if (profile->flags & PFLAG_UNCONFINED)
3329 +               return NULL;
3330 +       return profile;
3331 +}
3332 +
3333 +/**
3334 + * aa_get_profile - increment refcount on profile @p
3335 + * @p: profile
3336 + */
3337 +static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
3338 +{
3339 +       if (p)
3340 +               kref_get(&(p->base.count));
3341 +
3342 +       return p;
3343 +}
3344 +
3345 +/**
3346 + * aa_put_profile - decrement refcount on profile @p
3347 + * @p: profile
3348 + */
3349 +static inline void aa_put_profile(struct aa_profile *p)
3350 +{
3351 +       if (p)
3352 +               kref_put(&p->base.count, free_aa_profile_kref);
3353 +}
3354 +
3355 +static inline int PROFILE_AUDIT_MODE(struct aa_profile *profile)
3356 +{
3357 +       if (g_apparmor_audit != AUDIT_NORMAL)
3358 +               return g_apparmor_audit;
3359 +       if (profile)
3360 +               return profile->audit;
3361 +       return AUDIT_NORMAL;
3362 +}
3363 +
3364 +#endif /* __AA_POLICY_H */
3365 +
3366 diff --git a/security/apparmor/include/policy_interface.h b/security/apparmor/include/policy_interface.h
3367 new file mode 100644
3368 index 0000000..1440876
3369 --- /dev/null
3370 +++ b/security/apparmor/include/policy_interface.h
3371 @@ -0,0 +1,22 @@
3372 +/*
3373 + * AppArmor security module
3374 + *
3375 + * This file contains AppArmor policy loading interface function definitions.
3376 + *
3377 + * Copyright (C) 1998-2008 Novell/SUSE
3378 + * Copyright 2009 Canonical Ltd.
3379 + *
3380 + * This program is free software; you can redistribute it and/or
3381 + * modify it under the terms of the GNU General Public License as
3382 + * published by the Free Software Foundation, version 2 of the
3383 + * License.
3384 + */
3385 +
3386 +#ifndef __POLICY_INTERFACE_H
3387 +#define __POLICY_INTERFACE_H
3388 +
3389 +ssize_t aa_interface_add_profiles(void *data, size_t size);
3390 +ssize_t aa_interface_replace_profiles(void *udata, size_t size);
3391 +ssize_t aa_interface_remove_profiles(char *name, size_t size);
3392 +
3393 +#endif /* __POLICY_INTERFACE_H */
3394 diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h
3395 new file mode 100644
3396 index 0000000..52e46c5
3397 --- /dev/null
3398 +++ b/security/apparmor/include/procattr.h
3399 @@ -0,0 +1,26 @@
3400 +/*
3401 + * AppArmor security module
3402 + *
3403 + * This file contains AppArmor /proc/<pid>/attr/ interface function defintions.
3404 + *
3405 + * Copyright (C) 1998-2008 Novell/SUSE
3406 + * Copyright 2009 Canonical Ltd.
3407 + *
3408 + * This program is free software; you can redistribute it and/or
3409 + * modify it under the terms of the GNU General Public License as
3410 + * published by the Free Software Foundation, version 2 of the
3411 + * License.
3412 + */
3413 +
3414 +#ifndef __AA_PROCATTR_H
3415 +#define __AA_PROCATTR_H
3416 +
3417 +#define AA_DO_TEST 1
3418 +
3419 +int aa_getprocattr(struct aa_namespace *ns, struct aa_profile *profile,
3420 +                  char **string);
3421 +int aa_setprocattr_changehat(char *args, int test);
3422 +int aa_setprocattr_changeprofile(char *args, int onexec, int test);
3423 +int aa_setprocattr_permipc(char *args);
3424 +
3425 +#endif /* __AA_PROCATTR_H */
3426 diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
3427 new file mode 100644
3428 index 0000000..0662c91
3429 --- /dev/null
3430 +++ b/security/apparmor/include/resource.h
3431 @@ -0,0 +1,46 @@
3432 +/*
3433 + * AppArmor security module
3434 + *
3435 + * This file contains AppArmor resource limits function defintions.
3436 + *
3437 + * Copyright (C) 1998-2008 Novell/SUSE
3438 + * Copyright 2009 Canonical Ltd.
3439 + *
3440 + * This program is free software; you can redistribute it and/or
3441 + * modify it under the terms of the GNU General Public License as
3442 + * published by the Free Software Foundation, version 2 of the
3443 + * License.
3444 + */
3445 +
3446 +#ifndef __AA_RESOURCE_H
3447 +#define __AA_RESOURCE_H
3448 +
3449 +#include <linux/resource.h>
3450 +#include <linux/sched.h>
3451 +
3452 +struct aa_profile;
3453 +
3454 +/* struct aa_rlimit - rlimits settings for the profile
3455 + * @mask: which hard limits to set
3456 + * @limits: rlimit values that override task limits
3457 + *
3458 + * AppArmor rlimits are used to set confined task rlimits.  Only the
3459 + * limits specified in @mask will be controlled by apparmor.
3460 + */
3461 +struct aa_rlimit {
3462 +       unsigned int mask;
3463 +       struct rlimit limits[RLIM_NLIMITS];
3464 +};
3465 +
3466 +
3467 +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
3468 +                     struct rlimit *new_rlim);
3469 +
3470 +void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
3471 +
3472 +static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
3473 +{
3474 +       /* NOP */
3475 +}
3476 +
3477 +#endif /* __AA_RESOURCE_H */
3478 diff --git a/security/apparmor/include/sid.h b/security/apparmor/include/sid.h
3479 new file mode 100644
3480 index 0000000..83e3590
3481 --- /dev/null
3482 +++ b/security/apparmor/include/sid.h
3483 @@ -0,0 +1,46 @@
3484 +/*
3485 + * AppArmor security module
3486 + *
3487 + * This file contains AppArmor security identifier (sid) definitions
3488 + *
3489 + * Copyright 2009 Canonical Ltd.
3490 + *
3491 + * This program is free software; you can redistribute it and/or
3492 + * modify it under the terms of the GNU General Public License as
3493 + * published by the Free Software Foundation, version 2 of the
3494 + * License.
3495 + */
3496 +
3497 +#ifndef __AA_SID_H
3498 +#define __AA_SID_H
3499 +
3500 +#include <linux/types.h>
3501 +
3502 +struct aa_profile;
3503 +
3504 +#define AA_ALLOC_USR_SID 1
3505 +#define AA_ALLOC_SYS_SID 0
3506 +
3507 +u32 aa_alloc_sid(int is_usr);
3508 +void aa_free_sid(u32 sid);
3509 +int aa_add_sid_profile(u32 sid, struct aa_profile *profile);
3510 +int aa_replace_sid_profile(u32 sid, struct aa_profile *profile);
3511 +struct aa_profile *aa_get_sid_profile(u32 sid);
3512 +
3513 +
3514 +static inline u32 aa_compound_sid(u32 sys, u32 usr)
3515 +{
3516 +       return sys | usr;
3517 +}
3518 +
3519 +static inline u32 aa_usr_sid(u32 sid)
3520 +{
3521 +       return sid & 0xffff0000;
3522 +}
3523 +
3524 +static inline u32 aa_sys_sid(u32 sid)
3525 +{
3526 +       return sid & 0xffff;
3527 +}
3528 +
3529 +#endif /* __AA_SID_H */
3530 diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
3531 new file mode 100644
3532 index 0000000..381c164
3533 --- /dev/null
3534 +++ b/security/apparmor/ipc.c
3535 @@ -0,0 +1,106 @@
3536 +/*
3537 + * AppArmor security module
3538 + *
3539 + * This file contains AppArmor ipc mediation
3540 + *
3541 + * Copyright (C) 1998-2008 Novell/SUSE
3542 + * Copyright 2009 Canonical Ltd.
3543 + *
3544 + * This program is free software; you can redistribute it and/or
3545 + * modify it under the terms of the GNU General Public License as
3546 + * published by the Free Software Foundation, version 2 of the
3547 + * License.
3548 + */
3549 +
3550 +#include <linux/gfp.h>
3551 +#include <linux/ptrace.h>
3552 +
3553 +#include "include/audit.h"
3554 +#include "include/capability.h"
3555 +#include "include/context.h"
3556 +#include "include/policy.h"
3557 +
3558 +
3559 +struct aa_audit_ptrace {
3560 +       struct aa_audit base;
3561 +
3562 +       pid_t tracer, tracee;
3563 +};
3564 +
3565 +/* call back to audit ptrace fields */
3566 +static void audit_cb(struct audit_buffer *ab, void *va)
3567 +{
3568 +       struct aa_audit_ptrace *sa = va;
3569 +       audit_log_format(ab, " tracer=%d tracee=%d", sa->tracer, sa->tracee);
3570 +}
3571 +
3572 +static int aa_audit_ptrace(struct aa_profile *profile,
3573 +                          struct aa_audit_ptrace *sa)
3574 +{
3575 +       return aa_audit(AUDIT_APPARMOR_AUTO, profile, (struct aa_audit *)sa,
3576 +                       audit_cb);
3577 +}
3578 +
3579 +int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
3580 +                 struct aa_profile *tracee, unsigned int mode)
3581 +{
3582 +       /* TODO: currently only based on capability, not extended ptrace
3583 +        *       rules,
3584 +        *       Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
3585 +        */
3586 +
3587 +       if (!tracer || tracer == tracee)
3588 +               return 0;
3589 +       /* log this capability request */
3590 +       return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1);
3591 +}
3592 +
3593 +int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
3594 +             unsigned int mode)
3595 +{
3596 +       /*
3597 +        * tracer can ptrace tracee when
3598 +        * - tracer is unconfined ||
3599 +        * - tracer & tracee are in the same namespace &&
3600 +        *   - tracer is in complain mode
3601 +        *   - tracer has rules allowing it to trace tracee currently this is:
3602 +        *       - confined by the same profile ||
3603 +        *       - tracer profile has CAP_SYS_PTRACE
3604 +        */
3605 +
3606 +       struct aa_profile *tracer_p;
3607 +       const struct cred *cred = aa_get_task_policy(tracer, &tracer_p);
3608 +       int error = 0;
3609 +
3610 +       if (tracer_p) {
3611 +               struct aa_audit_ptrace sa;
3612 +               memset(&sa, 0, sizeof(sa));
3613 +               sa.base.operation = "ptrace";
3614 +               sa.base.gfp_mask = GFP_ATOMIC;
3615 +               sa.tracer = tracer->pid;
3616 +               sa.tracee = tracee->pid;
3617 +               /* FIXME: different namespace restriction can be lifted
3618 +                * if, namespace are matched to AppArmor namespaces
3619 +                */
3620 +               if (tracer->nsproxy != tracee->nsproxy) {
3621 +                       sa.base.info = "different namespaces";
3622 +                       sa.base.error = -EPERM;
3623 +                       aa_audit(AUDIT_APPARMOR_DENIED, tracer_p, &sa.base,
3624 +                                audit_cb);
3625 +               } else {
3626 +                       struct aa_profile *tracee_p;
3627 +                       struct cred *lcred = aa_get_task_policy(tracee,
3628 +                                                               &tracee_p);
3629 +
3630 +                       sa.base.error = aa_may_ptrace(tracer, tracer_p,
3631 +                                                     tracee_p, mode);
3632 +                       sa.base.error = aa_audit_ptrace(tracer_p, &sa);
3633 +
3634 +                       put_cred(lcred);
3635 +               }
3636 +               error = sa.base.error;
3637 +       }
3638 +       put_cred(cred);
3639 +
3640 +       return error;
3641 +}
3642 diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
3643 new file mode 100644
3644 index 0000000..5dbd16d
3645 --- /dev/null
3646 +++ b/security/apparmor/lib.c
3647 @@ -0,0 +1,100 @@
3648 +/*
3649 + * AppArmor security module
3650 + *
3651 + * This file contains basic common functions used in AppArmor
3652 + *
3653 + * Copyright (C) 1998-2008 Novell/SUSE
3654 + * Copyright 2009 Canonical Ltd.
3655 + *
3656 + * This program is free software; you can redistribute it and/or
3657 + * modify it under the terms of the GNU General Public License as
3658 + * published by the Free Software Foundation, version 2 of the
3659 + * License.
3660 + */
3661 +
3662 +#include <linux/slab.h>
3663 +#include <linux/string.h>
3664 +
3665 +#include "include/audit.h"
3666 +
3667 +void info_message(const char *str)
3668 +{
3669 +       struct aa_audit sa;
3670 +       memset(&sa, 0, sizeof(sa));
3671 +       sa.gfp_mask = GFP_KERNEL;
3672 +       sa.info = str;
3673 +       printk(KERN_INFO "AppArmor: %s\n", str);
3674 +       if (audit_enabled)
3675 +               aa_audit(AUDIT_APPARMOR_STATUS, NULL, &sa, NULL);
3676 +}
3677 +
3678 +char *strchrnul(const char *s, int c)
3679 +{
3680 +       for (; *s != (char)c && *s != '\0'; ++s)
3681 +               ;
3682 +       return (char *)s;
3683 +}
3684 +
3685 +char *aa_split_name_from_ns(char *args, char **ns_name)
3686 +{
3687 +       char *name = strstrip(args);
3688 +
3689 +       *ns_name  = NULL;
3690 +       if (args[0] == ':') {
3691 +               char *split = strstrip(strchr(&args[1], ':'));
3692 +
3693 +               if (!split)
3694 +                       return NULL;
3695 +
3696 +               *split = 0;
3697 +               *ns_name = &args[1];
3698 +               name = strstrip(split + 1);
3699 +       }
3700 +       if (*name == 0)
3701 +               name = NULL;
3702 +
3703 +       return name;
3704 +}
3705 +
3706 +char *new_compound_name(const char *n1, const char *n2)
3707 +{
3708 +       char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
3709 +       if (name)
3710 +               sprintf(name, "%s//%s", n1, n2);
3711 +       return name;
3712 +}
3713 +
3714 +/**
3715 + * aa_strneq - compare null terminated @str to a non null terminated substring
3716 + * @str: a null terminated string
3717 + * @sub: a substring, not necessarily null terminated
3718 + * @len: length of @sub to compare
3719 + *
3720 + * The @str string must be full consumed for this to be considered a match
3721 + */
3722 +int aa_strneq(const char *str, const char *sub, int len)
3723 +{
3724 +       int res = strncmp(str, sub, len);
3725 +       if (res)
3726 +               return 0;
3727 +       if (str[len] == 0)
3728 +               return 1;
3729 +       return 0;
3730 +}
3731 +
3732 +const char *fqname_subname(const char *name)
3733 +{
3734 +       char *split;
3735 +       /* check for namespace which begins with a : and ends with : or \0 */
3736 +       name = strstrip((char *) name);
3737 +       if (*name == ':') {
3738 +               split = strchrnul(name + 1, ':');
3739 +               if (*split == '\0')
3740 +                       return NULL;
3741 +               name = strstrip(split + 1);
3742 +       }
3743 +       for (split = strstr(name, "//"); split; split = strstr(name, "//")) {
3744 +               name = split + 2;
3745 +       }
3746 +       return name;
3747 +}
3748 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
3749 new file mode 100644
3750 index 0000000..5becf5e
3751 --- /dev/null
3752 +++ b/security/apparmor/lsm.c
3753 @@ -0,0 +1,1063 @@
3754 +/*
3755 + * AppArmor security module
3756 + *
3757 + * This file contains AppArmor LSM hooks.
3758 + *
3759 + * Copyright (C) 1998-2008 Novell/SUSE
3760 + * Copyright 2009 Canonical Ltd.
3761 + *
3762 + * This program is free software; you can redistribute it and/or
3763 + * modify it under the terms of the GNU General Public License as
3764 + * published by the Free Software Foundation, version 2 of the
3765 + * License.
3766 + */
3767 +
3768 +#include <linux/security.h>
3769 +#include <linux/moduleparam.h>
3770 +#include <linux/mm.h>
3771 +#include <linux/mman.h>
3772 +#include <linux/mount.h>
3773 +#include <linux/namei.h>
3774 +#include <linux/ptrace.h>
3775 +#include <linux/ctype.h>
3776 +#include <linux/sysctl.h>
3777 +#include <linux/audit.h>
3778 +#include <net/sock.h>
3779 +
3780 +#include "include/apparmor.h"
3781 +#include "include/apparmorfs.h"
3782 +#include "include/audit.h"
3783 +#include "include/capability.h"
3784 +#include "include/context.h"
3785 +#include "include/file.h"
3786 +#include "include/ipc.h"
3787 +#include "include/net.h"
3788 +#include "include/path.h"
3789 +#include "include/policy.h"
3790 +#include "include/procattr.h"
3791 +
3792 +/* Flag indicating whether initialization completed */
3793 +int apparmor_initialized;
3794 +
3795 +
3796 +/*
3797 + * LSM hook functions
3798 + */
3799 +
3800 +/*
3801 + * prepare new aa_task_context for modification by prepare_cred block
3802 + */
3803 +static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
3804 +                                gfp_t gfp)
3805 +{
3806 +       struct aa_task_context *cxt = aa_dup_task_context(old->security, gfp);
3807 +       if (!cxt)
3808 +               return -ENOMEM;
3809 +       new->security = cxt;
3810 +       return 0;
3811 +}
3812 +
3813 +/*
3814 + * free the associated aa_task_context and put its profiles
3815 + */
3816 +static void apparmor_cred_free(struct cred *cred)
3817 +{
3818 +       struct aa_task_context *cxt = cred->security;
3819 +       cred->security = NULL;
3820 +       aa_free_task_context(cxt);
3821 +}
3822 +
3823 +
3824 +static int apparmor_ptrace_may_access(struct task_struct *child,
3825 +                                     unsigned int mode)
3826 +{
3827 +       return aa_ptrace(current, child, mode);
3828 +}
3829 +
3830 +
3831 +static int apparmor_ptrace_traceme(struct task_struct *parent)
3832 +{
3833 +       return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
3834 +}
3835 +
3836 +/* Derived from security/commoncap.c:cap_capget */
3837 +static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
3838 +                          kernel_cap_t *inheritable, kernel_cap_t *permitted)
3839 +{
3840 +       struct aa_profile *profile;
3841 +       const struct cred *cred;
3842 +
3843 +       rcu_read_lock();
3844 +       cred = __task_cred(target);
3845 +       aa_cred_policy(cred, &profile);
3846 +
3847 +       *effective   = cred->cap_effective;
3848 +       *inheritable = cred->cap_inheritable;
3849 +       *permitted   = cred->cap_permitted;
3850 +
3851 +       if (profile) {
3852 +               *effective = cap_combine(*effective, profile->caps.set);
3853 +               *effective = cap_intersect(*effective, profile->caps.allowed);
3854 +       }
3855 +       rcu_read_unlock();
3856 +
3857 +       return 0;
3858 +}
3859 +
3860 +static int apparmor_capable(struct task_struct *task, const struct cred *cred,
3861 +                           int cap, int audit)
3862 +{
3863 +       struct aa_profile *profile;
3864 +       /* cap_capable returns 0 on success, else -EPERM */
3865 +       int error = cap_capable(task, cred, cap, audit);
3866 +
3867 +       aa_cred_policy(cred, &profile);
3868 +       if (profile && (!error || cap_raised(profile->caps.set, cap)))
3869 +               error = aa_capable(task, profile, cap, audit);
3870 +
3871 +       return error;
3872 +}
3873 +
3874 +static int apparmor_sysctl(struct ctl_table *table, int op)
3875 +{
3876 +       int error = 0;
3877 +       struct aa_profile *profile = aa_current_profile_wupd();
3878 +
3879 +       if (profile) {
3880 +               char *buffer, *name;
3881 +               int mask;
3882 +
3883 +               mask = 0;
3884 +               if (op & 4)
3885 +                       mask |= MAY_READ;
3886 +               if (op & 2)
3887 +                       mask |= MAY_WRITE;
3888 +
3889 +               error = -ENOMEM;
3890 +               buffer = (char *)__get_free_page(GFP_KERNEL);
3891 +               if (!buffer)
3892 +                       goto out;
3893 +
3894 +               /* 
3895 +                * TODO: convert this over to using a global or per
3896 +                * namespace control instead of a hard coded /proc
3897 +                */
3898 +               name = sysctl_pathname(table, buffer, PAGE_SIZE);
3899 +               if (name && name - buffer >= 5) {
3900 +                       struct path_cond cond = { 0, S_IFREG };
3901 +                       name -= 5;
3902 +                       memcpy(name, "/proc", 5);
3903 +                       error = aa_pathstr_perm(profile, "sysctl", name, mask,
3904 +                                               &cond);
3905 +               }
3906 +               free_page((unsigned long)buffer);
3907 +       }
3908 +
3909 +out:
3910 +       return error;
3911 +}
3912 +
3913 +static int common_perm(const char *op, struct path *path, u16 mask,
3914 +                      struct path_cond *cond)
3915 +{
3916 +       struct aa_profile *profile;
3917 +       int error = 0;
3918 +
3919 +       profile = aa_current_profile();
3920 +       if (profile)
3921 +               error = aa_path_perm(profile, op, path, mask, cond);
3922 +
3923 +       return error;
3924 +}
3925 +
3926 +static int common_perm_dentry(const char *op, struct path *dir,
3927 +                             struct dentry *dentry, u16 mask, 
3928 +                             struct path_cond *cond)
3929 +{
3930 +       struct path path = { dir->mnt, dentry };
3931 +
3932 +       return common_perm(op, &path, mask, cond);
3933 +}
3934 +
3935 +static int common_perm_rm(const char *op, struct path *dir,
3936 +                         struct dentry *dentry, u16 mask)
3937 +{
3938 +       struct inode *inode = dentry->d_inode;
3939 +       struct path_cond cond = {};
3940 +
3941 +       if (!dir->mnt || !inode || !mediated_filesystem(inode))
3942 +               return 0;
3943 +
3944 +       cond.uid = inode->i_uid;
3945 +       cond.mode = inode->i_mode;
3946 +
3947 +       return common_perm_dentry(op, dir, dentry, mask, &cond);
3948 +}
3949 +
3950 +static int common_perm_create(const char *op, struct path *dir,
3951 +                             struct dentry *dentry, u16 mask, umode_t mode)
3952 +{
3953 +       struct path_cond cond = { current_fsuid(), mode };
3954 +
3955 +       if (!dir->mnt || !mediated_filesystem(dir->dentry->d_inode))
3956 +               return 0;
3957 +
3958 +       return common_perm_dentry(op, dir, dentry, mask, &cond);
3959 +}
3960 +
3961 +static int apparmor_path_unlink(struct path *dir, struct dentry *dentry)
3962 +{
3963 +       return common_perm_rm("unlink", dir, dentry, MAY_WRITE);
3964 +}
3965 +
3966 +static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry,
3967 +                              int mode)
3968 +{
3969 +       return common_perm_create("mkdir", dir, dentry, AA_MAY_CREATE, S_IFDIR);
3970 +}
3971 +
3972 +static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry)
3973 +{
3974 +       return common_perm_rm("rmdir", dir, dentry, MAY_WRITE);
3975 +}
3976 +
3977 +static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
3978 +                              int mode, unsigned int dev)
3979 +{
3980 +       return common_perm_create("mknod", dir, dentry, AA_MAY_CREATE, mode);
3981 +}
3982 +
3983 +static int apparmor_path_truncate(struct path *path, loff_t length,
3984 +                                 unsigned int time_attrs)
3985 +{
3986 +       struct path_cond cond = { path->dentry->d_inode->i_uid,
3987 +                                 path->dentry->d_inode->i_mode };
3988 +
3989 +       if (!path->mnt || !mediated_filesystem(path->dentry->d_inode))
3990 +               return 0;
3991 +       return common_perm("truncate", path, MAY_WRITE, &cond);
3992 +}
3993 +
3994 +static int apparmor_path_symlink(struct path *dir, struct dentry *dentry,
3995 +                         const char *old_name)
3996 +{
3997 +       return common_perm_create("symlink_create", dir, dentry, AA_MAY_CREATE,
3998 +                                 S_IFLNK);
3999 +}
4000 +
4001 +static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir,
4002 +                             struct dentry *new_dentry)
4003 +{
4004 +       struct aa_profile *profile;
4005 +       int error = 0;
4006 +
4007 +       if (!mediated_filesystem(old_dentry->d_inode))
4008 +               return 0;
4009 +
4010 +       profile = aa_current_profile_wupd();
4011 +       if (profile)
4012 +               error = aa_path_link(profile, old_dentry, new_dir, new_dentry);
4013 +       return error;
4014 +}
4015 +
4016 +static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
4017 +                        struct path *new_dir, struct dentry *new_dentry)
4018 +{
4019 +       struct aa_profile *profile;
4020 +       int error = 0;
4021 +
4022 +       if (!mediated_filesystem(old_dentry->d_inode))
4023 +               return 0;
4024 +
4025 +       profile = aa_current_profile_wupd();
4026 +       if (profile) {
4027 +               struct path old_path = { old_dir->mnt, old_dentry };
4028 +               struct path new_path = { new_dir->mnt, new_dentry };
4029 +               struct path_cond cond = { old_dentry->d_inode->i_uid,
4030 +                                         old_dentry->d_inode->i_mode };
4031 +
4032 +               error = aa_path_perm(profile, "rename_src", &old_path,
4033 +                                    MAY_READ | MAY_WRITE, &cond);
4034 +               if (!error)
4035 +                       error = aa_path_perm(profile, "rename_dest", &new_path,
4036 +                                            AA_MAY_CREATE | MAY_WRITE, &cond);
4037 +                                            
4038 +       }
4039 +       return error;
4040 +}
4041 +
4042 +static int apparmor_dentry_open(struct file *file, const struct cred *cred)
4043 +{
4044 +       struct aa_profile *profile;
4045 +       int error = 0;
4046 +         
4047 +       /* If in exec permission is handled by bprm hooks */
4048 +       if (current->in_execve ||
4049 +           !mediated_filesystem(file->f_path.dentry->d_inode))
4050 +               return 0;
4051 +
4052 +       aa_cred_policy(cred, &profile);
4053 +       if (profile) {
4054 +               struct aa_file_cxt *fcxt = file->f_security;
4055 +               struct inode *inode = file->f_path.dentry->d_inode; 
4056 +               struct path_cond cond = { inode->i_uid, inode->i_mode };
4057 +
4058 +               error = aa_path_perm(profile, "open", &file->f_path,
4059 +                                    aa_map_file_to_perms(file), &cond);
4060 +               fcxt->profile = aa_get_profile(profile);
4061 +               /* todo cache actual allowed permissions */
4062 +               fcxt->allowed = 0;
4063 +       }
4064 +
4065 +       return error;
4066 +}
4067 +
4068 +static int apparmor_file_alloc_security(struct file *file)
4069 +{
4070 +       file->f_security = aa_alloc_file_context(GFP_KERNEL);
4071 +       if (!file->f_security)
4072 +               return -ENOMEM;
4073 +       return 0;
4074 +
4075 +}
4076 +
4077 +static void apparmor_file_free_security(struct file *file)
4078 +{
4079 +       struct aa_file_cxt *cxt = file->f_security;
4080 +
4081 +       aa_free_file_context(cxt);
4082 +}
4083 +
4084 +static int apparmor_file_permission(struct file *file, int mask)
4085 +{
4086 +       /*
4087 +        * Most basic (rw) file access is revalidated at exec.
4088 +        * The revalidation done here is for parent/child hat
4089 +        * file accesses.
4090 +        *
4091 +        * Currently profile replacement does not cause revalidation
4092 +        * or file revocation.
4093 +        *
4094 +        * TODO: cache profiles that have revalidated?
4095 +        */
4096 +       struct aa_file_cxt *fcxt = file->f_security;
4097 +       struct aa_profile *profile, *fprofile = fcxt->profile;
4098 +       int error = 0;
4099 +
4100 +       if (!fprofile || !file->f_path.mnt ||
4101 +           !mediated_filesystem(file->f_path.dentry->d_inode))
4102 +               return 0;
4103 +
4104 +       profile = aa_current_profile();
4105 +       /* TODO: Enable at exec time revalidation of files
4106 +       if (profile && (fprofile != profile) &&
4107 +           ((PROFILE_IS_HAT(profile) && (profile->parent == fprofile)) ||
4108 +            (PROFILE_IS_HAT(fprofile) && (fprofile->parent == profile))))
4109 +               error = aa_file_perm(profile, "file_perm", file, mask);
4110 +       */
4111 +       if (profile && ((fprofile != profile) || (mask & ~fcxt->allowed)))
4112 +               error = aa_file_perm(profile, "file_perm", file, mask);
4113 +
4114 +       return error;
4115 +}
4116 +
4117 +static int common_file_perm(const char *op, struct file *file, u16 mask)
4118 +{
4119 +       const struct aa_file_cxt *fcxt = file->f_security;
4120 +       struct aa_profile *profile, *fprofile = fcxt->profile;
4121 +       int error = 0;
4122 +
4123 +       if (!fprofile || !file->f_path.mnt ||
4124 +           !mediated_filesystem(file->f_path.dentry->d_inode))
4125 +               return 0;
4126 +
4127 +       profile = aa_current_profile_wupd();
4128 +       if (profile && ((fprofile != profile) || (mask & ~fcxt->allowed)))
4129 +               error = aa_file_perm(profile, op, file, mask);
4130 +
4131 +       return error;
4132 +}
4133 +
4134 +static int apparmor_file_lock(struct file *file, unsigned int cmd)
4135 +{
4136 +       u16 mask = AA_MAY_LOCK;
4137 +
4138 +       if (cmd == F_WRLCK)
4139 +               mask |= MAY_WRITE;
4140 +
4141 +       return common_file_perm("file_lock", file, mask);
4142 +}
4143 +
4144 +
4145 +/*
4146 + * AppArmor doesn't current use the fcntl hook.
4147 + * 
4148 + * FIXME - these are not implemented yet - REMOVE file_fcntl hook
4149 + * NOTE: some of the file control commands are further mediated
4150 + *       by other hooks
4151 + * F_SETOWN - security_file_set_fowner
4152 + * F_SETLK - security_file_lock
4153 + * F_SETLKW - security_file_lock
4154 + * O_APPEND - AppArmor mediates append as a subset of full write
4155 + *            so changing from full write to appending write is
4156 + *            dropping priviledge and not restricted.
4157 +
4158 +
4159 +static int apparmor_file_fcntl(struct file *file, unsigned int cmd,
4160 +                            unsigned long arg)
4161 +{
4162 +       return 0;
4163 +}
4164 +*/
4165 +
4166 +static int common_mmap(struct file *file, const char *operation,
4167 +                  unsigned long prot, unsigned long flags)
4168 +{
4169 +       struct dentry *dentry;
4170 +       int mask = 0;
4171 +
4172 +       if (!file || !file->f_security)
4173 +               return 0;
4174 +
4175 +       if (prot & PROT_READ)
4176 +               mask |= MAY_READ;
4177 +       /* Private mappings don't require write perms since they don't
4178 +        * write back to the files */
4179 +       if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
4180 +               mask |= MAY_WRITE;
4181 +       if (prot & PROT_EXEC)
4182 +               mask |= AA_EXEC_MMAP;
4183 +
4184 +       dentry = file->f_path.dentry;
4185 +       return common_file_perm(operation, file, mask);
4186 +}
4187 +
4188 +static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
4189 +                             unsigned long prot, unsigned long flags,
4190 +                             unsigned long addr, unsigned long addr_only)
4191 +{
4192 +       if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
4193 +               struct aa_profile *profile = aa_current_profile_wupd();
4194 +               if (profile)
4195 +                       /* future control check here */
4196 +                       return -EACCES;
4197 +               else
4198 +                       return -EACCES;
4199 +       }
4200 +
4201 +       return common_mmap(file, "file_mmap", prot, flags);
4202 +}
4203 +
4204 +static int apparmor_file_mprotect(struct vm_area_struct *vma,
4205 +                                 unsigned long reqprot, unsigned long prot)
4206 +{
4207 +       return common_mmap(vma->vm_file, "file_mprotect", prot,
4208 +                      !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
4209 +}
4210 +
4211 +static int apparmor_getprocattr(struct task_struct *task, char *name,
4212 +                               char **value)
4213 +{
4214 +       int error = -ENOENT;
4215 +       struct aa_namespace *ns;
4216 +       struct aa_profile *profile, *onexec, *prev;
4217 +       const struct cred *cred = aa_get_task_policy(task, &profile);
4218 +       struct aa_task_context *cxt = cred->security;
4219 +       ns = cxt->sys.profile->ns;
4220 +       onexec = cxt->sys.onexec;
4221 +       prev = cxt->sys.previous;
4222 +
4223 +       /* task must be either querying itself, unconfined or can ptrace */
4224 +       if (current != task && profile && !capable(CAP_SYS_PTRACE)) {
4225 +               error = -EPERM;
4226 +       } else {
4227 +               if (strcmp(name, "current") == 0) {
4228 +                       error = aa_getprocattr(ns, profile, value);
4229 +               } else if (strcmp(name, "prev") == 0) {
4230 +                       if (prev)
4231 +                               error = aa_getprocattr(ns, prev, value);
4232 +               } else if (strcmp(name, "exec") == 0) {
4233 +                       if (onexec)
4234 +                               error = aa_getprocattr(ns, onexec, value);
4235 +               } else {
4236 +                       error = -EINVAL;
4237 +               }
4238 +       }
4239 +
4240 +       put_cred(cred);
4241 +
4242 +       return error;
4243 +}
4244 +
4245 +static int apparmor_setprocattr(struct task_struct *task, char *name,
4246 +                               void *value, size_t size)
4247 +{
4248 +       char *command, *args;
4249 +       int error;
4250 +
4251 +       if (size == 0 || size >= PAGE_SIZE)
4252 +               return -EINVAL;
4253 +
4254 +       /* task can only write its own attributes */
4255 +       if (current != task)
4256 +               return -EACCES;
4257 +
4258 +       args = value;
4259 +       args[size] = '\0';
4260 +       args = strstrip(args);
4261 +       command = strsep(&args, " ");
4262 +       if (!args)
4263 +               return -EINVAL;
4264 +       while (isspace(*args))
4265 +               args++;
4266 +       if (!*args)
4267 +               return -EINVAL;
4268 +
4269 +       if (strcmp(name, "current") == 0) {
4270 +               if (strcmp(command, "changehat") == 0) {
4271 +                       error = aa_setprocattr_changehat(args, !AA_DO_TEST);
4272 +               } else if (strcmp(command, "permhat") == 0) {
4273 +                       error = aa_setprocattr_changehat(args, AA_DO_TEST);
4274 +               } else if (strcmp(command, "changeprofile") == 0) {
4275 +                       error = aa_setprocattr_changeprofile(args, 0,
4276 +                                                            !AA_DO_TEST);
4277 +               } else if (strcmp(command, "permprofile") == 0) {
4278 +                       error = aa_setprocattr_changeprofile(args, 0,
4279 +                                                            AA_DO_TEST);
4280 +               } else if (strcmp(command, "permipc") == 0) {
4281 +                       error = aa_setprocattr_permipc(args);
4282 +               } else {
4283 +                       struct aa_audit sa;
4284 +                       memset(&sa, 0, sizeof(sa));
4285 +                       sa.operation = "setprocattr";
4286 +                       sa.gfp_mask = GFP_KERNEL;
4287 +                       sa.info = name;
4288 +                       sa.error = -EINVAL;
4289 +                       return aa_audit(AUDIT_APPARMOR_DENIED, NULL, &sa, NULL);
4290 +               }
4291 +       } else if (strcmp(name, "exec") == 0) {
4292 +               error = aa_setprocattr_changeprofile(strstrip(args), 1,
4293 +                                                    !AA_DO_TEST);
4294 +       } else {
4295 +               /* only support the "current" and "exec" process attributes */
4296 +               return -EINVAL;
4297 +       }
4298 +       if (!error)
4299 +               error = size;
4300 +       return error;
4301 +}
4302 +
4303 +static int apparmor_task_setrlimit(unsigned int resource,
4304 +                                  struct rlimit *new_rlim)
4305 +{
4306 +       struct aa_profile *profile = aa_current_profile_wupd();
4307 +       int error = 0;
4308 +
4309 +       if (profile) {
4310 +               error = aa_task_setrlimit(profile, resource, new_rlim);
4311 +       }
4312 +
4313 +       return error;
4314 +}
4315 +
4316 +#ifdef CONFIG_SECURITY_APPARMOR_NETWORK
4317 +static int apparmor_socket_create(int family, int type, int protocol, int kern){
4318 +       struct aa_profile *profile;
4319 +       int error = 0;
4320 +
4321 +       if (kern)
4322 +               return 0;
4323 +
4324 +       profile = aa_current_profile();
4325 +       if (profile)
4326 +               error = aa_net_perm(profile, "socket_create", family,
4327 +                                                       type, protocol);
4328 +       return error;
4329 +}
4330 +
4331 +static int apparmor_socket_post_create(struct socket *sock, int family,
4332 +                                       int type, int protocol, int kern)
4333 +{
4334 +       struct sock *sk = sock->sk;
4335 +
4336 +       if (kern)
4337 +               return 0;
4338 +
4339 +       return aa_revalidate_sk(sk, "socket_post_create");
4340 +}
4341 +
4342 +static int apparmor_socket_bind(struct socket *sock,
4343 +                               struct sockaddr *address, int addrlen)
4344 +{
4345 +       struct sock *sk = sock->sk;
4346 +
4347 +       return aa_revalidate_sk(sk, "socket_bind");
4348 +}
4349 +
4350 +static int apparmor_socket_connect(struct socket *sock,
4351 +                                       struct sockaddr *address, int addrlen)
4352 +{
4353 +       struct sock *sk = sock->sk;
4354 +
4355 +       return aa_revalidate_sk(sk, "socket_connect");
4356 +}
4357 +
4358 +static int apparmor_socket_listen(struct socket *sock, int backlog)
4359 +{
4360 +       struct sock *sk = sock->sk;
4361 +
4362 +       return aa_revalidate_sk(sk, "socket_listen");
4363 +}
4364 +
4365 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
4366 +{
4367 +       struct sock *sk = sock->sk;
4368 +
4369 +       return aa_revalidate_sk(sk, "socket_accept");
4370 +}
4371 +
4372 +static int apparmor_socket_sendmsg(struct socket *sock,
4373 +                                       struct msghdr *msg, int size)
4374 +{
4375 +       struct sock *sk = sock->sk;
4376 +
4377 +       return aa_revalidate_sk(sk, "socket_sendmsg");
4378 +}
4379 +
4380 +static int apparmor_socket_recvmsg(struct socket *sock,
4381 +                                  struct msghdr *msg, int size, int flags)
4382 +{
4383 +       struct sock *sk = sock->sk;
4384 +
4385 +       return aa_revalidate_sk(sk, "socket_recvmsg");
4386 +}
4387 +
4388 +static int apparmor_socket_getsockname(struct socket *sock)
4389 +{
4390 +       struct sock *sk = sock->sk;
4391 +
4392 +       return aa_revalidate_sk(sk, "socket_getsockname");
4393 +}
4394 +
4395 +static int apparmor_socket_getpeername(struct socket *sock)
4396 +{
4397 +       struct sock *sk = sock->sk;
4398 +
4399 +       return aa_revalidate_sk(sk, "socket_getpeername");
4400 +}
4401 +
4402 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
4403 +                                       int optname)
4404 +{
4405 +       struct sock *sk = sock->sk;
4406 +
4407 +       return aa_revalidate_sk(sk, "socket_getsockopt");
4408 +}
4409 +
4410 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
4411 +                                       int optname)
4412 +{
4413 +       struct sock *sk = sock->sk;
4414 +
4415 +       return aa_revalidate_sk(sk, "socket_setsockopt");
4416 +}
4417 +
4418 +static int apparmor_socket_shutdown(struct socket *sock, int how)
4419 +{
4420 +       struct sock *sk = sock->sk;
4421 +
4422 +       return aa_revalidate_sk(sk, "socket_shutdown");
4423 +}
4424 +#endif
4425 +
4426 +static struct security_operations apparmor_ops = {
4427 +       .name =                         "apparmor",
4428 +
4429 +       .ptrace_may_access =            apparmor_ptrace_may_access,
4430 +       .ptrace_traceme =               apparmor_ptrace_traceme,
4431 +       .capget =                       apparmor_capget,
4432 +       .sysctl =                       apparmor_sysctl,
4433 +       .capable =                      apparmor_capable,
4434 +/*
4435 +       .inode_create =                 apparmor_inode_create,
4436 +       .inode_setattr =                apparmor_inode_setattr,
4437 +       .inode_setxattr =               apparmor_inode_setxattr,
4438 +       .inode_getxattr =               apparmor_inode_getxattr,
4439 +       .inode_listxattr =              apparmor_inode_listxattr,
4440 +       .inode_removexattr =            apparmor_inode_removexattr,
4441 +       .inode_permission = ??? use to mediate owner access to non-mediated fs
4442 +*/
4443 +
4444 +       .path_link =                    apparmor_path_link,
4445 +       .path_unlink =                  apparmor_path_unlink,
4446 +       .path_symlink =                 apparmor_path_symlink,
4447 +       .path_mkdir =                   apparmor_path_mkdir,
4448 +       .path_rmdir =                   apparmor_path_rmdir,
4449 +       .path_mknod =                   apparmor_path_mknod,
4450 +       .path_rename =                  apparmor_path_rename,
4451 +       .path_truncate =                apparmor_path_truncate,
4452 +       .dentry_open =                  apparmor_dentry_open,
4453 +
4454 +       .file_permission =              apparmor_file_permission,
4455 +       .file_alloc_security =          apparmor_file_alloc_security,
4456 +       .file_free_security =           apparmor_file_free_security,
4457 +       .file_mmap =                    apparmor_file_mmap,
4458 +       .file_mprotect =                apparmor_file_mprotect,
4459 +       .file_lock =                    apparmor_file_lock,
4460 +
4461 +/*     .file_fcntl =                   apparmor_file_fcntl, */
4462 +
4463 +       .getprocattr =                  apparmor_getprocattr,
4464 +       .setprocattr =                  apparmor_setprocattr,
4465 +
4466 +#ifdef CONFIG_SECURITY_APPARMOR_NETWORK
4467 +       .socket_create =                apparmor_socket_create,
4468 +       .socket_post_create =           apparmor_socket_post_create,
4469 +       .socket_bind =                  apparmor_socket_bind,
4470 +       .socket_connect =               apparmor_socket_connect,
4471 +       .socket_listen =                apparmor_socket_listen,
4472 +       .socket_accept =                apparmor_socket_accept,
4473 +       .socket_sendmsg =               apparmor_socket_sendmsg,
4474 +       .socket_recvmsg =               apparmor_socket_recvmsg,
4475 +       .socket_getsockname =           apparmor_socket_getsockname,
4476 +       .socket_getpeername =           apparmor_socket_getpeername,
4477 +       .socket_getsockopt =            apparmor_socket_getsockopt,
4478 +       .socket_setsockopt =            apparmor_socket_setsockopt,
4479 +       .socket_shutdown =              apparmor_socket_shutdown,
4480 +#endif
4481 +
4482 +       .cred_free =                    apparmor_cred_free,
4483 +       .cred_prepare =                 apparmor_cred_prepare,
4484 +
4485 +       .bprm_set_creds =               apparmor_bprm_set_creds,
4486 +       //      .bprm_committing_creds =        apparmor_bprm_committing_creds,
4487 +       .bprm_committed_creds =         apparmor_bprm_committed_creds,
4488 +       .bprm_secureexec =              apparmor_bprm_secureexec,
4489 +
4490 +       .task_setrlimit =               apparmor_task_setrlimit,
4491 +};
4492 +
4493 +
4494 +/*
4495 + * AppArmor sysfs module parameters
4496 + */
4497 +
4498 +static int param_set_aabool(const char *val, struct kernel_param *kp);
4499 +static int param_get_aabool(char *buffer, struct kernel_param *kp);
4500 +#define param_check_aabool(name, p) __param_check(name, p, int)
4501 +
4502 +static int param_set_aauint(const char *val, struct kernel_param *kp);
4503 +static int param_get_aauint(char *buffer, struct kernel_param *kp);
4504 +#define param_check_aauint(name, p) __param_check(name, p, int)
4505 +
4506 +static int param_set_aalockpolicy(const char *val, struct kernel_param *kp);
4507 +static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp);
4508 +#define param_check_aalockpolicy(name, p) __param_check(name, p, int)
4509 +
4510 +static int param_set_audit(const char *val, struct kernel_param *kp);
4511 +static int param_get_audit(char *buffer, struct kernel_param *kp);
4512 +#define param_check_audit(name, p) __param_check(name, p, int)
4513 +
4514 +static int param_set_mode(const char *val, struct kernel_param *kp);
4515 +static int param_get_mode(char *buffer, struct kernel_param *kp);
4516 +#define param_check_mode(name, p) __param_check(name, p, int)
4517 +
4518 +/* Flag values, also controllable via /sys/module/apparmor/parameters
4519 + * We define special types as we want to do additional mediation.
4520 + */
4521 +
4522 +/* AppArmor global enforcement switch - complain, enforce, kill */
4523 +enum profile_mode g_profile_mode = APPARMOR_ENFORCE;
4524 +module_param_call(mode, param_set_mode, param_get_mode,
4525 +                 &g_profile_mode, S_IRUSR | S_IWUSR);
4526 +
4527 +/* Debug mode */
4528 +int g_apparmor_debug;
4529 +module_param_named(debug, g_apparmor_debug, aabool, S_IRUSR | S_IWUSR);
4530 +
4531 +/* Audit mode */
4532 +enum audit_mode g_apparmor_audit;
4533 +module_param_call(audit, param_set_audit, param_get_audit,
4534 +                 &g_apparmor_audit, S_IRUSR | S_IWUSR);
4535 +
4536 +/* Determines if audit header is included in audited messages.  This
4537 + * provides more context if the audit daemon is not running
4538 + */
4539 +int g_apparmor_audit_header;
4540 +module_param_named(audit_header, g_apparmor_audit_header, aabool,
4541 +                  S_IRUSR | S_IWUSR);
4542 +
4543 +/* lock out loading/removal of policy
4544 + * TODO: add in at boot loading of policy, which is the only way to
4545 + *       load policy, if lock_policy is set
4546 + */
4547 +int g_apparmor_lock_policy;
4548 +module_param_named(lock_policy, g_apparmor_lock_policy, aalockpolicy,
4549 +                  S_IRUSR | S_IWUSR);
4550 +
4551 +/* Syscall logging mode */
4552 +int g_apparmor_logsyscall;
4553 +module_param_named(logsyscall, g_apparmor_logsyscall, aabool,
4554 +                  S_IRUSR | S_IWUSR);
4555 +
4556 +/* Maximum pathname length before accesses will start getting rejected */
4557 +unsigned int g_apparmor_path_max = 2 * PATH_MAX;
4558 +module_param_named(path_max, g_apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
4559 +
4560 +/* Boot time disable flag */
4561 +#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
4562 +#define AA_ENABLED_PERMS 0600
4563 +#else
4564 +#define AA_ENABLED_PERMS 0400
4565 +#endif
4566 +static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
4567 +static unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
4568 +module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
4569 +                 &apparmor_enabled, AA_ENABLED_PERMS);
4570 +
4571 +static int __init apparmor_enabled_setup(char *str)
4572 +{
4573 +       apparmor_enabled = simple_strtol(str, NULL, 0);
4574 +       return 1;
4575 +}
4576 +__setup("apparmor=", apparmor_enabled_setup);
4577 +
4578 +static int param_set_aalockpolicy(const char *val, struct kernel_param *kp)
4579 +{
4580 +       if (__aa_task_is_confined(current))
4581 +               return -EPERM;
4582 +       if (g_apparmor_lock_policy)
4583 +               return -EACCES;
4584 +       return param_set_bool(val, kp);
4585 +}
4586 +
4587 +static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp)
4588 +{
4589 +       if (__aa_task_is_confined(current))
4590 +               return -EPERM;
4591 +       return param_get_bool(buffer, kp);
4592 +}
4593 +
4594 +static int param_set_aabool(const char *val, struct kernel_param *kp)
4595 +{
4596 +       if (__aa_task_is_confined(current))
4597 +               return -EPERM;
4598 +       return param_set_bool(val, kp);
4599 +}
4600 +
4601 +static int param_get_aabool(char *buffer, struct kernel_param *kp)
4602 +{
4603 +       if (__aa_task_is_confined(current))
4604 +               return -EPERM;
4605 +       return param_get_bool(buffer, kp);
4606 +}
4607 +
4608 +static int param_set_aauint(const char *val, struct kernel_param *kp)
4609 +{
4610 +       if (__aa_task_is_confined(current))
4611 +               return -EPERM;
4612 +       return param_set_uint(val, kp);
4613 +}
4614 +
4615 +static int param_get_aauint(char *buffer, struct kernel_param *kp)
4616 +{
4617 +       if (__aa_task_is_confined(current))
4618 +               return -EPERM;
4619 +       return param_get_uint(buffer, kp);
4620 +}
4621 +
4622 +/* allow run time disabling of apparmor */
4623 +static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
4624 +{
4625 +       unsigned long l;
4626 +
4627 +       if (!apparmor_initialized) {
4628 +               apparmor_enabled = 0;
4629 +               return 0;
4630 +       }
4631 +
4632 +       if (__aa_task_is_confined(current))
4633 +               return -EPERM;
4634 +
4635 +       if (!apparmor_enabled)
4636 +               return -EINVAL;
4637 +
4638 +       if (!val)
4639 +               return -EINVAL;
4640 +
4641 +       if (strict_strtoul(val, 0, &l) || l != 0)
4642 +               return -EINVAL;
4643 +
4644 +       apparmor_enabled = 0;
4645 +       apparmor_disable();
4646 +       return 0;
4647 +}
4648 +
4649 +static int param_get_audit(char *buffer, struct kernel_param *kp)
4650 +{
4651 +       if (__aa_task_is_confined(current))
4652 +               return -EPERM;
4653 +
4654 +       if (!apparmor_enabled)
4655 +               return -EINVAL;
4656 +
4657 +       return sprintf(buffer, "%s", audit_mode_names[g_apparmor_audit]);
4658 +}
4659 +
4660 +static int param_set_audit(const char *val, struct kernel_param *kp)
4661 +{
4662 +       int i;
4663 +       if (__aa_task_is_confined(current))
4664 +               return -EPERM;
4665 +
4666 +       if (!apparmor_enabled)
4667 +               return -EINVAL;
4668 +
4669 +       if (!val)
4670 +               return -EINVAL;
4671 +
4672 +       for (i = 0; i < AUDIT_MAX_INDEX; i++) {
4673 +               if (strcmp(val, audit_mode_names[i]) == 0) {
4674 +                       g_apparmor_audit = i;
4675 +                       return 0;
4676 +               }
4677 +       }
4678 +
4679 +       return -EINVAL;
4680 +}
4681 +
4682 +static int param_get_mode(char *buffer, struct kernel_param *kp)
4683 +{
4684 +       if (__aa_task_is_confined(current))
4685 +               return -EPERM;
4686 +
4687 +       if (!apparmor_enabled)
4688 +               return -EINVAL;
4689 +
4690 +       return sprintf(buffer, "%s", profile_mode_names[g_profile_mode]);
4691 +}
4692 +
4693 +static int param_set_mode(const char *val, struct kernel_param *kp)
4694 +{
4695 +       int i;
4696 +       if (__aa_task_is_confined(current))
4697 +               return -EPERM;
4698 +
4699 +       if (!apparmor_enabled)
4700 +               return -EINVAL;
4701 +
4702 +       if (!val)
4703 +               return -EINVAL;
4704 +
4705 +       for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) {
4706 +               if (strcmp(val, profile_mode_names[i]) == 0) {
4707 +                       g_profile_mode = i;
4708 +                       return 0;
4709 +               }
4710 +       }
4711 +
4712 +       return -EINVAL;
4713 +}
4714 +
4715 +
4716 +/*
4717 + * AppArmor init functions
4718 + */
4719 +
4720 +static int set_init_cxt(void)
4721 +{
4722 +       struct cred *cred = (struct cred *) current->real_cred;
4723 +       struct aa_task_context *cxt;
4724 +
4725 +       cxt = aa_alloc_task_context(GFP_KERNEL);
4726 +       if (!cxt)
4727 +               return -ENOMEM;
4728 +
4729 +       cxt->sys.profile = aa_get_profile(default_namespace->unconfined);
4730 +       cred->security = cxt;
4731 +
4732 +       return 0;
4733 +}
4734 +
4735 +static int __init apparmor_init(void)
4736 +{
4737 +       int error;
4738 +
4739 +       if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
4740 +               info_message("AppArmor disabled by boot time parameter\n");
4741 +               apparmor_enabled = 0;
4742 +               return 0;
4743 +       }
4744 +
4745 +       /*
4746 +        * Activated with fs_initcall
4747 +       error = create_apparmorfs();
4748 +       if (error) {
4749 +               AA_ERROR("Unable to activate AppArmor filesystem\n");
4750 +               goto createfs_out;
4751 +       }
4752 +       */
4753 +
4754 +       error = alloc_default_namespace();
4755 +       if (error) {
4756 +               AA_ERROR("Unable to allocate default profile namespace\n");
4757 +               goto alloc_out;
4758 +       }
4759 +
4760 +       error = set_init_cxt();
4761 +       if (error) {
4762 +               AA_ERROR("Failed to set context on init task\n");
4763 +               goto alloc_out;
4764 +       }
4765 +
4766 +       error = register_security(&apparmor_ops);
4767 +       if (error) {
4768 +               AA_ERROR("Unable to register AppArmor\n");
4769 +               goto register_security_out;
4770 +       }
4771 +
4772 +       /* Report that AppArmor successfully initialized */
4773 +       apparmor_initialized = 1;
4774 +       if (g_profile_mode == APPARMOR_COMPLAIN)
4775 +               info_message("AppArmor initialized: complain mode enabled");
4776 +       else if (g_profile_mode == APPARMOR_KILL)
4777 +               info_message("AppArmor initialized: kill mode enabled");
4778 +       else
4779 +               info_message("AppArmor initialized");
4780 +
4781 +       return error;
4782 +
4783 +register_security_out:
4784 +       free_default_namespace();
4785 +
4786 +alloc_out:
4787 +       destroy_apparmorfs();
4788 +
4789 +/*createfs_out:*/
4790 +       apparmor_enabled = 0;
4791 +       return error;
4792 +
4793 +}
4794 +
4795 +security_initcall(apparmor_init);
4796 +
4797 +void apparmor_disable(void)
4798 +{
4799 +       /* Remove and release all the profiles on the profile list. */
4800 +       aa_profile_ns_list_release();
4801 +
4802 +       /* FIXME: cleanup profiles references on files */
4803 +       free_default_namespace();
4804 +
4805 +       /*
4806 +        * Delay for an rcu cycle to make sure that all active task
4807 +        * context readers have finished, and all profiles have been
4808 +        * freed by their rcu callbacks.
4809 +        */
4810 +       synchronize_rcu();
4811 +       destroy_apparmorfs();
4812 +       apparmor_initialized = 0;
4813 +
4814 +       info_message("AppArmor protection disabled");
4815 +}
4816 +
4817 diff --git a/security/apparmor/match.c b/security/apparmor/match.c
4818 new file mode 100644
4819 index 0000000..a22d106
4820 --- /dev/null
4821 +++ b/security/apparmor/match.c
4822 @@ -0,0 +1,293 @@
4823 +/*
4824 + * AppArmor security module
4825 + *
4826 + * This file contains AppArmor dfa based regular expression matching engine
4827 + *
4828 + * Copyright (C) 1998-2008 Novell/SUSE
4829 + * Copyright 2009 Canonical Ltd.
4830 + *
4831 + * This program is free software; you can redistribute it and/or
4832 + * modify it under the terms of the GNU General Public License as
4833 + * published by the Free Software Foundation, version 2 of the
4834 + * License.
4835 + */
4836 +
4837 +#include <linux/kernel.h>
4838 +#include <linux/slab.h>
4839 +#include <linux/errno.h>
4840 +
4841 +/* TODO: remove !!!! */
4842 +// #include <linux/fs.h>
4843 +
4844 +#include "include/apparmor.h"
4845 +#include "include/match.h"
4846 +#include "include/file.h"
4847 +
4848 +static struct table_header *unpack_table(void *blob, size_t bsize)
4849 +{
4850 +       struct table_header *table = NULL;
4851 +       struct table_header th;
4852 +       size_t tsize;
4853 +
4854 +       if (bsize < sizeof(struct table_header))
4855 +               goto out;
4856 +
4857 +       th.td_id = be16_to_cpu(*(u16 *) (blob));
4858 +       th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
4859 +       th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
4860 +       blob += sizeof(struct table_header);
4861 +
4862 +       if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
4863 +               th.td_flags == YYTD_DATA8))
4864 +               goto out;
4865 +
4866 +       tsize = table_size(th.td_lolen, th.td_flags);
4867 +       if (bsize < tsize)
4868 +               goto out;
4869 +
4870 +       table = kmalloc(tsize, GFP_KERNEL);
4871 +       if (table) {
4872 +               *table = th;
4873 +               if (th.td_flags == YYTD_DATA8)
4874 +                       UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
4875 +                                    u8, byte_to_byte);
4876 +               else if (th.td_flags == YYTD_DATA16)
4877 +                       UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
4878 +                                    u16, be16_to_cpu);
4879 +               else
4880 +                       UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
4881 +                                    u32, be32_to_cpu);
4882 +       }
4883 +
4884 +out:
4885 +       return table;
4886 +}
4887 +
4888 +int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
4889 +{
4890 +       int hsize, i;
4891 +       int error = -ENOMEM;
4892 +
4893 +       /* get dfa table set header */
4894 +       if (size < sizeof(struct table_set_header))
4895 +               goto fail;
4896 +
4897 +       if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
4898 +               goto fail;
4899 +
4900 +       hsize = ntohl(*(u32 *)(blob + 4));
4901 +       if (size < hsize)
4902 +               goto fail;
4903 +
4904 +       blob += hsize;
4905 +       size -= hsize;
4906 +
4907 +       error = -EPROTO;
4908 +       while (size > 0) {
4909 +               struct table_header *table;
4910 +               table = unpack_table(blob, size);
4911 +               if (!table)
4912 +                       goto fail;
4913 +
4914 +               switch (table->td_id) {
4915 +               case YYTD_ID_ACCEPT:
4916 +               case YYTD_ID_ACCEPT2:
4917 +               case YYTD_ID_BASE:
4918 +                       dfa->tables[table->td_id - 1] = table;
4919 +                       if (table->td_flags != YYTD_DATA32)
4920 +                               goto fail;
4921 +                       break;
4922 +               case YYTD_ID_DEF:
4923 +               case YYTD_ID_NXT:
4924 +               case YYTD_ID_CHK:
4925 +                       dfa->tables[table->td_id - 1] = table;
4926 +                       if (table->td_flags != YYTD_DATA16)
4927 +                               goto fail;
4928 +                       break;
4929 +               case YYTD_ID_EC:
4930 +                       dfa->tables[table->td_id - 1] = table;
4931 +                       if (table->td_flags != YYTD_DATA8)
4932 +                               goto fail;
4933 +                       break;
4934 +               default:
4935 +                       kfree(table);
4936 +                       goto fail;
4937 +               }
4938 +
4939 +               blob += table_size(table->td_lolen, table->td_flags);
4940 +               size -= table_size(table->td_lolen, table->td_flags);
4941 +       }
4942 +
4943 +       return 0;
4944 +
4945 +fail:
4946 +       for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
4947 +               kfree(dfa->tables[i]);
4948 +               dfa->tables[i] = NULL;
4949 +       }
4950 +       return error;
4951 +}
4952 +
4953 +/**
4954 + * verify_dfa - verify that all the transitions and states in the dfa tables
4955 + *              are in bounds.
4956 + * @dfa: dfa to test
4957 + *
4958 + * assumes dfa has gone through the verification done by unpacking
4959 + */
4960 +int verify_dfa(struct aa_dfa *dfa)
4961 +{
4962 +       size_t i, state_count, trans_count;
4963 +       int error = -EPROTO;
4964 +
4965 +       /* check that required tables exist */
4966 +       if (!(dfa->tables[YYTD_ID_ACCEPT - 1] &&
4967 +             dfa->tables[YYTD_ID_ACCEPT2 - 1] &&
4968 +             dfa->tables[YYTD_ID_DEF - 1] &&
4969 +             dfa->tables[YYTD_ID_BASE - 1] &&
4970 +             dfa->tables[YYTD_ID_NXT - 1] &&
4971 +             dfa->tables[YYTD_ID_CHK - 1]))
4972 +               goto out;
4973 +
4974 +       /* accept.size == default.size == base.size */
4975 +       state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
4976 +       if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
4977 +             state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen &&
4978 +             state_count == dfa->tables[YYTD_ID_ACCEPT2 - 1]->td_lolen))
4979 +               goto out;
4980 +
4981 +       /* next.size == chk.size */
4982 +       trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen;
4983 +       if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen)
4984 +               goto out;
4985 +
4986 +       /* if equivalence classes then its table size must be 256 */
4987 +       if (dfa->tables[YYTD_ID_EC - 1] &&
4988 +           dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256)
4989 +               goto out;
4990 +
4991 +       for (i = 0; i < state_count; i++) {
4992 +               if (DEFAULT_TABLE(dfa)[i] >= state_count)
4993 +                       goto out;
4994 +               if (BASE_TABLE(dfa)[i] >= trans_count + 256)
4995 +                       goto out;
4996 +       }
4997 +
4998 +       for (i = 0; i < trans_count ; i++) {
4999 +               if (NEXT_TABLE(dfa)[i] >= state_count)
5000 +                       goto out;
5001 +               if (CHECK_TABLE(dfa)[i] >= state_count)
5002 +                       goto out;
5003 +       }
5004 +
5005 +       /* verify accept permissions */
5006 +       for (i = 0; i < state_count; i++) {
5007 +               int mode = ACCEPT_TABLE(dfa)[i];
5008 +
5009 +               if (mode & ~DFA_VALID_PERM_MASK)
5010 +                       goto out;
5011 +               if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK)
5012 +                       goto out;
5013 +
5014 +       }
5015 +
5016 +       error = 0;
5017 +out:
5018 +       return error;
5019 +}
5020 +
5021 +struct aa_dfa *aa_match_alloc(void)
5022 +{
5023 +       return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
5024 +}
5025 +
5026 +void aa_match_free(struct aa_dfa *dfa)
5027 +{
5028 +       if (dfa) {
5029 +               int i;
5030 +
5031 +               for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
5032 +                       kfree(dfa->tables[i]);
5033 +       }
5034 +       kfree(dfa);
5035 +}
5036 +
5037 +/**
5038 + * aa_dfa_match_len - traverse @dfa to find state @str stops at
5039 + * @dfa: the dfa to match @str against
5040 + * @start: the state of the dfa to start matching in
5041 + * @str: the string of bytes to match against the dfa
5042 + * @len: length of the string of bytes to match
5043 + *
5044 + * aa_dfa_match_len will match @str against the dfa and return the state it
5045 + * finished matching in. The final state can be used to look up the accepting
5046 + * label, or as the start state of a continuing match.
5047 + *
5048 + * This function will happily match again the 0 byte and only finishes
5049 + * when @len input is consumed.
5050 + */
5051 +unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
5052 +                             const char *str, int len)
5053 +{
5054 +       u16 *def = DEFAULT_TABLE(dfa);
5055 +       u32 *base = BASE_TABLE(dfa);
5056 +       u16 *next = NEXT_TABLE(dfa);
5057 +       u16 *check = CHECK_TABLE(dfa);
5058 +       unsigned int state = start, pos;
5059 +
5060 +       if (state == 0)
5061 +               return 0;
5062 +
5063 +       /* current state is <state>, matching character *str */
5064 +       if (dfa->tables[YYTD_ID_EC - 1]) {
5065 +               u8 *equiv = EQUIV_TABLE(dfa);
5066 +               for (; len; len--) {
5067 +                       pos = base[state] + equiv[(u8)*str++];
5068 +                       if (check[pos] == state)
5069 +                               state = next[pos];
5070 +                       else
5071 +                               state = def[state];
5072 +               }
5073 +       } else {
5074 +               for (; len; len--) {
5075 +                       pos = base[state] + (u8)*str++;
5076 +                       if (check[pos] == state)
5077 +                               state = next[pos];
5078 +                       else
5079 +                               state = def[state];
5080 +               }
5081 +       }
5082 +       return state;
5083 +}
5084 +
5085 +
5086 +/**
5087 + * aa_dfa_next_state - traverse @dfa to find state @str stops at
5088 + * @dfa: the dfa to match @str against
5089 + * @start: the state of the dfa to start matching in
5090 + * @str: the null terminated string of bytes to match against the dfa
5091 + *
5092 + * aa_dfa_next_state will match @str against the dfa and return the state it
5093 + * finished matching in. The final state can be used to look up the accepting
5094 + * label, or as the start state of a continuing match.
5095 + */
5096 +unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
5097 +                         const char *str)
5098 +{
5099 +       return aa_dfa_match_len(dfa, start, str, strlen(str));
5100 +}
5101 +
5102 +/**
5103 + * aa_dfa_null_transition - step to next state after null character
5104 + * @dfa: the dfa to match against
5105 + * @start: the state of the dfa to start matching in
5106 + *
5107 + * aa_dfa_null_transition transitions to the next state after a null
5108 + * character which is not used in standard matching and is only
5109 + * used to seperate pairs.
5110 + */
5111 +unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
5112 +{
5113 +       return aa_dfa_match_len(dfa, start, "", 1);
5114 +}
5115 +
5116 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
5117 new file mode 100644
5118 index 0000000..beb8715
5119 --- /dev/null
5120 +++ b/security/apparmor/net.c
5121 @@ -0,0 +1,146 @@
5122 +/*
5123 + * AppArmor security module
5124 + *
5125 + * This file contains AppArmor network mediation
5126 + *
5127 + * Copyright (C) 1998-2008 Novell/SUSE
5128 + * Copyright 2009 Canonical Ltd.
5129 + *
5130 + * This program is free software; you can redistribute it and/or
5131 + * modify it under the terms of the GNU General Public License as
5132 + * published by the Free Software Foundation, version 2 of the
5133 + * License.
5134 + */
5135 +
5136 +#include "include/apparmor.h"
5137 +#include "include/audit.h"
5138 +#include "include/context.h"
5139 +#include "include/net.h"
5140 +#include "include/policy.h"
5141 +
5142 +#include "af_names.h"
5143 +
5144 +static const char *sock_type_names[] = {
5145 +       "unknown(0)",
5146 +       "stream",
5147 +       "dgram",
5148 +       "raw",
5149 +       "rdm",
5150 +       "seqpacket",
5151 +       "dccp",
5152 +       "unknown(7)",
5153 +       "unknown(8)",
5154 +       "unknown(9)",
5155 +       "packet",
5156 +};
5157 +
5158 +struct aa_audit_net {
5159 +       struct aa_audit base;
5160 +
5161 +       int family, type, protocol;
5162 +
5163 +};
5164 +
5165 +static void audit_cb(struct audit_buffer *ab, void *va)
5166 +{
5167 +       struct aa_audit_net *sa = va;
5168 +
5169 +       if (sa->family || sa->type) {
5170 +               if (address_family_names[sa->family])
5171 +                       audit_log_format(ab, " family=\"%s\"",
5172 +                                        address_family_names[sa->family]);
5173 +               else
5174 +                       audit_log_format(ab, " family=\"unknown(%d)\"",
5175 +                                        sa->family);
5176 +
5177 +               if (sock_type_names[sa->type])
5178 +                       audit_log_format(ab, " sock_type=\"%s\"",
5179 +                                        sock_type_names[sa->type]);
5180 +               else
5181 +                       audit_log_format(ab, " sock_type=\"unknown(%d)\"",
5182 +                                        sa->type);
5183 +
5184 +               audit_log_format(ab, " protocol=%d", sa->protocol);
5185 +       }
5186 +       
5187 +}
5188 +
5189 +static int aa_audit_net(struct aa_profile *profile, struct aa_audit_net *sa)
5190 +{
5191 +       int type = AUDIT_APPARMOR_AUTO;
5192 +
5193 +       if (likely(!sa->base.error)) {
5194 +               u16 audit_mask = profile->net.audit[sa->family];
5195 +               if (likely((PROFILE_AUDIT_MODE(profile) != AUDIT_ALL) &&
5196 +                          !(1 << sa->type & audit_mask)))
5197 +                       return 0;
5198 +       } else {
5199 +               u16 quiet_mask = profile->net.quiet[sa->family];
5200 +               u16 kill_mask = 0;
5201 +               u16 denied = (1 << sa->type) & ~quiet_mask;
5202 +
5203 +               if (denied & kill_mask)
5204 +                       type = AUDIT_APPARMOR_KILL;
5205 +
5206 +               if ((denied & quiet_mask) &&
5207 +                   PROFILE_AUDIT_MODE(profile) != AUDIT_NOQUIET &&
5208 +                   PROFILE_AUDIT_MODE(profile) != AUDIT_ALL)
5209 +                       return PROFILE_COMPLAIN(profile) ? 0 : sa->base.error;
5210 +       }
5211 +
5212 +       return aa_audit(type, profile, (struct aa_audit *)sa, audit_cb);
5213 +}
5214 +
5215 +int aa_net_perm(struct aa_profile *profile, char *operation,
5216 +               int family, int type, int protocol)
5217 +{
5218 +       struct aa_audit_net sa;
5219 +       u16 family_mask;
5220 +
5221 +       if ((family < 0) || (family >= AF_MAX))
5222 +               return -EINVAL;
5223 +
5224 +       if ((type < 0) || (type >= SOCK_MAX))
5225 +               return -EINVAL;
5226 +
5227 +       /* unix domain and netlink sockets are handled by ipc */
5228 +       if (family == AF_UNIX || family == AF_NETLINK)
5229 +               return 0;
5230 +
5231 +       family_mask = profile->net.allowed[family];
5232 +
5233 +       sa.base.error = (family_mask & (1 << type)) ? 0 : -EACCES;
5234 +
5235 +       memset(&sa, 0, sizeof(sa));
5236 +       sa.base.operation = operation;
5237 +       sa.base.gfp_mask = GFP_KERNEL;
5238 +       sa.family = family;
5239 +       sa.type = type;
5240 +       sa.protocol = protocol;
5241 +
5242 +       return  aa_audit_net(profile, &sa);
5243 +}
5244 +
5245 +int aa_revalidate_sk(struct sock *sk, char *operation)
5246 +{
5247 +       struct aa_profile *profile;
5248 +       struct cred *cred;
5249 +       int error = 0;
5250 +
5251 +       /* this is some debugging code to flush out the network hooks that
5252 +          that are called in interrupt context */
5253 +       if (in_interrupt()) {
5254 +               printk(KERN_WARNING "AppArmor Debug: Hook being called from interrupt context\n");
5255 +               dump_stack();
5256 +               return 0;
5257 +       }
5258 +
5259 +       cred = aa_get_task_policy(current, &profile);
5260 +       if (profile)
5261 +               error = aa_net_perm(profile, operation,
5262 +                                   sk->sk_family, sk->sk_type,
5263 +                                   sk->sk_protocol);
5264 +       put_cred(cred);
5265 +
5266 +       return error;
5267 +}
5268 diff --git a/security/apparmor/path.c b/security/apparmor/path.c
5269 new file mode 100644
5270 index 0000000..21f3e67
5271 --- /dev/null
5272 +++ b/security/apparmor/path.c
5273 @@ -0,0 +1,155 @@
5274 +/*
5275 + * AppArmor security module
5276 + *
5277 + * This file contains AppArmor function for pathnames
5278 + *
5279 + * Copyright (C) 1998-2008 Novell/SUSE
5280 + * Copyright 2009 Canonical Ltd.
5281 + *
5282 + * This program is free software; you can redistribute it and/or
5283 + * modify it under the terms of the GNU General Public License as
5284 + * published by the Free Software Foundation, version 2 of the
5285 + * License.
5286 + */
5287 +
5288 +#include <linux/mnt_namespace.h>
5289 +#include <linux/mount.h>
5290 +#include <linux/namei.h>
5291 +#include <linux/path.h>
5292 +#include <linux/sched.h>
5293 +#include <linux/slab.h>
5294 +#include <linux/fs_struct.h>
5295 +
5296 +#include "include/apparmor.h"
5297 +#include "include/path.h"
5298 +
5299 +int aa_get_name_to_buffer(struct path *path, int is_dir, char *buffer, int size,
5300 +                         char **name)
5301 +{
5302 +       int error = d_namespace_path(path, buffer, size - is_dir, name);
5303 +
5304 +       if (!error && is_dir && (*name)[1] != '\0')
5305 +               /*
5306 +                * Append "/" to the pathname.  The root directory is a special
5307 +                * case; it already ends in slash.
5308 +                */
5309 +               strcpy(&buffer[size - 2], "/");
5310 +
5311 +       return error;
5312 +}
5313 +
5314 +/**
5315 + * aa_get_name - compute the pathname of a file
5316 + * @path: path the file
5317 + * @is_dir: set if the file is a directory
5318 + * @buffer: buffer that aa_get_name() allocated
5319 + * @name: the error code indicating whether aa_get_name failed
5320 + *
5321 + * Returns an error code if the there was a failure in obtaining the
5322 + * name.
5323 + *
5324 + * @name is apointer to the beginning of the pathname (which usually differs
5325 + * from the beginning of the buffer), or NULL.  If there is an error @name
5326 + * may contain a partial or invalid name (in the case of a deleted file), that
5327 + * can be used for audit purposes, but it can not be used for mediation.
5328 + *
5329 + * We need @is_dir to indicate whether the file is a directory or not because
5330 + * the file may not yet exist, and so we cannot check the inode's file type.
5331 + */
5332 +int aa_get_name(struct path *path, int is_dir, char **buffer, char **name)
5333 +{
5334 +       char *buf, *str = NULL;
5335 +       int size = 256;
5336 +       int error;
5337 +
5338 +       *name = NULL;
5339 +       *buffer = NULL;
5340 +       for (;;) {
5341 +               buf = kmalloc(size, GFP_KERNEL);
5342 +               if (!buf)
5343 +                       return -ENOMEM;
5344 +
5345 +               error = aa_get_name_to_buffer(path, is_dir, buf, size, &str);
5346 +               if (!error || (error == -ENOENT) || (error == -ESTALE))
5347 +                       break;
5348 +
5349 +               kfree(buf);
5350 +               size <<= 1;
5351 +               if (size > g_apparmor_path_max)
5352 +                       return -ENAMETOOLONG;
5353 +       }
5354 +       *buffer = buf;
5355 +       *name = str;
5356 +
5357 +       return error;
5358 +}
5359 +
5360 +int d_namespace_path(struct path *path, char *buf, int buflen, char **name)
5361 +{
5362 +       struct path root, tmp, ns_root = { };
5363 +       char *res;
5364 +       int error = 0;
5365 +
5366 +       read_lock(&current->fs->lock);
5367 +       root = current->fs->root;
5368 +       path_get(&current->fs->root);
5369 +       read_unlock(&current->fs->lock);
5370 +       spin_lock(&vfsmount_lock);
5371 +       if (root.mnt && root.mnt->mnt_ns)
5372 +               ns_root.mnt = mntget(root.mnt->mnt_ns->root);
5373 +       if (ns_root.mnt)
5374 +               ns_root.dentry = dget(ns_root.mnt->mnt_root);
5375 +       spin_unlock(&vfsmount_lock);
5376 +       spin_lock(&dcache_lock);
5377 +       tmp = ns_root;
5378 +       res = __d_path(path, &tmp, buf, buflen);
5379 +
5380 +       *name = res;
5381 +       /* handle error conditions - and still allow a partial path to
5382 +        * be returned */
5383 +       if (IS_ERR(res)) {
5384 +               error = PTR_ERR(res);
5385 +               *name = buf;
5386 +       } else if (!IS_ROOT(path->dentry) && d_unhashed(path->dentry)) {
5387 +               error = -ENOENT;
5388 +#if 0
5389 +       } else if (tmp.dentry != ns_root.dentry && tmp.mnt != ns_root.mnt) {
5390 +               /* disconnected path don return pathname starting with '/' */
5391 +               error = -ESTALE;
5392 +               if (*res == '/')
5393 +                       *name = res + 1;
5394 +#endif
5395 +       }
5396 +
5397 +       spin_unlock(&dcache_lock);
5398 +       path_put(&root);
5399 +       path_put(&ns_root);
5400 +
5401 +       return error;
5402 +}
5403 +
5404 +char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
5405 +{
5406 +       if (buflen < 1)
5407 +               return NULL;
5408 +       buffer += --buflen;
5409 +       *buffer = '\0';
5410 +
5411 +       while (table) {
5412 +               int namelen = strlen(table->procname);
5413 +
5414 +               if (buflen < namelen + 1)
5415 +                       return NULL;
5416 +               buflen -= namelen + 1;
5417 +               buffer -= namelen;
5418 +               memcpy(buffer, table->procname, namelen);
5419 +               *--buffer = '/';
5420 +               table = table->parent;
5421 +       }
5422 +       if (buflen < 4)
5423 +               return NULL;
5424 +       buffer -= 4;
5425 +       memcpy(buffer, "/sys", 4);
5426 +
5427 +       return buffer;
5428 +}
5429 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
5430 new file mode 100644
5431 index 0000000..3ba2642
5432 --- /dev/null
5433 +++ b/security/apparmor/policy.c
5434 @@ -0,0 +1,727 @@
5435 +/*
5436 + * AppArmor security module
5437 + *
5438 + * This file contains AppArmor policy manipulation functions
5439 + *
5440 + * Copyright (C) 1998-2008 Novell/SUSE
5441 + * Copyright 2009 Canonical Ltd.
5442 + *
5443 + * This program is free software; you can redistribute it and/or
5444 + * modify it under the terms of the GNU General Public License as
5445 + * published by the Free Software Foundation, version 2 of the
5446 + * License.
5447 + *
5448 + *
5449 + * AppArmor policy is based around profiles, which contain the rules a
5450 + * task is confined by.  Every task in the sytem has a profile attached
5451 + * to it determined either by matching "unconfined" tasks against the
5452 + * visible set of profiles or by following a profiles attachment rules.
5453 + *
5454 + * Each profile exists in an AppArmor profile namespace which is a
5455 + * container of related profiles.  Each namespace contains a special
5456 + * "unconfined" profile, which doesn't efforce any confinement on
5457 + * a task beyond DAC.
5458 + *
5459 + * Namespace and profile names can be written together in either
5460 + * of two syntaxes.
5461 + *     :namespace:profile - used by kernel interfaces for easy detection
5462 + *     namespace://profile - used by policy
5463 + *
5464 + * Profile names name not start with : or @ and may not contain \0
5465 + * a // in a profile name indicates a compound name with the name before
5466 + * the // being the parent profile and the name after the child
5467 + *
5468 + * Reserved profile names
5469 + *     unconfined - special automatically generated unconfined profile
5470 + *     inherit - special name to indicate profile inheritance
5471 + *     null-XXXX-YYYY - special automically generated learning profiles
5472 + *
5473 + * Namespace names may not start with / or @ and may not contain \0 or //
5474 + * it is recommend that they do not contain any '/' characters
5475 + * Reserved namespace namespace
5476 + *     default - the default namespace setup by AppArmor
5477 + *     user-XXXX - user defined profiles
5478 + */
5479 +
5480 +#include <linux/slab.h>
5481 +#include <linux/spinlock.h>
5482 +#include <linux/string.h>
5483 +
5484 +#include "include/apparmor.h"
5485 +#include "include/capability.h"
5486 +#include "include/file.h"
5487 +#include "include/ipc.h"
5488 +#include "include/match.h"
5489 +#include "include/policy.h"
5490 +#include "include/resource.h"
5491 +#include "include/sid.h"
5492 +
5493 +/* list of profile namespaces and lock */
5494 +LIST_HEAD(ns_list);
5495 +DEFINE_RWLOCK(ns_list_lock);
5496 +
5497 +struct aa_namespace *default_namespace;
5498 +
5499 +const char *profile_mode_names[] = {
5500 +       "enforce",
5501 +       "complain",
5502 +       "kill",
5503 +};
5504 +
5505 +#define AA_SYS_SID 0
5506 +#define AA_USR_SID 1
5507 +
5508 +
5509 +static int common_init(struct aa_policy_common *common, const char *name)
5510 +{
5511 +       common->name = kstrdup(name, GFP_KERNEL);
5512 +       if (!common->name)
5513 +               return 0;
5514 +       INIT_LIST_HEAD(&common->list);
5515 +       INIT_LIST_HEAD(&common->profiles);
5516 +       kref_init(&common->count);
5517 +       rwlock_init(&common->lock);
5518 +
5519 +       return 1;
5520 +}
5521 +
5522 +static void common_free(struct aa_policy_common *common)
5523 +{
5524 +       /* still contains profiles -- invalid */
5525 +       if (!list_empty(&common->profiles)) {
5526 +               AA_ERROR("%s: internal error, "
5527 +                        "policy '%s' still contains profiles\n",
5528 +                        __func__, common->name);
5529 +               BUG();
5530 +       }
5531 +       if (!list_empty(&common->list)) {
5532 +               AA_ERROR("%s: internal error, policy '%s' still on list\n",
5533 +                        __func__, common->name);
5534 +               BUG();
5535 +       }
5536 +
5537 +       kfree(common->name);
5538 +}
5539 +
5540 +static struct aa_policy_common *__common_find(struct list_head *head,
5541 +                                             const char *name)
5542 +                                             
5543 +{
5544 +       struct aa_policy_common *common;
5545 +
5546 +       list_for_each_entry(common, head, list) {
5547 +               if (!strcmp(common->name, name))
5548 +                       return common;
5549 +       }
5550 +       return NULL;
5551 +}
5552 +
5553 +static struct aa_policy_common *__common_find_strn(struct list_head *head,
5554 +                                                  const char *str, int len)
5555 +{
5556 +       struct aa_policy_common *common;
5557 +
5558 +       list_for_each_entry(common, head, list) {
5559 +               if (aa_strneq(common->name, str, len))
5560 +                       return common;
5561 +       }
5562 +
5563 +       return NULL;
5564 +}
5565 +
5566 +/*
5567 + * Routines for AppArmor namespaces
5568 + */
5569 +
5570 +int alloc_default_namespace(void)
5571 +{
5572 +       struct aa_namespace *ns;
5573 +       ns = alloc_aa_namespace("default");
5574 +       if (!ns)
5575 +               return -ENOMEM;
5576 +
5577 +       default_namespace = aa_get_namespace(ns);
5578 +       write_lock(&ns_list_lock);
5579 +       list_add(&ns->base.list, &ns_list);
5580 +       write_unlock(&ns_list_lock);
5581 +
5582 +       return 0;
5583 +}
5584 +
5585 +void free_default_namespace(void)
5586 +{
5587 +       write_lock(&ns_list_lock);
5588 +       list_del_init(&default_namespace->base.list);
5589 +       aa_put_namespace(default_namespace);
5590 +       write_unlock(&ns_list_lock);
5591 +       aa_put_namespace(default_namespace);
5592 +       default_namespace = NULL;
5593 +}
5594 +
5595 +/**
5596 + * alloc_aa_namespace - allocate, initialize and return a new namespace
5597 + * @name: a preallocated name
5598 + * Returns NULL on failure.
5599 + */
5600 +struct aa_namespace *alloc_aa_namespace(const char *name)
5601 +{
5602 +       struct aa_namespace *ns;
5603 +
5604 +       ns = kzalloc(sizeof(*ns), GFP_KERNEL);
5605 +       AA_DEBUG("%s(%p)\n", __func__, ns);
5606 +       if (!ns)
5607 +               return NULL;
5608 +
5609 +       if (!common_init(&ns->base, name))
5610 +               goto fail_ns;
5611 +
5612 +       /* null profile is not added to the profile list */
5613 +       ns->unconfined = alloc_aa_profile("unconfined");
5614 +       if (!ns->unconfined)
5615 +               goto fail_unconfined;
5616 +
5617 +       ns->unconfined->sid = aa_alloc_sid(AA_ALLOC_SYS_SID);
5618 +       ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR |
5619 +               PFLAG_IMMUTABLE;
5620 +       ns->unconfined->ns = aa_get_namespace(ns);
5621 +
5622 +       return ns;
5623 +
5624 +fail_unconfined:
5625 +       if (ns->base.name)
5626 +               kfree(ns->base.name);
5627 +fail_ns:
5628 +       kfree(ns);
5629 +       return NULL;
5630 +}
5631 +
5632 +/**
5633 + * free_aa_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
5634 + * @kr: kref callback for freeing of a namespace
5635 + */
5636 +void free_aa_namespace_kref(struct kref *kref)
5637 +{
5638 +       free_aa_namespace(container_of(kref, struct aa_namespace, base.count));
5639 +}
5640 +
5641 +/**
5642 + * free_aa_namespace - free a profile namespace
5643 + * @namespace: the namespace to free
5644 + *
5645 + * Free a namespace.  All references to the namespace must have been put.
5646 + * If the namespace was referenced by a profile confining a task,
5647 + */
5648 +void free_aa_namespace(struct aa_namespace *ns)
5649 +{
5650 +       if (!ns)
5651 +               return;
5652 +
5653 +       common_free(&ns->base);
5654 +
5655 +       if (ns->unconfined && ns->unconfined->ns == ns)
5656 +               ns->unconfined->ns = NULL;
5657 +
5658 +       aa_put_profile(ns->unconfined);
5659 +       memset(ns, 0, sizeof(*ns));
5660 +       kfree(ns);
5661 +}
5662 +
5663 +struct aa_namespace *__aa_find_namespace(struct list_head *head,
5664 +                                        const char *name)
5665 +                                        
5666 +{
5667 +       return (struct aa_namespace *) __common_find(head, name);
5668 +}
5669 +
5670 +/**
5671 + * aa_find_namespace  -  look up a profile namespace on the namespace list
5672 + * @name: name of namespace to find
5673 + *
5674 + * Returns a pointer to the namespace on the list, or NULL if no namespace
5675 + * called @name exists.
5676 + */
5677 +struct aa_namespace *aa_find_namespace(const char *name)
5678 +{
5679 +       struct aa_namespace *ns = NULL;
5680 +
5681 +       read_lock(&ns_list_lock);
5682 +       ns = aa_get_namespace(__aa_find_namespace(&ns_list, name));
5683 +       read_unlock(&ns_list_lock);
5684 +
5685 +       return ns;
5686 +}
5687 +
5688 +static struct aa_namespace *__aa_find_namespace_by_strn(struct list_head *head,
5689 +                                                       const char *name,
5690 +                                                       int len)
5691 +{
5692 +       return (struct aa_namespace *) __common_find_strn(head, name, len);
5693 +}
5694 +
5695 +struct aa_namespace *aa_find_namespace_by_strn(const char *name, int len)
5696 +{
5697 +       struct aa_namespace *ns = NULL;
5698 +
5699 +       read_lock(&ns_list_lock);
5700 +       ns = aa_get_namespace(__aa_find_namespace_by_strn(&ns_list, name, len));
5701 +       read_unlock(&ns_list_lock);
5702 +
5703 +       return ns;
5704 +}
5705 +
5706 +/**
5707 + * aa_prepare_namespace - find an existing or create a new namespace of @name
5708 + * @name: the namespace to find or add
5709 + */
5710 +struct aa_namespace *aa_prepare_namespace(const char *name)
5711 +{
5712 +       struct aa_namespace *ns;
5713
5714 +       write_lock(&ns_list_lock);
5715 +       if (name)
5716 +               ns = aa_get_namespace(__aa_find_namespace(&ns_list, name));
5717 +       else
5718 +               ns = aa_get_namespace(default_namespace);
5719 +       if (!ns) {
5720 +               struct aa_namespace *new_ns;
5721 +               write_unlock(&ns_list_lock);
5722 +               new_ns = alloc_aa_namespace(name);
5723 +               if (!new_ns)
5724 +                       return NULL;
5725 +               write_lock(&ns_list_lock);
5726 +               ns = __aa_find_namespace(&ns_list, name);
5727 +               if (!ns) {
5728 +                       list_add(&new_ns->base.list, &ns_list);
5729 +                       ns = new_ns;
5730 +               } else {
5731 +                       /* raced so free the new one */
5732 +                       free_aa_namespace(new_ns);
5733 +                       aa_get_namespace(ns);
5734 +               }
5735 +       }
5736 +       write_unlock(&ns_list_lock);
5737 +
5738 +       return ns;
5739 +}
5740 +
5741 +/*
5742 + * requires profile->ns set first, takes profiles refcount
5743 + * TODO: add accounting
5744 + */
5745 +void __aa_add_profile(struct aa_policy_common *common,
5746 +                     struct aa_profile *profile)
5747 +{
5748 +       list_add(&profile->base.list, &common->profiles);
5749 +       if (!(profile->flags & PFLAG_NO_LIST_REF))
5750 +               aa_get_profile(profile);
5751 +}
5752 +
5753 +void __aa_remove_profile(struct aa_profile *profile,
5754 +                        struct aa_profile *replacement)
5755 +{
5756 +       if (replacement)
5757 +               profile->replacedby = aa_get_profile(replacement);
5758 +       else
5759 +               profile->replacedby = ERR_PTR(-EINVAL);
5760 +       list_del_init(&profile->base.list);
5761 +       if (!(profile->flags & PFLAG_NO_LIST_REF))
5762 +               aa_put_profile(profile);
5763 +}
5764 +
5765 +/* TODO: add accounting */
5766 +void __aa_replace_profile(struct aa_profile *profile,
5767 +                         struct aa_profile *replacement)
5768 +{
5769 +       if (replacement) {
5770 +               struct aa_policy_common *common;
5771 +
5772 +               if (profile->parent)
5773 +                       common = &profile->parent->base;
5774 +               else
5775 +                       common = &profile->ns->base;
5776 +
5777 +               __aa_remove_profile(profile, replacement);
5778 +               __aa_add_profile(common, replacement);
5779 +       } else
5780 +               __aa_remove_profile(profile, NULL);
5781 +}
5782 +
5783 +/**
5784 + * __aa_profile_list_release - remove all profiles on the list and put refs
5785 + * @head: list of profiles
5786 + */
5787 +void __aa_profile_list_release(struct list_head *head)
5788 +{
5789 +       struct aa_profile *profile, *tmp;
5790 +       list_for_each_entry_safe(profile, tmp, head, base.list) {
5791 +               __aa_profile_list_release(&profile->base.profiles);
5792 +               __aa_remove_profile(profile, NULL);
5793 +       }
5794 +}
5795 +
5796 +void __aa_remove_namespace(struct aa_namespace *ns)
5797 +{
5798 +       struct aa_profile *unconfined = ns->unconfined;
5799 +       list_del_init(&ns->base.list);
5800 +
5801 +       /*
5802 +        * break the ns, unconfined profile cyclic reference and forward
5803 +        * all new unconfined profiles requests to the default namespace
5804 +        */
5805 +       ns->unconfined = aa_get_profile(default_namespace->unconfined);
5806 +       __aa_profile_list_release(&ns->base.profiles);
5807 +       aa_put_profile(unconfined);
5808 +       aa_put_namespace(ns);
5809 +}
5810 +
5811 +/**
5812 + * aa_remove_namespace = Remove namespace from the list
5813 + * @ns: namespace to remove
5814 + */
5815 +void aa_remove_namespace(struct aa_namespace *ns)
5816 +{
5817 +       write_lock(&ns_list_lock);
5818 +       write_lock(&ns->base.lock);
5819 +       __aa_remove_namespace(ns);
5820 +       write_unlock(&ns->base.lock);
5821 +       write_unlock(&ns_list_lock);
5822 +}
5823 +
5824 +/**
5825 + * aa_profilelist_release - remove all namespaces and all associated profiles
5826 + */
5827 +void aa_profile_ns_list_release(void)
5828 +{
5829 +       struct aa_namespace *ns, *tmp;
5830 +
5831 +       /* Remove and release all the profiles on namespace profile lists. */
5832 +       write_lock(&ns_list_lock);
5833 +       list_for_each_entry_safe(ns, tmp, &ns_list, base.list) {
5834 +               write_lock(&ns->base.lock);
5835 +               __aa_remove_namespace(ns);
5836 +               write_unlock(&ns->base.lock);
5837 +       }
5838 +       write_unlock(&ns_list_lock);
5839 +}
5840 +
5841 +/**
5842 + * alloc_aa_profile - allocate, initialize and return a new profile
5843 + * @fqname: name of the profile
5844 + *
5845 + * Returns NULL on failure.
5846 + */
5847 +struct aa_profile *alloc_aa_profile(const char *fqname)
5848 +{
5849 +       struct aa_profile *profile;
5850 +
5851 +       profile = kzalloc(sizeof(*profile), GFP_KERNEL);
5852 +       if (!profile)
5853 +               return NULL;
5854
5855 +       if (!common_init(&profile->base, fqname)) {
5856 +               kfree(profile);
5857 +               return NULL;
5858 +       }
5859 +       
5860 +       profile->fqname = profile->base.name;
5861 +       profile->base.name = (char *) fqname_subname((const char *) profile->fqname);
5862 +       return profile;
5863 +}
5864 +
5865 +/**
5866 + * aa_new_null_profile - create a new null-X learning profile
5867 + * @parent: profile that caused this profile to be created
5868 + * @hat: true if the null- learning profile is a hat
5869 + *
5870 + * Create a null- complain mode profile used in learning mode.  The name of
5871 + * the profile is unique and follows the format of parent//null-sid.
5872 + *
5873 + * null profiles are added to the profile list but the list does not
5874 + * hold a count on them so that they are automatically released when
5875 + * not in use.
5876 + */
5877 +struct aa_profile *aa_alloc_null_profile(struct aa_profile *parent, int hat)
5878 +{
5879 +       struct aa_profile *profile = NULL;
5880 +       char *name;
5881 +       u32 sid = aa_alloc_sid(AA_ALLOC_SYS_SID);
5882 +
5883 +       name = kmalloc(strlen(parent->fqname) + 2 + 7 + 8, GFP_KERNEL);
5884 +       if (!name)
5885 +               goto fail;
5886 +       sprintf(name, "%s//null-%x", parent->fqname, sid);
5887 +
5888 +       profile = alloc_aa_profile(name);
5889 +       kfree(name);
5890 +       if (!profile)
5891 +               goto fail;
5892 +
5893 +       profile->sid = aa_alloc_sid(AA_ALLOC_SYS_SID);
5894 +       profile->mode = APPARMOR_COMPLAIN;
5895 +       profile->flags = PFLAG_NULL | PFLAG_NO_LIST_REF;
5896 +       if (hat)
5897 +         profile->flags |= PFLAG_HAT;
5898 +
5899 +       profile->parent = aa_get_profile(parent);
5900 +       profile->ns = aa_get_namespace(parent->ns);
5901 +
5902 +       write_lock(&profile->ns->base.lock);
5903 +       __aa_add_profile(&parent->base, profile);
5904 +       write_unlock(&profile->ns->base.lock);
5905 +
5906 +       return profile;
5907 +
5908 +fail:
5909 +       aa_free_sid(sid);
5910 +       return NULL;
5911 +}
5912 +
5913 +/**
5914 + * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
5915 + * @kr: kref callback for freeing of a profile
5916 + */
5917 +void free_aa_profile_kref(struct kref *kref)
5918 +{
5919 +       struct aa_profile *p = container_of(kref, struct aa_profile,
5920 +                                           base.count);
5921 +
5922 +       free_aa_profile(p);
5923 +}
5924 +
5925 +/**
5926 + * free_aa_profile - free a profile
5927 + * @profile: the profile to free
5928 + *
5929 + * Free a profile, its hats and null_profile. All references to the profile,
5930 + * its hats and null_profile must have been put.
5931 + *
5932 + * If the profile was referenced from a task context, free_aa_profile() will
5933 + * be called from an rcu callback routine, so we must not sleep here.
5934 + */
5935 +void free_aa_profile(struct aa_profile *profile)
5936 +{
5937 +       AA_DEBUG("%s(%p)\n", __func__, profile);
5938 +
5939 +       if (!profile)
5940 +               return;
5941 +
5942 +       /*
5943 +        * profile can still be on the list if the list doesn't hold a
5944 +        * reference.  There is no race as NULL profiles can't be attached
5945 +        */
5946 +       if (!list_empty(&profile->base.list)) {
5947 +               if ((profile->flags & PFLAG_NULL) && profile->ns) {
5948 +                       write_lock(&profile->ns->base.lock);
5949 +                       list_del_init(&profile->base.list);
5950 +                       write_unlock(&profile->ns->base.lock);
5951 +               } else {
5952 +                       AA_ERROR("%s: internal error, "
5953 +                                "profile '%s' still on ns list\n",
5954 +                                __func__, profile->base.name);
5955 +                       BUG();
5956 +               }
5957 +       }
5958 +
5959 +       /* profile->name is a substring of fqname */
5960 +       profile->base.name = NULL;
5961 +       common_free(&profile->base);
5962 +
5963 +       BUG_ON(!list_empty(&profile->base.profiles));
5964 +
5965 +       kfree(profile->fqname);
5966 +
5967 +       aa_put_namespace(profile->ns);
5968 +       aa_put_profile(profile->parent);
5969 +
5970 +       aa_free_file_rules(&profile->file);
5971 +       aa_free_cap_rules(&profile->caps);
5972 +       aa_free_net_rules(&profile->net);
5973 +       aa_free_rlimit_rules(&profile->rlimits);
5974 +
5975 +       aa_free_sid(profile->sid);
5976 +       aa_match_free(profile->xmatch);
5977 +
5978 +       if (profile->replacedby && !PTR_ERR(profile->replacedby))
5979 +               aa_put_profile(profile->replacedby);
5980 +
5981 +       memset(profile, 0, sizeof(profile));
5982 +       kfree(profile);
5983 +}
5984 +
5985 +
5986 +/* TODO: profile count accounting - setup in remove */
5987 +
5988 +
5989 +struct aa_profile *__aa_find_profile(struct list_head *head, const char *name)
5990 +{
5991 +       return (struct aa_profile *) __common_find(head, name);
5992 +}
5993 +
5994 +struct aa_profile *__aa_find_profile_by_strn(struct list_head *head,
5995 +                                            const char *name, int len)
5996 +{
5997 +       return (struct aa_profile *) __common_find_strn(head, name, len);
5998 +}
5999 +
6000 +
6001 +/**
6002 + * aa_find_child - find a profile by @name in @parent
6003 + * @parent: profile to search
6004 + * @name: profile name to search for
6005 + *
6006 + * Returns a ref counted profile or NULL if not found
6007 + */
6008 +struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
6009 +{
6010 +       struct aa_profile *profile;
6011 +
6012 +       read_lock(&parent->ns->base.lock);
6013 +       profile = aa_get_profile(__aa_find_profile(&parent->base.profiles,
6014 +                                                  name));
6015 +       read_unlock(&parent->ns->base.lock);
6016 +
6017 +       return profile;
6018 +}
6019 +
6020 +
6021 +struct aa_policy_common *__aa_find_parent_by_fqname(struct aa_namespace *ns,
6022 +                                                   const char *fqname)
6023 +{
6024 +       struct aa_policy_common *common;
6025 +       struct aa_profile *profile = NULL;
6026 +       char *split;
6027 +
6028 +       common = &ns->base;
6029 +
6030 +       
6031 +       for (split = strstr(fqname, "//"); split; ) {
6032 +               profile = __aa_find_profile_by_strn(&common->profiles, fqname,
6033 +                                                   split - fqname);
6034 +               if (!profile)
6035 +                       return NULL;
6036 +               common = &profile->base;
6037 +               fqname = split + 2;
6038 +               split = strstr(fqname, "//");
6039 +       }
6040 +       if (!profile)
6041 +               return &ns->base;
6042 +       return &profile->base;
6043 +}
6044 +
6045 +struct aa_profile *__aa_find_profile_by_fqname(struct aa_namespace *ns,
6046 +                                              const char *fqname)
6047 +{
6048 +       struct aa_policy_common *common;
6049 +       struct aa_profile *profile = NULL;
6050 +       char *split;
6051 +
6052 +       common = &ns->base;
6053 +       for (split = strstr(fqname, "//"); split; ) {
6054 +               profile = __aa_find_profile_by_strn(&common->profiles, fqname,
6055 +                                                   split - fqname);
6056 +               if (!profile)
6057 +                       return NULL;
6058 +
6059 +               common = &profile->base;
6060 +               fqname = split + 2;
6061 +               split = strstr(fqname, "//");
6062 +       }
6063 +
6064 +       profile = __aa_find_profile(&common->profiles, fqname);
6065 +
6066 +       return profile;
6067 +}
6068 +
6069 +/**
6070 + * aa_find_profile_by_name - find a profile by its full or partial name
6071 + * @ns: the namespace to start from
6072 + * @fqname: name to do lookup on.  Does not contain namespace prefix
6073 + */
6074 +struct aa_profile *aa_find_profile_by_fqname(struct aa_namespace *ns,
6075 +                                            const char *fqname)
6076 +{
6077 +       struct aa_profile *profile;
6078 +
6079 +       read_lock(&ns->base.lock);
6080 +       profile = aa_get_profile(__aa_find_profile_by_fqname(ns, fqname));
6081 +       read_unlock(&ns->base.lock);
6082 +       return profile;
6083 +}
6084 +
6085 +
6086 +/* __aa_attach_match_ - find an attachment match
6087 + * @name - to match against
6088 + * @head - profile list to walk
6089 + *
6090 + * Do a linear search on the profiles in the list.  There is a matching
6091 + * preference where an exact match is prefered over a name which uses
6092 + * expressions to match, and matching expressions with the greatest
6093 + * xmatch_len are prefered.
6094 + */
6095 +static struct aa_profile *__aa_attach_match(const char *name,
6096 +                                           struct list_head *head)
6097 +{
6098 +       int len = 0;
6099 +       struct aa_profile *profile, *candidate = NULL;
6100 +
6101 +       list_for_each_entry(profile, head, base.list) {
6102 +               if (profile->flags & PFLAG_NULL)
6103 +                       continue;
6104 +               if (profile->xmatch && profile->xmatch_len > len) {
6105 +                       unsigned int state = aa_dfa_match(profile->xmatch,
6106 +                                                         DFA_START, name);
6107 +                       /* any accepting state means a valid match */
6108 +                       if (state > DFA_START) {
6109 +                               candidate = profile;
6110 +                               len = profile->xmatch_len;
6111 +                       }
6112 +               } else if (!strcmp(profile->base.name, name))
6113 +                       /* exact non-re match, no more searching required */
6114 +                       return profile;
6115 +       }
6116 +
6117 +       return candidate;
6118 +}
6119 +
6120 +/**
6121 + * aa_sys_find_attach - do attachment search for sys unconfined processes
6122 + * @ns: the namespace to search
6123 + * name: the executable name to match against
6124 + */
6125 +struct aa_profile *aa_sys_find_attach(struct aa_namespace *ns, const char *name)
6126 +{
6127 +       struct aa_profile *profile;
6128 +
6129 +       read_lock(&ns->base.lock);
6130 +       profile = aa_get_profile(__aa_attach_match(name, &ns->base.profiles));
6131 +       read_unlock(&ns->base.lock);
6132 +
6133 +       return profile;
6134 +}
6135 +
6136 +/**
6137 + * aa_profile_newest - find the newest version of @profile
6138 + * @profile: the profile to check for newer versions of
6139 + *
6140 + * Find the newest version of @profile, if @profile is the newest version
6141 + * return @profile.  If @profile has been removed return NULL.
6142 + *
6143 + * NOTE: the profile returned is not refcounted, The refcount on @profile
6144 + * must be held until the caller decides what to do with the returned newest
6145 + * version.
6146 + */
6147 +struct aa_profile *aa_profile_newest(struct aa_profile *profile)
6148 +{
6149 +       if (unlikely(profile && profile->replacedby)) {
6150 +               for (;profile->replacedby; profile = profile->replacedby) {
6151 +                       if (IS_ERR(profile->replacedby)) {
6152 +                               /* profile has been removed */
6153 +                               profile = NULL;
6154 +                               break;
6155 +                       }
6156 +               } 
6157 +       }
6158 +
6159 +       return profile;
6160 +}
6161 +
6162 diff --git a/security/apparmor/policy_interface.c b/security/apparmor/policy_interface.c
6163 new file mode 100644
6164 index 0000000..24277dc
6165 --- /dev/null
6166 +++ b/security/apparmor/policy_interface.c
6167 @@ -0,0 +1,850 @@
6168 +/*
6169 + * AppArmor security module
6170 + *
6171 + * This file contains AppArmor functions for unpacking policy loaded from
6172 + * userspace.
6173 + *
6174 + * Copyright (C) 1998-2008 Novell/SUSE
6175 + * Copyright 2009 Canonical Ltd.
6176 + *
6177 + * This program is free software; you can redistribute it and/or
6178 + * modify it under the terms of the GNU General Public License as
6179 + * published by the Free Software Foundation, version 2 of the
6180 + * License.
6181 + *
6182 + * AppArmor uses a serialized binary format for loading policy.
6183 + * The policy format is documented in Documentation/???
6184 + * All policy is validated all before it is used.
6185 + */
6186 +
6187 +#include <asm/unaligned.h>
6188 +#include <linux/errno.h>
6189 +
6190 +#include "include/apparmor.h"
6191 +#include "include/audit.h"
6192 +#include "include/context.h"
6193 +#include "include/match.h"
6194 +#include "include/policy.h"
6195 +#include "include/policy_interface.h"
6196 +#include "include/sid.h"
6197 +
6198 +/* FIXME: convert profiles to internal hieracy, accounting
6199 + * FIXME: have replacement routines set replaced_by profile instead of error
6200 + * FIXME: name mapping to hierarchy
6201 + */
6202 +
6203 +/*
6204 + * The AppArmor interface treats data as a type byte followed by the
6205 + * actual data.  The interface has the notion of a a named entry
6206 + * which has a name (AA_NAME typecode followed by name string) followed by
6207 + * the entries typecode and data.  Named types allow for optional
6208 + * elements and extensions to be added and tested for without breaking
6209 + * backwards compatability.
6210 + */
6211 +
6212 +enum aa_code {
6213 +       AA_U8,
6214 +       AA_U16,
6215 +       AA_U32,
6216 +       AA_U64,
6217 +       AA_NAME,        /* same as string except it is items name */
6218 +       AA_STRING,
6219 +       AA_BLOB,
6220 +       AA_STRUCT,
6221 +       AA_STRUCTEND,
6222 +       AA_LIST,
6223 +       AA_LISTEND,
6224 +       AA_ARRAY,
6225 +       AA_ARRAYEND,
6226 +};
6227 +
6228 +/*
6229 + * aa_ext is the read of the buffer containing the serialized profile.  The
6230 + * data is copied into a kernel buffer in apparmorfs and then handed off to
6231 + * the unpack routines.
6232 + */
6233 +struct aa_ext {
6234 +       void *start;
6235 +       void *end;
6236 +       void *pos;      /* pointer to current position in the buffer */
6237 +       u32 version;
6238 +       char *ns_name;
6239 +};
6240 +
6241 +
6242 +struct aa_audit_iface {
6243 +       struct aa_audit base;
6244 +
6245 +       const char *name;
6246 +       const char *name2;
6247 +       const struct aa_ext *e;
6248 +};
6249 +
6250 +static void aa_audit_init(struct aa_audit_iface *sa, const char *operation,
6251 +                         struct aa_ext *e)
6252 +{
6253 +       memset(sa, 0, sizeof(*sa));
6254 +       sa->base.operation = operation;
6255 +       sa->base.gfp_mask = GFP_KERNEL;
6256 +       sa->e = e;
6257 +}
6258 +
6259 +static void audit_cb(struct audit_buffer *ab, void *va)
6260 +{
6261 +       struct aa_audit_iface *sa = va;
6262 +
6263 +       if (sa->name)
6264 +               audit_log_format(ab, " name=%s", sa->name);
6265 +       if (sa->name2)
6266 +               audit_log_format(ab, " namespace=%s", sa->name2);
6267 +       if (sa->base.error && sa->e)
6268 +               audit_log_format(ab, " offset=%d", sa->e->pos - sa->e->start);
6269 +}
6270 +
6271 +static int aa_audit_iface(struct aa_audit_iface *sa)
6272 +{
6273 +       struct aa_profile *profile;
6274 +       struct cred *cred = aa_get_task_policy(current, &profile);
6275 +       int error = aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa->base,
6276 +                            audit_cb);
6277 +       put_cred(cred);
6278 +       return error;
6279 +}
6280 +
6281 +static int aa_inbounds(struct aa_ext *e, size_t size)
6282 +{
6283 +       return (size <= e->end - e->pos);
6284 +}
6285 +
6286 +/**
6287 + * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
6288 + * @e: serialized data read head
6289 + * @chunk: start address for chunk of data
6290 + *
6291 + * return the size of chunk found with the read head at the end of
6292 + * the chunk.
6293 + */
6294 +static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
6295 +{
6296 +       void *pos = e->pos;
6297 +       size_t size = 0;
6298 +
6299 +       if (!aa_inbounds(e, sizeof(u16)))
6300 +               goto fail;
6301 +       size = le16_to_cpu(get_unaligned((u16 *)e->pos));
6302 +       e->pos += sizeof(u16);
6303 +       if (!aa_inbounds(e, size))
6304 +               goto fail;
6305 +       *chunk = e->pos;
6306 +       e->pos += size;
6307 +       return size;
6308 +
6309 +fail:
6310 +       e->pos = pos;
6311 +       return 0;
6312 +}
6313 +
6314 +static int aa_is_X(struct aa_ext *e, enum aa_code code)
6315 +{
6316 +       if (!aa_inbounds(e, 1))
6317 +               return 0;
6318 +       if (*(u8 *) e->pos != code)
6319 +               return 0;
6320 +       e->pos++;
6321 +       return 1;
6322 +}
6323 +
6324 +/**
6325 + * aa_is_nameX - check is the next element is of type X with a name of @name
6326 + * @e: serialized data extent information
6327 + * @code: type code
6328 + * @name: name to match to the serialized element.
6329 + *
6330 + * check that the next serialized data element is of type X and has a tag
6331 + * name @name.  If @name is specified then there must be a matching
6332 + * name element in the stream.  If @name is NULL any name element will be
6333 + * skipped and only the typecode will be tested.
6334 + * returns 1 on success (both type code and name tests match) and the read
6335 + * head is advanced past the headers
6336 + * returns %0 if either match failes, the read head does not move
6337 + */
6338 +static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
6339 +{
6340 +       void *pos = e->pos;
6341 +       /*
6342 +        * Check for presence of a tagname, and if present name size
6343 +        * AA_NAME tag value is a u16.
6344 +        */
6345 +       if (aa_is_X(e, AA_NAME)) {
6346 +               char *tag = NULL;
6347 +               size_t size = aa_is_u16_chunk(e, &tag);
6348 +               /* if a name is specified it must match. otherwise skip tag */
6349 +               if (name && (!size || strcmp(name, tag)))
6350 +                       goto fail;
6351 +       } else if (name) {
6352 +               /* if a name is specified and there is no name tag fail */
6353 +               goto fail;
6354 +       }
6355 +
6356 +       /* now check if type code matches */
6357 +       if (aa_is_X(e, code))
6358 +               return 1;
6359 +
6360 +fail:
6361 +       e->pos = pos;
6362 +       return 0;
6363 +}
6364 +
6365 +static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name)
6366 +{
6367 +       void *pos = e->pos;
6368 +       if (aa_is_nameX(e, AA_U16, name)) {
6369 +               if (!aa_inbounds(e, sizeof(u16)))
6370 +                       goto fail;
6371 +               if (data)
6372 +                       *data = le16_to_cpu(get_unaligned((u16 *)e->pos));
6373 +               e->pos += sizeof(u16);
6374 +               return 1;
6375 +       }
6376 +fail:
6377 +       e->pos = pos;
6378 +       return 0;
6379 +}
6380 +
6381 +static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
6382 +{
6383 +       void *pos = e->pos;
6384 +       if (aa_is_nameX(e, AA_U32, name)) {
6385 +               if (!aa_inbounds(e, sizeof(u32)))
6386 +                       goto fail;
6387 +               if (data)
6388 +                       *data = le32_to_cpu(get_unaligned((u32 *)e->pos));
6389 +               e->pos += sizeof(u32);
6390 +               return 1;
6391 +       }
6392 +fail:
6393 +       e->pos = pos;
6394 +       return 0;
6395 +}
6396 +
6397 +static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name)
6398 +{
6399 +       void *pos = e->pos;
6400 +       if (aa_is_nameX(e, AA_U64, name)) {
6401 +               if (!aa_inbounds(e, sizeof(u64)))
6402 +                       goto fail;
6403 +               if (data)
6404 +                       *data = le64_to_cpu(get_unaligned((u64 *)e->pos));
6405 +               e->pos += sizeof(u64);
6406 +               return 1;
6407 +       }
6408 +fail:
6409 +       e->pos = pos;
6410 +       return 0;
6411 +}
6412 +
6413 +static size_t aa_is_array(struct aa_ext *e, const char *name)
6414 +{
6415 +       void *pos = e->pos;
6416 +       if (aa_is_nameX(e, AA_ARRAY, name)) {
6417 +               int size;
6418 +               if (!aa_inbounds(e, sizeof(u16)))
6419 +                       goto fail;
6420 +               size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos));
6421 +               e->pos += sizeof(u16);
6422 +               return size;
6423 +       }
6424 +fail:
6425 +       e->pos = pos;
6426 +       return 0;
6427 +}
6428 +
6429 +static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
6430 +{
6431 +       void *pos = e->pos;
6432 +       if (aa_is_nameX(e, AA_BLOB, name)) {
6433 +               u32 size;
6434 +               if (!aa_inbounds(e, sizeof(u32)))
6435 +                       goto fail;
6436 +               size = le32_to_cpu(get_unaligned((u32 *)e->pos));
6437 +               e->pos += sizeof(u32);
6438 +               if (aa_inbounds(e, (size_t) size)) {
6439 +                       *blob = e->pos;
6440 +                       e->pos += size;
6441 +                       return size;
6442 +               }
6443 +       }
6444 +fail:
6445 +       e->pos = pos;
6446 +       return 0;
6447 +}
6448 +
6449 +static int aa_is_string(struct aa_ext *e, char **string, const char *name)
6450 +{
6451 +       char *src_str;
6452 +       size_t size = 0;
6453 +       void *pos = e->pos;
6454 +       *string = NULL;
6455 +       if (aa_is_nameX(e, AA_STRING, name) &&
6456 +           (size = aa_is_u16_chunk(e, &src_str))) {
6457 +               /* strings are null terminated, length is size - 1 */
6458 +               if (src_str[size - 1] != 0)
6459 +                       goto fail;
6460 +               *string = src_str;
6461 +       }
6462 +
6463 +       return size;
6464 +
6465 +fail:
6466 +       e->pos = pos;
6467 +       return 0;
6468 +}
6469 +
6470 +static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
6471 +{
6472 +       char *tmp;
6473 +       void *pos = e->pos;
6474 +       int res = aa_is_string(e, &tmp, name);
6475 +       *string = NULL;
6476 +
6477 +       if (!res)
6478 +               return res;
6479 +
6480 +       *string = kstrdup(tmp, GFP_KERNEL);
6481 +       if (!*string) {
6482 +               e->pos = pos;
6483 +               return 0;
6484 +       }
6485 +
6486 +       return res;
6487 +}
6488 +
6489 +/**
6490 + * aa_unpack_dfa - unpack a file rule dfa
6491 + * @e: serialized data extent information
6492 + *
6493 + * returns dfa or ERR_PTR
6494 + */
6495 +static struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
6496 +{
6497 +       char *blob = NULL;
6498 +       size_t size, error = 0;
6499 +       struct aa_dfa *dfa = NULL;
6500 +
6501 +       size = aa_is_blob(e, &blob, "aadfa");
6502 +       if (size) {
6503 +               dfa = aa_match_alloc();
6504 +               if (dfa) {
6505 +                       /*
6506 +                        * The dfa is aligned with in the blob to 8 bytes
6507 +                        * from the beginning of the stream.
6508 +                        */
6509 +                       size_t sz = blob - (char *) e->start;
6510 +                       size_t pad = ALIGN(sz, 8) - sz;
6511 +                       error = unpack_dfa(dfa, blob + pad, size - pad);
6512 +                       if (!error)
6513 +                               error = verify_dfa(dfa);
6514 +               } else {
6515 +                       error = -ENOMEM;
6516 +               }
6517 +
6518 +               if (error) {
6519 +                       aa_match_free(dfa);
6520 +                       dfa = ERR_PTR(error);
6521 +               }
6522 +       }
6523 +
6524 +       return dfa;
6525 +}
6526 +
6527 +static int aa_unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
6528 +{
6529 +       void *pos = e->pos;
6530 +
6531 +       /* exec table is optional */
6532 +       if (aa_is_nameX(e, AA_STRUCT, "xtable")) {
6533 +               int i, size;
6534 +
6535 +               size = aa_is_array(e, NULL);
6536 +               /* currently 4 exec bits and entries 0-3 are reserved iupcx */
6537 +               if (size > 16 - 4)
6538 +                       goto fail;
6539 +               profile->file.trans.table = kzalloc(sizeof(char *) * size,
6540 +                                                         GFP_KERNEL);
6541 +               if (!profile->file.trans.table)
6542 +                       goto fail;
6543 +
6544 +               for (i = 0; i < size; i++) {
6545 +                   char *tmp;
6546 +                       if (!aa_is_dynstring(e, &tmp, NULL))
6547 +                               goto fail;
6548 +                       /* note: strings beginning with a : have an embedded
6549 +                          \0 seperating the profile ns name from the profile
6550 +                          name */
6551 +                       profile->file.trans.table[i] = tmp;
6552 +               }
6553 +               if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
6554 +                       goto fail;
6555 +               if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
6556 +                       goto fail;
6557 +               profile->file.trans.size = size;
6558 +       }
6559 +       return 1;
6560 +
6561 +fail:
6562 +       e->pos = pos;
6563 +       return 0;
6564 +}
6565 +
6566 +int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
6567 +{
6568 +       void *pos = e->pos;
6569 +
6570 +       /* rlimits are optional */
6571 +       if (aa_is_nameX(e, AA_STRUCT, "rlimits")) {
6572 +               int i, size;
6573 +               u32 tmp = 0;
6574 +               if (!aa_is_u32(e, &tmp, NULL))
6575 +                       goto fail;
6576 +               profile->rlimits.mask = tmp;
6577 +
6578 +               size = aa_is_array(e, NULL);
6579 +               if (size > RLIM_NLIMITS)
6580 +                       goto fail;
6581 +               for (i = 0; i < size; i++) {
6582 +                       u64 tmp = 0;
6583 +                       if (!aa_is_u64(e, &tmp, NULL))
6584 +                               goto fail;
6585 +                       profile->rlimits.limits[i].rlim_max = tmp;
6586 +               }
6587 +               if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
6588 +                       goto fail;
6589 +               if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
6590 +                       goto fail;
6591 +       }
6592 +       return 1;
6593 +
6594 +fail:
6595 +       e->pos = pos;
6596 +       return 0;
6597 +}
6598 +
6599 +/**
6600 + * aa_unpack_profile - unpack a serialized profile
6601 + * @e: serialized data extent information
6602 + * @sa: audit struct for the operation
6603 + */
6604 +static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
6605 +                                           struct aa_audit_iface *sa)
6606 +{
6607 +       struct aa_profile *profile = NULL;
6608 +       char *name;
6609 +       size_t size = 0;
6610 +       int i, error = -EPROTO;
6611 +       u32 tmp;
6612 +
6613 +       /* check that we have the right struct being passed */
6614 +       if (!aa_is_nameX(e, AA_STRUCT, "profile"))
6615 +               goto fail;
6616 +       if (!aa_is_string(e, &name, NULL))
6617 +               goto fail;
6618 +
6619 +       profile = alloc_aa_profile(name);
6620 +       if (!profile)
6621 +               return ERR_PTR(-ENOMEM);
6622 +
6623 +       /* xmatch is optional and may be NULL */
6624 +       profile->xmatch = aa_unpack_dfa(e);
6625 +       if (IS_ERR(profile->xmatch)) {
6626 +               error = PTR_ERR(profile->xmatch);
6627 +               profile->xmatch = NULL;
6628 +               goto fail;
6629 +       }
6630 +       /* xmatch_len is not optional is xmatch is set */
6631 +       if (profile->xmatch && !aa_is_u32(e, &tmp, NULL))
6632 +               goto fail;
6633 +       profile->xmatch_len = tmp;
6634 +
6635 +       /* per profile debug flags (complain, audit) */
6636 +       if (!aa_is_nameX(e, AA_STRUCT, "flags"))
6637 +               goto fail;
6638 +       if (!aa_is_u32(e, &tmp, NULL))
6639 +               goto fail;
6640 +       if (tmp)
6641 +               profile->flags |= PFLAG_HAT;
6642 +       if (!aa_is_u32(e, &tmp, NULL))
6643 +               goto fail;
6644 +       if (tmp)
6645 +               profile->mode = APPARMOR_COMPLAIN;
6646 +       if (!aa_is_u32(e, &tmp, NULL))
6647 +               goto fail;
6648 +       if (tmp)
6649 +               profile->audit = AUDIT_ALL;
6650 +
6651 +       if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
6652 +               goto fail;
6653 +
6654 +       if (!aa_is_u32(e, &(profile->caps.allowed.cap[0]), NULL))
6655 +               goto fail;
6656 +       if (!aa_is_u32(e, &(profile->caps.audit.cap[0]), NULL))
6657 +               goto fail;
6658 +       if (!aa_is_u32(e, &(profile->caps.quiet.cap[0]), NULL))
6659 +               goto fail;
6660 +       if (!aa_is_u32(e, &(profile->caps.set.cap[0]), NULL))
6661 +               goto fail;
6662 +
6663 +       if (aa_is_nameX(e, AA_STRUCT, "caps64")) {
6664 +               /* optional upper half of 64 bit caps */
6665 +               if (!aa_is_u32(e, &(profile->caps.allowed.cap[1]), NULL))
6666 +                       goto fail;
6667 +               if (!aa_is_u32(e, &(profile->caps.audit.cap[1]), NULL))
6668 +                       goto fail;
6669 +               if (!aa_is_u32(e, &(profile->caps.quiet.cap[1]), NULL))
6670 +                       goto fail;
6671 +               if (!aa_is_u32(e, &(profile->caps.set.cap[1]), NULL))
6672 +                       goto fail;
6673 +               if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
6674 +                       goto fail;
6675 +       }
6676 +
6677 +       if (!aa_unpack_rlimits(e, profile))
6678 +               goto fail;
6679 +
6680 +       size = aa_is_array(e, "net_allowed_af");
6681 +       if (size) {
6682 +               if (size > AF_MAX)
6683 +                       goto fail;
6684 +
6685 +               for (i = 0; i < size; i++) {
6686 +                       if (!aa_is_u16(e, &profile->net.allowed[i], NULL))
6687 +                               goto fail;
6688 +                       if (!aa_is_u16(e, &profile->net.audit[i], NULL))
6689 +                               goto fail;
6690 +                       if (!aa_is_u16(e, &profile->net.quiet[i], NULL))
6691 +                               goto fail;
6692 +               }
6693 +               if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
6694 +                       goto fail;
6695 +               /* allow unix domain and netlink sockets they are handled
6696 +                * by IPC
6697 +                */
6698 +       }
6699 +       profile->net.allowed[AF_UNIX] = 0xffff;
6700 +       profile->net.allowed[AF_NETLINK] = 0xffff;
6701 +
6702 +       /* get file rules */
6703 +       profile->file.dfa = aa_unpack_dfa(e);
6704 +       if (IS_ERR(profile->file.dfa)) {
6705 +               error = PTR_ERR(profile->file.dfa);
6706 +               profile->file.dfa = NULL;
6707 +               goto fail;
6708 +       }
6709 +
6710 +       if (!aa_unpack_trans_table(e, profile))
6711 +               goto fail;
6712 +
6713 +       if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
6714 +               goto fail;
6715 +
6716 +       return profile;
6717 +
6718 +fail:
6719 +       sa->name = profile && profile->base.name ? profile->base.name :
6720 +                                                  "unknown";
6721 +       if (!sa->base.info)
6722 +               sa->base.info = "failed to unpack profile";
6723 +       aa_audit_iface(sa);
6724 +
6725 +       free_aa_profile(profile);
6726 +
6727 +       return ERR_PTR(error);
6728 +}
6729 +
6730 +/**
6731 + * aa_verify_head - unpack serialized stream header
6732 + * @e: serialized data read head
6733 + * @operation: operation header is being verified for
6734 + *
6735 + * returns error or 0 if header is good
6736 + */
6737 +static int aa_verify_header(struct aa_ext *e, struct aa_audit_iface *sa)
6738 +{
6739 +       /* get the interface version */
6740 +       if (!aa_is_u32(e, &e->version, "version")) {
6741 +               sa->base.info = "invalid profile format";
6742 +               aa_audit_iface(sa);
6743 +               return -EPROTONOSUPPORT;
6744 +       }
6745 +
6746 +       /* check that the interface version is currently supported */
6747 +       if (e->version != 5) {
6748 +               sa->base.info = "unsupported interface version";
6749 +               aa_audit_iface(sa);
6750 +               return -EPROTONOSUPPORT;
6751 +       }
6752 +
6753 +       /* read the namespace if present */
6754 +       if (!aa_is_string(e, &e->ns_name, "namespace"))
6755 +               e->ns_name = NULL;
6756 +
6757 +       return 0;
6758 +}
6759 +
6760 +
6761 +
6762 +/**
6763 + * aa_interface_add_profiles - Unpack and add new profile(s) to the profile list
6764 + * @data: serialized data stream
6765 + * @size: size of the serialized data stream
6766 + */
6767 +ssize_t aa_interface_add_profiles(void *data, size_t size)
6768 +{
6769 +       struct aa_profile *profile;
6770 +       struct aa_namespace *ns = NULL;
6771 +       struct aa_policy_common *common;
6772 +       struct aa_ext e = {
6773 +               .start = data,
6774 +               .end = data + size,
6775 +               .pos = data,
6776 +               .ns_name = NULL
6777 +       };
6778 +       ssize_t error;
6779 +       struct aa_audit_iface sa;
6780 +       aa_audit_init(&sa, "profile_load", &e);
6781 +
6782 +       error = aa_verify_header(&e, &sa);
6783 +       if (error)
6784 +               return error;
6785 +
6786 +       profile = aa_unpack_profile(&e, &sa);
6787 +       if (IS_ERR(profile))
6788 +               return PTR_ERR(profile);
6789 +
6790 +       sa.name2 = e.ns_name;
6791 +       ns = aa_prepare_namespace(e.ns_name);
6792 +       if (IS_ERR(ns)) {
6793 +               sa.base.info = "failed to prepare namespace";
6794 +               sa.base.error = PTR_ERR(ns);
6795 +               goto fail;
6796 +       }
6797 +       /* profiles are currently loaded flat with fqnames */
6798 +       sa.name = profile->fqname;
6799 +
6800 +       write_lock(&ns->base.lock);
6801 +
6802 +       common = __aa_find_parent_by_fqname(ns, sa.name);
6803 +       if (!common) {
6804 +               sa.base.info = "parent does not exist";
6805 +               sa.base.error = -ENOENT;
6806 +               goto fail2;
6807 +       }
6808 +
6809 +       if (common != &ns->base)
6810 +               profile->parent = aa_get_profile((struct aa_profile *) common);
6811 +
6812 +       if (__aa_find_profile(&common->profiles, profile->base.name)) {
6813 +               /* A profile with this name exists already. */
6814 +               sa.base.info = "profile already exists";
6815 +               goto fail2;
6816 +       }
6817 +       profile->sid = aa_alloc_sid(AA_ALLOC_SYS_SID);
6818 +       profile->ns = aa_get_namespace(ns);
6819 +
6820 +       __aa_add_profile(common, profile);
6821 +       write_unlock(&ns->base.lock);
6822 +
6823 +       aa_audit_iface(&sa);
6824 +       aa_put_namespace(ns);
6825 +       kfree(e.ns_name);
6826 +       return size;
6827 +
6828 +fail2:
6829 +       write_unlock(&ns->base.lock);
6830 +       sa.base.error = -EEXIST;
6831 +
6832 +fail:
6833 +       error = aa_audit_iface(&sa);
6834 +       aa_put_namespace(ns);
6835 +       aa_put_profile(profile);
6836 +       kfree(e.ns_name);
6837 +       return error;
6838 +}
6839 +
6840 +/**
6841 + * aa_interface_replace_profiles - replace profile(s) on the profile list
6842 + * @udata: serialized data stream
6843 + * @size: size of the serialized data stream
6844 + *
6845 + * unpack and replace a profile on the profile list and uses of that profile
6846 + * by any aa_task_context.  If the profile does not exist on the profile list
6847 + * it is added.  Return %0 or error.
6848 + */
6849 +ssize_t aa_interface_replace_profiles(void *udata, size_t size)
6850 +{
6851 +       struct aa_policy_common *common;
6852 +       struct aa_profile *old_profile = NULL, *new_profile;
6853 +       struct aa_namespace *ns;
6854 +       struct aa_ext e = {
6855 +               .start = udata,
6856 +               .end = udata + size,
6857 +               .pos = udata,
6858 +               .ns_name = NULL
6859 +       };
6860 +       ssize_t error;
6861 +       struct aa_audit_iface sa;
6862 +       aa_audit_init(&sa, "profile_replace", &e);
6863 +
6864 +       if (g_apparmor_lock_policy)
6865 +               return -EACCES;
6866 +
6867 +       error = aa_verify_header(&e, &sa);
6868 +       if (error)
6869 +               return error;
6870 +
6871 +       new_profile = aa_unpack_profile(&e, &sa);
6872 +       if (IS_ERR(new_profile))
6873 +               return PTR_ERR(new_profile);
6874 +
6875 +       sa.name2 = e.ns_name;
6876 +       ns = aa_prepare_namespace(e.ns_name);
6877 +       if (!ns) {
6878 +               sa.base.info = "failed to prepare namespace";
6879 +               sa.base.error = -ENOMEM;
6880 +               goto fail;
6881 +       }               
6882 +
6883 +       sa.name = new_profile->fqname;
6884 +
6885 +       write_lock(&ns->base.lock);
6886 +       common = __aa_find_parent_by_fqname(ns, sa.name);
6887 +
6888 +       if (!common) {
6889 +               sa.base.info = "parent does not exist";
6890 +               sa.base.error = -ENOENT;
6891 +               goto fail2;
6892 +       }
6893 +
6894 +       if (common != &ns->base)
6895 +               new_profile->parent = aa_get_profile((struct aa_profile *)
6896 +                                                    common);
6897 +
6898 +       old_profile = __aa_find_profile(&common->profiles,
6899 +                                       new_profile->base.name);
6900 +       aa_get_profile(old_profile);
6901 +       if (old_profile && old_profile->flags & PFLAG_IMMUTABLE) {
6902 +               sa.base.info = "cannot replace immutible profile";
6903 +               sa.base.error = -EPERM;
6904 +               goto fail2;
6905 +       } else  if (old_profile) {
6906 +         //            __aa_profile_list_release(&old_profile->base.profiles);
6907 +               /* TODO: remove for new interface
6908 +                * move children profiles over to the new profile so
6909 +                * that replacement behaves correctly
6910 +                */
6911 +         //            list_replace_init(&old_profile->base.profiles,
6912 +         //                              &new_profile->base.profiles);
6913 +         struct aa_profile *profile, *tmp;
6914 +         list_for_each_entry_safe(profile, tmp, &old_profile->base.profiles,
6915 +                                   base.list) {
6916 +                       aa_put_profile(profile->parent);
6917 +                       list_del(&profile->base.list);
6918 +                       profile->parent = aa_get_profile(new_profile);
6919 +                       list_add(&profile->base.list,
6920 +                                &new_profile->base.profiles);
6921 +               }
6922 +               __aa_replace_profile(old_profile, new_profile);
6923 +               new_profile->sid = old_profile->sid;
6924 +       } else {
6925 +               __aa_add_profile(common, new_profile);
6926 +               new_profile->sid = aa_alloc_sid(AA_ALLOC_SYS_SID);
6927 +       }
6928 +
6929 +       new_profile->ns = aa_get_namespace(ns);
6930 +
6931 +       write_unlock(&ns->base.lock);
6932 +
6933 +       if (!old_profile)
6934 +               sa.base.operation = "profile_load";
6935 +
6936 +       aa_audit_iface(&sa);
6937 +       aa_put_namespace(ns);
6938 +       aa_put_profile(old_profile);
6939 +       kfree(e.ns_name);
6940 +       return size;
6941 +
6942 +fail2:
6943 +       write_unlock(&ns->base.lock);
6944 +fail:
6945 +       error = aa_audit_iface(&sa);
6946 +       aa_put_namespace(ns);
6947 +       aa_put_profile(old_profile);
6948 +       aa_put_profile(new_profile);
6949 +       kfree(e.ns_name);
6950 +       return error;
6951 +}
6952 +
6953 +/**
6954 + * aa_interface_remove_profiles - remove profile(s) from the system
6955 + * @name: name of the profile to remove
6956 + * @size: size of the name
6957 + *
6958 + * remove a profile from the profile list and all aa_task_context references
6959 + * to said profile.
6960 + * NOTE: removing confinement does not restore rlimits to preconfinemnet values
6961 + */
6962 +ssize_t aa_interface_remove_profiles(char *name, size_t size)
6963 +{
6964 +       struct aa_namespace *ns;
6965 +       struct aa_profile *profile;
6966 +       struct aa_audit_iface sa;
6967 +       aa_audit_init(&sa, "profile_remove", NULL);
6968 +
6969 +       if (g_apparmor_lock_policy)
6970 +               return -EACCES;
6971 +
6972 +       write_lock(&ns_list_lock);
6973 +       if (name[0] == ':') {
6974 +               char *ns_name;
6975 +               name = aa_split_name_from_ns(name, &ns_name);
6976 +               ns = __aa_find_namespace(&ns_list, ns_name);
6977 +       } else {
6978 +               ns = aa_get_namespace(default_namespace);
6979 +       }
6980 +
6981 +       if (!ns) {
6982 +               sa.base.info = "failed: namespace does not exist";
6983 +               goto fail_ns_list_lock;
6984 +       }
6985 +
6986 +       sa.name2 = ns->base.name;
6987 +       write_lock(&ns->base.lock);
6988 +       if (!name) {
6989 +               /* remove namespace */
6990 +         //            __aa_remove_namespace(ns);
6991 +       } else {
6992 +               /* remove profile */
6993 +               profile = __aa_find_profile_by_fqname(ns, name);
6994 +               if (!profile) {
6995 +                       sa.name = name;
6996 +                       sa.base.info = "failed: profile does not exist";
6997 +                       goto fail_ns_lock;
6998 +               }
6999 +               sa.name = profile->fqname;
7000 +               __aa_profile_list_release(&profile->base.profiles);
7001 +               __aa_remove_profile(profile, profile->ns->unconfined);
7002 +       }
7003 +       write_unlock(&ns->base.lock);
7004 +       write_unlock(&ns_list_lock);
7005 +
7006 +       aa_audit_iface(&sa);
7007 +       aa_put_namespace(ns);
7008 +       return size;
7009 +
7010 +fail_ns_lock:
7011 +       write_unlock(&ns->base.lock);
7012 +
7013 +fail_ns_list_lock:
7014 +       write_unlock(&ns_list_lock);
7015 +       aa_audit_iface(&sa);
7016 +       return 0; //-ENOENT;
7017 +}
7018 diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
7019 new file mode 100644
7020 index 0000000..834cfab
7021 --- /dev/null
7022 +++ b/security/apparmor/procattr.c
7023 @@ -0,0 +1,117 @@
7024 +/*
7025 + * AppArmor security module
7026 + *
7027 + * This file contains AppArmor /proc/<pid>/attr/ interface functions
7028 + *
7029 + * Copyright (C) 1998-2008 Novell/SUSE
7030 + * Copyright 2009 Canonical Ltd.
7031 + *
7032 + * This program is free software; you can redistribute it and/or
7033 + * modify it under the terms of the GNU General Public License as
7034 + * published by the Free Software Foundation, version 2 of the
7035 + * License.
7036 + */
7037 +
7038 +#include "include/apparmor.h"
7039 +#include "include/policy.h"
7040 +#include "include/domain.h"
7041 +
7042 +/* FIXME show profile multiplexing */
7043 +int aa_getprocattr(struct aa_namespace *ns, struct aa_profile *profile,
7044 +                  char **string)
7045 +{
7046 +       char *str;
7047 +       int len = 0;
7048 +
7049 +       if (profile) {
7050 +               int mode_len, name_len, ns_len = 0;
7051 +               const char *mode_str = profile_mode_names[profile->mode];
7052 +               char *s;
7053 +
7054 +               mode_len = strlen(mode_str) + 3;  /* _(mode_str)\n */
7055 +               name_len = strlen(profile->fqname);
7056 +               if (ns != default_namespace)
7057 +                       ns_len = strlen(ns->base.name) + 3;
7058 +               len = mode_len + ns_len + name_len + 1;
7059 +               s = str = kmalloc(len + 1, GFP_ATOMIC);
7060 +               if (!str)
7061 +                       return -ENOMEM;
7062 +
7063 +               if (ns_len) {
7064 +                       sprintf(s, "%s://", ns->base.name);
7065 +                       s += ns_len;
7066 +               }
7067 +               memcpy(s, profile->fqname, name_len);
7068 +               s += name_len;
7069 +               sprintf(s, " (%s)\n", mode_str);
7070 +       } else {
7071 +               const char *unconfined_str = "unconfined\n";
7072 +
7073 +               len = strlen(unconfined_str);
7074 +               if (ns != default_namespace)
7075 +                       len += strlen(ns->base.name) + 1;
7076 +
7077 +               str = kmalloc(len + 1, GFP_ATOMIC);
7078 +               if (!str)
7079 +                       return -ENOMEM;
7080 +
7081 +               if (ns != default_namespace)
7082 +                       sprintf(str, "%s://%s", ns->base.name, unconfined_str);
7083 +               else
7084 +                       memcpy(str, unconfined_str, len);
7085 +       }
7086 +       *string = str;
7087 +
7088 +       return len;
7089 +}
7090 +
7091 +static char *split_token_from_name(const char *op, char *args, u64 *token)
7092 +{
7093 +       char *name;
7094 +
7095 +       *token = simple_strtoull(args, &name, 16);
7096 +       if ((name == args) || *name != '^') {
7097 +               AA_ERROR("%s: Invalid input '%s'", op, args);
7098 +               return ERR_PTR(-EINVAL);
7099 +       }
7100 +
7101 +       name++;  /* skip ^ */
7102 +       if (!*name)
7103 +               name = NULL;
7104 +       return name;
7105 +}
7106 +
7107 +int aa_setprocattr_changehat(char *args, int test)
7108 +{
7109 +       char *hat;
7110 +       u64 token;
7111 +
7112 +       hat = split_token_from_name("change_hat", args, &token);
7113 +       if (IS_ERR(hat))
7114 +               return PTR_ERR(hat);
7115 +
7116 +       if (!hat && !token) {
7117 +               AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
7118 +               return -EINVAL;
7119 +       }
7120 +
7121 +       AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
7122 +                __func__, token, hat ? hat : NULL);
7123 +
7124 +       return aa_change_hat(hat, token, test);
7125 +}
7126 +
7127 +int aa_setprocattr_changeprofile(char *args, int onexec, int test)
7128 +{
7129 +       char *name, *ns_name;
7130 +
7131 +       name = aa_split_name_from_ns(args, &ns_name);
7132 +       return aa_change_profile(ns_name, name, onexec, test);
7133 +}
7134 +
7135 +
7136 +int aa_setprocattr_permipc(char *args)
7137 +{
7138 +       /* TODO: add ipc permission querying */
7139 +       return -ENOTSUPP;
7140 +}
7141 diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
7142 new file mode 100644
7143 index 0000000..f00165b
7144 --- /dev/null
7145 +++ b/security/apparmor/resource.c
7146 @@ -0,0 +1,104 @@
7147 +/*
7148 + * AppArmor security module
7149 + *
7150 + * This file contains AppArmor resource mediation and attachment
7151 + *
7152 + * Copyright (C) 1998-2008 Novell/SUSE
7153 + * Copyright 2009 Canonical Ltd.
7154 + *
7155 + * This program is free software; you can redistribute it and/or
7156 + * modify it under the terms of the GNU General Public License as
7157 + * published by the Free Software Foundation, version 2 of the
7158 + * License.
7159 + */
7160 +
7161 +#include <linux/audit.h>
7162 +
7163 +#include "include/audit.h"
7164 +#include "include/resource.h"
7165 +#include "include/policy.h"
7166 +
7167 +struct aa_audit_resource {
7168 +       struct aa_audit base;
7169 +
7170 +       int rlimit;
7171 +};
7172 +
7173 +static void audit_cb(struct audit_buffer *ab, void *va)
7174 +{
7175 +       struct aa_audit_resource *sa = va;
7176 +
7177 +       if (sa->rlimit)
7178 +               audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
7179 +}
7180 +
7181 +static int aa_audit_resource(struct aa_profile *profile,
7182 +                            struct aa_audit_resource *sa)
7183 +{
7184 +       return aa_audit(AUDIT_APPARMOR_AUTO, profile, (struct aa_audit *)sa,
7185 +                       audit_cb);
7186 +}
7187 +
7188 +/**
7189 + * aa_task_setrlimit - test permission to set an rlimit
7190 + * @profile - profile confining the task
7191 + * @resource - the resource being set
7192 + * @new_rlim - the new resource limit
7193 + *
7194 + * Control raising the processes hard limit.
7195 + */
7196 +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
7197 +                     struct rlimit *new_rlim)
7198 +{
7199 +       struct aa_audit_resource sa;
7200 +       int error = 0;
7201 +
7202 +       memset(&sa, 0, sizeof(sa));
7203 +       sa.base.operation = "setrlimit";
7204 +       sa.base.gfp_mask = GFP_KERNEL;
7205 +       sa.rlimit = resource + 1;
7206 +
7207 +       if (profile->rlimits.mask & (1 << resource) &&
7208 +           new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
7209 +               sa.base.error = -EACCES;
7210 +
7211 +               error = aa_audit_resource(profile, &sa);
7212 +       }
7213 +
7214 +       return error;
7215 +}
7216 +
7217 +void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new)
7218 +{
7219 +       unsigned int mask = 0;
7220 +       struct rlimit *rlim, *initrlim;
7221 +       int i;
7222 +
7223 +       /* for any rlimits the profile controlled reset the soft limit
7224 +        * to the less of the tasks hard limit and the init tasks soft limit
7225 +        */
7226 +       if (old && old->rlimits.mask) {
7227 +               for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<=1) {
7228 +                       if (old->rlimits.mask & mask) {
7229 +                               rlim = current->signal->rlim + i;
7230 +                               initrlim = init_task.signal->rlim + i;
7231 +                               rlim->rlim_cur = min(rlim->rlim_max,
7232 +                                                    initrlim->rlim_cur);
7233 +                       }
7234 +               }
7235 +       }
7236 +
7237 +       /* set any new hard limits as dictated by the new profile */
7238 +       if (!(new && new->rlimits.mask))
7239 +               return;
7240 +       for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<=1) {
7241 +               if (!(new->rlimits.mask & mask))
7242 +                       continue;
7243 +
7244 +               rlim = current->signal->rlim + i;
7245 +               rlim->rlim_max = min(rlim->rlim_max,
7246 +                                    new->rlimits.limits[i].rlim_max);
7247 +               /* soft limit should not exceed hard limit */
7248 +               rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
7249 +       }
7250 +}
7251 diff --git a/security/apparmor/sid.c b/security/apparmor/sid.c
7252 new file mode 100644
7253 index 0000000..aa41a35
7254 --- /dev/null
7255 +++ b/security/apparmor/sid.c
7256 @@ -0,0 +1,113 @@
7257 +/*
7258 + * AppArmor security module
7259 + *
7260 + * This file contains AppArmor security identifier (sid) manipulation fns
7261 + *
7262 + * Copyright 2009 Canonical Ltd.
7263 + *
7264 + * This program is free software; you can redistribute it and/or
7265 + * modify it under the terms of the GNU General Public License as
7266 + * published by the Free Software Foundation, version 2 of the
7267 + * License.
7268 + *
7269 + *
7270 + * AppArmor allocates a unique sid for every profile loaded.  If a profile
7271 + * is replaced it receive the sid of the profile it is replacing.  Each sid
7272 + * is a u32 with the lower u16 being sids of system profiles and the
7273 + * upper u16 being user profile sids.
7274 + *
7275 + * The sid value of 0 is invalid for system sids and is used to indicate
7276 + * unconfined for user sids.
7277 + *
7278 + * A compound sid is a pair of user and system sids that is used to identify
7279 + * both profiles confining a task.
7280 + *
7281 + * Both system and user sids are globally unique with all users pulling
7282 + * from the same sid pool.  User sid allocation is limited by the
7283 + * user controls, that can limit how many profiles are loaded by a user.
7284 + */
7285 +
7286 +#include <linux/spinlock.h>
7287 +#include <linux/errno.h>
7288 +#include <linux/err.h>
7289 +
7290 +#include "include/sid.h"
7291 +
7292 +/* global counter from which sids are allocated */
7293 +static u16 global_sys_sid;
7294 +static u16 global_usr_sid;
7295 +static DEFINE_SPINLOCK(sid_lock);
7296 +
7297 +
7298 +/* TODO FIXME: add sid to profile mapping, and sid recycling */
7299 +
7300 +
7301 +/**
7302 + * aa_alloc_sid - allocate a new sid for a profile
7303 + * @is_usr: true if the new sid is a user based sid
7304 + */
7305 +u32 aa_alloc_sid(int is_usr)
7306 +{
7307 +       u32 sid;
7308 +
7309 +       /* 
7310 +        * TODO FIXME: sid recycling - part of profile mapping table
7311 +        */
7312 +       spin_lock(&sid_lock);
7313 +       if (is_usr) {
7314 +               sid = (++global_usr_sid) << 16;
7315 +               
7316 +       } else {
7317 +               sid = ++global_sys_sid;
7318 +       }
7319 +       spin_unlock(&sid_lock);
7320 +       return sid;
7321 +}
7322 +
7323 +/**
7324 + * aa_free_sid - free a sid
7325 + * @sid: sid to free
7326 + */
7327 +void aa_free_sid(u32 sid)
7328 +{
7329 +       ;       /* NOP ATM */
7330 +}
7331 +
7332 +/**
7333 + * aa_add_sid_profile - associate a profile to a sid for sid -> profile lookup
7334 + * @sid: sid of te profile
7335 + * @profile: profile to associate
7336 + *
7337 + * return 0 or error
7338 + */
7339 +int aa_add_sid_profile(u32 sid, struct aa_profile *profile)
7340 +{
7341 +       /* NOP ATM */
7342 +       return 0;
7343 +}
7344 +
7345 +/**
7346 + * aa_replace_sid_profile - replace the profile associated with a sid
7347 + * @sid: sid to associate a new profile with
7348 + * @profile: profile to associate with side
7349 + *
7350 + * return 0 or error
7351 + */
7352 +int aa_replace_sid_profile(u32 sid, struct aa_profile *profile)
7353 +{
7354 +       /* NOP ATM */
7355 +       return 0;
7356 +}
7357 +
7358 +/**
7359 + * aa_get_sid_profile - get the profile associated with the sid
7360 + * @sid: sid to lookup
7361 + *
7362 + * returns - the profile, or NULL for unconfined user.
7363 + *         - if there is an error -ENOENT, -EINVAL
7364 + */
7365 +struct aa_profile *aa_get_sid_profile(u32 sid)
7366 +{
7367 +       return ERR_PTR(-EINVAL);
7368 +}
7369 +
This page took 0.612525 seconds and 4 git commands to generate.