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