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
5 A lot of drivers has their options described inside of
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
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
25 #define AUDIT_MAC_UNLBL_STCADD 1416 /* NetLabel: add a static label */
26 #define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */
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 */
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
43 source security/selinux/Kconfig
44 source security/smack/Kconfig
45 source security/tomoyo/Kconfig
46 +source security/apparmor/Kconfig
48 source security/integrity/ima/Kconfig
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
55 + * AppArmor security module
57 + * This file contains AppArmor /proc/<pid>/attr interface functions
59 + * Copyright (C) 1998-2008 Novell/SUSE
60 + * Copyright 2009 Canonical Ltd.
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
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>
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"
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)
85 + const struct cred *cred;
86 + struct aa_profile *profile;
90 + /* only writes from pos 0, that is complete writes */
91 + data = ERR_PTR(-ESPIPE);
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.
100 + cred = aa_current_policy(&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,
112 + data = vmalloc(alloc_size);
113 + if (data == NULL) {
114 + data = ERR_PTR(-ENOMEM);
118 + if (copy_from_user(data, userbuf, copy_size)) {
120 + data = ERR_PTR(-EFAULT);
128 +static struct aa_profile *next_profile(struct aa_profile *profile)
130 + struct aa_profile *parent;
131 + struct aa_namespace *ns = profile->ns;
133 + if (!list_empty(&profile->base.profiles))
134 + return list_first_entry(&profile->base.profiles,
135 + struct aa_profile, base.list);
137 + parent = profile->parent;
139 + list_for_each_entry_continue(profile, &parent->base.profiles,
143 + parent = parent->parent;
146 + list_for_each_entry_continue(profile, &ns->base.profiles, base.list)
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,
154 + read_unlock(&ns->base.lock);
159 +static void *p_start(struct seq_file *f, loff_t *pos)
160 + __acquires(ns_list_lock)
162 + struct aa_namespace *ns;
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);
177 + read_unlock(&ns->base.lock);
182 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
184 + struct aa_profile *profile = (struct aa_profile *) p;
187 + profile = next_profile(profile);
192 +static void p_stop(struct seq_file *f, void *p)
193 + __releases(ns_list_lock)
195 + struct aa_profile *profile = (struct aa_profile *) p;
198 + read_unlock(&profile->ns->base.lock);
199 + read_unlock(&ns_list_lock);
202 +static void print_name(struct seq_file *f, struct aa_profile *profile)
204 + if (profile->parent) {
205 + print_name(f, profile->parent);
206 + seq_printf(f, "//");
208 + seq_printf(f, "%s", profile->base.name);
211 +static int seq_show_profile(struct seq_file *f, void *p)
213 + struct aa_profile *profile = (struct aa_profile *)p;
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");
224 +/* Used in apparmorfs.c */
225 +static struct seq_operations apparmorfs_profiles_op = {
229 + .show = seq_show_profile,
232 +static int aa_profiles_open(struct inode *inode, struct file *file)
234 + return seq_open(file, &apparmorfs_profiles_op);
238 +static int aa_profiles_release(struct inode *inode, struct file *file)
240 + return seq_release(inode, file);
243 +static struct file_operations apparmorfs_profiles_fops = {
244 + .open = aa_profiles_open,
246 + .llseek = seq_lseek,
247 + .release = aa_profiles_release,
250 +/* apparmor/matching */
251 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
252 + size_t size, loff_t *ppos)
254 + const char *matching = "pattern=aadfa audit perms=crwxamlk/ user::other";
256 + return simple_read_from_buffer(buf, size, ppos, matching,
260 +static struct file_operations apparmorfs_matching_fops = {
261 + .read = aa_matching_read,
264 +/* apparmor/features */
265 +static ssize_t aa_features_read(struct file *file, char __user *buf,
266 + size_t size, loff_t *ppos)
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";
272 + return simple_read_from_buffer(buf, size, ppos, features,
276 +static struct file_operations apparmorfs_features_fops = {
277 + .read = aa_features_read,
280 +/* apparmor/.load */
281 +static ssize_t aa_profile_load(struct file *f, const char __user *buf,
282 + size_t size, loff_t *pos)
287 + data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
289 + error = PTR_ERR(data);
290 + if (!IS_ERR(data)) {
291 + error = aa_interface_add_profiles(data, size);
299 +static struct file_operations apparmorfs_profile_load = {
300 + .write = aa_profile_load
303 +/* apparmor/.replace */
304 +static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
305 + size_t size, loff_t *pos)
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);
322 +static struct file_operations apparmorfs_profile_replace = {
323 + .write = aa_profile_replace
326 +/* apparmor/.remove */
327 +static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
328 + size_t size, loff_t *pos)
334 + * aa_remove_profile needs a null terminated string so 1 extra
335 + * byte is allocated and the copied data is null terminated.
337 + data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
340 + error = PTR_ERR(data);
341 + if (!IS_ERR(data)) {
343 + error = aa_interface_remove_profiles(data, size);
350 +static struct file_operations apparmorfs_profile_remove = {
351 + .write = aa_profile_remove
354 +static struct dentry *apparmorfs_dentry;
355 +struct dentry *apparmorfs_null;
356 +struct vfsmount *apparmorfs_mnt;
358 +static void aafs_remove(const char *name)
360 + struct dentry *dentry;
362 + dentry = lookup_one_len(name, apparmorfs_dentry, strlen(name));
363 + if (!IS_ERR(dentry)) {
364 + securityfs_remove(dentry);
369 +static int aafs_create(const char *name, int mask, struct file_operations *fops)
371 + struct dentry *dentry;
373 + dentry = securityfs_create_file(name, S_IFREG | mask, apparmorfs_dentry,
376 + return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
379 +void destroy_apparmorfs(void)
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;
393 +int create_apparmorfs(void)
397 + if (!apparmor_initialized)
400 + if (apparmorfs_dentry) {
401 + AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
405 + apparmorfs_dentry = securityfs_create_dir("apparmor", NULL);
406 + if (IS_ERR(apparmorfs_dentry)) {
407 + error = PTR_ERR(apparmorfs_dentry);
408 + apparmorfs_dentry = NULL;
411 + error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
414 + error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
417 + error = aafs_create("features", 0444, &apparmorfs_features_fops);
420 + error = aafs_create(".load", 0640, &apparmorfs_profile_load);
423 + error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
426 + error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
430 + /* TODO: add support for apparmorfs_null and apparmorfs_mnt */
432 + /* Report that AppArmor fs is enabled */
433 + info_message("AppArmor Filesystem Enabled");
437 + destroy_apparmorfs();
438 + AA_ERROR("Error creating AppArmor securityfs\n");
439 + apparmor_disable();
443 +fs_initcall(create_apparmorfs);
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
450 + * AppArmor security module
452 + * This file contains AppArmor auditing functions
454 + * Copyright (C) 1998-2008 Novell/SUSE
455 + * Copyright 2009 Canonical Ltd.
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
463 +#include <linux/audit.h>
464 +#include <linux/socket.h>
466 +#include "include/apparmor.h"
467 +#include "include/audit.h"
468 +#include "include/policy.h"
470 +const char *audit_mode_names[] = {
478 +static char* aa_audit_type[] = {
480 + "APPARMOR_ALLOWED",
490 + * user auditing - netlink interface
491 + * system control of whether user audit messages go to system log
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 *))
497 + struct audit_buffer *ab = NULL;
499 + if (profile && PROFILE_KILL(profile) && type == AUDIT_APPARMOR_DENIED)
500 + type = AUDIT_APPARMOR_KILL;
502 + ab = audit_log_start(audit_cxt, sa->gfp_mask, type);
505 + AA_ERROR("(%d) Unable to log event of type (%d)\n",
507 + /* don't fail operations in complain mode even if logging
509 + return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
512 + if (g_apparmor_audit_header)
513 + audit_log_format(ab, "type=%s ",
514 + aa_audit_type[type - AUDIT_APPARMOR_AUDIT]);
517 + audit_log_format(ab, "operation=\"%s\"", sa->operation);
520 + audit_log_format(ab, " info=\"%s\"", sa->info);
522 + audit_log_format(ab, " error=%d", sa->error);
525 + audit_log_format(ab, " pid=%d", sa->task ?sa->task->pid : current->pid);
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);
534 + if (profile->ns != default_namespace) {
535 + audit_log_format(ab, " namespace=");
536 + audit_log_untrustedstring(ab, profile->ns->base.name);
545 + if (type == AUDIT_APPARMOR_KILL)
546 + (void)send_sig_info(SIGKILL, NULL,
547 + sa->task ? sa->task : current);
549 + return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error;
553 + * aa_audit - Log an audit event to the audit subsystem
554 + * @type: audit type for the message
555 + * @profile: profile to check against
558 +int aa_audit(int type, struct aa_profile *profile, struct aa_audit *sa,
559 + void(*cb)(struct audit_buffer *, void *))
561 + struct audit_context *audit_cxt;
562 + audit_cxt = g_apparmor_logsyscall ? current->audit_context : NULL;
564 + if (type == AUDIT_APPARMOR_AUTO) {
565 + if (likely(!sa->error)) {
566 + if (PROFILE_AUDIT_MODE(profile) != AUDIT_ALL)
568 + type = AUDIT_APPARMOR_AUDIT;
569 + } else if (PROFILE_COMPLAIN(profile))
570 + type = AUDIT_APPARMOR_ALLOWED;
572 + type = AUDIT_APPARMOR_DENIED;
574 + if (PROFILE_AUDIT_MODE(profile) == AUDIT_QUIET ||
575 + (type == AUDIT_APPARMOR_DENIED &&
576 + PROFILE_AUDIT_MODE(profile) == AUDIT_QUIET))
579 + return aa_audit_base(type, profile, sa, audit_cxt, cb);
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
588 +int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
590 + void(*cb)(struct audit_buffer *, void *))
592 + struct aa_audit sa;
593 + memset(&sa, 0, sizeof(sa));
594 + sa.operation = "syscall";
597 + sa.error = -EACCES;
599 + return aa_audit_base(AUDIT_APPARMOR_DENIED, profile, &sa,
600 + current->audit_context, NULL);
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
607 + * AppArmor security module
609 + * This file contains AppArmor capability mediation functions
611 + * Copyright (C) 1998-2008 Novell/SUSE
612 + * Copyright 2009 Canonical Ltd.
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
620 +#include <linux/capability.h>
621 +#include <linux/errno.h>
622 +#include <linux/gfp.h>
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"
631 + * Table of capability names: we generate it from capabilities.h.
633 +#include "capability_names.h"
635 +struct audit_cache {
636 + struct task_struct *task;
640 +static DEFINE_PER_CPU(struct audit_cache, audit_cache);
642 +struct aa_audit_caps {
643 + struct aa_audit base;
648 +static void audit_cb(struct audit_buffer *ab, void *va)
650 + struct aa_audit_caps *sa = va;
652 + audit_log_format(ab, " name=");
653 + audit_log_untrustedstring(ab, capability_names[sa->cap]);
656 +static int aa_audit_caps(struct aa_profile *profile, struct aa_audit_caps *sa)
658 + struct audit_cache *ent;
659 + int type = AUDIT_APPARMOR_AUTO;
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)))
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;
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))
682 + return sa->base.error;
684 + ent->task = sa->base.task;
685 + cap_raise(ent->caps, sa->cap);
687 + put_cpu_var(audit_cache);
689 + return aa_audit(type, profile, &sa->base, audit_cb);
692 +int aa_profile_capable(struct aa_profile *profile, int cap)
694 + return cap_raised(profile->caps.allowed, cap) ? 0 : -EPERM;
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
704 + * Look up capability in profile capability set.
705 + * Returns 0 on success, or else an error code.
707 +int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
710 + int error = aa_profile_capable(profile, cap);
711 + struct aa_audit_caps sa;
714 + if (PROFILE_COMPLAIN(profile))
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;
726 + return aa_audit_caps(profile, &sa);
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
733 + * AppArmor security module
735 + * This file contains AppArmor functions used to manipulate object security
738 + * Copyright (C) 1998-2008 Novell/SUSE
739 + * Copyright 2009 Canonical Ltd.
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
747 +#include "include/context.h"
748 +#include "include/policy.h"
752 +struct aa_task_context *aa_alloc_task_context(gfp_t flags)
754 + return kzalloc(sizeof(struct aa_task_context), flags);
757 +void aa_free_task_context(struct aa_task_context *cxt)
760 + aa_put_profile(cxt->sys.profile);
761 + aa_put_profile(cxt->sys.previous);
762 + aa_put_profile(cxt->sys.onexec);
764 + memset(cxt, 0, sizeof(*cxt));
770 + * duplicate a task context, incrementing reference counts
772 +struct aa_task_context *aa_dup_task_context(struct aa_task_context *old_cxt,
775 + struct aa_task_context *cxt;
777 + cxt = kmemdup(old_cxt, sizeof(*cxt), gfp);
781 + aa_get_profile(cxt->sys.profile);
782 + aa_get_profile(cxt->sys.previous);
783 + aa_get_profile(cxt->sys.onexec);
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
794 +void aa_cred_policy(const struct cred *cred, struct aa_profile **sys)
796 + struct aa_task_context *cxt = cred->security;
798 + *sys = aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
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
806 + * Only gets the cred ref count which has ref counts on the profiles returned
808 +struct cred *aa_get_task_policy(const struct task_struct *task,
809 + struct aa_profile **sys)
811 + struct cred *cred = get_task_cred(task);
812 + aa_cred_policy(cred, sys);
816 +void aa_put_task_policy(struct cred *cred)
821 +static void replace_group(struct aa_task_cxt_group *cgrp,
822 + struct aa_profile *profile)
824 + if (cgrp->profile == profile)
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;
835 + aa_put_profile(cgrp->profile);
836 + cgrp->profile = aa_get_profile(profile);
840 + * aa_replace_current_profiles - replace the current tasks profiles
841 + * @sys: new system profile
843 + * Returns: error on failure
845 +int aa_replace_current_profiles(struct aa_profile *sys)
847 + struct aa_task_context *cxt;
848 + struct cred *new = prepare_creds();
852 + cxt = new->security;
853 + replace_group(&cxt->sys, sys);
859 +int aa_set_current_onexec(struct aa_profile *sys)
861 + struct aa_task_context *cxt;
862 + struct cred *new = prepare_creds();
866 + cxt = new->security;
867 + aa_put_profile(cxt->sys.onexec);
868 + cxt->sys.onexec = aa_get_profile(sys);
875 + * Do the actual cred switching of a changehat
876 + * profile must be valid
878 +int aa_set_current_hat(struct aa_profile *profile, u64 token)
880 + struct aa_task_context *cxt;
881 + struct cred *new = prepare_creds();
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);
892 + /* previous_profile && cxt->token != token */
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;
906 + * Attempt to return out of a hat to the previous profile
908 +int aa_restore_previous_profile(u64 token)
910 + struct aa_task_context *cxt;
911 + struct cred *new = prepare_creds();
915 + cxt = new->security;
916 + if (cxt->sys.token != token) {
920 + /* ignore restores when there is no saved profile */
921 + if (!cxt->sys.previous) {
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);
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;
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
946 + * AppArmor security module
948 + * This file contains AppArmor policy attachment and domain transitions
950 + * Copyright (C) 2002-2008 Novell/SUSE
951 + * Copyright 2009 Canonical Ltd.
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
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>
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"
978 + * aa_free_domain_entries - free entries in a domain table
979 + * @domain: the domain table to free
981 +void aa_free_domain_entries(struct aa_domain *domain)
985 + if (!domain->table)
988 + for (i = 0; i < domain->size; i++)
989 + kfree(domain->table[i]);
990 + kfree(domain->table);
994 + * check if the task is ptraced and if so if the tracing task is allowed
995 + * to trace the new domain
997 +static int aa_may_change_ptraced_domain(struct task_struct *task,
998 + struct aa_profile *to_profile)
1000 + struct task_struct *tracer;
1001 + struct cred *cred = NULL;
1002 + struct aa_profile *tracerp = NULL;
1006 + tracer = tracehook_tracer_task(task);
1008 + cred = aa_get_task_policy(tracer, &tracerp);
1009 + rcu_read_unlock();
1014 + error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
1021 + * change_profile_perms
1023 +static struct file_perms change_profile_perms(struct aa_profile *profile,
1024 + struct aa_namespace *ns,
1026 + unsigned int *rstate)
1028 + struct file_perms perms;
1029 + struct path_cond cond = { 0, 0 };
1030 + unsigned int state;
1034 + perms.allowed = AA_MAY_CHANGE_PROFILE;
1035 + perms.xindex = perms.dindex = 0;
1036 + perms.audit = perms.quiet = perms.kill = 0;
1040 + } else if (!profile->file.dfa) {
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,
1046 + if (COMBINED_PERM_MASK(perms) & AA_MAY_CHANGE_PROFILE)
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);
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
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
1072 +static const char *next_name(int xtype, const char *name)
1074 +/* TODO: fix parser and enable
1075 + if (xtype == AA_X_TABLE) {
1076 + name = name + strlen(name) + 1;
1085 + * get target profile for xindex
1087 +static struct aa_profile *x_to_profile(struct aa_namespace *ns,
1088 + struct aa_profile *profile,
1089 + const char *name, u16 xindex)
1092 + struct aa_profile *new_profile = NULL;
1093 + u16 xtype = xindex & AA_X_TYPE_MASK;
1094 + int index = xindex & AA_X_INDEX_MASK;
1097 + profile = ns->unconfined;
1101 + /* fail exec unless ix || ux fallback - handled by caller */
1102 + return ERR_PTR(-EACCES);
1104 + if (xindex & AA_X_CHILD)
1105 + new_profile = aa_sys_find_attach(&profile->base, name);
1107 + new_profile = aa_sys_find_attach(&ns->base, name);
1111 + if (index > profile->file.trans.size) {
1112 + AA_ERROR("Invalid named transition\n");
1113 + return ERR_PTR(-EACCES);
1115 + name = profile->file.trans.table[index];
1119 + for (; !new_profile && name; name = next_name(xtype, name)) {
1120 + struct aa_namespace *new_ns;
1121 + const char *xname = NULL;
1124 + if (xindex & AA_X_CHILD) {
1125 + new_profile = aa_find_child(profile, name);
1127 + return new_profile;
1129 + } else if (*name == ':') {
1130 + /* switching namespace */
1131 + const char *ns_name = name + 1;
1132 + name = xname = ns_name + strlen(ns_name) + 1;
1134 + /* no name so use profile name */
1135 + xname = profile->fqname;
1136 + if (*ns_name == '@') {
1137 + /* TODO: variable support */
1140 + new_ns = aa_find_namespace(ns_name);
1143 + } else if (*name == '@') {
1144 + /* TODO: variable support */
1150 + new_profile = aa_find_profile_by_fqname(new_ns ? new_ns : ns,
1152 + aa_put_namespace(new_ns);
1157 + return ERR_PTR(-ENOENT);
1159 + return new_profile;
1162 +int apparmor_bprm_set_creds(struct linux_binprm *bprm)
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 };
1173 + sa.base.error = cap_bprm_set_creds(bprm);
1174 + if (sa.base.error)
1175 + return sa.base.error;
1177 + if (bprm->cred_prepared)
1180 + memset(&sa, 0, sizeof(sa));
1181 + sa.base.operation = "exec";
1182 + sa.base.gfp_mask = GFP_KERNEL;
1183 + sa.request = MAY_EXEC;
1186 + cxt = bprm->cred->security;
1189 + profile = aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
1190 + ns = cxt->sys.profile->ns;
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;
1203 + /* unconfined task - attach profile if one matches */
1204 + new_profile = aa_sys_find_attach(&ns->base, sa.name);
1208 + } else if (cxt->sys.onexec) {
1210 + * onexec permissions are stored in a pair, rewalk the
1211 + * dfa to get start of the exec path match.
1213 + sa.perms = change_profile_perms(profile, cxt->sys.onexec->ns,
1215 + state = aa_dfa_null_transition(profile->file.dfa, state);
1217 + sa.perms = aa_str_perms(profile->file.dfa, state, sa.name, &cond,
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,
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";
1231 + } else if (sa.perms.xindex & AA_X_UNCONFINED) {
1232 + new_profile = aa_get_profile(ns->unconfined);
1233 + sa.base.info = "ux fallback";
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;
1241 + } else if (PROFILE_COMPLAIN(profile)) {
1242 + new_profile = aa_alloc_null_profile(profile, 0);
1243 + sa.base.error = -EACCES;
1245 + sa.base.error = -ENOMEM;
1246 + sa.name2 = new_profile->fqname;
1247 + sa.perms.xindex |= AA_X_UNSAFE;
1249 + sa.base.error = -EACCES;
1255 + if (profile == new_profile) {
1256 + aa_put_profile(new_profile);
1260 + if (bprm->unsafe & LSM_UNSAFE_SHARE) {
1261 + /* FIXME: currently don't mediate shared state */
1265 + if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
1266 + sa.base.error = aa_may_change_ptraced_domain(current,
1268 + if (sa.base.error)
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
1278 + * Cases 2 and 3 are marked as requiring secure exec
1279 + * (unless policy specified "unsafe exec")
1281 + * bprm->unsafe is used to cache the AA_X_UNSAFE permission
1282 + * to avoid having to recompute in secureexec
1284 + if (!(sa.perms.xindex & AA_X_UNSAFE))
1285 + bprm->unsafe |= AA_SECURE_X_NEEDED;
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;
1293 + /* when transitioning profiles clear unsafe personality bits */
1294 + bprm->per_clear |= PER_CLEAR_ON_SETID;
1296 + aa_put_profile(cxt->sys.profile);
1297 + cxt->sys.profile = new_profile;
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;
1307 + sa.base.error = aa_audit_file(profile, &sa);
1312 + return sa.base.error;
1315 +int apparmor_bprm_secureexec(struct linux_binprm *bprm)
1317 + int ret = cap_bprm_secureexec(bprm);
1319 + /* the decision to use secure exec is computed in set_creds
1320 + * and stored in bprm->unsafe. The AppArmor X_UNSAFE flag is
1323 + if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
1330 +static int aa_revalidate_perm(struct aa_profile *profile, struct file *file,
1331 + char *buffer, int size)
1333 + umode_t mode = file->f_path.dentry->d_inode->i_mode;
1337 + error = aa_get_name_to_buffer(&file->f_path, S_ISDIR(mode), buffer,
1339 + return aa_file_common_perm(profile, "file_inherit", file,
1340 + aa_map_file_to_perms(file), name,
1344 +static void revalidate_file(struct aa_profile *profile, struct file *file,
1345 + unsigned long i, char *buffer, int size,
1346 + struct cred *cred)
1348 + if (aa_revalidate_perm(profile, file, buffer, size)) {
1349 + struct file *devnull = NULL;
1350 + int fd = get_unused_fd();
1354 + put_unused_fd(fd);
1358 + get_file(devnull);
1359 + } else if (apparmorfs_null) {
1360 + devnull = dentry_open(dget(apparmorfs_null),
1361 + mntget(apparmorfs_mnt),
1363 + if (IS_ERR(devnull)) {
1365 + put_unused_fd(fd);
1369 + /* apparmorfs_null not setup */
1370 + put_unused_fd(fd);
1373 + fd_install(fd, devnull);
1378 + * derived from security/selinux/hooks.c: flush_unauthorized_files &&
1379 + * fs/exec.c:flush_old_files
1381 +static int revalidate_files(struct aa_profile *profile,
1382 + struct files_struct *files, gfp_t gfp,
1383 + struct cred *cred)
1385 + struct file *file;
1386 + struct fdtable *fdt;
1388 + char *buffer = kmalloc(g_apparmor_path_max, gfp);
1392 + spin_lock(&files->file_lock);
1394 + unsigned long set, i;
1397 + i = j * __NFDBITS;
1398 + fdt = files_fdtable(files);
1399 + if (i >= fdt->max_fds)
1401 + set = fdt->open_fds->fds_bits[j];
1404 + spin_unlock(&files->file_lock);
1405 + for ( ; set ; i++,set >>= 1) {
1410 + revalidate_file(profile, file, i, buffer,
1411 + g_apparmor_path_max, cred);
1415 + spin_lock(&files->file_lock);
1417 + spin_unlock(&files->file_lock);
1422 +int apparmor_bprm_committing_creds(struct linux_binprm *bprm)
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;
1429 + if ((new_cxt->sys.profile == profile) ||
1430 + (new_cxt->sys.profile->flags & PFLAG_UNCONFINED)) {
1436 + error = revalidate_files(new_cxt->sys.profile, current->files,
1437 + GFP_KERNEL, bprm->cred);
1441 + current->pdeath_signal = 0;
1443 + /* reset soft limits and set hard limits for the new profile */
1444 + __aa_transition_rlimits(profile, new_cxt->sys.profile);
1448 +void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
1450 + /* TODO: cleanup signals - ipc mediation */
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
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
1464 + * Returns %0 on success, error otherwise.
1466 +int aa_change_hat(const char *hat_name, u64 token, int permtest)
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;
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;
1479 + cred = aa_current_policy(&profile);
1480 + cxt = cred->security;
1481 + previous_profile = cxt->sys.previous;
1484 + sa.base.info = "unconfined";
1485 + sa.base.error = -EPERM;
1490 + sa.name2 = profile->ns->base.name;
1492 + if (PROFILE_IS_HAT(profile))
1493 + hat = aa_find_child(profile->parent, hat_name);
1495 + hat = aa_find_child(profile, hat_name);
1497 + if (PROFILE_IS_HAT(profile))
1498 + name = new_compound_name(profile->parent->fqname,
1501 + name = new_compound_name(profile->fqname,
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
1511 + hat = aa_alloc_null_profile(profile, 1);
1513 + sa.base.info = "failed null profile create";
1514 + sa.base.error = -ENOMEM;
1518 + sa.name = hat->fqname;
1519 + if (!PROFILE_IS_HAT(hat)) {
1520 + sa.base.info = "target not hat";
1521 + sa.base.error = -EPERM;
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;
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,
1541 + } else if (name && !sa.base.error)
1542 + /* reset error for learning of new hats */
1543 + sa.base.error = -ENOENT;
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;
1551 + ignore restores when there is no saved profile
1556 + sa.base.error = aa_audit_file(profile, &sa);
1560 + aa_put_profile(hat);
1563 + return sa.base.error;
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
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
1577 + * Returns %0 on success, error otherwise.
1579 +int aa_change_profile(const char *ns_name, const char *fqname, int onexec,
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;
1588 + if (!fqname && !ns_name)
1591 + memset(&sa, 0, sizeof(sa));
1592 + sa.request = AA_MAY_CHANGE_PROFILE;
1593 + sa.base.gfp_mask = GFP_KERNEL;
1595 + sa.base.operation = "change_onexec";
1597 + sa.base.operation = "change_profile";
1599 + cred = aa_current_policy(&profile);
1600 + cxt = cred->security;
1603 + sa.name2 = ns_name;
1604 + ns = aa_find_namespace(ns_name);
1606 + /* we don't create new namespace in complain mode */
1607 + sa.base.info = "namespace not found";
1608 + sa.base.error = -ENOENT;
1612 + ns = aa_get_namespace(cxt->sys.profile->ns);
1613 + sa.name2 = ns->base.name;
1616 + /* if the name was not specified, use the name of the current profile */
1619 + fqname = ns->unconfined->fqname;
1621 + fqname = profile->fqname;
1625 + sa.perms = change_profile_perms(profile, ns, fqname, NULL);
1626 + if (!(sa.perms.allowed & AA_MAY_CHANGE_PROFILE)) {
1627 + sa.base.error = -EACCES;
1631 + target = aa_find_profile_by_fqname(ns, fqname);
1633 + sa.base.info = "profile not found";
1634 + sa.base.error = -ENOENT;
1635 + if (permtest || !PROFILE_COMPLAIN(profile))
1637 + target = aa_alloc_null_profile(profile, 0);
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";
1651 + sa.base.error = aa_set_current_onexec(target);
1653 + sa.base.error = aa_replace_current_profiles(target);
1657 + sa.base.error = aa_audit_file(profile, &sa);
1659 + aa_put_namespace(ns);
1660 + aa_put_profile(target);
1662 + return sa.base.error;
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
1669 + * AppArmor security module
1671 + * This file contains AppArmor mediation of files
1673 + * Copyright (C) 1998-2008 Novell/SUSE
1674 + * Copyright 2009 Canonical Ltd.
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
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"
1689 +struct file_perms nullperms;
1691 +static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
1692 + u16 mask, u16 xindex)
1695 + /* const char xchar[] = "PpCc";*/
1699 + if (mask & AA_EXEC_MMAP)
1701 + if (mask & MAY_READ)
1703 + if (mask & (MAY_WRITE | AA_MAY_CREATE))
1705 + else if (mask & MAY_APPEND)
1707 + if (mask & AA_MAY_LINK)
1709 + if (mask & AA_MAY_LOCK)
1711 + if (mask & MAY_EXEC) {
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) {
1721 + } else if (xindex & AA_X_UNCONFINED) {
1722 + if (xindex & AA_X_UNSAFE)
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);
1739 +static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
1740 + u16 mask, int xindex, int owner)
1742 +/* char str[18]; */
1745 + aa_audit_file_sub_mask(ab, str, mask, xindex);
1747 + audit_log_format(ab, " %s=\"%s::\"", name, str);
1749 + audit_log_format(ab, " %s=\"::%s\"", name, str);
1752 +void file_audit_cb(struct audit_buffer *ab, void *va)
1754 + struct aa_audit_file *sa = va;
1755 + u16 denied = sa->request & ~sa->perms.allowed;
1758 + if (sa->base.task)
1759 + fsuid = task_uid(sa->base.task);
1761 + fsuid = current_fsuid();
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);
1767 + if (denied & AA_AUDIT_FILE_MASK)
1768 + aa_audit_file_mask(ab, "denied_mask", denied, sa->perms.xindex,
1769 + fsuid == sa->cond->uid);
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);
1777 + audit_log_format(ab, " name=");
1778 + audit_log_untrustedstring(ab, sa->name);
1782 + audit_log_format(ab, " name2=");
1783 + audit_log_untrustedstring(ab, sa->name2);
1787 + audit_log_format(ab, " name3=");
1788 + audit_log_untrustedstring(ab, sa->name3);
1792 +int aa_audit_file(struct aa_profile *profile, struct aa_audit_file *sa)
1794 + int type = AUDIT_APPARMOR_AUTO;
1796 + if (likely(!sa->base.error)) {
1797 + u16 mask = sa->perms.audit;
1799 + if (unlikely(PROFILE_AUDIT_MODE(profile) == AUDIT_ALL))
1802 + /* mask off perms that are not being force audited */
1803 + sa->request &= mask;
1805 + if (likely(!sa->request))
1807 + type = AUDIT_APPARMOR_AUDIT;
1809 + /* quiet auditing of specific known rejects */
1810 + u16 mask = sa->perms.quiet;
1811 + u16 denied = sa->request & ~sa->perms.allowed;
1813 + if (denied & sa->perms.kill)
1814 + type = AUDIT_APPARMOR_KILL;
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)
1823 + return PROFILE_COMPLAIN(profile) ? 0 : sa->base.error;
1825 + return aa_audit(type, profile, (struct aa_audit *)sa, file_audit_cb);
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)
1832 + struct file_perms perms;
1834 + /* FIXME: change over to new dfa format */
1835 + /* currently file perms are encoded in the dfa */
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);
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);
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;
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
1858 + if (perms.allowed & AA_MAY_LOCK)
1859 + perms.allowed |= AA_LINK_SUBSET;
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;
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)
1872 + unsigned int state;
1876 + state = aa_dfa_match(dfa, start, name);
1881 + /* TODO: convert to new dfa format */
1883 + return aa_compute_perms(dfa, state, cond);
1886 +int aa_pathstr_perm(struct aa_profile *profile, const char *op,
1887 + const char *name, u16 request, struct path_cond *cond)
1889 + struct aa_audit_file sa;
1891 + memset(&sa, 0, sizeof(sa));
1892 + sa.base.operation = op;
1893 + sa.base.gfp_mask = GFP_KERNEL;
1894 + sa.request = request;
1898 + sa.perms = aa_str_perms(profile->file.dfa, DFA_START, sa.name, cond,
1900 + if (request & ~sa.perms.allowed)
1901 + sa.base.error = -EACCES;
1902 + return aa_audit_file(profile, &sa);
1905 +int aa_path_perm(struct aa_profile *profile, const char *operation,
1906 + struct path *path, u16 request, struct path_cond *cond)
1908 + struct aa_audit_file sa;
1909 + char *buffer, *name;
1911 + memset(&sa, 0, sizeof(sa));
1912 + sa.base.operation = operation;
1913 + sa.base.gfp_mask = GFP_KERNEL;
1914 + sa.request = request;
1917 + sa.base.error = aa_get_name(path, S_ISDIR(cond->mode), &buffer,
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";
1929 + sa.base.info = "Failed name lookup";
1931 + sa.perms = aa_str_perms(profile->file.dfa, DFA_START, sa.name,
1933 + if (request & ~sa.perms.allowed)
1934 + sa.base.error = -EACCES;
1936 + sa.base.error = aa_audit_file(profile, &sa);
1939 + return sa.base.error;
1942 +int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
1943 + struct path *new_dir, struct dentry *new_dentry)
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;
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;
1960 + sa.perms = nullperms;
1962 + sa.base.error = aa_get_name(&link, 0, &buffer, &lname);
1964 + if (sa.base.error)
1967 + sa.base.error = aa_get_name(&target, 0, &buffer2, &tname);
1969 + if (sa.base.error)
1973 + sa.perms = aa_str_perms(profile->file.dfa, DFA_START, sa.name, &cond,
1975 + sa.perms.audit &= AA_MAY_LINK;
1976 + sa.perms.quiet &= AA_MAY_LINK;
1977 + sa.perms.kill &= AA_MAY_LINK;
1979 + if (!(sa.perms.allowed & AA_MAY_LINK)) {
1980 + sa.base.error = -EACCES;
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";
1993 + /* done if link subset test is not required */
1994 + if (!(perms.allowed & AA_LINK_SUBSET))
1997 + /* Do link perm subset test requiring allowed permission on link are a
1998 + * subset of the allowed permissions on target.
2000 + perms = aa_str_perms(profile->file.dfa, DFA_START, sa.name2, &cond,
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;
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";
2023 + sa.base.error = aa_audit_file(profile, &sa);
2027 + return sa.base.error;
2031 +static inline int aa_is_deleted_file(struct dentry *dentry)
2033 + if (d_unhashed(dentry))
2038 +int aa_file_common_perm(struct aa_profile *profile, const char *operation,
2039 + struct file *file, u16 request, const char *name,
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;
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;
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
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";
2070 + sa.base.info = "Failed name lookup";
2072 + sa.perms = aa_str_perms(profile->file.dfa, DFA_START, sa.name,
2074 + if (request & ~sa.perms.allowed)
2075 + sa.base.error = -EACCES;
2077 + sa.base.error = aa_audit_file(profile, &sa);
2079 + return sa.base.error;
2082 +int aa_file_perm(struct aa_profile *profile, const char *operation,
2083 + struct file *file, u16 request)
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);
2089 + error = aa_file_common_perm(profile, operation, file, request, name,
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
2099 +# Generated include files
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
2108 + * AppArmor security module
2110 + * This file contains AppArmor filesystem definitions.
2112 + * Copyright (C) 1998-2008 Novell/SUSE
2113 + * Copyright 2009 Canonical Ltd.
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
2121 +#ifndef __AA_APPARMORFS_H
2122 +#define __AA_APPARMORFS_H
2124 +extern struct dentry *apparmorfs_null;
2125 +extern struct vfsmount *apparmorfs_mnt;
2127 +extern int create_apparmorfs(void);
2128 +extern void destroy_apparmorfs(void);
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
2136 + * AppArmor security module
2138 + * This file contains AppArmor basic global and lib definitions
2140 + * Copyright (C) 1998-2008 Novell/SUSE
2141 + * Copyright 2009 Canonical Ltd.
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
2149 +#ifndef __APPARMOR_H
2150 +#define __APPARMOR_H
2152 +#include <linux/fs.h>
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;
2165 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
2166 + * which is not related to profile accesses.
2169 +#define AA_DEBUG(fmt, args...) \
2171 + if (g_apparmor_debug && printk_ratelimit()) \
2172 + printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
2175 +#define AA_ERROR(fmt, args...) \
2177 + if (printk_ratelimit()) \
2178 + printk(KERN_ERR "AppArmor: " fmt, ##args); \
2181 +/* Flag indicating whether initialization completed */
2182 +extern int apparmor_initialized;
2183 +void apparmor_disable(void);
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);
2193 +static inline int mediated_filesystem(struct inode *inode)
2195 + return !(inode->i_sb->s_flags & MS_NOUSER);
2198 +#endif /* __APPARMOR_H */
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
2205 + * AppArmor security module
2207 + * This file contains AppArmor auditing function definitions.
2209 + * Copyright (C) 1998-2008 Novell/SUSE
2210 + * Copyright 2009 Canonical Ltd.
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
2218 +#ifndef __AA_AUDIT_H
2219 +#define __AA_AUDIT_H
2221 +#include <linux/audit.h>
2222 +#include <linux/fs.h>
2223 +#include <linux/sched.h>
2224 +#include <linux/slab.h>
2229 +extern const char *audit_mode_names[];
2230 +#define AUDIT_MAX_INDEX 5
2232 +#define AUDIT_APPARMOR_AUTO 0 /* auto choose audit message type */
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 */
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.
2248 + struct task_struct *task;
2251 + const char *operation;
2255 +int aa_audit(int type, struct aa_profile *profile, struct aa_audit *sa,
2256 + void(*cb)(struct audit_buffer *, void *));
2258 +int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp, const char *,
2259 + void(*cb)(struct audit_buffer *, void *));
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
2268 + * AppArmor security module
2270 + * This file contains AppArmor capability mediation definitions.
2272 + * Copyright (C) 1998-2008 Novell/SUSE
2273 + * Copyright 2009 Canonical Ltd.
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
2281 +#ifndef __AA_CAPABILITY_H
2282 +#define __AA_CAPABILITY_H
2284 +#include <linux/sched.h>
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
2296 + kernel_cap_t allowed;
2297 + kernel_cap_t audit;
2298 + kernel_cap_t quiet;
2299 + kernel_cap_t kill;
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,
2306 +static inline void aa_free_cap_rules(struct aa_caps *caps)
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
2317 + * AppArmor security module
2319 + * This file contains AppArmor contexts used to associate "labels" to objects.
2321 + * Copyright (C) 1998-2008 Novell/SUSE
2322 + * Copyright 2009 Canonical Ltd.
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
2330 +#ifndef __AA_CONTEXT_H
2331 +#define __AA_CONTEXT_H
2333 +#include <linux/cred.h>
2334 +#include <linux/slab.h>
2335 +#include <linux/sched.h>
2337 +#include "policy.h"
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
2344 +struct aa_file_cxt {
2345 + struct aa_profile *profile;
2349 +static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp)
2351 + return kzalloc(sizeof(struct aa_file_cxt), gfp);
2354 +static inline void aa_free_file_context(struct aa_file_cxt *cxt)
2356 + aa_put_profile(cxt->profile);
2357 + memset(cxt, 0, sizeof(struct aa_file_cxt));
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
2371 + * Contains the task's current profile (which could change due to
2372 + * change_hat). Plus the hat_magic needed during change_hat.
2374 +struct aa_task_cxt_group {
2375 + struct aa_profile *profile;
2376 + struct aa_profile *onexec;
2377 + struct aa_profile *previous;
2382 + * struct aa_task_context - primary label for confined tasks
2383 + * @sys: the system labeling for the task
2385 + * A task is confined by the intersection of its system and user profiles
2387 +struct aa_task_context {
2388 + struct aa_task_cxt_group sys;
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,
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);
2405 +static inline struct aa_task_context *__aa_task_cxt(struct task_struct *task)
2407 + return __task_cred(task)->security;
2411 + * __aa_task_is_confined - determine if @task has any confinement
2412 + * @task: task to check confinement of
2414 + * If @task != current needs to be in RCU safe critical section
2416 +static inline int __aa_task_is_confined(struct task_struct *task)
2418 + struct aa_task_context *cxt;
2421 + cxt = __aa_task_cxt(task);
2422 + if (!cxt || (cxt->sys.profile->flags & PFLAG_UNCONFINED))
2428 +static inline const struct cred *aa_current_policy(struct aa_profile **sys)
2430 + const struct cred *cred = current_cred();
2431 + struct aa_task_context *cxt = cred->security;
2433 + *sys = aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
2438 +static inline const struct cred *aa_current_policy_wupd(struct aa_profile **sys)
2440 + const struct cred *cred = current_cred();
2441 + struct aa_task_context *cxt = cred->security;
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);
2452 +static inline struct aa_profile *aa_current_profile(void)
2454 + const struct cred *cred = current_cred();
2455 + struct aa_task_context *cxt = cred->security;
2457 + return aa_filtered_profile(aa_profile_newest(cxt->sys.profile));
2460 +static inline struct aa_profile *aa_current_profile_wupd(void)
2462 + struct aa_profile *p;
2463 + aa_current_policy_wupd(&p);
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
2474 + * AppArmor security module
2476 + * This file contains AppArmor security domain transition function definitions.
2478 + * Copyright (C) 1998-2008 Novell/SUSE
2479 + * Copyright 2009 Canonical Ltd.
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
2487 +#include <linux/binfmts.h>
2488 +#include <linux/types.h>
2490 +#ifndef __AA_DOMAIN_H
2491 +#define __AA_DOMAIN_H
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);
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,
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
2515 + * AppArmor security module
2517 + * This file contains AppArmor file mediation function definitions.
2519 + * Copyright (C) 1998-2008 Novell/SUSE
2520 + * Copyright 2009 Canonical Ltd.
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
2528 +#ifndef __AA_FILE_H
2529 +#define __AA_FILE_H
2531 +#include <linux/path.h>
2534 +#include "domain.h"
2540 + * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags
2541 + * for profile permissions
2543 +#define AA_MAY_LINK 0x0010
2544 +#define AA_MAY_LOCK 0x0020
2545 +#define AA_EXEC_MMAP 0x0040
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*/
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
2557 +#define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\
2558 + AA_MAY_LINK | AA_MAY_LOCK | AA_EXEC_MMAP | \
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
2567 +#define AA_X_INDEX_MASK 0x03ff
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# */
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
2581 +/* AA_SECURE_X_NEEDED - is passed in the bprm->unsafe field */
2582 +#define AA_SECURE_X_NEEDED 0x8000
2584 +/* need to conditionalize which ones are being set */
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
2598 + * The @audit and @queit mask should be mutually exclusive.
2600 +struct file_perms {
2609 +extern struct file_perms nullperms;
2611 +#define COMBINED_PERM_MASK(X) ((X).allowed | (X).audit | (X).quiet | (X).kill)
2613 +/* FIXME: split perms from dfa and match this to description
2614 + * also add delegation info.
2616 +static inline u16 dfa_map_xindex(u16 mask)
2618 + u16 old_index = (mask >> 10) & 0xf;
2621 +//printk("mask x%x\n", mask);
2623 + index |= AA_X_UNSAFE;
2625 + index |= AA_X_INHERIT;
2627 + index |= AA_X_UNCONFINED;
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;
2636 + index |= AA_X_TABLE;
2637 + index |= old_index - 4;
2644 + * map old dfa inline permissions to new format
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))
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)
2659 +struct aa_audit_file {
2660 + struct aa_audit base;
2663 + const char *name2;
2664 + const char *name3;
2665 + struct file_perms perms;
2667 + struct path_cond *cond;
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);
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
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.
2684 +struct aa_file_rules {
2685 + struct aa_dfa *dfa;
2686 + /* struct perms perms; */
2687 + struct aa_domain trans;
2688 + /* TODO: add delegate table */
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);
2695 +int aa_pathstr_perm(struct aa_profile *profile, const char *op,
2696 + const char *name, u16 request, struct path_cond *cond);
2698 +int aa_path_perm(struct aa_profile *profile, const char *operation,
2699 + struct path *path, u16 request, struct path_cond *cond);
2701 +int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
2702 + struct path *new_dir, struct dentry *new_dentry);
2704 +int aa_file_common_perm(struct aa_profile *profile, const char *operation,
2705 + struct file *file, u16 request, const char *name,
2708 +int aa_file_perm(struct aa_profile *profile, const char *operation,
2709 + struct file *file, u16 request);
2712 +static inline void aa_free_file_rules(struct aa_file_rules *rules)
2714 + aa_match_free(rules->dfa);
2715 + aa_free_domain_entries(&rules->trans);
2718 +#define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40))
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))
2724 + * map file flags to AppArmor permissions
2726 +static inline u16 aa_map_file_to_perms(struct file *file)
2728 + int flags = MAP_OPEN_FLAGS(file->f_flags);
2729 + u16 perms = ACC_FMODE(file->f_mode);
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;
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
2748 + * AppArmor security module
2750 + * This file contains AppArmor ipc mediation function definitions.
2752 + * Copyright (C) 1998-2008 Novell/SUSE
2753 + * Copyright 2009 Canonical Ltd.
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
2764 +#include <linux/sched.h>
2768 +int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
2769 + struct aa_profile *tracee, unsigned int mode);
2771 +int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
2772 + unsigned int mode);
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
2780 + * AppArmor security module
2782 + * This file contains AppArmor policy dfa matching engine definitions.
2784 + * Copyright (C) 1998-2008 Novell/SUSE
2785 + * Copyright 2009 Canonical Ltd.
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
2793 +#ifndef __AA_MATCH_H
2794 +#define __AA_MATCH_H
2796 +#define DFA_NOMATCH 0
2797 +#define DFA_START 1
2799 +#define DFA_VALID_PERM_MASK 0xffffffff
2800 +#define DFA_VALID_PERM2_MASK 0xffffffff
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).
2812 +#define YYTH_MAGIC 0x1B5E783D
2814 +struct table_set_header {
2815 + u32 th_magic; /* YYTH_MAGIC */
2819 + char th_version[];
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
2832 +#define YYTD_DATA8 1
2833 +#define YYTD_DATA16 2
2834 +#define YYTD_DATA32 4
2836 +struct table_header {
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))
2853 + struct table_header *tables[YYTD_ID_NXT];
2856 +#define byte_to_byte(X) (X)
2858 +#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
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]); \
2868 +static inline size_t table_size(size_t len, size_t el_size)
2870 + return ALIGN(sizeof(struct table_header) + len * el_size, 8);
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,
2881 +unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start);
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
2889 + * AppArmor security module
2891 + * This file contains AppArmor network mediation definitions.
2893 + * Copyright (C) 1998-2008 Novell/SUSE
2894 + * Copyright 2009 Canonical Ltd.
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
2905 +#include <net/sock.h>
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
2913 + u16 allowed[AF_MAX];
2914 + u16 audit[AF_MAX];
2915 + u16 quiet[AF_MAX];
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);
2922 +static inline void aa_free_net_rules(struct aa_net *new)
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
2933 + * AppArmor security module
2935 + * This file contains AppArmor basic path manipulation function definitions.
2937 + * Copyright (C) 1998-2008 Novell/SUSE
2938 + * Copyright 2009 Canonical Ltd.
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
2946 +#ifndef __AA_PATH_H
2947 +#define __AA_PATH_H
2949 +int aa_get_name_to_buffer(struct path *path, int is_dir, char *buffer, int size,
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);
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
2961 + * AppArmor security module
2963 + * This file contains AppArmor policy definitions.
2965 + * Copyright (C) 1998-2008 Novell/SUSE
2966 + * Copyright 2009 Canonical Ltd.
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
2974 +#ifndef __AA_POLICY_H
2975 +#define __AA_POLICY_H
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>
2984 +#include "apparmor.h"
2986 +#include "capability.h"
2987 +#include "domain.h"
2990 +#include "resource.h"
2992 +extern const char *profile_mode_names[];
2993 +#define APPARMOR_NAMES_MAX_INDEX 3
2995 +#define PROFILE_COMPLAIN(_profile) \
2996 + ((g_profile_mode == APPARMOR_COMPLAIN) || ((_profile) && \
2997 + (_profile)->mode == APPARMOR_COMPLAIN))
2999 +#define PROFILE_KILL(_profile) \
3000 + ((g_profile_mode == APPARMOR_KILL) || ((_profile) && \
3001 + (_profile)->mode == APPARMOR_KILL))
3003 +#define PROFILE_IS_HAT(_profile) \
3004 + ((_profile) && (_profile)->flags & PFLAG_HAT)
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.
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 */
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 */
3029 +#define AA_NEW_SID 0
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
3040 +struct aa_policy_common {
3042 + struct kref count;
3044 + struct list_head list;
3045 + struct list_head profiles;
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)
3054 +struct aa_ns_acct {
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
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.
3078 + * Namespace names must be unique and can not contain the characters :/\0
3080 + * FIXME TODO: add vserver support so a vserer gets a default namespace
3082 +struct aa_namespace {
3083 + struct aa_policy_common base;
3084 + struct aa_ns_acct acct;
3086 + struct aa_profile *unconfined;
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
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.
3113 + * The @replacedby field is write protected by the profile lock. Reads
3114 + * are assumed to be atomic, and are done without locking.
3116 + * Profiles have a hierachy where hats and children profiles keep
3117 + * a reference to their parent.
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.
3123 +struct aa_profile {
3124 + struct aa_policy_common base;
3127 + struct aa_namespace *ns;
3128 + struct aa_profile *parent;
3129 + struct aa_profile *replacedby;
3131 + struct aa_dfa *xmatch;
3134 + enum audit_mode audit;
3135 + enum profile_mode mode;
3139 + struct aa_file_rules file;
3140 + struct aa_caps caps;
3141 + struct aa_net net;
3142 + struct aa_rlimit rlimits;
3146 +extern struct list_head ns_list;
3147 +extern rwlock_t ns_list_lock;
3149 +extern struct aa_namespace *default_namespace;
3150 +extern enum profile_mode g_profile_mode;
3153 +void aa_add_profile(struct aa_policy_common *common,
3154 + struct aa_profile *profile);
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);
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);
3173 +static inline struct aa_policy_common *aa_get_common(struct aa_policy_common *c)
3176 + kref_get(&c->count);
3181 +static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
3184 + kref_get(&(ns->base.count));
3189 +static inline void aa_put_namespace(struct aa_namespace *ns)
3192 + kref_put(&ns->base.count, free_aa_namespace_kref);
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);
3221 +static inline struct aa_profile *aa_filtered_profile(struct aa_profile *profile)
3223 + if (profile->flags & PFLAG_UNCONFINED)
3229 + * aa_get_profile - increment refcount on profile @p
3232 +static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
3235 + kref_get(&(p->base.count));
3241 + * aa_put_profile - decrement refcount on profile @p
3244 +static inline void aa_put_profile(struct aa_profile *p)
3247 + kref_put(&p->base.count, free_aa_profile_kref);
3250 +static inline int PROFILE_AUDIT_MODE(struct aa_profile *profile)
3252 + if (g_apparmor_audit != AUDIT_NORMAL)
3253 + return g_apparmor_audit;
3255 + return profile->audit;
3256 + return AUDIT_NORMAL;
3259 +#endif /* __AA_POLICY_H */
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
3266 + * AppArmor security module
3268 + * This file contains AppArmor policy loading interface function definitions.
3270 + * Copyright (C) 1998-2008 Novell/SUSE
3271 + * Copyright 2009 Canonical Ltd.
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
3279 +#ifndef __POLICY_INTERFACE_H
3280 +#define __POLICY_INTERFACE_H
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);
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
3292 + * AppArmor security module
3294 + * This file contains AppArmor /proc/<pid>/attr/ interface function defintions.
3296 + * Copyright (C) 1998-2008 Novell/SUSE
3297 + * Copyright 2009 Canonical Ltd.
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
3305 +#ifndef __AA_PROCATTR_H
3306 +#define __AA_PROCATTR_H
3308 +#define AA_DO_TEST 1
3310 +int aa_getprocattr(struct aa_namespace *ns, struct aa_profile *profile,
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);
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
3322 + * AppArmor security module
3324 + * This file contains AppArmor resource limits function defintions.
3326 + * Copyright (C) 1998-2008 Novell/SUSE
3327 + * Copyright 2009 Canonical Ltd.
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
3335 +#ifndef __AA_RESOURCE_H
3336 +#define __AA_RESOURCE_H
3338 +#include <linux/resource.h>
3339 +#include <linux/sched.h>
3343 +/* struct aa_rlimit - rlimits settings for the profile
3344 + * @mask: which hard limits to set
3345 + * @limits: rlimit values that override task limits
3347 + * AppArmor rlimits are used to set confined task rlimits. Only the
3348 + * limits specified in @mask will be controlled by apparmor.
3351 + unsigned int mask;
3352 + struct rlimit limits[RLIM_NLIMITS];
3356 +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
3357 + struct rlimit *new_rlim);
3359 +void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
3361 +static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
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
3372 + * AppArmor security module
3374 + * This file contains AppArmor security identifier (sid) definitions
3376 + * Copyright 2009 Canonical Ltd.
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
3387 +#include <linux/types.h>
3391 +#define AA_ALLOC_USR_SID 1
3392 +#define AA_ALLOC_SYS_SID 0
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);
3401 +static inline u32 aa_compound_sid(u32 sys, u32 usr)
3406 +static inline u32 aa_usr_sid(u32 sid)
3408 + return sid & 0xffff0000;
3411 +static inline u32 aa_sys_sid(u32 sid)
3413 + return sid & 0xffff;
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
3422 + * AppArmor security module
3424 + * This file contains AppArmor ipc mediation
3426 + * Copyright (C) 1998-2008 Novell/SUSE
3427 + * Copyright 2009 Canonical Ltd.
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
3435 +#include <linux/gfp.h>
3436 +#include <linux/ptrace.h>
3438 +#include "include/audit.h"
3439 +#include "include/capability.h"
3440 +#include "include/context.h"
3441 +#include "include/policy.h"
3444 +struct aa_audit_ptrace {
3445 + struct aa_audit base;
3447 + pid_t tracer, tracee;
3450 +/* call back to audit ptrace fields */
3451 +static void audit_cb(struct audit_buffer *ab, void *va)
3453 + struct aa_audit_ptrace *sa = va;
3454 + audit_log_format(ab, " tracer=%d tracee=%d", sa->tracer, sa->tracee);
3457 +static int aa_audit_ptrace(struct aa_profile *profile,
3458 + struct aa_audit_ptrace *sa)
3460 + return aa_audit(AUDIT_APPARMOR_AUTO, profile, (struct aa_audit *)sa,
3464 +int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
3465 + struct aa_profile *tracee, unsigned int mode)
3467 + /* TODO: currently only based on capability, not extended ptrace
3469 + * Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
3472 + if (!tracer || tracer == tracee)
3474 + /* log this capability request */
3475 + return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1);
3478 +int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
3479 + unsigned int mode)
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
3491 + struct aa_profile *tracer_p;
3492 + const struct cred *cred = aa_get_task_policy(tracer, &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
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,
3511 + struct aa_profile *tracee_p;
3512 + struct cred *lcred = aa_get_task_policy(tracee,
3515 + sa.base.error = aa_may_ptrace(tracer, tracer_p,
3517 + sa.base.error = aa_audit_ptrace(tracer_p, &sa);
3521 + error = sa.base.error;
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
3531 +config SECURITY_APPARMOR
3532 + bool "AppArmor support"
3533 + depends on SECURITY && SECURITY_NETWORK && NET && INET
3535 + select SECURITY_PATH
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>
3544 + If you are unsure how to answer this question, answer N.
3546 +config SECURITY_APPARMOR_NETWORK
3547 + bool "AppArmor network support"
3548 + depends on SECURITY_APPARMOR
3551 + This enables AppArmor to mediate applications network use.
3552 + This will enable the SECURITY_NETWORK hooks.
3554 +config SECURITY_APPARMOR_BOOTPARAM_VALUE
3555 + int "AppArmor boot parameter default value"
3556 + depends on SECURITY_APPARMOR
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
3568 + If you are unsure how to answer this question, answer 1.
3570 +config SECURITY_APPARMOR_DISABLE
3571 + bool "AppArmor runtime disable"
3572 + depends on SECURITY_APPARMOR
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.
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
3589 + * AppArmor security module
3591 + * This file contains basic common functions used in AppArmor
3593 + * Copyright (C) 1998-2008 Novell/SUSE
3594 + * Copyright 2009 Canonical Ltd.
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
3602 +#include <linux/slab.h>
3603 +#include <linux/string.h>
3605 +#include "include/audit.h"
3607 +void info_message(const char *str)
3609 + struct aa_audit sa;
3610 + memset(&sa, 0, sizeof(sa));
3611 + sa.gfp_mask = GFP_KERNEL;
3613 + printk(KERN_INFO "AppArmor: %s\n", str);
3614 + if (audit_enabled)
3615 + aa_audit(AUDIT_APPARMOR_STATUS, NULL, &sa, NULL);
3618 +char *strchrnul(const char *s, int c)
3620 + for (; *s != (char)c && *s != '\0'; ++s)
3625 +char *aa_split_name_from_ns(char *args, char **ns_name)
3627 + char *name = strstrip(args);
3630 + if (args[0] == ':') {
3631 + char *split = strstrip(strchr(&args[1], ':'));
3637 + *ns_name = &args[1];
3638 + name = strstrip(split + 1);
3646 +char *new_compound_name(const char *n1, const char *n2)
3648 + char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
3650 + sprintf(name, "%s//%s", n1, n2);
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
3660 + * The @str string must be full consumed for this to be considered a match
3662 +int aa_strneq(const char *str, const char *sub, int len)
3664 + int res = strncmp(str, sub, len);
3667 + if (str[len] == 0)
3672 +const char *fqname_subname(const char *name)
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')
3681 + name = strstrip(split + 1);
3683 + for (split = strstr(name, "//"); split; split = strstr(name, "//")) {
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
3693 + * AppArmor security module
3695 + * This file contains AppArmor LSM hooks.
3697 + * Copyright (C) 1998-2008 Novell/SUSE
3698 + * Copyright 2009 Canonical Ltd.
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
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>
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"
3730 +/* Flag indicating whether initialization completed */
3731 +int apparmor_initialized;
3735 + * LSM hook functions
3739 + * prepare new aa_task_context for modification by prepare_cred block
3741 +static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
3744 + struct aa_task_context *cxt = aa_dup_task_context(old->security, gfp);
3747 + new->security = cxt;
3752 + * free the associated aa_task_context and put its profiles
3754 +static void apparmor_cred_free(struct cred *cred)
3756 + struct aa_task_context *cxt = cred->security;
3757 + cred->security = NULL;
3758 + aa_free_task_context(cxt);
3762 +static int apparmor_ptrace_may_access(struct task_struct *child,
3763 + unsigned int mode)
3765 + return aa_ptrace(current, child, mode);
3769 +static int apparmor_ptrace_traceme(struct task_struct *parent)
3771 + return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
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)
3778 + struct aa_profile *profile;
3779 + const struct cred *cred;
3782 + cred = __task_cred(target);
3783 + aa_cred_policy(cred, &profile);
3785 + *effective = cred->cap_effective;
3786 + *inheritable = cred->cap_inheritable;
3787 + *permitted = cred->cap_permitted;
3790 + *effective = cap_combine(*effective, profile->caps.set);
3791 + *effective = cap_intersect(*effective, profile->caps.allowed);
3793 + rcu_read_unlock();
3798 +static int apparmor_capable(struct task_struct *task, const struct cred *cred,
3799 + int cap, int audit)
3801 + struct aa_profile *profile;
3802 + /* cap_capable returns 0 on success, else -EPERM */
3803 + int error = cap_capable(task, cred, cap, audit);
3805 + aa_cred_policy(cred, &profile);
3806 + if (profile && (!error || cap_raised(profile->caps.set, cap)))
3807 + error = aa_capable(task, profile, cap, audit);
3812 +static int apparmor_sysctl(struct ctl_table *table, int op)
3815 + struct aa_profile *profile = aa_current_profile_wupd();
3818 + char *buffer, *name;
3825 + mask |= MAY_WRITE;
3828 + buffer = (char *)__get_free_page(GFP_KERNEL);
3833 + * TODO: convert this over to using a global or per
3834 + * namespace control instead of a hard coded /proc
3836 + name = sysctl_pathname(table, buffer, PAGE_SIZE);
3837 + if (name && name - buffer >= 5) {
3838 + struct path_cond cond = { 0, S_IFREG };
3840 + memcpy(name, "/proc", 5);
3841 + error = aa_pathstr_perm(profile, "sysctl", name, mask,
3844 + free_page((unsigned long)buffer);
3851 +static int common_perm(const char *op, struct path *path, u16 mask,
3852 + struct path_cond *cond)
3854 + struct aa_profile *profile;
3857 + profile = aa_current_profile();
3859 + error = aa_path_perm(profile, op, path, mask, cond);
3864 +static int common_perm_dentry(const char *op, struct path *dir,
3865 + struct dentry *dentry, u16 mask,
3866 + struct path_cond *cond)
3868 + struct path path = { dir->mnt, dentry };
3870 + return common_perm(op, &path, mask, cond);
3873 +static int common_perm_rm(const char *op, struct path *dir,
3874 + struct dentry *dentry, u16 mask)
3876 + struct inode *inode = dentry->d_inode;
3877 + struct path_cond cond = {};
3879 + if (!dir->mnt || !inode || !mediated_filesystem(inode))
3882 + cond.uid = inode->i_uid;
3883 + cond.mode = inode->i_mode;
3885 + return common_perm_dentry(op, dir, dentry, mask, &cond);
3888 +static int common_perm_create(const char *op, struct path *dir,
3889 + struct dentry *dentry, u16 mask, umode_t mode)
3891 + struct path_cond cond = { current_fsuid(), mode };
3893 + if (!dir->mnt || !mediated_filesystem(dir->dentry->d_inode))
3896 + return common_perm_dentry(op, dir, dentry, mask, &cond);
3899 +static int apparmor_path_unlink(struct path *dir, struct dentry *dentry)
3901 + return common_perm_rm("unlink", dir, dentry, MAY_WRITE);
3904 +static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry,
3907 + return common_perm_create("mkdir", dir, dentry, AA_MAY_CREATE, S_IFDIR);
3910 +static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry)
3912 + return common_perm_rm("rmdir", dir, dentry, MAY_WRITE);
3915 +static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
3916 + int mode, unsigned int dev)
3918 + return common_perm_create("mknod", dir, dentry, AA_MAY_CREATE, mode);
3921 +static int apparmor_path_truncate(struct path *path, loff_t length,
3922 + unsigned int time_attrs)
3924 + struct path_cond cond = { path->dentry->d_inode->i_uid,
3925 + path->dentry->d_inode->i_mode };
3927 + if (!path->mnt || !mediated_filesystem(path->dentry->d_inode))
3929 + return common_perm("truncate", path, MAY_WRITE, &cond);
3932 +static int apparmor_path_symlink(struct path *dir, struct dentry *dentry,
3933 + const char *old_name)
3935 + return common_perm_create("symlink_create", dir, dentry, AA_MAY_CREATE,
3939 +static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir,
3940 + struct dentry *new_dentry)
3942 + struct aa_profile *profile;
3945 + if (!mediated_filesystem(old_dentry->d_inode))
3948 + profile = aa_current_profile_wupd();
3950 + error = aa_path_link(profile, old_dentry, new_dir, new_dentry);
3954 +static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
3955 + struct path *new_dir, struct dentry *new_dentry)
3957 + struct aa_profile *profile;
3960 + if (!mediated_filesystem(old_dentry->d_inode))
3963 + profile = aa_current_profile_wupd();
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 };
3970 + error = aa_path_perm(profile, "rename_src", &old_path,
3971 + MAY_READ | MAY_WRITE, &cond);
3973 + error = aa_path_perm(profile, "rename_dest", &new_path,
3974 + AA_MAY_CREATE | MAY_WRITE, &cond);
3980 +static int apparmor_dentry_open(struct file *file, const struct cred *cred)
3982 + struct aa_profile *profile;
3985 + /* If in exec permission is handled by bprm hooks */
3986 + if (current->in_execve ||
3987 + !mediated_filesystem(file->f_path.dentry->d_inode))
3990 + aa_cred_policy(cred, &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 };
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;
4006 +static int apparmor_file_alloc_security(struct file *file)
4008 + file->f_security = aa_alloc_file_context(GFP_KERNEL);
4009 + if (!file->f_security)
4015 +static void apparmor_file_free_security(struct file *file)
4017 + struct aa_file_cxt *cxt = file->f_security;
4019 + aa_free_file_context(cxt);
4022 +static int apparmor_file_permission(struct file *file, int mask)
4025 + * Most basic (rw) file access is revalidated at exec.
4026 + * The revalidation done here is for parent/child hat
4029 + * Currently profile replacement does not cause revalidation
4030 + * or file revocation.
4032 + * TODO: cache profiles that have revalidated?
4034 + struct aa_file_cxt *fcxt = file->f_security;
4035 + struct aa_profile *profile, *fprofile = fcxt->profile;
4038 + if (!fprofile || !file->f_path.mnt ||
4039 + !mediated_filesystem(file->f_path.dentry->d_inode))
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);
4049 + if (profile && ((fprofile != profile) || (mask & ~fcxt->allowed)))
4050 + error = aa_file_perm(profile, "file_perm", file, mask);
4055 +static int common_file_perm(const char *op, struct file *file, u16 mask)
4057 + const struct aa_file_cxt *fcxt = file->f_security;
4058 + struct aa_profile *profile, *fprofile = fcxt->profile;
4061 + if (!fprofile || !file->f_path.mnt ||
4062 + !mediated_filesystem(file->f_path.dentry->d_inode))
4065 + profile = aa_current_profile_wupd();
4066 + if (profile && ((fprofile != profile) || (mask & ~fcxt->allowed)))
4067 + error = aa_file_perm(profile, op, file, mask);
4072 +static int apparmor_file_lock(struct file *file, unsigned int cmd)
4074 + u16 mask = AA_MAY_LOCK;
4076 + if (cmd == F_WRLCK)
4077 + mask |= MAY_WRITE;
4079 + return common_file_perm("file_lock", file, mask);
4084 + * AppArmor doesn't current use the fcntl hook.
4086 + * FIXME - these are not implemented yet - REMOVE file_fcntl hook
4087 + * NOTE: some of the file control commands are further mediated
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.
4097 +static int apparmor_file_fcntl(struct file *file, unsigned int cmd,
4098 + unsigned long arg)
4104 +static int common_mmap(struct file *file, const char *operation,
4105 + unsigned long prot, unsigned long flags)
4107 + struct dentry *dentry;
4110 + if (!file || !file->f_security)
4113 + if (prot & PROT_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;
4122 + dentry = file->f_path.dentry;
4123 + return common_file_perm(operation, file, mask);
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)
4130 + if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
4131 + struct aa_profile *profile = aa_current_profile_wupd();
4133 + /* future control check here */
4139 + return common_mmap(file, "file_mmap", prot, flags);
4142 +static int apparmor_file_mprotect(struct vm_area_struct *vma,
4143 + unsigned long reqprot, unsigned long prot)
4145 + return common_mmap(vma->vm_file, "file_mprotect", prot,
4146 + !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
4149 +static int apparmor_getprocattr(struct task_struct *task, char *name,
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;
4161 + /* task must be either querying itself, unconfined or can ptrace */
4162 + if (current != task && profile && !capable(CAP_SYS_PTRACE)) {
4165 + if (strcmp(name, "current") == 0) {
4166 + error = aa_getprocattr(ns, profile, value);
4167 + } else if (strcmp(name, "prev") == 0) {
4169 + error = aa_getprocattr(ns, prev, value);
4170 + } else if (strcmp(name, "exec") == 0) {
4172 + error = aa_getprocattr(ns, onexec, value);
4183 +static int apparmor_setprocattr(struct task_struct *task, char *name,
4184 + void *value, size_t size)
4186 + char *command, *args;
4189 + if (size == 0 || size >= PAGE_SIZE)
4192 + /* task can only write its own attributes */
4193 + if (current != task)
4197 + args[size] = '\0';
4198 + args = strstrip(args);
4199 + command = strsep(&args, " ");
4202 + while (isspace(*args))
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,
4215 + } else if (strcmp(command, "permprofile") == 0) {
4216 + error = aa_setprocattr_changeprofile(args, 0,
4218 + } else if (strcmp(command, "permipc") == 0) {
4219 + error = aa_setprocattr_permipc(args);
4221 + struct aa_audit sa;
4222 + memset(&sa, 0, sizeof(sa));
4223 + sa.operation = "setprocattr";
4224 + sa.gfp_mask = GFP_KERNEL;
4226 + sa.error = -EINVAL;
4227 + return aa_audit(AUDIT_APPARMOR_DENIED, NULL, &sa, NULL);
4229 + } else if (strcmp(name, "exec") == 0) {
4230 + error = aa_setprocattr_changeprofile(strstrip(args), 1,
4233 + /* only support the "current" and "exec" process attributes */
4241 +static int apparmor_task_setrlimit(unsigned int resource,
4242 + struct rlimit *new_rlim)
4244 + struct aa_profile *profile = aa_current_profile_wupd();
4248 + error = aa_task_setrlimit(profile, resource, new_rlim);
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;
4262 + profile = aa_current_profile();
4264 + error = aa_net_perm(profile, "socket_create", family,
4269 +static int apparmor_socket_post_create(struct socket *sock, int family,
4270 + int type, int protocol, int kern)
4272 + struct sock *sk = sock->sk;
4277 + return aa_revalidate_sk(sk, "socket_post_create");
4280 +static int apparmor_socket_bind(struct socket *sock,
4281 + struct sockaddr *address, int addrlen)
4283 + struct sock *sk = sock->sk;
4285 + return aa_revalidate_sk(sk, "socket_bind");
4288 +static int apparmor_socket_connect(struct socket *sock,
4289 + struct sockaddr *address, int addrlen)
4291 + struct sock *sk = sock->sk;
4293 + return aa_revalidate_sk(sk, "socket_connect");
4296 +static int apparmor_socket_listen(struct socket *sock, int backlog)
4298 + struct sock *sk = sock->sk;
4300 + return aa_revalidate_sk(sk, "socket_listen");
4303 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
4305 + struct sock *sk = sock->sk;
4307 + return aa_revalidate_sk(sk, "socket_accept");
4310 +static int apparmor_socket_sendmsg(struct socket *sock,
4311 + struct msghdr *msg, int size)
4313 + struct sock *sk = sock->sk;
4315 + return aa_revalidate_sk(sk, "socket_sendmsg");
4318 +static int apparmor_socket_recvmsg(struct socket *sock,
4319 + struct msghdr *msg, int size, int flags)
4321 + struct sock *sk = sock->sk;
4323 + return aa_revalidate_sk(sk, "socket_recvmsg");
4326 +static int apparmor_socket_getsockname(struct socket *sock)
4328 + struct sock *sk = sock->sk;
4330 + return aa_revalidate_sk(sk, "socket_getsockname");
4333 +static int apparmor_socket_getpeername(struct socket *sock)
4335 + struct sock *sk = sock->sk;
4337 + return aa_revalidate_sk(sk, "socket_getpeername");
4340 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
4343 + struct sock *sk = sock->sk;
4345 + return aa_revalidate_sk(sk, "socket_getsockopt");
4348 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
4351 + struct sock *sk = sock->sk;
4353 + return aa_revalidate_sk(sk, "socket_setsockopt");
4356 +static int apparmor_socket_shutdown(struct socket *sock, int how)
4358 + struct sock *sk = sock->sk;
4360 + return aa_revalidate_sk(sk, "socket_shutdown");
4364 +static struct security_operations apparmor_ops = {
4365 + .name = "apparmor",
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,
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
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,
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,
4399 +/* .file_fcntl = apparmor_file_fcntl, */
4401 + .getprocattr = apparmor_getprocattr,
4402 + .setprocattr = apparmor_setprocattr,
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,
4420 + .cred_free = apparmor_cred_free,
4421 + .cred_prepare = apparmor_cred_prepare,
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,
4428 + .task_setrlimit = apparmor_task_setrlimit,
4433 + * AppArmor sysfs module parameters
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)
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)
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)
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)
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)
4456 +/* Flag values, also controllable via /sys/module/apparmor/parameters
4457 + * We define special types as we want to do additional mediation.
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);
4466 +int g_apparmor_debug;
4467 +module_param_named(debug, g_apparmor_debug, aabool, S_IRUSR | S_IWUSR);
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);
4474 +/* Determines if audit header is included in audited messages. This
4475 + * provides more context if the audit daemon is not running
4477 +int g_apparmor_audit_header;
4478 +module_param_named(audit_header, g_apparmor_audit_header, aabool,
4479 + S_IRUSR | S_IWUSR);
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
4485 +int g_apparmor_lock_policy;
4486 +module_param_named(lock_policy, g_apparmor_lock_policy, aalockpolicy,
4487 + S_IRUSR | S_IWUSR);
4489 +/* Syscall logging mode */
4490 +int g_apparmor_logsyscall;
4491 +module_param_named(logsyscall, g_apparmor_logsyscall, aabool,
4492 + S_IRUSR | S_IWUSR);
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);
4498 +/* Boot time disable flag */
4499 +#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
4500 +#define AA_ENABLED_PERMS 0600
4502 +#define AA_ENABLED_PERMS 0400
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);
4509 +static int __init apparmor_enabled_setup(char *str)
4511 + apparmor_enabled = simple_strtol(str, NULL, 0);
4514 +__setup("apparmor=", apparmor_enabled_setup);
4516 +static int param_set_aalockpolicy(const char *val, struct kernel_param *kp)
4518 + if (__aa_task_is_confined(current))
4520 + if (g_apparmor_lock_policy)
4522 + return param_set_bool(val, kp);
4525 +static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp)
4527 + if (__aa_task_is_confined(current))
4529 + return param_get_bool(buffer, kp);
4532 +static int param_set_aabool(const char *val, struct kernel_param *kp)
4534 + if (__aa_task_is_confined(current))
4536 + return param_set_bool(val, kp);
4539 +static int param_get_aabool(char *buffer, struct kernel_param *kp)
4541 + if (__aa_task_is_confined(current))
4543 + return param_get_bool(buffer, kp);
4546 +static int param_set_aauint(const char *val, struct kernel_param *kp)
4548 + if (__aa_task_is_confined(current))
4550 + return param_set_uint(val, kp);
4553 +static int param_get_aauint(char *buffer, struct kernel_param *kp)
4555 + if (__aa_task_is_confined(current))
4557 + return param_get_uint(buffer, kp);
4560 +/* allow run time disabling of apparmor */
4561 +static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
4565 + if (!apparmor_initialized) {
4566 + apparmor_enabled = 0;
4570 + if (__aa_task_is_confined(current))
4573 + if (!apparmor_enabled)
4579 + if (strict_strtoul(val, 0, &l) || l != 0)
4582 + apparmor_enabled = 0;
4583 + apparmor_disable();
4587 +static int param_get_audit(char *buffer, struct kernel_param *kp)
4589 + if (__aa_task_is_confined(current))
4592 + if (!apparmor_enabled)
4595 + return sprintf(buffer, "%s", audit_mode_names[g_apparmor_audit]);
4598 +static int param_set_audit(const char *val, struct kernel_param *kp)
4601 + if (__aa_task_is_confined(current))
4604 + if (!apparmor_enabled)
4610 + for (i = 0; i < AUDIT_MAX_INDEX; i++) {
4611 + if (strcmp(val, audit_mode_names[i]) == 0) {
4612 + g_apparmor_audit = i;
4620 +static int param_get_mode(char *buffer, struct kernel_param *kp)
4622 + if (__aa_task_is_confined(current))
4625 + if (!apparmor_enabled)
4628 + return sprintf(buffer, "%s", profile_mode_names[g_profile_mode]);
4631 +static int param_set_mode(const char *val, struct kernel_param *kp)
4634 + if (__aa_task_is_confined(current))
4637 + if (!apparmor_enabled)
4643 + for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) {
4644 + if (strcmp(val, profile_mode_names[i]) == 0) {
4645 + g_profile_mode = i;
4655 + * AppArmor init functions
4658 +static int set_init_cxt(void)
4660 + struct cred *cred = (struct cred *) current->real_cred;
4661 + struct aa_task_context *cxt;
4663 + cxt = aa_alloc_task_context(GFP_KERNEL);
4667 + cxt->sys.profile = aa_get_profile(default_namespace->unconfined);
4668 + cred->security = cxt;
4673 +static int __init apparmor_init(void)
4677 + if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
4678 + info_message("AppArmor disabled by boot time parameter\n");
4679 + apparmor_enabled = 0;
4684 + * Activated with fs_initcall
4685 + error = create_apparmorfs();
4687 + AA_ERROR("Unable to activate AppArmor filesystem\n");
4688 + goto createfs_out;
4692 + error = alloc_default_namespace();
4694 + AA_ERROR("Unable to allocate default profile namespace\n");
4698 + error = set_init_cxt();
4700 + AA_ERROR("Failed to set context on init task\n");
4704 + error = register_security(&apparmor_ops);
4706 + AA_ERROR("Unable to register AppArmor\n");
4707 + goto register_security_out;
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");
4717 + info_message("AppArmor initialized");
4721 +register_security_out:
4722 + free_default_namespace();
4725 + destroy_apparmorfs();
4728 + apparmor_enabled = 0;
4733 +security_initcall(apparmor_init);
4735 +void apparmor_disable(void)
4737 + /* Remove and release all the profiles on the profile list. */
4738 + aa_profile_ns_list_release();
4740 + /* FIXME: cleanup profiles references on files */
4741 + free_default_namespace();
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.
4748 + synchronize_rcu();
4749 + destroy_apparmorfs();
4750 + apparmor_initialized = 0;
4752 + info_message("AppArmor protection disabled");
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
4759 +# Makefile for AppArmor Linux Security Module
4761 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
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
4767 +apparmor-$(CONFIG_SECURITY_APPARMOR_NETWORK) += net.o
4769 +clean-files: capability_names.h af_names.h
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 "};" >> $@
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 "};" >> $@
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
4788 + * AppArmor security module
4790 + * This file contains AppArmor dfa based regular expression matching engine
4792 + * Copyright (C) 1998-2008 Novell/SUSE
4793 + * Copyright 2009 Canonical Ltd.
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
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>
4807 +/* TODO: remove !!!! */
4808 +// #include <linux/fs.h>
4810 +#include "include/apparmor.h"
4811 +#include "include/match.h"
4812 +#include "include/file.h"
4814 +static void free_table(struct table_header *table)
4816 + if (is_vmalloc_addr(table))
4822 +static struct table_header *unpack_table(void *blob, size_t bsize)
4824 + struct table_header *table = NULL;
4825 + struct table_header th;
4828 + if (bsize < sizeof(struct table_header))
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);
4836 + if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
4837 + th.td_flags == YYTD_DATA8))
4840 + tsize = table_size(th.td_lolen, th.td_flags);
4841 + if (bsize < tsize)
4844 + table = kmalloc(tsize, GFP_KERNEL);
4846 + table = vmalloc(tsize);
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);
4856 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
4857 + u32, be32_to_cpu);
4864 +int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
4867 + int error = -ENOMEM;
4869 + /* get dfa table set header */
4870 + if (size < sizeof(struct table_set_header))
4873 + if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
4876 + hsize = ntohl(*(u32 *)(blob + 4));
4884 + while (size > 0) {
4885 + struct table_header *table;
4886 + table = unpack_table(blob, size);
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)
4901 + dfa->tables[table->td_id - 1] = table;
4902 + if (table->td_flags != YYTD_DATA16)
4906 + dfa->tables[table->td_id - 1] = table;
4907 + if (table->td_flags != YYTD_DATA8)
4911 + free_table(table);
4915 + blob += table_size(table->td_lolen, table->td_flags);
4916 + size -= table_size(table->td_lolen, table->td_flags);
4922 + for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
4923 + free_table(dfa->tables[i]);
4924 + dfa->tables[i] = NULL;
4930 + * verify_dfa - verify that all the transitions and states in the dfa tables
4932 + * @dfa: dfa to test
4934 + * assumes dfa has gone through the verification done by unpacking
4936 +int verify_dfa(struct aa_dfa *dfa)
4938 + size_t i, state_count, trans_count;
4939 + int error = -EPROTO;
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]))
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))
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)
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)
4967 + for (i = 0; i < state_count; i++) {
4968 + if (DEFAULT_TABLE(dfa)[i] >= state_count)
4970 + if (BASE_TABLE(dfa)[i] >= trans_count + 256)
4974 + for (i = 0; i < trans_count ; i++) {
4975 + if (NEXT_TABLE(dfa)[i] >= state_count)
4977 + if (CHECK_TABLE(dfa)[i] >= state_count)
4981 + /* verify accept permissions */
4982 + for (i = 0; i < state_count; i++) {
4983 + int mode = ACCEPT_TABLE(dfa)[i];
4985 + if (mode & ~DFA_VALID_PERM_MASK)
4987 + if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK)
4997 +struct aa_dfa *aa_match_alloc(void)
4999 + return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
5002 +void aa_match_free(struct aa_dfa *dfa)
5007 + for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
5008 + free_table(dfa->tables[i]);
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
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.
5024 + * This function will happily match again the 0 byte and only finishes
5025 + * when @len input is consumed.
5027 +unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
5028 + const char *str, int len)
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;
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];
5047 + state = def[state];
5050 + for (; len; len--) {
5051 + pos = base[state] + (u8)*str++;
5052 + if (check[pos] == state)
5053 + state = next[pos];
5055 + state = def[state];
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
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.
5072 +unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
5075 + return aa_dfa_match_len(dfa, start, str, strlen(str));
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
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.
5087 +unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
5089 + return aa_dfa_match_len(dfa, start, "", 1);
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
5097 + * AppArmor security module
5099 + * This file contains AppArmor network mediation
5101 + * Copyright (C) 1998-2008 Novell/SUSE
5102 + * Copyright 2009 Canonical Ltd.
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
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"
5116 +#include "af_names.h"
5118 +static const char *sock_type_names[] = {
5132 +struct aa_audit_net {
5133 + struct aa_audit base;
5135 + int family, type, protocol;
5139 +static void audit_cb(struct audit_buffer *ab, void *va)
5141 + struct aa_audit_net *sa = va;
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]);
5148 + audit_log_format(ab, " family=\"unknown(%d)\"",
5151 + if (sock_type_names[sa->type])
5152 + audit_log_format(ab, " sock_type=\"%s\"",
5153 + sock_type_names[sa->type]);
5155 + audit_log_format(ab, " sock_type=\"unknown(%d)\"",
5158 + audit_log_format(ab, " protocol=%d", sa->protocol);
5163 +static int aa_audit_net(struct aa_profile *profile, struct aa_audit_net *sa)
5165 + int type = AUDIT_APPARMOR_AUTO;
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)))
5172 + type = AUDIT_APPARMOR_AUDIT;
5174 + u16 quiet_mask = profile->net.quiet[sa->family];
5175 + u16 kill_mask = 0;
5176 + u16 denied = (1 << sa->type) & ~quiet_mask;
5178 + if (denied & kill_mask)
5179 + type = AUDIT_APPARMOR_KILL;
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;
5187 + return aa_audit(type, profile, (struct aa_audit *)sa, audit_cb);
5190 +int aa_net_perm(struct aa_profile *profile, char *operation,
5191 + int family, int type, int protocol)
5193 + struct aa_audit_net sa;
5196 + if ((family < 0) || (family >= AF_MAX))
5199 + if ((type < 0) || (type >= SOCK_MAX))
5202 + /* unix domain and netlink sockets are handled by ipc */
5203 + if (family == AF_UNIX || family == AF_NETLINK)
5206 + family_mask = profile->net.allowed[family];
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;
5214 + sa.protocol = protocol;
5216 + return aa_audit_net(profile, &sa);
5219 +int aa_revalidate_sk(struct sock *sk, char *operation)
5221 + struct aa_profile *profile;
5222 + struct cred *cred;
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");
5233 + cred = aa_get_task_policy(current, &profile);
5235 + error = aa_net_perm(profile, operation,
5236 + sk->sk_family, sk->sk_type,
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
5247 + * AppArmor security module
5249 + * This file contains AppArmor function for pathnames
5251 + * Copyright (C) 1998-2008 Novell/SUSE
5252 + * Copyright 2009 Canonical Ltd.
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
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>
5268 +#include "include/apparmor.h"
5269 +#include "include/path.h"
5271 +int aa_get_name_to_buffer(struct path *path, int is_dir, char *buffer, int size,
5274 + int error = d_namespace_path(path, buffer, size - is_dir, name);
5276 + if (!error && is_dir && (*name)[1] != '\0')
5278 + * Append "/" to the pathname. The root directory is a special
5279 + * case; it already ends in slash.
5281 + strcpy(&buffer[size - 2], "/");
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
5293 + * Returns an error code if the there was a failure in obtaining the
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.
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.
5304 +int aa_get_name(struct path *path, int is_dir, char **buffer, char **name)
5306 + char *buf, *str = NULL;
5313 + buf = kmalloc(size, GFP_KERNEL);
5317 + error = aa_get_name_to_buffer(path, is_dir, buf, size, &str);
5318 + if (!error || (error == -ENOENT) || (error == -ESTALE))
5323 + if (size > g_apparmor_path_max)
5324 + return -ENAMETOOLONG;
5332 +int d_namespace_path(struct path *path, char *buf, int buflen, char **name)
5334 + struct path root, tmp, ns_root = { };
5338 + read_lock(¤t->fs->lock);
5339 + root = current->fs->root;
5340 + path_get(¤t->fs->root);
5341 + read_unlock(¤t->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);
5346 + ns_root.dentry = dget(ns_root.mnt->mnt_root);
5347 + spin_unlock(&vfsmount_lock);
5348 + spin_lock(&dcache_lock);
5350 + res = __d_path(path, &tmp, buf, buflen);
5353 + /* handle error conditions - and still allow a partial path to
5355 + if (IS_ERR(res)) {
5356 + error = PTR_ERR(res);
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.
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
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)) {
5376 + } else if (tmp.dentry != ns_root.dentry && tmp.mnt != ns_root.mnt) {
5377 + /* disconnected path don return pathname starting with '/' */
5384 + spin_unlock(&dcache_lock);
5386 + path_put(&ns_root);
5391 +char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
5395 + buffer += --buflen;
5399 + int namelen = strlen(table->procname);
5401 + if (buflen < namelen + 1)
5403 + buflen -= namelen + 1;
5404 + buffer -= namelen;
5405 + memcpy(buffer, table->procname, namelen);
5407 + table = table->parent;
5412 + memcpy(buffer, "/sys", 4);
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
5421 + * AppArmor security module
5423 + * This file contains AppArmor policy manipulation functions
5425 + * Copyright (C) 1998-2008 Novell/SUSE
5426 + * Copyright 2009 Canonical Ltd.
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
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.
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.
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
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
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
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
5465 +#include <linux/slab.h>
5466 +#include <linux/spinlock.h>
5467 +#include <linux/string.h>
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"
5478 +/* list of profile namespaces and lock */
5479 +LIST_HEAD(ns_list);
5480 +DEFINE_RWLOCK(ns_list_lock);
5482 +struct aa_namespace *default_namespace;
5484 +const char *profile_mode_names[] = {
5490 +#define AA_SYS_SID 0
5491 +#define AA_USR_SID 1
5494 +static int common_init(struct aa_policy_common *common, const char *name)
5496 + common->name = kstrdup(name, GFP_KERNEL);
5497 + if (!common->name)
5499 + INIT_LIST_HEAD(&common->list);
5500 + INIT_LIST_HEAD(&common->profiles);
5501 + kref_init(&common->count);
5502 + rwlock_init(&common->lock);
5507 +static void common_free(struct aa_policy_common *common)
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);
5516 + if (!list_empty(&common->list)) {
5517 + AA_ERROR("%s: internal error, policy '%s' still on list\n",
5518 + __func__, common->name);
5522 + kfree(common->name);
5525 +static struct aa_policy_common *__common_find(struct list_head *head,
5529 + struct aa_policy_common *common;
5531 + list_for_each_entry(common, head, list) {
5532 + if (!strcmp(common->name, name))
5538 +static struct aa_policy_common *__common_find_strn(struct list_head *head,
5539 + const char *str, int len)
5541 + struct aa_policy_common *common;
5543 + list_for_each_entry(common, head, list) {
5544 + if (aa_strneq(common->name, str, len))
5552 + * Routines for AppArmor namespaces
5555 +int alloc_default_namespace(void)
5557 + struct aa_namespace *ns;
5558 + ns = alloc_aa_namespace("default");
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);
5570 +void free_default_namespace(void)
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;
5581 + * alloc_aa_namespace - allocate, initialize and return a new namespace
5582 + * @name: a preallocated name
5583 + * Returns NULL on failure.
5585 +struct aa_namespace *alloc_aa_namespace(const char *name)
5587 + struct aa_namespace *ns;
5589 + ns = kzalloc(sizeof(*ns), GFP_KERNEL);
5590 + AA_DEBUG("%s(%p)\n", __func__, ns);
5594 + if (!common_init(&ns->base, name))
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;
5602 + ns->unconfined->sid = aa_alloc_sid(AA_ALLOC_SYS_SID);
5603 + ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR |
5605 + ns->unconfined->ns = aa_get_namespace(ns);
5610 + if (ns->base.name)
5611 + kfree(ns->base.name);
5618 + * free_aa_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
5619 + * @kr: kref callback for freeing of a namespace
5621 +void free_aa_namespace_kref(struct kref *kref)
5623 + free_aa_namespace(container_of(kref, struct aa_namespace, base.count));
5627 + * free_aa_namespace - free a profile namespace
5628 + * @namespace: the namespace to free
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,
5633 +void free_aa_namespace(struct aa_namespace *ns)
5638 + common_free(&ns->base);
5640 + if (ns->unconfined && ns->unconfined->ns == ns)
5641 + ns->unconfined->ns = NULL;
5643 + aa_put_profile(ns->unconfined);
5644 + memset(ns, 0, sizeof(*ns));
5648 +struct aa_namespace *__aa_find_namespace(struct list_head *head,
5652 + return (struct aa_namespace *) __common_find(head, name);
5656 + * aa_find_namespace - look up a profile namespace on the namespace list
5657 + * @name: name of namespace to find
5659 + * Returns a pointer to the namespace on the list, or NULL if no namespace
5660 + * called @name exists.
5662 +struct aa_namespace *aa_find_namespace(const char *name)
5664 + struct aa_namespace *ns = NULL;
5666 + read_lock(&ns_list_lock);
5667 + ns = aa_get_namespace(__aa_find_namespace(&ns_list, name));
5668 + read_unlock(&ns_list_lock);
5673 +static struct aa_namespace *__aa_find_namespace_by_strn(struct list_head *head,
5677 + return (struct aa_namespace *) __common_find_strn(head, name, len);
5680 +struct aa_namespace *aa_find_namespace_by_strn(const char *name, int len)
5682 + struct aa_namespace *ns = NULL;
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);
5692 + * aa_prepare_namespace - find an existing or create a new namespace of @name
5693 + * @name: the namespace to find or add
5695 +struct aa_namespace *aa_prepare_namespace(const char *name)
5697 + struct aa_namespace *ns;
5699 + write_lock(&ns_list_lock);
5701 + ns = aa_get_namespace(__aa_find_namespace(&ns_list, name));
5703 + ns = aa_get_namespace(default_namespace);
5705 + struct aa_namespace *new_ns;
5706 + write_unlock(&ns_list_lock);
5707 + new_ns = alloc_aa_namespace(name);
5710 + write_lock(&ns_list_lock);
5711 + ns = __aa_find_namespace(&ns_list, name);
5713 + list_add(&new_ns->base.list, &ns_list);
5716 + /* raced so free the new one */
5717 + free_aa_namespace(new_ns);
5718 + aa_get_namespace(ns);
5721 + write_unlock(&ns_list_lock);
5727 + * requires profile->ns set first, takes profiles refcount
5728 + * TODO: add accounting
5730 +void __aa_add_profile(struct aa_policy_common *common,
5731 + struct aa_profile *profile)
5733 + list_add(&profile->base.list, &common->profiles);
5734 + if (!(profile->flags & PFLAG_NO_LIST_REF))
5735 + aa_get_profile(profile);
5738 +void __aa_remove_profile(struct aa_profile *profile,
5739 + struct aa_profile *replacement)
5742 + profile->replacedby = aa_get_profile(replacement);
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);
5750 +/* TODO: add accounting */
5751 +void __aa_replace_profile(struct aa_profile *profile,
5752 + struct aa_profile *replacement)
5754 + if (replacement) {
5755 + struct aa_policy_common *common;
5757 + if (profile->parent)
5758 + common = &profile->parent->base;
5760 + common = &profile->ns->base;
5762 + __aa_remove_profile(profile, replacement);
5763 + __aa_add_profile(common, replacement);
5765 + __aa_remove_profile(profile, NULL);
5769 + * __aa_profile_list_release - remove all profiles on the list and put refs
5770 + * @head: list of profiles
5772 +void __aa_profile_list_release(struct list_head *head)
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);
5781 +void __aa_remove_namespace(struct aa_namespace *ns)
5783 + struct aa_profile *unconfined = ns->unconfined;
5784 + list_del_init(&ns->base.list);
5787 + * break the ns, unconfined profile cyclic reference and forward
5788 + * all new unconfined profiles requests to the default namespace
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);
5797 + * aa_remove_namespace = Remove namespace from the list
5798 + * @ns: namespace to remove
5800 +void aa_remove_namespace(struct aa_namespace *ns)
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);
5810 + * aa_profilelist_release - remove all namespaces and all associated profiles
5812 +void aa_profile_ns_list_release(void)
5814 + struct aa_namespace *ns, *tmp;
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);
5823 + write_unlock(&ns_list_lock);
5827 + * alloc_aa_profile - allocate, initialize and return a new profile
5828 + * @fqname: name of the profile
5830 + * Returns NULL on failure.
5832 +struct aa_profile *alloc_aa_profile(const char *fqname)
5834 + struct aa_profile *profile;
5836 + profile = kzalloc(sizeof(*profile), GFP_KERNEL);
5840 + if (!common_init(&profile->base, fqname)) {
5845 + profile->fqname = profile->base.name;
5846 + profile->base.name = (char *) fqname_subname((const char *) profile->fqname);
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
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.
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
5862 +struct aa_profile *aa_alloc_null_profile(struct aa_profile *parent, int hat)
5864 + struct aa_profile *profile = NULL;
5866 + u32 sid = aa_alloc_sid(AA_ALLOC_SYS_SID);
5868 + name = kmalloc(strlen(parent->fqname) + 2 + 7 + 8, GFP_KERNEL);
5871 + sprintf(name, "%s//null-%x", parent->fqname, sid);
5873 + profile = alloc_aa_profile(name);
5878 + profile->sid = aa_alloc_sid(AA_ALLOC_SYS_SID);
5879 + profile->mode = APPARMOR_COMPLAIN;
5880 + profile->flags = PFLAG_NULL | PFLAG_NO_LIST_REF;
5882 + profile->flags |= PFLAG_HAT;
5884 + profile->parent = aa_get_profile(parent);
5885 + profile->ns = aa_get_namespace(parent->ns);
5887 + write_lock(&profile->ns->base.lock);
5888 + __aa_add_profile(&parent->base, profile);
5889 + write_unlock(&profile->ns->base.lock);
5899 + * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
5900 + * @kr: kref callback for freeing of a profile
5902 +void free_aa_profile_kref(struct kref *kref)
5904 + struct aa_profile *p = container_of(kref, struct aa_profile,
5907 + free_aa_profile(p);
5911 + * free_aa_profile - free a profile
5912 + * @profile: the profile to free
5914 + * Free a profile, its hats and null_profile. All references to the profile,
5915 + * its hats and null_profile must have been put.
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.
5920 +void free_aa_profile(struct aa_profile *profile)
5922 + AA_DEBUG("%s(%p)\n", __func__, profile);
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
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);
5937 + AA_ERROR("%s: internal error, "
5938 + "profile '%s' still on ns list\n",
5939 + __func__, profile->base.name);
5944 + /* profile->name is a substring of fqname */
5945 + profile->base.name = NULL;
5946 + common_free(&profile->base);
5948 + BUG_ON(!list_empty(&profile->base.profiles));
5950 + kfree(profile->fqname);
5952 + aa_put_namespace(profile->ns);
5953 + aa_put_profile(profile->parent);
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);
5960 + aa_free_sid(profile->sid);
5961 + aa_match_free(profile->xmatch);
5963 + if (profile->replacedby && !PTR_ERR(profile->replacedby))
5964 + aa_put_profile(profile->replacedby);
5966 + memset(profile, 0, sizeof(profile));
5971 +/* TODO: profile count accounting - setup in remove */
5974 +struct aa_profile *__aa_find_profile(struct list_head *head, const char *name)
5976 + return (struct aa_profile *) __common_find(head, name);
5979 +struct aa_profile *__aa_find_profile_by_strn(struct list_head *head,
5980 + const char *name, int len)
5982 + return (struct aa_profile *) __common_find_strn(head, name, len);
5987 + * aa_find_child - find a profile by @name in @parent
5988 + * @parent: profile to search
5989 + * @name: profile name to search for
5991 + * Returns a ref counted profile or NULL if not found
5993 +struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
5995 + struct aa_profile *profile;
5997 + read_lock(&parent->ns->base.lock);
5998 + profile = aa_get_profile(__aa_find_profile(&parent->base.profiles,
6000 + read_unlock(&parent->ns->base.lock);
6006 +struct aa_policy_common *__aa_find_parent_by_fqname(struct aa_namespace *ns,
6007 + const char *fqname)
6009 + struct aa_policy_common *common;
6010 + struct aa_profile *profile = NULL;
6013 + common = &ns->base;
6016 + for (split = strstr(fqname, "//"); split; ) {
6017 + profile = __aa_find_profile_by_strn(&common->profiles, fqname,
6021 + common = &profile->base;
6022 + fqname = split + 2;
6023 + split = strstr(fqname, "//");
6027 + return &profile->base;
6030 +struct aa_profile *__aa_find_profile_by_fqname(struct aa_namespace *ns,
6031 + const char *fqname)
6033 + struct aa_policy_common *common;
6034 + struct aa_profile *profile = NULL;
6037 + common = &ns->base;
6038 + for (split = strstr(fqname, "//"); split; ) {
6039 + profile = __aa_find_profile_by_strn(&common->profiles, fqname,
6044 + common = &profile->base;
6045 + fqname = split + 2;
6046 + split = strstr(fqname, "//");
6049 + profile = __aa_find_profile(&common->profiles, fqname);
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
6059 +struct aa_profile *aa_find_profile_by_fqname(struct aa_namespace *ns,
6060 + const char *fqname)
6062 + struct aa_profile *profile;
6064 + read_lock(&ns->base.lock);
6065 + profile = aa_get_profile(__aa_find_profile_by_fqname(ns, fqname));
6066 + read_unlock(&ns->base.lock);
6071 +/* __aa_attach_match_ - find an attachment match
6072 + * @name - to match against
6073 + * @head - profile list to walk
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.
6080 +static struct aa_profile *__aa_attach_match(const char *name,
6081 + struct list_head *head)
6084 + struct aa_profile *profile, *candidate = NULL;
6086 + list_for_each_entry(profile, head, base.list) {
6087 + if (profile->flags & PFLAG_NULL)
6089 + if (profile->xmatch && profile->xmatch_len > len) {
6090 + unsigned int state = aa_dfa_match(profile->xmatch,
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;
6098 + } else if (!strcmp(profile->base.name, name))
6099 + /* exact non-re match, no more searching required */
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
6111 +struct aa_profile *aa_sys_find_attach(struct aa_policy_common *base,
6114 + struct aa_profile *profile;
6116 + read_lock(&base->lock);
6117 + profile = aa_get_profile(__aa_attach_match(name, &base->profiles));
6118 + read_unlock(&base->lock);
6124 + * aa_profile_newest - find the newest version of @profile
6125 + * @profile: the profile to check for newer versions of
6127 + * Find the newest version of @profile, if @profile is the newest version
6128 + * return @profile. If @profile has been removed return NULL.
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
6134 +struct aa_profile *aa_profile_newest(struct aa_profile *profile)
6136 + if (unlikely(profile && profile->replacedby)) {
6137 + for (;profile->replacedby; profile = profile->replacedby) {
6138 + if (IS_ERR(profile->replacedby)) {
6139 + /* profile has been removed */
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
6154 + * AppArmor security module
6156 + * This file contains AppArmor functions for unpacking policy loaded from
6159 + * Copyright (C) 1998-2008 Novell/SUSE
6160 + * Copyright 2009 Canonical Ltd.
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
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.
6172 +#include <asm/unaligned.h>
6173 +#include <linux/errno.h>
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"
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
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.
6202 + AA_NAME, /* same as string except it is items name */
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.
6221 + void *pos; /* pointer to current position in the buffer */
6227 +struct aa_audit_iface {
6228 + struct aa_audit base;
6231 + const char *name2;
6232 + const struct aa_ext *e;
6235 +static void aa_audit_init(struct aa_audit_iface *sa, const char *operation,
6238 + memset(sa, 0, sizeof(*sa));
6239 + sa->base.operation = operation;
6240 + sa->base.gfp_mask = GFP_KERNEL;
6244 +static void audit_cb(struct audit_buffer *ab, void *va)
6246 + struct aa_audit_iface *sa = va;
6249 + audit_log_format(ab, " name=%s", sa->name);
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);
6258 +static int aa_audit_iface(struct aa_audit_iface *sa)
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,
6268 +static int aa_inbounds(struct aa_ext *e, size_t size)
6270 + return (size <= e->end - e->pos);
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
6278 + * return the size of chunk found with the read head at the end of
6281 +static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
6283 + void *pos = e->pos;
6286 + if (!aa_inbounds(e, sizeof(u16)))
6288 + size = le16_to_cpu(get_unaligned((u16 *)e->pos));
6289 + e->pos += sizeof(u16);
6290 + if (!aa_inbounds(e, size))
6301 +static int aa_is_X(struct aa_ext *e, enum aa_code code)
6303 + if (!aa_inbounds(e, 1))
6305 + if (*(u8 *) e->pos != code)
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.
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
6325 +static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
6327 + void *pos = e->pos;
6329 + * Check for presence of a tagname, and if present name size
6330 + * AA_NAME tag value is a u16.
6332 + if (aa_is_X(e, AA_NAME)) {
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)))
6338 + } else if (name) {
6339 + /* if a name is specified and there is no name tag fail */
6343 + /* now check if type code matches */
6344 + if (aa_is_X(e, code))
6352 +static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name)
6354 + void *pos = e->pos;
6355 + if (aa_is_nameX(e, AA_U16, name)) {
6356 + if (!aa_inbounds(e, sizeof(u16)))
6359 + *data = le16_to_cpu(get_unaligned((u16 *)e->pos));
6360 + e->pos += sizeof(u16);
6368 +static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
6370 + void *pos = e->pos;
6371 + if (aa_is_nameX(e, AA_U32, name)) {
6372 + if (!aa_inbounds(e, sizeof(u32)))
6375 + *data = le32_to_cpu(get_unaligned((u32 *)e->pos));
6376 + e->pos += sizeof(u32);
6384 +static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name)
6386 + void *pos = e->pos;
6387 + if (aa_is_nameX(e, AA_U64, name)) {
6388 + if (!aa_inbounds(e, sizeof(u64)))
6391 + *data = le64_to_cpu(get_unaligned((u64 *)e->pos));
6392 + e->pos += sizeof(u64);
6400 +static size_t aa_is_array(struct aa_ext *e, const char *name)
6402 + void *pos = e->pos;
6403 + if (aa_is_nameX(e, AA_ARRAY, name)) {
6405 + if (!aa_inbounds(e, sizeof(u16)))
6407 + size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos));
6408 + e->pos += sizeof(u16);
6416 +static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
6418 + void *pos = e->pos;
6419 + if (aa_is_nameX(e, AA_BLOB, name)) {
6421 + if (!aa_inbounds(e, sizeof(u32)))
6423 + size = le32_to_cpu(get_unaligned((u32 *)e->pos));
6424 + e->pos += sizeof(u32);
6425 + if (aa_inbounds(e, (size_t) size)) {
6436 +static int aa_is_string(struct aa_ext *e, char **string, const char *name)
6440 + void *pos = e->pos;
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)
6447 + *string = src_str;
6457 +static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
6460 + void *pos = e->pos;
6461 + int res = aa_is_string(e, &tmp, name);
6467 + *string = kstrdup(tmp, GFP_KERNEL);
6477 + * aa_unpack_dfa - unpack a file rule dfa
6478 + * @e: serialized data extent information
6480 + * returns dfa or ERR_PTR
6482 +static struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
6484 + char *blob = NULL;
6485 + size_t size, error = 0;
6486 + struct aa_dfa *dfa = NULL;
6488 + size = aa_is_blob(e, &blob, "aadfa");
6490 + dfa = aa_match_alloc();
6493 + * The dfa is aligned with in the blob to 8 bytes
6494 + * from the beginning of the stream.
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);
6500 + error = verify_dfa(dfa);
6506 + aa_match_free(dfa);
6507 + dfa = ERR_PTR(error);
6514 +static int aa_unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
6516 + void *pos = e->pos;
6518 + /* exec table is optional */
6519 + if (aa_is_nameX(e, AA_STRUCT, "xtable")) {
6522 + size = aa_is_array(e, NULL);
6523 + /* currently 4 exec bits and entries 0-3 are reserved iupcx */
6524 + if (size > 16 - 4)
6526 + profile->file.trans.table = kzalloc(sizeof(char *) * size,
6528 + if (!profile->file.trans.table)
6531 + for (i = 0; i < size; i++) {
6533 + if (!aa_is_dynstring(e, &tmp, NULL))
6535 + /* note: strings beginning with a : have an embedded
6536 + \0 seperating the profile ns name from the profile
6538 + profile->file.trans.table[i] = tmp;
6540 + if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
6542 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
6544 + profile->file.trans.size = size;
6553 +int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
6555 + void *pos = e->pos;
6557 + /* rlimits are optional */
6558 + if (aa_is_nameX(e, AA_STRUCT, "rlimits")) {
6561 + if (!aa_is_u32(e, &tmp, NULL))
6563 + profile->rlimits.mask = tmp;
6565 + size = aa_is_array(e, NULL);
6566 + if (size > RLIM_NLIMITS)
6568 + for (i = 0; i < size; i++) {
6570 + if (!aa_is_u64(e, &tmp, NULL))
6572 + profile->rlimits.limits[i].rlim_max = tmp;
6574 + if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
6576 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
6587 + * aa_unpack_profile - unpack a serialized profile
6588 + * @e: serialized data extent information
6589 + * @sa: audit struct for the operation
6591 +static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
6592 + struct aa_audit_iface *sa)
6594 + struct aa_profile *profile = NULL;
6597 + int i, error = -EPROTO;
6600 + /* check that we have the right struct being passed */
6601 + if (!aa_is_nameX(e, AA_STRUCT, "profile"))
6603 + if (!aa_is_string(e, &name, NULL))
6606 + profile = alloc_aa_profile(name);
6608 + return ERR_PTR(-ENOMEM);
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;
6617 + /* xmatch_len is not optional is xmatch is set */
6618 + if (profile->xmatch && !aa_is_u32(e, &tmp, NULL))
6620 + profile->xmatch_len = tmp;
6622 + /* per profile debug flags (complain, audit) */
6623 + if (!aa_is_nameX(e, AA_STRUCT, "flags"))
6625 + if (!aa_is_u32(e, &tmp, NULL))
6628 + profile->flags |= PFLAG_HAT;
6629 + if (!aa_is_u32(e, &tmp, NULL))
6632 + profile->mode = APPARMOR_COMPLAIN;
6633 + if (!aa_is_u32(e, &tmp, NULL))
6636 + profile->audit = AUDIT_ALL;
6638 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
6641 + if (!aa_is_u32(e, &(profile->caps.allowed.cap[0]), NULL))
6643 + if (!aa_is_u32(e, &(profile->caps.audit.cap[0]), NULL))
6645 + if (!aa_is_u32(e, &(profile->caps.quiet.cap[0]), NULL))
6647 + if (!aa_is_u32(e, &(profile->caps.set.cap[0]), NULL))
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))
6654 + if (!aa_is_u32(e, &(profile->caps.audit.cap[1]), NULL))
6656 + if (!aa_is_u32(e, &(profile->caps.quiet.cap[1]), NULL))
6658 + if (!aa_is_u32(e, &(profile->caps.set.cap[1]), NULL))
6660 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
6664 + if (!aa_unpack_rlimits(e, profile))
6667 + size = aa_is_array(e, "net_allowed_af");
6669 + if (size > AF_MAX)
6672 + for (i = 0; i < size; i++) {
6673 + if (!aa_is_u16(e, &profile->net.allowed[i], NULL))
6675 + if (!aa_is_u16(e, &profile->net.audit[i], NULL))
6677 + if (!aa_is_u16(e, &profile->net.quiet[i], NULL))
6680 + if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
6682 + /* allow unix domain and netlink sockets they are handled
6686 + profile->net.allowed[AF_UNIX] = 0xffff;
6687 + profile->net.allowed[AF_NETLINK] = 0xffff;
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;
6697 + if (!aa_unpack_trans_table(e, profile))
6700 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
6706 + sa->name = profile && profile->base.name ? profile->base.name :
6708 + if (!sa->base.info)
6709 + sa->base.info = "failed to unpack profile";
6710 + aa_audit_iface(sa);
6712 + free_aa_profile(profile);
6714 + return ERR_PTR(error);
6718 + * aa_verify_head - unpack serialized stream header
6719 + * @e: serialized data read head
6720 + * @operation: operation header is being verified for
6722 + * returns error or 0 if header is good
6724 +static int aa_verify_header(struct aa_ext *e, struct aa_audit_iface *sa)
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;
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;
6740 + /* read the namespace if present */
6741 + if (!aa_is_string(e, &e->ns_name, "namespace"))
6742 + e->ns_name = NULL;
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
6754 +ssize_t aa_interface_add_profiles(void *data, size_t size)
6756 + struct aa_profile *profile;
6757 + struct aa_namespace *ns = NULL;
6758 + struct aa_policy_common *common;
6759 + struct aa_ext e = {
6761 + .end = data + size,
6766 + struct aa_audit_iface sa;
6767 + aa_audit_init(&sa, "profile_load", &e);
6769 + error = aa_verify_header(&e, &sa);
6773 + profile = aa_unpack_profile(&e, &sa);
6774 + if (IS_ERR(profile))
6775 + return PTR_ERR(profile);
6777 + sa.name2 = e.ns_name;
6778 + ns = aa_prepare_namespace(e.ns_name);
6780 + sa.base.info = "failed to prepare namespace";
6781 + sa.base.error = PTR_ERR(ns);
6784 + /* profiles are currently loaded flat with fqnames */
6785 + sa.name = profile->fqname;
6787 + write_lock(&ns->base.lock);
6789 + common = __aa_find_parent_by_fqname(ns, sa.name);
6791 + sa.base.info = "parent does not exist";
6792 + sa.base.error = -ENOENT;
6796 + if (common != &ns->base)
6797 + profile->parent = aa_get_profile((struct aa_profile *) common);
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;
6805 + profile->sid = aa_alloc_sid(AA_ALLOC_SYS_SID);
6806 + profile->ns = aa_get_namespace(ns);
6808 + __aa_add_profile(common, profile);
6809 + write_unlock(&ns->base.lock);
6811 + aa_audit_iface(&sa);
6812 + aa_put_namespace(ns);
6817 + write_unlock(&ns->base.lock);
6820 + error = aa_audit_iface(&sa);
6821 + aa_put_namespace(ns);
6822 + aa_put_profile(profile);
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
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.
6836 +ssize_t aa_interface_replace_profiles(void *udata, size_t size)
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 = {
6843 + .end = udata + size,
6848 + struct aa_audit_iface sa;
6849 + aa_audit_init(&sa, "profile_replace", &e);
6851 + if (g_apparmor_lock_policy)
6854 + error = aa_verify_header(&e, &sa);
6858 + new_profile = aa_unpack_profile(&e, &sa);
6859 + if (IS_ERR(new_profile))
6860 + return PTR_ERR(new_profile);
6862 + sa.name2 = e.ns_name;
6863 + ns = aa_prepare_namespace(e.ns_name);
6865 + sa.base.info = "failed to prepare namespace";
6866 + sa.base.error = -ENOMEM;
6870 + sa.name = new_profile->fqname;
6872 + write_lock(&ns->base.lock);
6873 + common = __aa_find_parent_by_fqname(ns, sa.name);
6876 + sa.base.info = "parent does not exist";
6877 + sa.base.error = -ENOENT;
6881 + if (common != &ns->base)
6882 + new_profile->parent = aa_get_profile((struct aa_profile *)
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;
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
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,
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);
6909 + __aa_replace_profile(old_profile, new_profile);
6910 + new_profile->sid = old_profile->sid;
6912 + __aa_add_profile(common, new_profile);
6913 + new_profile->sid = aa_alloc_sid(AA_ALLOC_SYS_SID);
6916 + new_profile->ns = aa_get_namespace(ns);
6918 + write_unlock(&ns->base.lock);
6921 + sa.base.operation = "profile_load";
6923 + aa_audit_iface(&sa);
6924 + aa_put_namespace(ns);
6925 + aa_put_profile(old_profile);
6930 + write_unlock(&ns->base.lock);
6932 + error = aa_audit_iface(&sa);
6933 + aa_put_namespace(ns);
6934 + aa_put_profile(old_profile);
6935 + aa_put_profile(new_profile);
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
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
6949 +ssize_t aa_interface_remove_profiles(char *name, size_t size)
6951 + struct aa_namespace *ns;
6952 + struct aa_profile *profile;
6953 + struct aa_audit_iface sa;
6954 + aa_audit_init(&sa, "profile_remove", NULL);
6956 + if (g_apparmor_lock_policy)
6959 + write_lock(&ns_list_lock);
6960 + if (name[0] == ':') {
6962 + name = aa_split_name_from_ns(name, &ns_name);
6963 + ns = __aa_find_namespace(&ns_list, ns_name);
6965 + ns = aa_get_namespace(default_namespace);
6969 + sa.base.info = "failed: namespace does not exist";
6970 + goto fail_ns_list_lock;
6973 + sa.name2 = ns->base.name;
6974 + write_lock(&ns->base.lock);
6976 + /* remove namespace */
6977 + // __aa_remove_namespace(ns);
6979 + /* remove profile */
6980 + profile = __aa_find_profile_by_fqname(ns, name);
6983 + sa.base.info = "failed: profile does not exist";
6984 + goto fail_ns_lock;
6986 + sa.name = profile->fqname;
6987 + __aa_profile_list_release(&profile->base.profiles);
6988 + __aa_remove_profile(profile, profile->ns->unconfined);
6990 + write_unlock(&ns->base.lock);
6991 + write_unlock(&ns_list_lock);
6993 + aa_audit_iface(&sa);
6994 + aa_put_namespace(ns);
6998 + write_unlock(&ns->base.lock);
7001 + write_unlock(&ns_list_lock);
7002 + aa_audit_iface(&sa);
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
7010 + * AppArmor security module
7012 + * This file contains AppArmor /proc/<pid>/attr/ interface functions
7014 + * Copyright (C) 1998-2008 Novell/SUSE
7015 + * Copyright 2009 Canonical Ltd.
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
7023 +#include "include/apparmor.h"
7024 +#include "include/policy.h"
7025 +#include "include/domain.h"
7027 +/* FIXME show profile multiplexing */
7028 +int aa_getprocattr(struct aa_namespace *ns, struct aa_profile *profile,
7035 + int mode_len, name_len, ns_len = 0;
7036 + const char *mode_str = profile_mode_names[profile->mode];
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);
7049 + sprintf(s, "%s://", ns->base.name);
7052 + memcpy(s, profile->fqname, name_len);
7054 + sprintf(s, " (%s)\n", mode_str);
7056 + const char *unconfined_str = "unconfined\n";
7058 + len = strlen(unconfined_str);
7059 + if (ns != default_namespace)
7060 + len += strlen(ns->base.name) + 3; /* :// */
7062 + str = kmalloc(len + 1, GFP_ATOMIC);
7066 + if (ns != default_namespace)
7067 + sprintf(str, "%s://%s", ns->base.name, unconfined_str);
7069 + memcpy(str, unconfined_str, len);
7076 +static char *split_token_from_name(const char *op, char *args, u64 *token)
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);
7086 + name++; /* skip ^ */
7092 +int aa_setprocattr_changehat(char *args, int test)
7097 + hat = split_token_from_name("change_hat", args, &token);
7099 + return PTR_ERR(hat);
7101 + if (!hat && !token) {
7102 + AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
7106 + AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
7107 + __func__, token, hat ? hat : NULL);
7109 + return aa_change_hat(hat, token, test);
7112 +int aa_setprocattr_changeprofile(char *args, int onexec, int test)
7114 + char *name, *ns_name;
7116 + name = aa_split_name_from_ns(args, &ns_name);
7117 + return aa_change_profile(ns_name, name, onexec, test);
7121 +int aa_setprocattr_permipc(char *args)
7123 + /* TODO: add ipc permission querying */
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
7131 + * AppArmor security module
7133 + * This file contains AppArmor resource mediation and attachment
7135 + * Copyright (C) 1998-2008 Novell/SUSE
7136 + * Copyright 2009 Canonical Ltd.
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
7144 +#include <linux/audit.h>
7146 +#include "include/audit.h"
7147 +#include "include/resource.h"
7148 +#include "include/policy.h"
7150 +struct aa_audit_resource {
7151 + struct aa_audit base;
7156 +static void audit_cb(struct audit_buffer *ab, void *va)
7158 + struct aa_audit_resource *sa = va;
7161 + audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
7164 +static int aa_audit_resource(struct aa_profile *profile,
7165 + struct aa_audit_resource *sa)
7167 + return aa_audit(AUDIT_APPARMOR_AUTO, profile, (struct aa_audit *)sa,
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
7177 + * Control raising the processes hard limit.
7179 +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
7180 + struct rlimit *new_rlim)
7182 + struct aa_audit_resource sa;
7185 + memset(&sa, 0, sizeof(sa));
7186 + sa.base.operation = "setrlimit";
7187 + sa.base.gfp_mask = GFP_KERNEL;
7188 + sa.rlimit = resource + 1;
7190 + if (profile->rlimits.mask & (1 << resource) &&
7191 + new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
7192 + sa.base.error = -EACCES;
7194 + error = aa_audit_resource(profile, &sa);
7200 +void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new)
7202 + unsigned int mask = 0;
7203 + struct rlimit *rlim, *initrlim;
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
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);
7220 + /* set any new hard limits as dictated by the new profile */
7221 + if (!(new && new->rlimits.mask))
7223 + for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<=1) {
7224 + if (!(new->rlimits.mask & mask))
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);
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
7239 + * AppArmor security module
7241 + * This file contains AppArmor security identifier (sid) manipulation fns
7243 + * Copyright 2009 Canonical Ltd.
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
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.
7256 + * The sid value of 0 is invalid for system sids and is used to indicate
7257 + * unconfined for user sids.
7259 + * A compound sid is a pair of user and system sids that is used to identify
7260 + * both profiles confining a task.
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.
7267 +#include <linux/spinlock.h>
7268 +#include <linux/errno.h>
7269 +#include <linux/err.h>
7271 +#include "include/sid.h"
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);
7279 +/* TODO FIXME: add sid to profile mapping, and sid recycling */
7283 + * aa_alloc_sid - allocate a new sid for a profile
7284 + * @is_usr: true if the new sid is a user based sid
7286 +u32 aa_alloc_sid(int is_usr)
7291 + * TODO FIXME: sid recycling - part of profile mapping table
7293 + spin_lock(&sid_lock);
7295 + sid = (++global_usr_sid) << 16;
7298 + sid = ++global_sys_sid;
7300 + spin_unlock(&sid_lock);
7305 + * aa_free_sid - free a sid
7306 + * @sid: sid to free
7308 +void aa_free_sid(u32 sid)
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
7318 + * return 0 or error
7320 +int aa_add_sid_profile(u32 sid, struct aa_profile *profile)
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
7331 + * return 0 or error
7333 +int aa_replace_sid_profile(u32 sid, struct aa_profile *profile)
7340 + * aa_get_sid_profile - get the profile associated with the sid
7341 + * @sid: sid to lookup
7343 + * returns - the profile, or NULL for unconfined user.
7344 + * - if there is an error -ENOENT, -EINVAL
7346 +struct aa_profile *aa_get_sid_profile(u32 sid)
7348 + return ERR_PTR(-EINVAL);