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