1 diff --git a/include/linux/audit.h b/include/linux/audit.h
2 index 3c7a358..a1db25b 100644
3 --- a/include/linux/audit.h
4 +++ b/include/linux/audit.h
6 * 1200 - 1299 messages internal to the audit daemon
7 * 1300 - 1399 audit event messages
8 * 1400 - 1499 SE Linux use
9 - * 1500 - 1599 kernel LSPP events
10 + * 1500 - 1599 AppArmor use
11 * 1600 - 1699 kernel crypto events
12 * 1700 - 1799 kernel anomaly records
13 * 1800 - 1899 kernel integrity events
15 #define AUDIT_MAC_UNLBL_STCADD 1416 /* NetLabel: add a static label */
16 #define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */
18 +#define AUDIT_APPARMOR_AUDIT 1501 /* AppArmor audited grants */
19 +#define AUDIT_APPARMOR_ALLOWED 1502 /* Allowed Access for learning */
20 +#define AUDIT_APPARMOR_DENIED 1503
21 +#define AUDIT_APPARMOR_HINT 1504 /* Process Tracking information */
22 +#define AUDIT_APPARMOR_STATUS 1505 /* Changes in config */
23 +#define AUDIT_APPARMOR_ERROR 1506 /* Internal AppArmor Errors */
24 +#define AUDIT_APPARMOR_KILL 1507 /* AppArmor killing processes */
26 #define AUDIT_FIRST_KERN_ANOM_MSG 1700
27 #define AUDIT_LAST_KERN_ANOM_MSG 1799
28 #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
29 diff --git a/security/Kconfig b/security/Kconfig
30 index 226b955..bd72ae6 100644
31 --- a/security/Kconfig
32 +++ b/security/Kconfig
33 @@ -140,6 +140,7 @@ config LSM_MMAP_MIN_ADDR
34 source security/selinux/Kconfig
35 source security/smack/Kconfig
36 source security/tomoyo/Kconfig
37 +source security/apparmor/Kconfig
39 source security/integrity/ima/Kconfig
41 @@ -148,6 +149,7 @@ choice
42 default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX
43 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
44 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
45 + default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
46 default DEFAULT_SECURITY_DAC
49 @@ -163,6 +165,9 @@ choice
50 config DEFAULT_SECURITY_TOMOYO
51 bool "TOMOYO" if SECURITY_TOMOYO=y
53 + config DEFAULT_SECURITY_APPARMOR
54 + bool "AppArmor" if SECURITY_APPARMOR=y
56 config DEFAULT_SECURITY_DAC
57 bool "Unix Discretionary Access Controls"
59 @@ -173,6 +178,7 @@ config DEFAULT_SECURITY
60 default "selinux" if DEFAULT_SECURITY_SELINUX
61 default "smack" if DEFAULT_SECURITY_SMACK
62 default "tomoyo" if DEFAULT_SECURITY_TOMOYO
63 + default "apparmor" if DEFAULT_SECURITY_APPARMOR
64 default "" if DEFAULT_SECURITY_DAC
67 diff --git a/security/Makefile b/security/Makefile
68 index da20a19..8bb0fe9 100644
69 --- a/security/Makefile
70 +++ b/security/Makefile
71 @@ -6,6 +6,7 @@ obj-$(CONFIG_KEYS) += keys/
72 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
73 subdir-$(CONFIG_SECURITY_SMACK) += smack
74 subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
75 +subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
77 # always enable default capabilities
79 @@ -19,6 +20,7 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
80 obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
81 obj-$(CONFIG_AUDIT) += lsm_audit.o
82 obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
83 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o
84 obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
86 # Object integrity file lists
87 diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
89 index 0000000..0a0a99f
91 +++ b/security/apparmor/.gitignore
94 +# Generated include files
98 diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
100 index 0000000..5c57df7
102 +++ b/security/apparmor/Kconfig
104 +config SECURITY_APPARMOR
105 + bool "AppArmor support"
106 + depends on SECURITY
108 + select SECURITY_PATH
110 + select SECURITY_NETWORK
113 + This enables the AppArmor security module.
114 + Required userspace tools (if they are not included in your
115 + distribution) and further information may be found at
116 + <http://forge.novell.com/modules/xfmod/project/?apparmor>
118 + If you are unsure how to answer this question, answer N.
120 +config SECURITY_APPARMOR_BOOTPARAM_VALUE
121 + int "AppArmor boot parameter default value"
122 + depends on SECURITY_APPARMOR
126 + This option sets the default value for the kernel parameter
127 + 'apparmor', which allows AppArmor to be enabled or disabled
128 + at boot. If this option is set to 0 (zero), the AppArmor
129 + kernel parameter will default to 0, disabling AppArmor at
130 + bootup. If this option is set to 1 (one), the AppArmor
131 + kernel parameter will default to 1, enabling AppArmor at
134 + If you are unsure how to answer this question, answer 1.
136 +config SECURITY_APPARMOR_COMPAT_24
137 + bool "Enable AppArmor 2.4 compatability"
138 + depends on SECURITY_APPARMOR
141 + This option enables compatability with AppArmor 2.4. It is
142 + recommended if compatability with older versions of AppArmor
144 diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
146 index 0000000..554cba7
148 +++ b/security/apparmor/Makefile
150 +# Makefile for AppArmor Linux Security Module
152 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
154 +apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
155 + path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
156 + resource.o sid.o file.o net.o
158 +apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
160 +clean-files: capability_names.h af_names.h
162 +quiet_cmd_make-caps = GEN $@
163 +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 "};" >> $@
165 +quiet_cmd_make-af = GEN $@
166 +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 "};" >> $@
168 +$(obj)/capability.o : $(obj)/capability_names.h
169 +$(obj)/net.o : $(obj)/af_names.h
170 +$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
171 + $(call cmd,make-caps)
172 +$(obj)/af_names.h : $(srctree)/include/linux/socket.h
173 + $(call cmd,make-af)
174 diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
176 index 0000000..f64aae8
178 +++ b/security/apparmor/apparmorfs-24.c
181 + * AppArmor security module
183 + * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
185 + * Copyright (C) 1998-2008 Novell/SUSE
186 + * Copyright 2009-2010 Canonical Ltd.
188 + * This program is free software; you can redistribute it and/or
189 + * modify it under the terms of the GNU General Public License as
190 + * published by the Free Software Foundation, version 2 of the
194 + * This file contain functions providing an interface for <= AppArmor 2.4
195 + * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
196 + * being set (see Makefile).
199 +#include <linux/security.h>
200 +#include <linux/vmalloc.h>
201 +#include <linux/module.h>
202 +#include <linux/seq_file.h>
203 +#include <linux/uaccess.h>
204 +#include <linux/namei.h>
206 +#include "include/apparmor.h"
207 +#include "include/audit.h"
208 +#include "include/context.h"
209 +#include "include/policy.h"
212 +/* apparmor/matching */
213 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
214 + size_t size, loff_t *ppos)
216 + const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
219 + return simple_read_from_buffer(buf, size, ppos, matching,
220 + sizeof(matching) - 1);
223 +const struct file_operations aa_fs_matching_fops = {
224 + .read = aa_matching_read,
227 +/* apparmor/features */
228 +static ssize_t aa_features_read(struct file *file, char __user *buf,
229 + size_t size, loff_t *ppos)
231 + const char features[] = "file=3.1 capability=2.0 network=1.0 "
232 + "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
234 + return simple_read_from_buffer(buf, size, ppos, features,
235 + sizeof(features) - 1);
238 +const struct file_operations aa_fs_features_fops = {
239 + .read = aa_features_read,
241 diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
243 index 0000000..89a26a0
245 +++ b/security/apparmor/apparmorfs.c
248 + * AppArmor security module
250 + * This file contains AppArmor /sys/kernel/security/apparmor interface functions
252 + * Copyright (C) 1998-2008 Novell/SUSE
253 + * Copyright 2009-2010 Canonical Ltd.
255 + * This program is free software; you can redistribute it and/or
256 + * modify it under the terms of the GNU General Public License as
257 + * published by the Free Software Foundation, version 2 of the
261 +#include <linux/security.h>
262 +#include <linux/vmalloc.h>
263 +#include <linux/module.h>
264 +#include <linux/seq_file.h>
265 +#include <linux/uaccess.h>
266 +#include <linux/namei.h>
268 +#include "include/apparmor.h"
269 +#include "include/apparmorfs.h"
270 +#include "include/audit.h"
271 +#include "include/context.h"
272 +#include "include/policy.h"
275 + * kvmalloc - do allocation prefering kmalloc but falling back to vmalloc
276 + * @size: size of allocation
278 + * Return: allocated buffer or NULL if failed
280 + * It is possible that policy being loaded from the user is larger than
281 + * what can be allocated by kmalloc, in those cases fall back to vmalloc.
283 +static void *kvmalloc(size_t size)
290 + buffer = kmalloc(size, GFP_KERNEL);
292 + buffer = vmalloc(size);
297 + * kvfree - free an allocation do by kvmalloc
298 + * @buffer: buffer to free
300 + * Free a buffer allocated by kvmalloc
302 +static void kvfree(void *buffer)
307 + if (is_vmalloc_addr(buffer))
314 + * aa_simple_write_to_buffer - common routine for getting policy from user
315 + * @userbuf: user buffer to copy data from (NOT NULL)
316 + * @alloc_size: size of user buffer
317 + * @copy_size: size of data to copy from user buffer
318 + * @pos: position write is at in the file
319 + * @operation: name of operation doing the user buffer copy (NOT NULL)
321 + * Returns: kernel buffer containing copy of user buffer data or an
322 + * ERR_PTR on failure.
324 +static char *aa_simple_write_to_buffer(const char __user *userbuf,
325 + size_t alloc_size, size_t copy_size,
326 + loff_t *pos, const char *operation)
331 + /* only writes from pos 0, that is complete writes */
332 + data = ERR_PTR(-ESPIPE);
337 + * Don't allow profile load/replace/remove from profiles that don't
338 + * have CAP_MAC_ADMIN
340 + if (!capable(CAP_MAC_ADMIN)) {
341 + struct aa_profile *profile = NULL;
342 + struct aa_audit sa = {
343 + .operation = operation,
344 + .gfp_mask = GFP_KERNEL,
347 + profile = aa_current_profile();
348 + data = ERR_PTR(aa_audit(AUDIT_APPARMOR_DENIED, profile, &sa,
352 + /* freed by caller to aa_simple_write_to_buffer */
353 + data = kvmalloc(alloc_size);
354 + if (data == NULL) {
355 + data = ERR_PTR(-ENOMEM);
359 + if (copy_from_user(data, userbuf, copy_size)) {
361 + data = ERR_PTR(-EFAULT);
370 +/* .load file hook fn to load policy */
371 +static ssize_t aa_profile_load(struct file *f, const char __user *buf,
372 + size_t size, loff_t *pos)
377 + data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
379 + error = PTR_ERR(data);
380 + if (!IS_ERR(data)) {
381 + error = aa_interface_replace_profiles(data, size, 1);
388 +static const struct file_operations aa_fs_profile_load = {
389 + .write = aa_profile_load
392 +/* .replace file hook fn to load and/or replace policy */
393 +static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
394 + size_t size, loff_t *pos)
399 + data = aa_simple_write_to_buffer(buf, size, size, pos,
400 + "profile_replace");
401 + error = PTR_ERR(data);
402 + if (!IS_ERR(data)) {
403 + error = aa_interface_replace_profiles(data, size, 0);
410 +static const struct file_operations aa_fs_profile_replace = {
411 + .write = aa_profile_replace
414 +/* .remove file hook fn to remove loaded policy */
415 +static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
416 + size_t size, loff_t *pos)
422 + * aa_remove_profile needs a null terminated string so 1 extra
423 + * byte is allocated and the copied data is null terminated.
425 + data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
428 + error = PTR_ERR(data);
429 + if (!IS_ERR(data)) {
431 + error = aa_interface_remove_profiles(data, size);
438 +static const struct file_operations aa_fs_profile_remove = {
439 + .write = aa_profile_remove
444 + * __next_namespace - find the next namespace to list
445 + * @root: root namespace to stop search at (NOT NULL)
446 + * @ns: current ns position (NOT NULL)
448 + * Find the next namespace from @ns under @root and handle all locking needed
449 + * while switching current namespace.
451 + * Returns: next namespace or NULL if at last namespace under @root
452 + * NOTE: will not unlock root->lock
454 +static struct aa_namespace *__next_namespace(struct aa_namespace *root,
455 + struct aa_namespace *ns)
457 + struct aa_namespace *parent;
459 + /* is next namespace a child */
460 + if (!list_empty(&ns->sub_ns)) {
461 + struct aa_namespace *next;
462 + next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
463 + read_lock(&next->lock);
467 + /* check if the next ns is a sibling, parent, gp, .. */
468 + parent = ns->parent;
470 + read_unlock(&ns->lock);
471 + list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
472 + read_lock(&ns->lock);
475 + if (parent == root)
478 + parent = parent->parent;
485 + * __first_profile - find the first profile in a namespace
486 + * @root: namespace that is root of profiles being displayed (NOT NULL)
487 + * @ns: namespace to start in (NOT NULL)
489 + * Returns: unrefcounted profile or NULL if no profile
491 + static struct aa_profile *__first_profile(struct aa_namespace *root,
492 + struct aa_namespace *ns)
494 + for ( ; ns; ns = __next_namespace(root, ns)) {
495 + if (!list_empty(&ns->base.profiles))
496 + return list_first_entry(&ns->base.profiles,
497 + struct aa_profile, base.list);
503 + * __next_profile - step to the next profile in a profile tree
504 + * @profile: current profile in tree (NOT NULL)
506 + * Perform a depth first taversal on the profile tree in a namespace
508 + * Returns: next profile or NULL if done
509 + * Requires: profile->ns.lock to be held
511 +static struct aa_profile *__next_profile(struct aa_profile *p)
513 + struct aa_profile *parent;
514 + struct aa_namespace *ns = p->ns;
516 + /* is next profile a child */
517 + if (!list_empty(&p->base.profiles))
518 + return list_first_entry(&p->base.profiles, typeof(*p),
521 + /* is next profile a sibling, parent sibling, gp, subling, .. */
522 + parent = p->parent;
524 + list_for_each_entry_continue(p, &parent->base.profiles,
528 + parent = parent->parent;
531 + /* is next another profile in the namespace */
532 + list_for_each_entry_continue(p, &ns->base.profiles, base.list)
539 + * next_profile - step to the next profile in where ever it may be
540 + * @root: root namespace (NOT NULL)
541 + * @profile: current profile (NOT NULL)
543 + * Returns: next profile or NULL if there isn't one
545 +static struct aa_profile *next_profile(struct aa_namespace *root,
546 + struct aa_profile *profile)
548 + struct aa_profile *next = __next_profile(profile);
552 + /* finished all profiles in namespace move to next namespace */
553 + return __first_profile(root, __next_namespace(root, profile->ns));
557 + * p_start - start a depth first traversal of profile tree
558 + * @f: seq_file to fill
559 + * @pos: current position
561 + * Returns: first profile under current namespace or NULL if none found
563 + * acquires first ns->lock
565 +static void *p_start(struct seq_file *f, loff_t *pos)
566 + __acquires(root->lock)
568 + struct aa_profile *profile = NULL;
569 + struct aa_namespace *root = aa_current_profile()->ns;
571 + f->private = aa_get_namespace(root);
574 + /* find the first profile */
575 + read_lock(&root->lock);
576 + profile = __first_profile(root, root);
578 + /* skip to position */
579 + for (; profile && l > 0; l--)
580 + profile = next_profile(root, profile);
586 + * p_next - read the next profile entry
587 + * @f: seq_file to fill
588 + * @p: profile previously returned
589 + * @pos: current position
591 + * Returns: next profile after @p or NULL if none
593 + * may acquire/release locks in namespace tree as necessary
595 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
597 + struct aa_profile *profile = p;
598 + struct aa_namespace *root = f->private;
601 + return next_profile(root, profile);
605 + * p_stop - stop depth first traversal
606 + * @f: seq_file we are filling
607 + * @p: the last profile writen
609 + * Release all locking done by p_start/p_next on namespace tree
611 +static void p_stop(struct seq_file *f, void *p)
612 + __releases(root->lock)
614 + struct aa_profile *profile = p;
615 + struct aa_namespace *root = f->private, *ns;
618 + for (ns = profile->ns; ns && ns != root; ns = ns->parent)
619 + read_unlock(&ns->lock);
621 + read_unlock(&root->lock);
622 + aa_put_namespace(root);
626 + * print_ns_name - print a namespace name back to @root
627 + * @root: root namespace to stop at
628 + * @ns: namespace to gen name for
630 + * Returns: true if it printed a name
632 +static bool print_ns_name(struct seq_file *f, struct aa_namespace *root,
633 + struct aa_namespace *ns)
635 + if (!ns || ns == root)
638 + if (ns->parent && print_ns_name(f, root, ns->parent))
639 + seq_printf(f, "//");
641 + seq_printf(f, "%s", ns->base.name);
646 + * seq_show_profile -
647 + * @f: seq_file to file
648 + * @p: current position (profile) (NOT NULL)
650 + * Returns: error on failure
652 +static int seq_show_profile(struct seq_file *f, void *p)
654 + struct aa_profile *profile = (struct aa_profile *)p;
655 + struct aa_namespace *root = f->private;
657 + if (profile->ns != root)
658 + seq_printf(f, ":");
659 + if (print_ns_name(f, root, profile->ns))
660 + seq_printf(f, "://");
661 + seq_printf(f, "%s (%s)\n", profile->base.hname,
662 + COMPLAIN_MODE(profile) ? "complain" : "enforce");
667 +static const struct seq_operations aa_fs_profiles_op = {
671 + .show = seq_show_profile,
674 +static int aa_profiles_open(struct inode *inode, struct file *file)
676 + return seq_open(file, &aa_fs_profiles_op);
679 +static int aa_profiles_release(struct inode *inode, struct file *file)
681 + return seq_release(inode, file);
684 +static const struct file_operations aa_fs_profiles_fops = {
685 + .open = aa_profiles_open,
687 + .llseek = seq_lseek,
688 + .release = aa_profiles_release,
692 +/** Base file system setup **/
694 +static struct dentry *aa_fs_dentry;
695 +struct dentry *aa_fs_null;
696 +struct vfsmount *aa_fs_mnt;
698 +static void aafs_remove(const char *name)
700 + struct dentry *dentry;
702 + dentry = lookup_one_len(name, aa_fs_dentry, strlen(name));
703 + if (!IS_ERR(dentry)) {
704 + securityfs_remove(dentry);
710 + * aafs_create - create an entry in the apparmor filesystem
711 + * @name: name of the entry
712 + * @mask: file permission mask of the file
713 + * @fops: file operations for the file
715 + * Used aafs_remove to remove entries created with this fn.
717 +static int aafs_create(const char *name, int mask,
718 + const struct file_operations *fops)
720 + struct dentry *dentry;
722 + dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry,
725 + return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
729 + * aa_destroy_aafs - cleanup and free aafs
731 + * releases dentries allocated by aa_create_aafs
733 +void aa_destroy_aafs(void)
735 + if (aa_fs_dentry) {
736 + aafs_remove(".remove");
737 + aafs_remove(".replace");
738 + aafs_remove(".load");
739 + aafs_remove("profiles");
740 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
741 + aafs_remove("matching");
742 + aafs_remove("features");
744 + securityfs_remove(aa_fs_dentry);
745 + aa_fs_dentry = NULL;
750 + * aa_create_aafs - create the apparmor security filesystem
752 + * dentries created here are released by aa_destroy_aafs
754 + * Returns: error on failure
756 +int aa_create_aafs(void)
760 + if (!apparmor_initialized)
763 + if (aa_fs_dentry) {
764 + AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
768 + aa_fs_dentry = securityfs_create_dir("apparmor", NULL);
769 + if (IS_ERR(aa_fs_dentry)) {
770 + error = PTR_ERR(aa_fs_dentry);
771 + aa_fs_dentry = NULL;
774 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
775 + error = aafs_create("matching", 0444, &aa_fs_matching_fops);
778 + error = aafs_create("features", 0444, &aa_fs_features_fops);
782 + error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
785 + error = aafs_create(".load", 0640, &aa_fs_profile_load);
788 + error = aafs_create(".replace", 0640, &aa_fs_profile_replace);
791 + error = aafs_create(".remove", 0640, &aa_fs_profile_remove);
795 + /* TODO: add support for apparmorfs_null and apparmorfs_mnt */
797 + /* Report that AppArmor fs is enabled */
798 + aa_info_message("AppArmor Filesystem Enabled");
803 + AA_ERROR("Error creating AppArmor securityfs\n");
807 +fs_initcall(aa_create_aafs);
808 diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
810 index 0000000..38ac7a7
812 +++ b/security/apparmor/audit.c
815 + * AppArmor security module
817 + * This file contains AppArmor auditing functions
819 + * Copyright (C) 1998-2008 Novell/SUSE
820 + * Copyright 2009-2010 Canonical Ltd.
822 + * This program is free software; you can redistribute it and/or
823 + * modify it under the terms of the GNU General Public License as
824 + * published by the Free Software Foundation, version 2 of the
828 +#include <linux/audit.h>
829 +#include <linux/socket.h>
831 +#include "include/apparmor.h"
832 +#include "include/audit.h"
833 +#include "include/policy.h"
835 +const char *audit_mode_names[] = {
843 +static char *aa_audit_type[] = {
845 + "APPARMOR_ALLOWED",
854 + * Currently AppArmor auditing is fed straight into the audit framework.
857 + * convert to LSM audit
858 + * netlink interface for complain mode
859 + * user auditing, - send user auditing to netlink interface
860 + * system control of whether user audit messages go to system log
864 + * aa_audit_base - core AppArmor function.
865 + * @type: type of audit message (see include/linux/apparmor.h)
866 + * @profile: active profile for event (MAY BE NULL)
867 + * @sa: audit structure containing data to audit
868 + * @audit_cxt: audit_cxt that event is under
869 + * @cb: audit cb for this event
871 + * Record an audit message for data is @sa, and handle deal with kill and
872 + * complain messages switches.
874 + * Returns: 0 or sa->error on success, else error
876 +static int aa_audit_base(int type, struct aa_profile *profile,
877 + struct aa_audit *sa, struct audit_context *audit_cxt,
878 + void (*cb) (struct audit_buffer *, struct aa_audit *))
880 + struct audit_buffer *ab = NULL;
881 + struct task_struct *task = sa->task ? sa->task : current;
883 + if (profile && DO_KILL(profile) && type == AUDIT_APPARMOR_DENIED)
884 + type = AUDIT_APPARMOR_KILL;
886 + /* ab freed below in audit_log_end */
887 + ab = audit_log_start(audit_cxt, sa->gfp_mask, type);
890 + AA_ERROR("(%d) Unable to log event of type (%d)\n",
892 + sa->error = -ENOMEM;
896 + if (aa_g_audit_header) {
897 + audit_log_format(ab, " type=");
898 + audit_log_string(ab, aa_audit_type[type - AUDIT_APPARMOR_AUDIT]);
901 + if (sa->operation) {
902 + audit_log_format(ab, " operation=");
903 + audit_log_string(ab, sa->operation);
907 + audit_log_format(ab, " info=");
908 + audit_log_string(ab, sa->info);
910 + audit_log_format(ab, " error=%d", sa->error);
913 + audit_log_format(ab, " pid=%d", task->pid);
915 + if (profile && !unconfined(profile)) {
918 + pid = task->real_parent->pid;
920 + audit_log_format(ab, " parent=%d", pid);
921 + audit_log_format(ab, " profile=");
922 + audit_log_untrustedstring(ab, profile->base.hname);
924 + if (profile->ns != root_ns) {
925 + audit_log_format(ab, " namespace=");
926 + audit_log_untrustedstring(ab, profile->ns->base.hname);
936 + if (type == AUDIT_APPARMOR_KILL)
937 + (void)send_sig_info(SIGKILL, NULL, task);
939 + return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error;
943 + * aa_audit - Log an audit event to the audit subsystem
944 + * @type: audit type for the message
945 + * @profile: profile to check against
947 + * @cb: optional callback fn for type specific fields
949 + * Handle default message switching based off of audit mode flags
951 + * Returns: error on failure
953 +int aa_audit(int type, struct aa_profile *profile, struct aa_audit *sa,
954 + void (*cb) (struct audit_buffer *, struct aa_audit *))
956 + struct audit_context *audit_cxt;
957 + audit_cxt = aa_g_logsyscall ? current->audit_context : NULL;
959 + if (type == AUDIT_APPARMOR_AUTO) {
960 + if (likely(!sa->error)) {
961 + if (AUDIT_MODE(profile) != AUDIT_ALL)
963 + type = AUDIT_APPARMOR_AUDIT;
964 + } else if (COMPLAIN_MODE(profile))
965 + type = AUDIT_APPARMOR_ALLOWED;
967 + type = AUDIT_APPARMOR_DENIED;
969 + if (AUDIT_MODE(profile) == AUDIT_QUIET ||
970 + (type == AUDIT_APPARMOR_DENIED &&
971 + AUDIT_MODE(profile) == AUDIT_QUIET))
974 + return aa_audit_base(type, profile, sa, audit_cxt, cb);
976 diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
978 index 0000000..c8a80ba
980 +++ b/security/apparmor/capability.c
983 + * AppArmor security module
985 + * This file contains AppArmor capability mediation functions
987 + * Copyright (C) 1998-2008 Novell/SUSE
988 + * Copyright 2009-2010 Canonical Ltd.
990 + * This program is free software; you can redistribute it and/or
991 + * modify it under the terms of the GNU General Public License as
992 + * published by the Free Software Foundation, version 2 of the
996 +#include <linux/capability.h>
997 +#include <linux/errno.h>
998 +#include <linux/gfp.h>
1000 +#include "include/apparmor.h"
1001 +#include "include/capability.h"
1002 +#include "include/context.h"
1003 +#include "include/policy.h"
1004 +#include "include/audit.h"
1007 + * Table of capability names: we generate it from capabilities.h.
1009 +#include "capability_names.h"
1011 +struct audit_cache {
1012 + struct aa_profile *profile;
1013 + kernel_cap_t caps;
1016 +static DEFINE_PER_CPU(struct audit_cache, audit_cache);
1018 +struct aa_audit_caps {
1019 + struct aa_audit base;
1025 + * audit_cb - call back for capability components of audit struct
1026 + * @ab - audit buffer (NOT NULL)
1027 + * @va - audit struct to audit data from (NOT NULL)
1029 +static void audit_cb(struct audit_buffer *ab, struct aa_audit *va)
1031 + struct aa_audit_caps *sa = container_of(va, struct aa_audit_caps, base);
1033 + audit_log_format(ab, " name=");
1034 + audit_log_untrustedstring(ab, capability_names[sa->cap]);
1038 + * aa_audit_caps - audit a capability
1039 + * @profile: profile confining task
1040 + * @sa: audit structure containing data to audit
1042 + * Do auditing of capability and handle, audit/complain/kill modes switching
1043 + * and duplicate message elimination.
1045 + * returns: 0 or sa->error on succes, error code on failure
1047 +static int aa_audit_caps(struct aa_profile *profile, struct aa_audit_caps *sa)
1049 + struct audit_cache *ent;
1050 + int type = AUDIT_APPARMOR_AUTO;
1052 + if (likely(!sa->base.error)) {
1053 + /* test if auditing is being forced */
1054 + if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
1055 + !cap_raised(profile->caps.audit, sa->cap)))
1057 + type = AUDIT_APPARMOR_AUDIT;
1058 + } else if (DO_KILL(profile) ||
1059 + cap_raised(profile->caps.kill, sa->cap)) {
1060 + type = AUDIT_APPARMOR_KILL;
1061 + } else if (cap_raised(profile->caps.quiet, sa->cap) &&
1062 + AUDIT_MODE(profile) != AUDIT_NOQUIET &&
1063 + AUDIT_MODE(profile) != AUDIT_ALL) {
1064 + /* quiet auditing */
1065 + return sa->base.error;
1068 + /* Do simple duplicate message elimination */
1069 + ent = &get_cpu_var(audit_cache);
1070 + if (profile == ent->profile && cap_raised(ent->caps, sa->cap)) {
1071 + put_cpu_var(audit_cache);
1072 + if (COMPLAIN_MODE(profile))
1074 + return sa->base.error;
1076 + aa_put_profile(ent->profile);
1077 + ent->profile = aa_get_profile(profile);
1078 + cap_raise(ent->caps, sa->cap);
1080 + put_cpu_var(audit_cache);
1082 + return aa_audit(type, profile, &sa->base, audit_cb);
1086 + * aa_profile_capable - test if profile allows use of capability @cap
1087 + * @profile: profile being enforced (NOT NULL, NOT unconfined)
1088 + * @cap: capability to test if allowed
1090 + * Returns: 0 if allowed else -EPERM
1092 +static int aa_profile_capable(struct aa_profile *profile, int cap)
1094 + return cap_raised(profile->caps.allowed, cap) ? 0 : -EPERM;
1098 + * aa_capable - test permission to use capability
1099 + * @task: task doing capability test against
1100 + * @profile: profile confining @task
1101 + * @cap: capability to be tested
1102 + * @audit: whether an audit record should be generated
1104 + * Look up capability in profile capability set.
1106 + * Returns: 0 on success, or else an error code.
1108 +int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
1111 + int error = aa_profile_capable(profile, cap);
1112 + struct aa_audit_caps sa = {
1113 + .base.operation = "capable",
1114 + .base.task = task,
1115 + .base.gfp_mask = GFP_ATOMIC,
1116 + .base.error = error,
1121 + if (COMPLAIN_MODE(profile))
1126 + return aa_audit_caps(profile, &sa);
1128 diff --git a/security/apparmor/context.c b/security/apparmor/context.c
1129 new file mode 100644
1130 index 0000000..caaa277
1132 +++ b/security/apparmor/context.c
1135 + * AppArmor security module
1137 + * This file contains AppArmor functions used to manipulate object security
1140 + * Copyright (C) 1998-2008 Novell/SUSE
1141 + * Copyright 2009-2010 Canonical Ltd.
1143 + * This program is free software; you can redistribute it and/or
1144 + * modify it under the terms of the GNU General Public License as
1145 + * published by the Free Software Foundation, version 2 of the
1149 + * AppArmor sets confinement on every task, via the the aa_task_cxt and
1150 + * the aa_task_cxt profile, both of which are required and are not allowed
1151 + * to be NULL. The aa_task_cxt is not reference counted and is unique
1152 + * to each cred (which is reference count). The profile pointed to by
1153 + * the task_cxt is reference counted.
1156 + * If a task uses change_hat it currently does not return to the old
1157 + * cred or task context but instead creates a new one. Ideally the task
1158 + * should return to the previous cred if it has not been modified.
1162 +#include "include/context.h"
1163 +#include "include/policy.h"
1166 + * aa_alloc_task_context - allocat a new task_cxt
1167 + * @flags: gfp flags for allocation
1169 + * Returns: allocated buffer or NULL on failure
1171 +struct aa_task_cxt *aa_alloc_task_context(gfp_t flags)
1173 + return kzalloc(sizeof(struct aa_task_cxt), flags);
1177 + * aa_free_task_context - free a task_cxt
1178 + * @cxt: task_cxt to free (MAYBE NULL)
1180 +void aa_free_task_context(struct aa_task_cxt *cxt)
1183 + aa_put_profile(cxt->profile);
1184 + aa_put_profile(cxt->previous);
1185 + aa_put_profile(cxt->onexec);
1192 + * aa_dup_task_context - duplicate a task context, incrementing reference counts
1193 + * @new: a blank task context (NOT NULL)
1194 + * @old: the task context to copy (NOT NULL)
1196 +void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
1199 + aa_get_profile(new->profile);
1200 + aa_get_profile(new->previous);
1201 + aa_get_profile(new->onexec);
1205 + * replace_cxt - replace a context profile
1206 + * @cxt: task context (NOT NULL)
1207 + * @profile: profile to replace cxt group (NOT NULL)
1209 + * Replace context grouping profile reference with @profile
1211 +static void replace_group(struct aa_task_cxt *cxt, struct aa_profile *profile)
1213 + if (cxt->profile == profile)
1217 + if (unconfined(profile) || (cxt->profile->ns != profile->ns)) {
1218 + /* if switching to unconfined or a different profile namespace
1219 + * clear out context state
1221 + aa_put_profile(cxt->previous);
1222 + aa_put_profile(cxt->onexec);
1223 + cxt->previous = NULL;
1224 + cxt->onexec = NULL;
1227 + aa_put_profile(cxt->profile);
1228 + cxt->profile = aa_get_profile(profile);
1232 + * aa_replace_current_profiles - replace the current tasks profiles
1233 + * @profile: new profile (NOT NULL)
1235 + * Returns: 0 or error on failure
1237 +int aa_replace_current_profiles(struct aa_profile *profile)
1239 + struct aa_task_cxt *cxt;
1240 + struct cred *new = prepare_creds();
1244 + cxt = new->security;
1245 + replace_group(cxt, profile);
1246 + /* todo add user group */
1248 + commit_creds(new);
1253 + * aa_set_current_onexec - set the tasks change_profile to happen onexec
1254 + * @profile: system profile to set at exec (MAYBE NULL)
1256 + * Returns: 0 or error on failure
1258 +int aa_set_current_onexec(struct aa_profile *profile)
1260 + struct aa_task_cxt *cxt;
1261 + struct cred *new = prepare_creds();
1265 + cxt = new->security;
1266 + aa_put_profile(cxt->onexec);
1267 + cxt->onexec = aa_get_profile(profile);
1269 + commit_creds(new);
1274 + * aa_set_current_hat - set the current tasks hat
1275 + * @profile: profile to set as the current hat (NOT NULL)
1276 + * @token: token value that must be specified to change from the hat
1278 + * Do switch of tasks hat. If the task is currently in a hat
1279 + * validate the token to match.
1281 + * Returns: 0 or error on failure
1283 +int aa_set_current_hat(struct aa_profile *profile, u64 token)
1285 + struct aa_task_cxt *cxt;
1286 + struct cred *new = prepare_creds();
1291 + cxt = new->security;
1292 + if (!cxt->previous) {
1293 + cxt->previous = cxt->profile;
1294 + cxt->token = token;
1295 + } else if (cxt->token == token) {
1296 + aa_put_profile(cxt->profile);
1298 + /* previous_profile && cxt->token != token */
1302 + cxt->profile = aa_get_profile(aa_newest_version(profile));
1303 + /* clear exec on switching context */
1304 + aa_put_profile(cxt->onexec);
1305 + cxt->onexec = NULL;
1307 + commit_creds(new);
1312 + * aa_restore_previous_profile - exit from hat context restoring the profile
1313 + * @token: the token that must be matched to exit hat context
1315 + * Attempt to return out of a hat to the previous profile. The token
1316 + * must match the stored token value.
1318 + * Returns: 0 or error of failure
1320 +int aa_restore_previous_profile(u64 token)
1322 + struct aa_task_cxt *cxt;
1323 + struct cred *new = prepare_creds();
1327 + cxt = new->security;
1328 + if (cxt->token != token) {
1332 + /* ignore restores when there is no saved profile */
1333 + if (!cxt->previous) {
1338 + aa_put_profile(cxt->profile);
1339 + cxt->profile = aa_newest_version(cxt->previous);
1340 + BUG_ON(!cxt->profile);
1341 + if (unlikely(cxt->profile != cxt->previous)) {
1342 + aa_get_profile(cxt->profile);
1343 + aa_put_profile(cxt->previous);
1345 + /* clear exec && prev information when restoring to previous context */
1346 + cxt->previous = NULL;
1348 + aa_put_profile(cxt->onexec);
1349 + cxt->onexec = NULL;
1351 + commit_creds(new);
1354 diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
1355 new file mode 100644
1356 index 0000000..cd8ec99
1358 +++ b/security/apparmor/domain.c
1361 + * AppArmor security module
1363 + * This file contains AppArmor policy attachment and domain transitions
1365 + * Copyright (C) 2002-2008 Novell/SUSE
1366 + * Copyright 2009-2010 Canonical Ltd.
1368 + * This program is free software; you can redistribute it and/or
1369 + * modify it under the terms of the GNU General Public License as
1370 + * published by the Free Software Foundation, version 2 of the
1374 +#include <linux/errno.h>
1375 +#include <linux/fdtable.h>
1376 +#include <linux/file.h>
1377 +#include <linux/mount.h>
1378 +#include <linux/syscalls.h>
1379 +#include <linux/tracehook.h>
1380 +#include <linux/personality.h>
1382 +#include "include/audit.h"
1383 +#include "include/apparmorfs.h"
1384 +#include "include/context.h"
1385 +#include "include/domain.h"
1386 +#include "include/file.h"
1387 +#include "include/ipc.h"
1388 +#include "include/match.h"
1389 +#include "include/path.h"
1390 +#include "include/policy.h"
1393 + * aa_free_domain_entries - free entries in a domain table
1394 + * @domain: the domain table to free (MAYBE NULL)
1396 +void aa_free_domain_entries(struct aa_domain *domain)
1400 + if (!domain->table)
1403 + for (i = 0; i < domain->size; i++)
1404 + kzfree(domain->table[i]);
1405 + kzfree(domain->table);
1406 + domain->table = NULL;
1411 + * aa_may_change_ptraced_domain - check if can change profile on ptraced task
1412 + * @task: task we want to change profile of (NOT NULL)
1413 + * @to_profile: profile to change to (NOT NULL)
1415 + * Check if the task is ptraced and if so if the tracing task is allowed
1416 + * to trace the new domain
1418 + * Returns: %0 or error if change not allowed
1420 +static int aa_may_change_ptraced_domain(struct task_struct *task,
1421 + struct aa_profile *to_profile)
1423 + struct task_struct *tracer;
1424 + struct cred *cred = NULL;
1425 + struct aa_profile *tracerp = NULL;
1429 + tracer = tracehook_tracer_task(task);
1431 + /* released below */
1432 + cred = get_task_cred(tracer);
1433 + tracerp = aa_cred_profile(cred);
1435 + rcu_read_unlock();
1438 + if (!tracer || unconfined(tracerp))
1441 + error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
1451 + * change_profile_perms - find permissions for change_profile
1452 + * @profile: the current profile (NOT NULL)
1453 + * @ns: the namespace being switched to (NOT NULL)
1454 + * @name: the name of the profile to change to (NOT NULL)
1455 + * @rstate: if !NULL will contain the state the match finished in (MAYBE NULL)
1457 + * Returns: permission set
1459 +static struct file_perms change_profile_perms(struct aa_profile *profile,
1460 + struct aa_namespace *ns,
1462 + unsigned int *rstate)
1464 + struct file_perms perms;
1465 + struct path_cond cond = { };
1466 + unsigned int state;
1468 + if (unconfined(profile)) {
1469 + perms.allowed = AA_MAY_CHANGE_PROFILE;
1470 + perms.xindex = perms.xdelegate = perms.dindex = 0;
1471 + perms.audit = perms.quiet = perms.kill = 0;
1475 + } else if (!profile->file.dfa) {
1477 + } else if ((ns == profile->ns)) {
1478 + /* try matching against rules with out namespace prependend */
1479 + perms = aa_str_perms(profile->file.dfa, profile->file.start,
1480 + name, &cond, rstate);
1481 + if (COMBINED_PERM_MASK(perms) & AA_MAY_CHANGE_PROFILE)
1485 + /* try matching with namespace name and then profile */
1486 + state = aa_dfa_match(profile->file.dfa, profile->file.start,
1488 + state = aa_dfa_null_transition(profile->file.dfa, state, 0);
1489 + return aa_str_perms(profile->file.dfa, state, name, &cond, rstate);
1493 + * __aa_attach_match_ - find an attachment match
1494 + * @name - to match against (NOT NULL)
1495 + * @head - profile list to walk (NOT NULL)
1497 + * Do a linear search on the profiles in the list. There is a matching
1498 + * preference where an exact match is prefered over a name which uses
1499 + * expressions to match, and matching expressions with the greatest
1500 + * xmatch_len are prefered.
1502 + * Requires: @head not be shared or have appropriate locks held
1504 + * Returns: profile or NULL if no match found
1506 +static struct aa_profile *__aa_attach_match(const char *name,
1507 + struct list_head *head)
1510 + struct aa_profile *profile, *candidate = NULL;
1512 + list_for_each_entry(profile, head, base.list) {
1513 + if (profile->flags & PFLAG_NULL)
1515 + if (profile->xmatch && profile->xmatch_len > len) {
1516 + unsigned int state = aa_dfa_match(profile->xmatch,
1518 + u16 perm = dfa_user_allow(profile->xmatch, state);
1519 + /* any accepting state means a valid match. */
1520 + if (perm & MAY_EXEC) {
1521 + candidate = profile;
1522 + len = profile->xmatch_len;
1524 + } else if (!strcmp(profile->base.name, name))
1525 + /* exact non-re match, no more searching required */
1533 + * aa_find_attach - do attachment search for unconfined processes
1534 + * @ns: the current namespace (NOT NULL)
1535 + * @list: list to search (NOT NULL)
1536 + * @name: the executable name to match against (NOT NULL)
1538 + * Returns: profile or NULL if no match found
1540 +static struct aa_profile *aa_find_attach(struct aa_namespace *ns,
1541 + struct list_head *list,
1544 + struct aa_profile *profile;
1546 + read_lock(&ns->lock);
1547 + profile = aa_get_profile(__aa_attach_match(name, list));
1548 + read_unlock(&ns->lock);
1554 + * separate_fqname - separate the namespace and profile names
1555 + * @fqname: the fqname name to split (NOT NULL)
1556 + * @ns_name: the namespace name if it exists (NOT NULL)
1558 + * This is the xtable equivalent routine of aa_split_fqname. It finds the
1559 + * split in an xtable fqname which contains an embedded \0 instead of a :
1560 + * if a namespace is specified. This is done so the xtable is constant and
1561 + * isn't resplit on every lookup.
1563 + * Either the profile or namespace name may be optional but if the namespace
1564 + * is specified the profile name termination must be present. This results
1565 + * in the following possible encodings:
1567 + * :ns_name\0profile_name\0
1570 + * NOTE: the xtable fqname is prevalidated at load time in unpack_trans_table
1572 + * Returns: profile name if it is specified else NULL
1574 +static const char *separate_fqname(const char *fqname, const char **ns_name)
1578 + if (fqname[0] == ':') {
1579 + *ns_name = fqname + 1; /* skip : */
1580 + name = *ns_name + strlen(*ns_name) + 1;
1591 +static const char *next_name(int xtype, const char *name)
1597 + * x_to_profile - get target profile for a given xindex
1598 + * @profile: current profile (NOT NULL)
1599 + * @name: to to lookup if specified (NOT NULL)
1600 + * @xindex: index into x transition table
1602 + * find profile for a transition index
1604 + * Returns: refcounted profile or NULL if not found available
1606 +static struct aa_profile *x_to_profile(struct aa_profile *profile,
1607 + const char *name, u16 xindex)
1609 + struct aa_profile *new_profile = NULL;
1610 + struct aa_namespace *ns = profile->ns;
1611 + u16 xtype = xindex & AA_X_TYPE_MASK;
1612 + int index = xindex & AA_X_INDEX_MASK;
1616 + /* fail exec unless ix || ux fallback - handled by caller */
1619 + if (xindex & AA_X_CHILD)
1620 + /* released by caller */
1621 + new_profile = aa_find_attach(ns,
1622 + &profile->base.profiles,
1625 + /* released by caller */
1626 + new_profile = aa_find_attach(ns, &ns->base.profiles,
1628 + /* released by caller */
1629 + return new_profile;
1631 + /* index is guarenteed to be in range */
1632 + name = profile->file.trans.table[index];
1636 + for (; !new_profile && name; name = next_name(xtype, name)) {
1637 + struct aa_namespace *new_ns;
1638 + const char *xname = NULL;
1641 + if (xindex & AA_X_CHILD) {
1642 + /* release by caller */
1643 + new_profile = aa_find_child(profile, name);
1645 + return new_profile;
1647 + } else if (*name == ':') {
1648 + /* switching namespace */
1649 + const char *ns_name;
1650 + xname = name = separate_fqname(name, &ns_name);
1652 + /* no name so use profile name */
1653 + xname = profile->base.hname;
1654 + if (*ns_name == '@') {
1655 + /* TODO: variable support */
1658 + /* released below */
1659 + new_ns = aa_find_namespace(ns, ns_name);
1662 + } else if (*name == '@') {
1663 + /* TODO: variable support */
1669 + /* released by caller */
1670 + new_profile = aa_find_profile(new_ns ? new_ns : ns, xname);
1671 + aa_put_namespace(new_ns);
1674 + /* released by caller */
1675 + return new_profile;
1679 + * apparmor_bprm_set_creds - set the new creds on the bprm struct
1680 + * @bprm: binprm for the exec (NOT NULL)
1682 + * Returns: %0 or error on failure
1684 +int apparmor_bprm_set_creds(struct linux_binprm *bprm)
1686 + struct aa_task_cxt *cxt;
1687 + struct aa_profile *profile, *new_profile = NULL;
1688 + struct aa_namespace *ns;
1689 + char *buffer = NULL;
1690 + unsigned int state;
1691 + struct path_cond cond = {
1692 + bprm->file->f_path.dentry->d_inode->i_uid,
1693 + bprm->file->f_path.dentry->d_inode->i_mode
1695 + struct aa_audit_file sa = {
1696 + .base.operation = "exec",
1697 + .base.gfp_mask = GFP_KERNEL,
1698 + .request = MAY_EXEC,
1702 + sa.base.error = cap_bprm_set_creds(bprm);
1703 + if (sa.base.error)
1704 + return sa.base.error;
1706 + if (bprm->cred_prepared)
1709 + cxt = bprm->cred->security;
1712 + profile = aa_newest_version(cxt->profile);
1714 + * get the namespace from the replacement profile as replacement
1715 + * can change the namespace
1718 + state = profile->file.start;
1720 + /* buffer freed below, name is pointer inside of buffer */
1721 + sa.base.error = aa_get_name(&bprm->file->f_path, profile->path_flags,
1722 + &buffer, (char **)&sa.name);
1723 + if (sa.base.error) {
1724 + if (profile->flags &
1725 + (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED))
1726 + sa.base.error = 0;
1727 + sa.base.info = "Exec failed name resolution";
1728 + sa.name = bprm->filename;
1732 + if (unconfined(profile)) {
1733 + /* unconfined task - attach profile if one matches */
1734 + new_profile = aa_find_attach(ns, &ns->base.profiles, sa.name);
1738 + } else if (cxt->onexec) {
1740 + * onexec permissions are stored in a pair, rewalk the
1741 + * dfa to get start of the exec path match.
1743 + sa.perms = change_profile_perms(profile, cxt->onexec->ns,
1745 + state = aa_dfa_null_transition(profile->file.dfa, state, 0);
1747 + sa.perms = aa_str_perms(profile->file.dfa, state, sa.name, &cond, NULL);
1748 + if (cxt->onexec && sa.perms.allowed & AA_MAY_ONEXEC) {
1749 + /* transfer the onexec reference, this is allowed as the
1750 + * cred is being prepared, and isn't committed yet.
1752 + new_profile = cxt->onexec;
1753 + cxt->onexec = NULL;
1754 + sa.base.info = "change_profile onexec";
1755 + } else if (sa.perms.allowed & MAY_EXEC) {
1756 + new_profile = x_to_profile(profile, sa.name, sa.perms.xindex);
1757 + if (!new_profile) {
1758 + if (sa.perms.xindex & AA_X_INHERIT) {
1759 + /* (p|c|n)ix - don't change profile */
1760 + sa.base.info = "ix fallback";
1762 + } else if (sa.perms.xindex & AA_X_UNCONFINED) {
1763 + new_profile = aa_get_profile(ns->unconfined);
1764 + sa.base.info = "ux fallback";
1766 + sa.base.error = -ENOENT;
1767 + sa.base.info = "profile not found";
1770 + } else if (COMPLAIN_MODE(profile)) {
1771 + new_profile = aa_new_null_profile(profile, 0);
1772 + sa.base.error = -EACCES;
1773 + if (!new_profile) {
1774 + sa.base.error = -ENOMEM;
1775 + sa.base.info = "could not create null profile";
1777 + sa.name2 = new_profile->base.hname;
1778 + sa.perms.xindex |= AA_X_UNSAFE;
1780 + sa.base.error = -EACCES;
1786 + if (profile == new_profile) {
1787 + aa_put_profile(new_profile);
1791 + if (bprm->unsafe & LSM_UNSAFE_SHARE) {
1792 + /* FIXME: currently don't mediate shared state */
1796 + if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
1797 + sa.base.error = aa_may_change_ptraced_domain(current,
1799 + if (sa.base.error)
1803 + /* Determine if secure exec is needed.
1804 + * Can be at this point for the following reasons:
1805 + * 1. unconfined switching to confined
1806 + * 2. confined switching to different confinement
1807 + * 3. confined switching to unconfined
1809 + * Cases 2 and 3 are marked as requiring secure exec
1810 + * (unless policy specified "unsafe exec")
1812 + * bprm->unsafe is used to cache the AA_X_UNSAFE permission
1813 + * to avoid having to recompute in secureexec
1815 + if (!(sa.perms.xindex & AA_X_UNSAFE)) {
1816 + AA_DEBUG("scubbing environment variables for %s profile=%s\n",
1817 + sa.name, new_profile->base.hname);
1818 + bprm->unsafe |= AA_SECURE_X_NEEDED;
1821 + sa.name2 = new_profile->base.hname;
1822 + /* When switching namespace ensure its part of audit message */
1823 + if (new_profile->ns != ns)
1824 + sa.name3 = new_profile->ns->base.hname;
1826 + /* when transitioning profiles clear unsafe personality bits */
1827 + bprm->per_clear |= PER_CLEAR_ON_SETID;
1829 + aa_put_profile(cxt->profile);
1830 + /* transfer new profile reference will be released when cxt is freed */
1831 + cxt->profile = new_profile;
1834 + aa_put_profile(cxt->previous);
1835 + aa_put_profile(cxt->onexec);
1836 + cxt->previous = NULL;
1837 + cxt->onexec = NULL;
1841 + sa.base.error = aa_audit_file(profile, &sa);
1846 + return sa.base.error;
1850 + * apparmor_bprm_secureexec - determine if secureexec is needed
1851 + * @bprm: binprm for exec (NOT NULL)
1853 + * Returns: %1 if secureexec is needed else %0
1855 +int apparmor_bprm_secureexec(struct linux_binprm *bprm)
1857 + int ret = cap_bprm_secureexec(bprm);
1859 + /* the decision to use secure exec is computed in set_creds
1860 + * and stored in bprm->unsafe.
1862 + if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
1869 + * apparmor_bprm_committing_creds - do task cleanup on committing new creds
1870 + * @bprm: binprm for the exec (NOT NULL)
1872 +void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
1874 + struct aa_profile *profile = __aa_current_profile();
1875 + struct aa_task_cxt *new_cxt = bprm->cred->security;
1877 + /* bail out if unconfined or not changing profile */
1878 + if ((new_cxt->profile == profile) ||
1879 + (unconfined(new_cxt->profile)))
1882 + current->pdeath_signal = 0;
1884 + /* reset soft limits and set hard limits for the new profile */
1885 + __aa_transition_rlimits(profile, new_cxt->profile);
1889 + * apparmor_bprm_commited_cred - do cleanup after new creds committed
1890 + * @bprm: binprm for the exec (NOT NULL)
1892 +void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
1894 + /* TODO: cleanup signals - ipc mediation */
1899 + * Functions for self directed profile change
1903 + * new_compound_name - create an hname with @n2 appended to @n1
1904 + * @n1: base of hname (NOT NULL)
1905 + * @n2: name to append (NOT NULL)
1907 + * Returns: new name or NULL on error
1909 +static char *new_compound_name(const char *n1, const char *n2)
1911 + char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
1913 + sprintf(name, "%s//%s", n1, n2);
1918 + * aa_change_hat - change hat to/from subprofile
1919 + * @hats: vector of hat names to try changing into (unused if @count == 0)
1920 + * @count: number of hat names in @hats
1921 + * @token: magic value to validate the hat change
1922 + * @permtest: true if this is just a permission test
1924 + * Change to the first profile specified in @hats that exists, and store
1925 + * the @hat_magic in the current task context. If the count == 0 and the
1926 + * @token matches that stored in the current task context, return to the
1927 + * top level profile.
1929 + * Returns %0 on success, error otherwise.
1931 +int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
1933 + const struct cred *cred;
1934 + struct aa_task_cxt *cxt;
1935 + struct aa_profile *profile, *previous_profile, *hat = NULL;
1936 + struct aa_audit_file sa = {
1937 + .base.gfp_mask = GFP_KERNEL,
1938 + .base.operation = "change_hat",
1939 + .request = AA_MAY_CHANGEHAT,
1941 + char *name = NULL;
1944 + /* released below */
1945 + cred = get_current_cred();
1946 + cxt = cred->security;
1947 + profile = aa_cred_profile(cred);
1948 + previous_profile = cxt->previous;
1950 + if (unconfined(profile)) {
1951 + sa.base.info = "unconfined";
1952 + sa.base.error = -EPERM;
1957 + /* attempting to change into a new hat or switch to a sibling */
1958 + struct aa_profile *root;
1959 + root = PROFILE_IS_HAT(profile) ? profile->parent : profile;
1960 + sa.name2 = profile->ns->base.hname;
1962 + /* find first matching hat */
1963 + for (i = 0; i < count && !hat; i++)
1964 + /* released below */
1965 + hat = aa_find_child(root, hats[i]);
1967 + if (!COMPLAIN_MODE(root) || permtest) {
1968 + sa.base.info = "hat not found";
1969 + if (list_empty(&root->base.profiles))
1970 + sa.base.error = -ECHILD;
1972 + sa.base.error = -ENOENT;
1977 + * In complain mode and failed to match any hats.
1978 + * Audit the failure based off of the first hat
1979 + * supplied. This is done due how userspace
1980 + * interacts with change_hat.
1982 + * TODO: Add logging of all failed hats
1986 + name = new_compound_name(root->base.hname, hats[0]);
1988 + /* released below */
1989 + hat = aa_new_null_profile(profile, 1);
1991 + sa.base.info = "failed null profile create";
1992 + sa.base.error = -ENOMEM;
1996 + sa.name = hat->base.hname;
1997 + if (!PROFILE_IS_HAT(hat)) {
1998 + sa.base.info = "target not hat";
1999 + sa.base.error = -EPERM;
2004 + sa.base.error = aa_may_change_ptraced_domain(current, hat);
2005 + if (sa.base.error) {
2006 + sa.base.info = "ptraced";
2007 + sa.base.error = -EPERM;
2012 + sa.base.error = aa_set_current_hat(hat, token);
2013 + if (sa.base.error == -EACCES)
2014 + /* kill task incase of brute force attacks */
2015 + sa.perms.kill = AA_MAY_CHANGEHAT;
2016 + else if (name && !sa.base.error)
2017 + /* reset error for learning of new hats */
2018 + sa.base.error = -ENOENT;
2020 + } else if (previous_profile) {
2021 + /* Return to saved profile. Kill task if restore fails
2022 + * to avoid brute force attacks
2024 + sa.name = previous_profile->base.hname;
2025 + sa.base.error = aa_restore_previous_profile(token);
2026 + sa.perms.kill = AA_MAY_CHANGEHAT;
2028 + /* ignore restores when there is no saved profile */
2033 + sa.base.error = aa_audit_file(profile, &sa);
2036 + aa_put_profile(hat);
2040 + return sa.base.error;
2044 + * aa_change_profile - perform a one-way profile transition
2045 + * @ns_name: name of the profile namespace to change to
2046 + * @hname: name of profile to change to
2047 + * @onexec: whether this transition is to take place immediately or at exec
2048 + * @permtest: true if this is just a permission test
2050 + * Change to new profile @name. Unlike with hats, there is no way
2051 + * to change back. If @onexec then the transition is delayed until
2054 + * Returns %0 on success, error otherwise.
2056 +int aa_change_profile(const char *ns_name, const char *hname, int onexec,
2059 + const struct cred *cred;
2060 + struct aa_task_cxt *cxt;
2061 + struct aa_profile *profile, *target = NULL;
2062 + struct aa_namespace *ns = NULL;
2063 + struct aa_audit_file sa = {
2064 + .request = AA_MAY_CHANGE_PROFILE,
2065 + .base.gfp_mask = GFP_KERNEL,
2068 + if (!hname && !ns_name)
2072 + sa.base.operation = "change_onexec";
2074 + sa.base.operation = "change_profile";
2076 + cred = get_current_cred();
2077 + cxt = cred->security;
2078 + profile = aa_cred_profile(cred);
2081 + /* released below */
2082 + ns = aa_find_namespace(profile->ns, ns_name);
2084 + /* we don't create new namespace in complain mode */
2085 + sa.name2 = ns_name;
2086 + sa.base.info = "namespace not found";
2087 + sa.base.error = -ENOENT;
2090 + sa.name2 = ns->base.hname;
2092 + /* released below */
2093 + ns = aa_get_namespace(profile->ns);
2094 + sa.name2 = ns->base.hname;
2097 + /* if the name was not specified, use the name of the current profile */
2099 + if (unconfined(profile))
2100 + hname = ns->unconfined->base.hname;
2102 + hname = profile->base.hname;
2106 + sa.perms = change_profile_perms(profile, ns, hname, NULL);
2107 + if (!(sa.perms.allowed & AA_MAY_CHANGE_PROFILE)) {
2108 + sa.base.error = -EACCES;
2112 + /* released below */
2113 + target = aa_find_profile(ns, hname);
2115 + sa.base.info = "profile not found";
2116 + sa.base.error = -ENOENT;
2117 + if (permtest || !COMPLAIN_MODE(profile))
2119 + /* release below */
2120 + target = aa_new_null_profile(profile, 0);
2122 + sa.base.info = "failed null profile create";
2123 + sa.base.error = -ENOMEM;
2128 + /* check if tracing task is allowed to trace target domain */
2129 + sa.base.error = aa_may_change_ptraced_domain(current, target);
2130 + if (sa.base.error) {
2131 + sa.base.info = "ptrace prevents transition";
2139 + sa.base.error = aa_set_current_onexec(target);
2141 + sa.base.error = aa_replace_current_profiles(target);
2145 + sa.base.error = aa_audit_file(profile, &sa);
2147 + aa_put_namespace(ns);
2148 + aa_put_profile(target);
2151 + return sa.base.error;
2153 diff --git a/security/apparmor/file.c b/security/apparmor/file.c
2154 new file mode 100644
2155 index 0000000..43be391
2157 +++ b/security/apparmor/file.c
2160 + * AppArmor security module
2162 + * This file contains AppArmor mediation of files
2164 + * Copyright (C) 1998-2008 Novell/SUSE
2165 + * Copyright 2009-2010 Canonical Ltd.
2167 + * This program is free software; you can redistribute it and/or
2168 + * modify it under the terms of the GNU General Public License as
2169 + * published by the Free Software Foundation, version 2 of the
2173 +#include "include/apparmor.h"
2174 +#include "include/audit.h"
2175 +#include "include/file.h"
2176 +#include "include/match.h"
2177 +#include "include/path.h"
2178 +#include "include/policy.h"
2180 +struct file_perms nullperms;
2183 + * aa_audit_file_sub_mask - convert a permission mask into string
2184 + * @buffer: buffer to write string to (NOT NULL)
2185 + * @mask: permission mask to convert
2188 + * NOTE: caller must make sure buffer is large enough for @mask
2190 +static void aa_audit_file_sub_mask(char *buffer, u16 mask, u16 xindex)
2194 + if (mask & AA_EXEC_MMAP)
2196 + if (mask & MAY_READ)
2198 + if (mask & (MAY_WRITE | AA_MAY_CHMOD | AA_MAY_CHOWN))
2200 + else if (mask & MAY_APPEND)
2202 + if (mask & AA_MAY_CREATE)
2204 + if (mask & AA_MAY_DELETE)
2206 + if (mask & AA_MAY_LINK)
2208 + if (mask & AA_MAY_LOCK)
2210 + if (mask & MAY_EXEC)
2216 + * aa_audit_file_mask - convert mask to owner::other string
2217 + * @buffer: buffer to write string to (NOT NULL)
2218 + * @mask: permission mask to convert
2220 + * @owner: if the mask is for owner or other
2222 +static void aa_audit_file_mask(struct audit_buffer *ab, u16 mask, int xindex,
2228 + aa_audit_file_sub_mask(str, mask, xindex);
2229 + strcat(str, "::");
2231 + strcpy(str, "::");
2232 + aa_audit_file_sub_mask(str + 2, mask, xindex);
2234 + audit_log_string(ab, str);
2238 + * file_audit_cb - call back for file specific audit fields
2239 + * @ab: audit_buffer (NOT NULL)
2240 + * @va: audit struct to audit values of (NOT NULL)
2242 +static void file_audit_cb(struct audit_buffer *ab, struct aa_audit *va)
2244 + struct aa_audit_file *sa = container_of(va, struct aa_audit_file, base);
2245 + u16 denied = sa->request & ~sa->perms.allowed;
2248 + fsuid = current_fsuid();
2250 + if (sa->request & AA_AUDIT_FILE_MASK) {
2251 + audit_log_format(ab, " requested_mask=");
2252 + aa_audit_file_mask(ab, sa->request, AA_X_NONE,
2253 + fsuid == sa->cond->uid);
2255 + if (denied & AA_AUDIT_FILE_MASK) {
2256 + audit_log_format(ab, " denied_mask=");
2257 + aa_audit_file_mask(ab, denied, sa->perms.xindex,
2258 + fsuid == sa->cond->uid);
2260 + if (sa->request & AA_AUDIT_FILE_MASK) {
2261 + audit_log_format(ab, " fsuid=%d", fsuid);
2262 + audit_log_format(ab, " ouid=%d", sa->cond->uid);
2266 + audit_log_format(ab, " name=");
2267 + audit_log_untrustedstring(ab, sa->name);
2271 + audit_log_format(ab, " name2=");
2272 + audit_log_untrustedstring(ab, sa->name2);
2276 + audit_log_format(ab, " name3=");
2277 + audit_log_untrustedstring(ab, sa->name3);
2282 + * aa_audit_file - handle the auditing of file operations
2283 + * @profile: the profile being enforced (NOT NULL)
2284 + * @sa: file auditing context (NOT NULL)
2286 + * Returns: %0 or error on failure
2288 +int aa_audit_file(struct aa_profile *profile, struct aa_audit_file *sa)
2290 + int type = AUDIT_APPARMOR_AUTO;
2292 + if (likely(!sa->base.error)) {
2293 + u16 mask = sa->perms.audit;
2295 + if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
2298 + /* mask off perms that are not being force audited */
2299 + sa->request &= mask;
2301 + if (likely(!sa->request))
2303 + type = AUDIT_APPARMOR_AUDIT;
2305 + /* only report permissions that were denied */
2306 + sa->request = sa->request & ~sa->perms.allowed;
2308 + if (sa->request & sa->perms.kill)
2309 + type = AUDIT_APPARMOR_KILL;
2311 + /* quiet known rejects, assumes quiet and kill do not overlap */
2312 + if ((sa->request & sa->perms.quiet) &&
2313 + AUDIT_MODE(profile) != AUDIT_NOQUIET &&
2314 + AUDIT_MODE(profile) != AUDIT_ALL)
2315 + sa->request &= ~sa->perms.quiet;
2318 + return COMPLAIN_MODE(profile) ? 0 : sa->base.error;
2320 + return aa_audit(type, profile, &sa->base, file_audit_cb);
2324 + * aa_compute_perms - convert dfa compressed perms to internal perms
2325 + * @dfa: dfa to compute perms for (NOT NULL)
2326 + * @state: state in dfa
2327 + * @cond: conditions to consider (NOT NULL)
2329 + * TODO: convert from dfa + state to permission entry, do computation conversion
2332 + * Returns: computed permission set
2334 +static struct file_perms aa_compute_perms(struct aa_dfa *dfa,
2335 + unsigned int state,
2336 + struct path_cond *cond)
2338 + struct file_perms perms;
2340 + /* FIXME: change over to new dfa format
2341 + * currently file perms are encoded in the dfa, new format
2342 + * splits the permissions from the dfa. This mapping can be
2343 + * done at profile load
2348 + if (current_fsuid() == cond->uid) {
2349 + perms.allowed = dfa_user_allow(dfa, state);
2350 + perms.audit = dfa_user_audit(dfa, state);
2351 + perms.quiet = dfa_user_quiet(dfa, state);
2352 + perms.xindex = dfa_user_xindex(dfa, state);
2354 + perms.allowed = dfa_other_allow(dfa, state);
2355 + perms.audit = dfa_other_audit(dfa, state);
2356 + perms.quiet = dfa_other_quiet(dfa, state);
2357 + perms.xindex = dfa_other_xindex(dfa, state);
2359 + /* in the old mapping MAY_WRITE implies
2360 + * AA_MAY_CREATE | AA_MAY_CHMOD | AA_MAY_CHOWN */
2361 + if (perms.allowed & MAY_WRITE)
2362 + perms.allowed |= AA_MAY_CREATE | AA_MAY_CHMOD | AA_MAY_CHOWN |
2364 + if (perms.audit & MAY_WRITE)
2365 + perms.audit |= AA_MAY_CREATE | AA_MAY_CHMOD | AA_MAY_CHOWN |
2367 + if (perms.quiet & MAY_WRITE)
2368 + perms.quiet |= AA_MAY_CREATE | AA_MAY_CHMOD | AA_MAY_CHOWN |
2371 + /* in the old mapping AA_MAY_LOCK and link subset are overlayed
2372 + * and only determined by which part of a pair they are in
2374 + if (perms.allowed & AA_MAY_LOCK)
2375 + perms.allowed |= AA_LINK_SUBSET;
2377 + /* change_profile wasn't determined by ownership in old mapping */
2378 + if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
2379 + perms.allowed |= AA_MAY_CHANGE_PROFILE;
2385 + * aa_str_perms - find permission that match @name
2386 + * @dfa: to match against (NOT NULL)
2387 + * @state: state to start matching in
2388 + * @name: string to match against dfa (NOT NULL)
2389 + * @cond: conditions to consider for permission set computation (NOT NULL)
2390 + * @rstate: if !NULL return state match finished in (MAYBE NULL)
2392 + * TODO: Update when permission mapping is moved to load time
2394 + * Returns: file permission for @name
2396 +struct file_perms aa_str_perms(struct aa_dfa *dfa, unsigned int start,
2397 + const char *name, struct path_cond *cond,
2398 + unsigned int *rstate)
2400 + unsigned int state;
2404 + state = aa_dfa_match(dfa, start, name);
2409 + /* TODO: convert to new dfa format */
2411 + return aa_compute_perms(dfa, state, cond);
2415 + * aa_pathstr_perm - do permission check & audit for @name
2416 + * @profile: profile being enforced (NOT NULL)
2417 + * @op: name of the operation (NOT NULL)
2418 + * @name: path string to check permission for (NOT NULL)
2419 + * @request: requested permissions
2420 + * @cond: conditional info for this request (NOT NULL)
2422 + * Do permission check for paths that are predefined. This fn will
2423 + * be removed once security_sysctl goes away.
2425 + * Returns: %0 else error if access denied or other error
2427 +int aa_pathstr_perm(struct aa_profile *profile, const char *op,
2428 + const char *name, u16 request, struct path_cond *cond)
2430 + struct aa_audit_file sa = {
2431 + .base.operation = op,
2432 + .base.gfp_mask = GFP_KERNEL,
2433 + .request = request,
2438 + sa.perms = aa_str_perms(profile->file.dfa, profile->file.start, sa.name,
2441 + if (request & ~sa.perms.allowed)
2442 + sa.base.error = -EACCES;
2443 + return aa_audit_file(profile, &sa);
2447 + * aa_path_perm - do permissions check & audit for @path
2448 + * @profile: profile being enforced (NOT NULL)
2449 + * @operation: name of the operation being enforced (NOT NULL)
2450 + * @path: path to check permissions of (NOT NULL)
2451 + * @request: requested permissions
2452 + * @cond: conditional info for this request (NOT NULL)
2454 + * Returns: %0 else error if access denied or other error
2456 +int aa_path_perm(struct aa_profile *profile, const char *operation,
2457 + struct path *path, u16 request, struct path_cond *cond)
2459 + char *buffer, *name;
2460 + struct aa_audit_file sa = {
2461 + .base.operation = operation,
2462 + .base.gfp_mask = GFP_KERNEL,
2463 + .request = request,
2466 + int flags = profile->path_flags |
2467 + (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
2468 + /* buffer freed below - name is pointer inside buffer */
2469 + sa.base.error = aa_get_name(path, flags, &buffer, &name);
2471 + if (sa.base.error) {
2472 + sa.perms = nullperms;
2473 + if (sa.base.error == -ENOENT)
2474 + sa.base.info = "Failed name lookup - deleted entry";
2475 + else if (sa.base.error == -ESTALE)
2476 + sa.base.info = "Failed name lookup - disconnected path";
2477 + else if (sa.base.error == -ENAMETOOLONG)
2478 + sa.base.info = "Failed name lookup - name too long";
2480 + sa.base.info = "Failed name lookup";
2482 + sa.perms = aa_str_perms(profile->file.dfa, profile->file.start,
2483 + sa.name, cond, NULL);
2484 + if (request & ~sa.perms.allowed)
2485 + sa.base.error = -EACCES;
2487 + sa.base.error = aa_audit_file(profile, &sa);
2490 + return sa.base.error;
2494 + * xindex_is_subset - helper for aa_path_link
2495 + * @link: link permission set
2496 + * @target: target permission set
2498 + * test target x permissions are equal OR a subset of link x permissions
2499 + * this is done as part of the subset test, where a hardlink must have
2500 + * a subset of permissions that the target has.
2502 + * Returns: %1 if subset else %0
2504 +static inline bool xindex_is_subset(u16 link, u16 target)
2506 + if (((link & ~AA_X_UNSAFE) != (target & ~AA_X_UNSAFE)) ||
2507 + ((link & AA_X_UNSAFE) && !(target & AA_X_UNSAFE)))
2514 + * aa_path_link - Handle hard link permission check
2515 + * @profile: the profile being enforced (NOT NULL)
2516 + * @old_dentry: the target dentry (NOT NULL)
2517 + * @new_dir: directory the new link will be created in (NOT NULL)
2518 + * @new_dentry: the link being created (NOT NULL)
2520 + * Handle the permission test for a link & target pair. Permission
2521 + * is encoded as a pair where the link permission is determined
2522 + * first, and if allowed, the target is tested. The target test
2523 + * is done from the point of the link match (not start of DFA)
2524 + * making the target permission dependent on the link permission match.
2526 + * The subset test if required forces that permissions granted
2527 + * on link are a subset of the permission granted to target.
2529 + * Returns: %0 if allowed else error
2531 +int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
2532 + struct path *new_dir, struct dentry *new_dentry)
2534 + struct path link = { new_dir->mnt, new_dentry };
2535 + struct path target = { new_dir->mnt, old_dentry };
2536 + struct path_cond cond = {
2537 + old_dentry->d_inode->i_uid,
2538 + old_dentry->d_inode->i_mode
2540 + char *buffer = NULL, *buffer2 = NULL;
2541 + char *lname, *tname;
2542 + struct file_perms perms;
2543 + unsigned int state;
2545 + struct aa_audit_file sa = {
2546 + .base.operation = "link",
2547 + .base.gfp_mask = GFP_KERNEL,
2548 + .request = AA_MAY_LINK,
2550 + .perms = nullperms,
2552 + /* buffer freed below, lname is pointer in buffer */
2553 + sa.base.error = aa_get_name(&link, profile->path_flags, &buffer,
2556 + if (sa.base.error)
2559 + /* buffer2 freed below, tname is pointer in buffer2 */
2560 + sa.base.error = aa_get_name(&target, profile->path_flags, &buffer2,
2563 + if (sa.base.error)
2566 + sa.base.error = -EACCES;
2568 + /* aa_str_perms - handles the case of the dfa being NULL */
2569 + sa.perms = aa_str_perms(profile->file.dfa, profile->file.start, lname,
2571 + sa.perms.audit &= AA_MAY_LINK;
2572 + sa.perms.quiet &= AA_MAY_LINK;
2573 + sa.perms.kill &= AA_MAY_LINK;
2575 + if (!(sa.perms.allowed & AA_MAY_LINK))
2578 + /* test to see if target can be paired with link */
2579 + state = aa_dfa_null_transition(profile->file.dfa, state,
2580 + profile->flags & PFLAG_OLD_NULL_TRANS);
2581 + perms = aa_str_perms(profile->file.dfa, state, tname, &cond, NULL);
2582 + if (!(perms.allowed & AA_MAY_LINK)) {
2583 + sa.base.info = "target restricted";
2587 + /* done if link subset test is not required */
2588 + if (!(perms.allowed & AA_LINK_SUBSET))
2591 + /* Do link perm subset test requiring allowed permission on link are a
2592 + * subset of the allowed permissions on target.
2594 + perms = aa_str_perms(profile->file.dfa, profile->file.start, tname,
2597 + /* AA_MAY_LINK is not considered in the subset test */
2598 + sa.request = sa.perms.allowed & ~AA_MAY_LINK;
2599 + sa.perms.allowed &= perms.allowed | AA_MAY_LINK;
2601 + sa.request |= AA_AUDIT_FILE_MASK & (sa.perms.allowed & ~perms.allowed);
2602 + if (sa.request & ~sa.perms.allowed) {
2604 + } else if ((sa.perms.allowed & MAY_EXEC) &&
2605 + !xindex_is_subset(sa.perms.xindex, perms.xindex)) {
2606 + sa.perms.allowed &= ~MAY_EXEC;
2607 + sa.request |= MAY_EXEC;
2608 + sa.base.info = "link not subset of target";
2613 + sa.base.error = 0;
2616 + sa.base.error = aa_audit_file(profile, &sa);
2620 + return sa.base.error;
2624 + * aa_is_deleted_file - test if a file has been completely unlinked
2625 + * @dentry: dentry of file to test for deletion (NOT NULL)
2627 + * Returns: %1 if deleted else %0
2629 +static inline bool aa_is_deleted_file(struct dentry *dentry)
2631 + if (d_unlinked(dentry) && dentry->d_inode->i_nlink == 0)
2637 + * aa_file_common_perm - core permission check & audit for files
2638 + * @profile: profile being enforced (NOT NULL)
2639 + * @operation: name of operation (NOT NULL)
2640 + * @file: file to check permissions of (NOT NULL)
2641 + * @request: requested permissions
2642 + * @name: path name to revalidate permission on (MAYBE NULL if @error != 0)
2643 + * @error: error result of name lookup when find @name
2645 + * Returns: %0 if access allowed else %1
2647 +static int aa_file_common_perm(struct aa_profile *profile,
2648 + const char *operation, struct file *file,
2649 + u16 request, const char *name, int error)
2651 + struct path_cond cond = {
2652 + .uid = file->f_path.dentry->d_inode->i_uid,
2653 + .mode = file->f_path.dentry->d_inode->i_mode
2655 + struct aa_audit_file sa = {
2656 + .base.operation = operation,
2657 + .base.gfp_mask = GFP_KERNEL,
2658 + .request = request,
2659 + .base.error = error,
2664 + if (sa.base.error) {
2665 + sa.perms = nullperms;
2666 + if (sa.base.error == -ENOENT &&
2667 + aa_is_deleted_file(file->f_path.dentry)) {
2668 + /* Access to open files that are deleted are
2669 + * give a pass (implicit delegation)
2671 + sa.base.error = 0;
2672 + sa.perms.allowed = sa.request;
2673 + } else if (sa.base.error == -ENOENT)
2674 + sa.base.info = "Failed name lookup - deleted entry";
2675 + else if (sa.base.error == -ESTALE)
2676 + sa.base.info = "Failed name lookup - disconnected path";
2677 + else if (sa.base.error == -ENAMETOOLONG)
2678 + sa.base.info = "Failed name lookup - name too long";
2680 + sa.base.info = "Failed name lookup";
2682 + sa.perms = aa_str_perms(profile->file.dfa, profile->file.start,
2683 + sa.name, &cond, NULL);
2684 + if (request & ~sa.perms.allowed)
2685 + sa.base.error = -EACCES;
2687 + sa.base.error = aa_audit_file(profile, &sa);
2689 + return sa.base.error;
2693 + * aa_file_perm - do permission revalidation check & audit for @file
2694 + * @profile: profile being enforced (NOT NULL)
2695 + * @operation: name of the operation (NOT NULL)
2696 + * @file: file to revalidate access permissions on (NOT NULL)
2697 + * @request: requested permissions
2699 + * Returns: %0 if access allowed else error
2701 +int aa_file_perm(struct aa_profile *profile, const char *operation,
2702 + struct file *file, u16 request)
2704 + char *buffer, *name;
2705 + umode_t mode = file->f_path.dentry->d_inode->i_mode;
2706 + /* buffer freed below, name is a pointer inside of buffer */
2707 + int flags = profile->path_flags | (S_ISDIR(mode) ? PATH_IS_DIR : 0);
2708 + int error = aa_get_name(&file->f_path, flags, &buffer, &name);
2710 + error = aa_file_common_perm(profile, operation, file, request, name,
2715 diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
2716 new file mode 100644
2717 index 0000000..25c1647
2719 +++ b/security/apparmor/include/apparmor.h
2722 + * AppArmor security module
2724 + * This file contains AppArmor basic global and lib definitions
2726 + * Copyright (C) 1998-2008 Novell/SUSE
2727 + * Copyright 2009-2010 Canonical Ltd.
2729 + * This program is free software; you can redistribute it and/or
2730 + * modify it under the terms of the GNU General Public License as
2731 + * published by the Free Software Foundation, version 2 of the
2735 +#ifndef __APPARMOR_H
2736 +#define __APPARMOR_H
2738 +#include <linux/fs.h>
2742 +/* Control parameters settable thru module/boot flags or
2743 + * via /sys/kernel/security/apparmor/control */
2744 +extern enum audit_mode aa_g_audit;
2745 +extern int aa_g_audit_header;
2746 +extern int aa_g_debug;
2747 +extern int aa_g_lock_policy;
2748 +extern int aa_g_logsyscall;
2749 +extern int aa_g_paranoid_load;
2750 +extern unsigned int aa_g_path_max;
2753 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
2754 + * which is not related to profile accesses.
2757 +#define AA_DEBUG(fmt, args...) \
2759 + if (aa_g_debug && printk_ratelimit()) \
2760 + printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
2763 +#define AA_ERROR(fmt, args...) \
2765 + if (printk_ratelimit()) \
2766 + printk(KERN_ERR "AppArmor: " fmt, ##args); \
2769 +/* Flag indicating whether initialization completed */
2770 +extern int apparmor_initialized;
2771 +void apparmor_disable(void);
2774 +char *aa_split_fqname(char *args, char **ns_name);
2775 +bool aa_strneq(const char *str, const char *sub, int len);
2776 +void aa_info_message(const char *str);
2779 + * aa_dfa_null_transition - step to next state after null character
2780 + * @dfa: the dfa to match against
2781 + * @start: the state of the dfa to start matching in
2782 + * @old: true if using // as the null transition
2784 + * aa_dfa_null_transition transitions to the next state after a null
2785 + * character which is not used in standard matching and is only
2786 + * used to seperate pairs.
2788 +static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
2789 + unsigned int start, bool old)
2791 + if (unlikely(old))
2792 + return aa_dfa_match_len(dfa, start, "//", 2);
2794 + return aa_dfa_match_len(dfa, start, "\0", 1);
2797 +static inline bool mediated_filesystem(struct inode *inode)
2799 + return !(inode->i_sb->s_flags & MS_NOUSER);
2802 +#endif /* __APPARMOR_H */
2803 diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
2804 new file mode 100644
2805 index 0000000..d071bf1
2807 +++ b/security/apparmor/include/apparmorfs.h
2810 + * AppArmor security module
2812 + * This file contains AppArmor filesystem definitions.
2814 + * Copyright (C) 1998-2008 Novell/SUSE
2815 + * Copyright 2009-2010 Canonical Ltd.
2817 + * This program is free software; you can redistribute it and/or
2818 + * modify it under the terms of the GNU General Public License as
2819 + * published by the Free Software Foundation, version 2 of the
2823 +#ifndef __AA_APPARMORFS_H
2824 +#define __AA_APPARMORFS_H
2826 +extern struct dentry *aa_fs_null;
2827 +extern struct vfsmount *aa_fs_mnt;
2829 +extern void aa_destroy_aafs(void);
2831 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
2832 +extern const struct file_operations aa_fs_matching_fops;
2833 +extern const struct file_operations aa_fs_features_fops;
2836 +#endif /* __AA_APPARMORFS_H */
2837 diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
2838 new file mode 100644
2839 index 0000000..d86cfee
2841 +++ b/security/apparmor/include/audit.h
2844 + * AppArmor security module
2846 + * This file contains AppArmor auditing function definitions.
2848 + * Copyright (C) 1998-2008 Novell/SUSE
2849 + * Copyright 2009-2010 Canonical Ltd.
2851 + * This program is free software; you can redistribute it and/or
2852 + * modify it under the terms of the GNU General Public License as
2853 + * published by the Free Software Foundation, version 2 of the
2857 +#ifndef __AA_AUDIT_H
2858 +#define __AA_AUDIT_H
2860 +#include <linux/audit.h>
2861 +#include <linux/fs.h>
2862 +#include <linux/sched.h>
2863 +#include <linux/slab.h>
2867 +extern const char *audit_mode_names[];
2868 +#define AUDIT_MAX_INDEX 5
2870 +#define AUDIT_APPARMOR_AUTO 0 /* auto choose audit message type */
2873 + AUDIT_NORMAL, /* follow normal auditing of accesses */
2874 + AUDIT_QUIET_DENIED, /* quiet all denied access messages */
2875 + AUDIT_QUIET, /* quiet all messages */
2876 + AUDIT_NOQUIET, /* do not quiet audit messages */
2877 + AUDIT_ALL /* audit all accesses */
2881 + * aa_audit - AppArmor auditing structure
2882 + * Structure is populated by access control code and passed to aa_audit which
2883 + * provides for a single point of logging.
2886 + struct task_struct *task;
2889 + const char *operation;
2893 +int aa_audit(int type, struct aa_profile *profile, struct aa_audit *sa,
2894 + void (*cb) (struct audit_buffer *, struct aa_audit *));
2896 +#endif /* __AA_AUDIT_H */
2897 diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
2898 new file mode 100644
2899 index 0000000..8287e9d
2901 +++ b/security/apparmor/include/capability.h
2904 + * AppArmor security module
2906 + * This file contains AppArmor capability mediation definitions.
2908 + * Copyright (C) 1998-2008 Novell/SUSE
2909 + * Copyright 2009-2010 Canonical Ltd.
2911 + * This program is free software; you can redistribute it and/or
2912 + * modify it under the terms of the GNU General Public License as
2913 + * published by the Free Software Foundation, version 2 of the
2917 +#ifndef __AA_CAPABILITY_H
2918 +#define __AA_CAPABILITY_H
2920 +#include <linux/sched.h>
2924 +/* aa_caps - confinement data for capabilities
2925 + * @allowed: capabilities mask
2926 + * @audit: caps that are to be audited
2927 + * @quiet: caps that should not be audited
2928 + * @kill: caps that when requested will result in the task being killed
2929 + * @extended: caps that are subject finer grained mediation
2932 + kernel_cap_t allowed;
2933 + kernel_cap_t audit;
2934 + kernel_cap_t quiet;
2935 + kernel_cap_t kill;
2936 + kernel_cap_t extended;
2939 +int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
2942 +static inline void aa_free_cap_rules(struct aa_caps *caps)
2947 +#endif /* __AA_CAPBILITY_H */
2948 diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h
2949 new file mode 100644
2950 index 0000000..1560adc
2952 +++ b/security/apparmor/include/context.h
2955 + * AppArmor security module
2957 + * This file contains AppArmor contexts used to associate "labels" to objects.
2959 + * Copyright (C) 1998-2008 Novell/SUSE
2960 + * Copyright 2009-2010 Canonical Ltd.
2962 + * This program is free software; you can redistribute it and/or
2963 + * modify it under the terms of the GNU General Public License as
2964 + * published by the Free Software Foundation, version 2 of the
2968 +#ifndef __AA_CONTEXT_H
2969 +#define __AA_CONTEXT_H
2971 +#include <linux/cred.h>
2972 +#include <linux/slab.h>
2973 +#include <linux/sched.h>
2975 +#include "policy.h"
2977 +/* struct aa_file_cxt - the AppArmor context the file was opened in
2978 + * @profile: the profile the file was opened under
2979 + * @perms: the permission the file was opened with
2981 +struct aa_file_cxt {
2982 + struct aa_profile *profile;
2987 + * aa_alloc_file_context - allocate file_cxt
2988 + * @gfp: gfp flags for allocation
2990 + * Returns: file_cxt or NULL on failure
2992 +static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp)
2994 + return kzalloc(sizeof(struct aa_file_cxt), gfp);
2998 + * aa_free_file_context - free a file_cxt
2999 + * @cxt: file_cxt to free (MAYBE_NULL)
3001 +static inline void aa_free_file_context(struct aa_file_cxt *cxt)
3004 + aa_put_profile(cxt->profile);
3010 + * struct aa_task_cxt - primary label for confined tasks
3011 + * @profile: the current profile (NOT NULL)
3012 + * @exec: profile to transition to on next exec (MAYBE NULL)
3013 + * @previous: profile the task may return to (MAYBE NULL)
3014 + * @token: magic value the task must know for returning to @previous_profile
3016 + * Contains the task's current profile (which could change due to
3017 + * change_hat). Plus the hat_magic needed during change_hat.
3019 + * TODO: make so a task can be confined by a stack of contexts
3021 +struct aa_task_cxt {
3022 + struct aa_profile *profile;
3023 + struct aa_profile *onexec;
3024 + struct aa_profile *previous;
3028 +struct aa_task_cxt *aa_alloc_task_context(gfp_t flags);
3029 +void aa_free_task_context(struct aa_task_cxt *cxt);
3030 +void aa_dup_task_context(struct aa_task_cxt *new,
3031 + const struct aa_task_cxt *old);
3032 +int aa_replace_current_profiles(struct aa_profile *profile);
3033 +int aa_set_current_onexec(struct aa_profile *profile);
3034 +int aa_set_current_hat(struct aa_profile *profile, u64 token);
3035 +int aa_restore_previous_profile(u64 cookie);
3038 + * __aa_task_is_confined - determine if @task has any confinement
3039 + * @task: task to check confinement of (NOT NULL)
3041 + * If @task != current needs to be called in RCU safe critical section
3043 +static inline bool __aa_task_is_confined(struct task_struct *task)
3045 + struct aa_task_cxt *cxt = __task_cred(task)->security;
3047 + BUG_ON(!cxt || !cxt->profile);
3048 + if (unconfined(aa_newest_version(cxt->profile)))
3055 + * aa_cred_profile - obtain cred's profiles
3056 + * @cred: cred to obtain profiles from (NOT NULL)
3058 + * Returns: confining profile
3060 + * does NOT increment reference count
3062 +static inline struct aa_profile *aa_cred_profile(const struct cred *cred)
3064 + struct aa_task_cxt *cxt = cred->security;
3065 + BUG_ON(!cxt || !cxt->profile);
3066 + return aa_newest_version(cxt->profile);
3070 + * __aa_current_profile - find the current tasks confining profile
3072 + * Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
3074 + * This fn will not update the tasks cred to the most up to date version
3075 + * of the profile so it is safe to call when inside of locks.
3077 +static inline struct aa_profile *__aa_current_profile(void)
3079 + return aa_cred_profile(current_cred());
3083 + * aa_current_profile - find the current tasks confining profile and do updates
3085 + * Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
3087 + * This fn will update the tasks cred structure if the profile has been
3088 + * replaced. Not safe to call inside locks
3090 +static inline struct aa_profile *aa_current_profile(void)
3092 + const struct aa_task_cxt *cxt = current_cred()->security;
3093 + struct aa_profile *profile;
3094 + BUG_ON(!cxt || !cxt->profile);
3096 + profile = aa_newest_version(cxt->profile);
3098 + * Whether or not replacement succeeds, use newest profile so
3099 + * there is no need to update it after replacement.
3101 + if (unlikely((cxt->profile != profile)))
3102 + aa_replace_current_profiles(profile);
3107 +#endif /* __AA_CONTEXT_H */
3108 diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
3109 new file mode 100644
3110 index 0000000..b1ba488
3112 +++ b/security/apparmor/include/domain.h
3115 + * AppArmor security module
3117 + * This file contains AppArmor security domain transition function definitions.
3119 + * Copyright (C) 1998-2008 Novell/SUSE
3120 + * Copyright 2009-2010 Canonical Ltd.
3122 + * This program is free software; you can redistribute it and/or
3123 + * modify it under the terms of the GNU General Public License as
3124 + * published by the Free Software Foundation, version 2 of the
3128 +#include <linux/binfmts.h>
3129 +#include <linux/types.h>
3131 +#ifndef __AA_DOMAIN_H
3132 +#define __AA_DOMAIN_H
3139 +int apparmor_bprm_set_creds(struct linux_binprm *bprm);
3140 +int apparmor_bprm_secureexec(struct linux_binprm *bprm);
3141 +void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
3142 +void apparmor_bprm_committed_creds(struct linux_binprm *bprm);
3144 +void aa_free_domain_entries(struct aa_domain *domain);
3145 +int aa_change_hat(const char *hats[], int count, u64 token, bool permtest);
3146 +int aa_change_profile(const char *ns_name, const char *name, int onexec,
3149 +#endif /* __AA_DOMAIN_H */
3150 diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
3151 new file mode 100644
3152 index 0000000..559f085
3154 +++ b/security/apparmor/include/file.h
3157 + * AppArmor security module
3159 + * This file contains AppArmor file mediation function definitions.
3161 + * Copyright (C) 1998-2008 Novell/SUSE
3162 + * Copyright 2009-2010 Canonical Ltd.
3164 + * This program is free software; you can redistribute it and/or
3165 + * modify it under the terms of the GNU General Public License as
3166 + * published by the Free Software Foundation, version 2 of the
3170 +#ifndef __AA_FILE_H
3171 +#define __AA_FILE_H
3173 +#include <linux/path.h>
3176 +#include "domain.h"
3182 + * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags
3183 + * for profile permissions
3185 +#define AA_MAY_LINK 0x0010
3186 +#define AA_MAY_LOCK 0x0020
3187 +#define AA_EXEC_MMAP 0x0040
3189 +#define AA_MAY_CREATE 0x0080
3190 +#define AA_MAY_DELETE 0x0100
3191 +#define AA_MAY_CHMOD 0x0200
3192 +#define AA_MAY_CHOWN 0x0400
3194 +#define AA_LINK_SUBSET 0x0800
3195 +#define AA_MAY_CHANGEHAT 0x2000 /* ctrl auditing only */
3196 +#define AA_MAY_ONEXEC 0x4000 /* exec allows onexec */
3197 +#define AA_MAY_CHANGE_PROFILE 0x8000
3199 +#define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\
3200 + AA_MAY_LINK | AA_MAY_LOCK | AA_EXEC_MMAP | \
3201 + AA_MAY_CREATE | AA_MAY_DELETE | AA_MAY_CHMOD |\
3205 + * The xindex is broken into 3 parts
3206 + * - index - an index into either the exec name table or the variable table
3207 + * - exec type - which determines how the executable name and index are used
3208 + * - flags - which modify how the destination name is applied
3210 +#define AA_X_INDEX_MASK 0x03ff
3212 +#define AA_X_TYPE_MASK 0x0c00
3213 +#define AA_X_TYPE_SHIFT 10
3214 +#define AA_X_NONE 0x0000
3215 +#define AA_X_NAME 0x0400 /* use executable name px */
3216 +#define AA_X_TABLE 0x0800 /* use a specified name ->n# */
3218 +#define AA_X_UNSAFE 0x1000
3219 +#define AA_X_CHILD 0x2000 /* make >AA_X_NONE apply to children */
3220 +#define AA_X_INHERIT 0x4000
3221 +#define AA_X_UNCONFINED 0x8000
3223 +/* AA_SECURE_X_NEEDED - is passed in the bprm->unsafe field */
3224 +#define AA_SECURE_X_NEEDED 0x8000
3226 +/* need to conditionalize which ones are being set */
3232 +/* struct file_perms - file permission fo
3233 + * @allowed: mask of permissions that are allowed
3234 + * @audit: mask of permissions to force an audit message for
3235 + * @quiet: mask of permissions to quiet audit messages for
3236 + * @kill: mask of permissions that when matched will kill the task
3237 + * @xindex: exec transition index if @allowed contains MAY_EXEC
3238 + * @xdelegate: used by exec to determine set of delegates allowed
3239 + * @dindex: delegate table index, 0 if no delegation allowed
3241 + * The @audit and @queit mask should be mutually exclusive.
3243 +struct file_perms {
3253 +extern struct file_perms nullperms;
3255 +#define COMBINED_PERM_MASK(X) ((X).allowed | (X).audit | (X).quiet | (X).kill)
3257 +/* FIXME: split perms from dfa and match this to description
3258 + * also add delegation info.
3260 +static inline u16 dfa_map_xindex(u16 mask)
3262 + u16 old_index = (mask >> 10) & 0xf;
3266 + index |= AA_X_UNSAFE;
3268 + index |= AA_X_INHERIT;
3270 + index |= AA_X_UNCONFINED;
3272 + if (old_index == 1) {
3273 + index |= AA_X_UNCONFINED;
3274 + } else if (old_index == 2) {
3275 + index |= AA_X_NAME;
3276 + } else if (old_index == 3) {
3277 + index |= AA_X_NAME | AA_X_CHILD;
3279 + index |= AA_X_TABLE;
3280 + index |= old_index - 4;
3287 + * map old dfa inline permissions to new format
3289 +#define dfa_user_allow(dfa, state) ((ACCEPT_TABLE(dfa)[state]) & 0x7f)
3290 +#define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f)
3291 +#define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f)
3292 +#define dfa_user_xindex(dfa, state) \
3293 + (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff))
3295 +#define dfa_other_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) >> 14) & 0x7f)
3296 +#define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f)
3297 +#define dfa_other_quiet(dfa, state) \
3298 + ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f)
3299 +#define dfa_other_xindex(dfa, state) \
3300 + dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
3302 +struct aa_audit_file {
3303 + struct aa_audit base;
3306 + const char *name2;
3307 + const char *name3;
3308 + struct file_perms perms;
3310 + struct path_cond *cond;
3313 +int aa_audit_file(struct aa_profile *profile, struct aa_audit_file *sa);
3316 + * struct aa_file_rules - components used for file rule permissions
3317 + * @dfa: dfa to match path names and conditionals against
3318 + * @perms: permission table indexed by the matched state accept entry of @dfa
3319 + * @trans: transition table for indexed by named x transitions
3321 + * File permission are determined by matching a path against @dfa and then
3322 + * then using the value of the accept entry for the matching state as
3323 + * an index into @perms. If a named exec transition is required it is
3324 + * looked up in the transition table.
3326 +struct aa_file_rules {
3327 + unsigned int start;
3328 + struct aa_dfa *dfa;
3329 + /* struct perms perms; */
3330 + struct aa_domain trans;
3331 + /* TODO: add delegate table */
3334 +struct file_perms aa_str_perms(struct aa_dfa *dfa, unsigned int start,
3335 + const char *name, struct path_cond *cond,
3336 + unsigned int *rstate);
3338 +int aa_pathstr_perm(struct aa_profile *profile, const char *op,
3339 + const char *name, u16 request, struct path_cond *cond);
3341 +int aa_path_perm(struct aa_profile *profile, const char *operation,
3342 + struct path *path, u16 request, struct path_cond *cond);
3344 +int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
3345 + struct path *new_dir, struct dentry *new_dentry);
3347 +int aa_file_perm(struct aa_profile *profile, const char *operation,
3348 + struct file *file, u16 request);
3350 +static inline void aa_free_file_rules(struct aa_file_rules *rules)
3352 + aa_put_dfa(rules->dfa);
3353 + aa_free_domain_entries(&rules->trans);
3356 +#define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40))
3359 +#define MAP_OPEN_FLAGS(x) ((((x) + 1) & O_ACCMODE) ? (x) + 1 : (x))
3362 + * aa_map_file_perms - map file flags to AppArmor permissions
3363 + * @file: open file to map flags to AppArmor permissions
3365 + * Returns: apparmor permission set for the file
3367 +static inline u16 aa_map_file_to_perms(struct file *file)
3369 + int flags = MAP_OPEN_FLAGS(file->f_flags);
3370 + u16 perms = ACC_FMODE(file->f_mode);
3372 + if ((flags & O_APPEND) && (perms & MAY_WRITE))
3373 + perms = (perms & ~MAY_WRITE) | MAY_APPEND;
3374 + /* trunc implies write permission */
3375 + if (flags & O_TRUNC)
3376 + perms |= MAY_WRITE;
3377 + if (flags & O_CREAT)
3378 + perms |= AA_MAY_CREATE;
3383 +#endif /* __AA_FILE_H */
3384 diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h
3385 new file mode 100644
3386 index 0000000..aeda0fb
3388 +++ b/security/apparmor/include/ipc.h
3391 + * AppArmor security module
3393 + * This file contains AppArmor ipc mediation function definitions.
3395 + * Copyright (C) 1998-2008 Novell/SUSE
3396 + * Copyright 2009-2010 Canonical Ltd.
3398 + * This program is free software; you can redistribute it and/or
3399 + * modify it under the terms of the GNU General Public License as
3400 + * published by the Free Software Foundation, version 2 of the
3407 +#include <linux/sched.h>
3411 +int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
3412 + struct aa_profile *tracee, unsigned int mode);
3414 +int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
3415 + unsigned int mode);
3417 +#endif /* __AA_IPC_H */
3418 diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
3419 new file mode 100644
3420 index 0000000..5465d4d
3422 +++ b/security/apparmor/include/match.h
3425 + * AppArmor security module
3427 + * This file contains AppArmor policy dfa matching engine definitions.
3429 + * Copyright (C) 1998-2008 Novell/SUSE
3430 + * Copyright 2009-2010 Canonical Ltd.
3432 + * This program is free software; you can redistribute it and/or
3433 + * modify it under the terms of the GNU General Public License as
3434 + * published by the Free Software Foundation, version 2 of the
3438 +#ifndef __AA_MATCH_H
3439 +#define __AA_MATCH_H
3441 +#define DFA_NOMATCH 0
3442 +#define DFA_START 1
3444 +#define DFA_VALID_PERM_MASK 0xffffffff
3445 +#define DFA_VALID_PERM2_MASK 0xffffffff
3448 + * The format used for transition tables is based on the GNU flex table
3449 + * file format (--tables-file option; see Table File Format in the flex
3450 + * info pages and the flex sources for documentation). The magic number
3451 + * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
3452 + * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
3453 + * slightly differently (see the apparmor-parser package).
3456 +#define YYTH_MAGIC 0x1B5E783D
3457 +#define YYTH_DEF_RECURSE 0x1 /* DEF Table is recursive */
3459 +struct table_set_header {
3460 + u32 th_magic; /* YYTH_MAGIC */
3464 + char th_version[];
3467 +/* The YYTD_ID are one less than flex table mappings. The flex id
3468 + * has 1 subtracted at table load time, this allows us to directly use the
3469 + * ID's as indexes.
3471 +#define YYTD_ID_ACCEPT 0
3472 +#define YYTD_ID_BASE 1
3473 +#define YYTD_ID_CHK 2
3474 +#define YYTD_ID_DEF 3
3475 +#define YYTD_ID_EC 4
3476 +#define YYTD_ID_META 5
3477 +#define YYTD_ID_ACCEPT2 6
3478 +#define YYTD_ID_NXT 7
3479 +#define YYTD_ID_TSIZE 8
3481 +#define YYTD_DATA8 1
3482 +#define YYTD_DATA16 2
3483 +#define YYTD_DATA32 4
3484 +#define YYTD_DATA64 8
3486 +/* Each ACCEPT2 table gets 6 dedicated flags, YYTD_DATAX define the
3489 +#define ACCEPT1_FLAGS(X) ((X) & 0x3f)
3490 +#define ACCEPT2_FLAGS(X) ACCEPT1_FLAGS((X) >> YYTD_ID_ACCEPT2)
3491 +#define TO_ACCEPT1_FLAG(X) ACCEPT1_FLAGS(X)
3492 +#define TO_ACCEPT2_FLAG(X) (ACCEPT1_FLAGS(X) << YYTD_ID_ACCEPT2)
3493 +#define DFA_FLAG_VERIFY_STATES 0x1000
3495 +struct table_header {
3503 +#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF]->td_data))
3504 +#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE]->td_data))
3505 +#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT]->td_data))
3506 +#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK]->td_data))
3507 +#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC]->td_data))
3508 +#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT]->td_data))
3509 +#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2]->td_data))
3512 + struct kref count;
3514 + struct table_header *tables[YYTD_ID_TSIZE];
3517 +#define byte_to_byte(X) (X)
3519 +#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
3521 + typeof(LEN) __i; \
3522 + TYPE *__t = (TYPE *) TABLE; \
3523 + TYPE *__b = (TYPE *) BLOB; \
3524 + for (__i = 0; __i < LEN; __i++) { \
3525 + __t[__i] = NTOHX(__b[__i]); \
3529 +static inline size_t table_size(size_t len, size_t el_size)
3531 + return ALIGN(sizeof(struct table_header) + len * el_size, 8);
3534 +struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
3535 +unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
3536 + const char *str, int len);
3537 +unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
3539 +void aa_dfa_free_kref(struct kref *kref);
3542 + * aa_put_dfa - put a dfa refcount
3543 + * @dfa: dfa to put refcount (MAYBE NULL)
3545 + * Requires: if @dfa != NULL that valid refcount be held
3547 +static inline void aa_put_dfa(struct aa_dfa *dfa)
3550 + kref_put(&dfa->count, aa_dfa_free_kref);
3553 +#endif /* __AA_MATCH_H */
3554 diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
3555 new file mode 100644
3556 index 0000000..7d6ddeb
3558 +++ b/security/apparmor/include/net.h
3561 + * AppArmor security module
3563 + * This file contains AppArmor network mediation definitions.
3565 + * Copyright (C) 1998-2008 Novell/SUSE
3566 + * Copyright 2009-2010 Canonical Ltd.
3568 + * This program is free software; you can redistribute it and/or
3569 + * modify it under the terms of the GNU General Public License as
3570 + * published by the Free Software Foundation, version 2 of the
3577 +#include <net/sock.h>
3579 +/* struct aa_net - network confinement data
3580 + * @allowed: basic network families permissions
3581 + * @audit_network: which network permissions to force audit
3582 + * @quiet_network: which network permissions to quiet rejects
3585 + u16 allowed[AF_MAX];
3586 + u16 audit[AF_MAX];
3587 + u16 quiet[AF_MAX];
3590 +extern int aa_net_perm(struct aa_profile *profile, char *operation,
3591 + int family, int type, int protocol);
3592 +extern int aa_revalidate_sk(struct sock *sk, char *operation);
3594 +static inline void aa_free_net_rules(struct aa_net *new)
3599 +#endif /* __AA_NET_H */
3600 diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
3601 new file mode 100644
3602 index 0000000..6933d64
3604 +++ b/security/apparmor/include/path.h
3607 + * AppArmor security module
3609 + * This file contains AppArmor basic path manipulation function definitions.
3611 + * Copyright (C) 1998-2008 Novell/SUSE
3612 + * Copyright 2009-2010 Canonical Ltd.
3614 + * This program is free software; you can redistribute it and/or
3615 + * modify it under the terms of the GNU General Public License as
3616 + * published by the Free Software Foundation, version 2 of the
3620 +#ifndef __AA_PATH_H
3621 +#define __AA_PATH_H
3625 + PATH_IS_DIR = 0x1, /* path is a directory */
3626 + PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */
3627 + PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */
3628 + PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */
3630 + PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */
3633 +int aa_get_name(struct path *path, int flags, char **buffer, char **name);
3634 +char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen);
3636 +#endif /* __AA_PATH_H */
3637 diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
3638 new file mode 100644
3639 index 0000000..56fc38a
3641 +++ b/security/apparmor/include/policy.h
3644 + * AppArmor security module
3646 + * This file contains AppArmor policy definitions.
3648 + * Copyright (C) 1998-2008 Novell/SUSE
3649 + * Copyright 2009-2010 Canonical Ltd.
3651 + * This program is free software; you can redistribute it and/or
3652 + * modify it under the terms of the GNU General Public License as
3653 + * published by the Free Software Foundation, version 2 of the
3657 +#ifndef __AA_POLICY_H
3658 +#define __AA_POLICY_H
3660 +#include <linux/capability.h>
3661 +#include <linux/cred.h>
3662 +#include <linux/kref.h>
3663 +#include <linux/sched.h>
3664 +#include <linux/slab.h>
3665 +#include <linux/socket.h>
3667 +#include "apparmor.h"
3669 +#include "capability.h"
3670 +#include "domain.h"
3673 +#include "resource.h"
3675 +extern const char *profile_mode_names[];
3676 +#define APPARMOR_NAMES_MAX_INDEX 3
3678 +#define COMPLAIN_MODE(_profile) \
3679 + ((aa_g_profile_mode == APPARMOR_COMPLAIN) || ((_profile) && \
3680 + (_profile)->mode == APPARMOR_COMPLAIN))
3682 +#define DO_KILL(_profile) \
3683 + ((aa_g_profile_mode == APPARMOR_KILL) || ((_profile) && \
3684 + (_profile)->mode == APPARMOR_KILL))
3686 +#define PROFILE_IS_HAT(_profile) \
3687 + ((_profile) && (_profile)->flags & PFLAG_HAT)
3690 + * FIXME: currently need a clean way to replace and remove profiles as a
3691 + * set. It should be done at the namespace level.
3692 + * Either, with a set of profiles loaded at the namespace level or via
3693 + * a mark and remove marked interface.
3695 +enum profile_mode {
3696 + APPARMOR_ENFORCE, /* enforce access rules */
3697 + APPARMOR_COMPLAIN, /* allow and log access violations */
3698 + APPARMOR_KILL, /* kill task on access violation */
3701 +enum profile_flags {
3702 + PFLAG_HAT = 1, /* profile is a hat */
3703 + PFLAG_UNCONFINED = 2, /* profile is the unconfined profile */
3704 + PFLAG_NULL = 4, /* profile is null learning profile */
3705 + PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */
3706 + PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */
3707 + PFLAG_USER_DEFINED = 0x20, /* user based profile */
3708 + PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */
3709 + PFLAG_MMAP_MIN_ADDR = 0x80, /* profile controls mmap_min_addr */
3710 + PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */
3712 + /* These flags must coorespond with PATH_flags */
3713 + PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */
3716 +#define AA_NEW_SID 0
3720 +/* struct aa_policy - common part of both namespaces and profiles
3721 + * @name: name of the object
3722 + * @hname - The hierarchical name
3723 + * @count: reference count of the obj
3724 + * @list: list policy object is on
3725 + * @profiles: head of the profiles list contained in the object
3730 + struct kref count;
3731 + struct list_head list;
3732 + struct list_head profiles;
3735 +/* struct aa_ns_acct - accounting of profiles in namespace
3736 + * @max_size: maximum space allowed for all profiles in namespace
3737 + * @max_count: maximum number of profiles that can be in this namespace
3738 + * @size: current size of profiles
3739 + * @count: current count of profiles (includes null profiles)
3741 +struct aa_ns_acct {
3748 +/* struct aa_namespace - namespace for a set of profiles
3749 + * @base: common policy
3750 + * @parent: parent of namespace
3751 + * @lock: lock for modifying the object
3752 + * @acct: accounting for the namespace
3753 + * @unconfined: special unconfined profile for the namespace
3754 + * @sub_ns: list of namespaces under the current namespace.
3756 + * An aa_namespace defines the set profiles that are searched to determine
3757 + * which profile to attach to a task. Profiles can not be shared between
3758 + * aa_namespaces and profile names within a namespace are guarenteed to be
3759 + * unique. When profiles in seperate namespaces have the same name they
3760 + * are NOT considered to be equivalent.
3762 + * Namespaces are hierarchical and only namespaces and profiles below the
3763 + * current namespace are visible.
3765 + * Namespace names must be unique and can not contain the characters :/\0
3767 + * FIXME TODO: add vserver support so a vserer (can it all be done in userspace)
3769 +struct aa_namespace {
3770 + struct aa_policy base;
3771 + struct aa_namespace *parent;
3773 + struct aa_ns_acct acct;
3774 + struct aa_profile *unconfined;
3775 + struct list_head sub_ns;
3778 +/* struct aa_profile - basic confinement data
3779 + * @base - base componets of the profile (name, refcount, lists, lock ...)
3780 + * @parent: parent of profile
3781 + * @ns: namespace the profile is in
3782 + * @replacedby: is set profile that replaced this profile
3783 + * @xmatch: optional extended matching for unconfined executables names
3784 + * @xmatch_len: xmatch prefix len, used to determine xmatch priority
3785 + * @sid: the unique security id number of this profile
3786 + * @audit: the auditing mode of the profile
3787 + * @mode: the enforcement mode of the profile
3788 + * @flags: flags controlling profile behavior
3789 + * @path_flags: flags controlling path generation behavior
3790 + * @size: the memory consumed by this profiles rules
3791 + * @file: The set of rules governing basic file access and domain transitions
3792 + * @caps: capabilities for the profile
3793 + * @net: network controls for the profile
3794 + * @rlimits: rlimits for the profile
3796 + * The AppArmor profile contains the basic confinement data. Each profile
3797 + * has a name, and exist in a namespace. The @name and @exec_match are
3798 + * used to determine profile attachment against unconfined tasks. All other
3799 + * attachments are determined by in profile X transition rules.
3801 + * The @replacedby field is write protected by the profile lock. Reads
3802 + * are assumed to be atomic, and are done without locking.
3804 + * Profiles have a hierachy where hats and children profiles keep
3805 + * a reference to their parent.
3807 + * Profile names can not begin with a : and can not contain the \0
3808 + * character. If a profile name begins with / it will be considered when
3809 + * determining profile attachment on "unconfined" tasks.
3811 +struct aa_profile {
3812 + struct aa_policy base;
3813 + struct aa_profile *parent;
3815 + struct aa_namespace *ns;
3817 + struct aa_profile *replacedby;
3818 + const char *rename;
3820 + struct aa_dfa *xmatch;
3823 + enum audit_mode audit;
3824 + enum profile_mode mode;
3829 + unsigned long mmap_min_addr;
3831 + struct aa_file_rules file;
3832 + struct aa_caps caps;
3833 + struct aa_net net;
3834 + struct aa_rlimit rlimits;
3837 +extern struct aa_namespace *root_ns;
3838 +extern enum profile_mode aa_g_profile_mode;
3840 +void aa_add_profile(struct aa_policy *common, struct aa_profile *profile);
3842 +int aa_alloc_root_ns(void);
3843 +void aa_free_root_ns(void);
3844 +void aa_free_namespace_kref(struct kref *kref);
3846 +struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
3847 + const char *name);
3849 +static inline struct aa_policy *aa_get_common(struct aa_policy *c)
3852 + kref_get(&c->count);
3858 + * aa_get_namespace - increment references count on @ns
3859 + * @ns: namespace to increment reference count of (MAYBE NULL)
3861 + * Returns: pointer to @ns if @ns is NULL returns NULL
3862 + * Requires: @ns must be held with valid refcount when called
3864 +static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
3867 + kref_get(&(ns->base.count));
3873 + * aa_put_namespace - decrement refcount on @ns
3874 + * @ns: namespace to put reference to
3876 + * Decrement reference count to @ns and if no longer in use free it
3878 +static inline void aa_put_namespace(struct aa_namespace *ns)
3881 + kref_put(&ns->base.count, aa_free_namespace_kref);
3884 +struct aa_profile *aa_alloc_profile(const char *name);
3885 +struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat);
3886 +void aa_free_profile_kref(struct kref *kref);
3887 +struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
3888 +struct aa_profile *aa_find_profile(struct aa_namespace *ns, const char *name);
3889 +struct aa_profile *aa_match_profile(struct aa_namespace *ns, const char *name);
3891 +ssize_t aa_interface_replace_profiles(void *udata, size_t size, bool add_only);
3892 +ssize_t aa_interface_remove_profiles(char *name, size_t size);
3894 +#define unconfined(X) ((X)->flags & PFLAG_UNCONFINED)
3897 + * aa_newest_version - find the newest version of @profile
3898 + * @profile: the profile to check for newer versions of (NOT NULL)
3900 + * Returns: newest version of @profile, if @profile is the newest version
3901 + * return @profile.
3903 + * NOTE: the profile returned is not refcounted, The refcount on @profile
3904 + * must be held until the caller decides what to do with the returned newest
3907 +static inline struct aa_profile *aa_newest_version(struct aa_profile *profile)
3909 + if (unlikely(profile && profile->replacedby))
3910 + for (; profile->replacedby; profile = profile->replacedby) ;
3916 + * aa_get_profile - increment refcount on profile @p
3917 + * @p: profile (MAYBE NULL)
3919 + * Returns: pointer to @p if @p is NULL will return NULL
3920 + * Requires: @p must be held with valid refcount when called
3922 +static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
3925 + kref_get(&(p->base.count));
3931 + * aa_put_profile - decrement refcount on profile @p
3932 + * @p: profile (MAYBE NULL)
3934 +static inline void aa_put_profile(struct aa_profile *p)
3937 + kref_put(&p->base.count, aa_free_profile_kref);
3940 +static inline int AUDIT_MODE(struct aa_profile *profile)
3942 + if (aa_g_audit != AUDIT_NORMAL)
3943 + return aa_g_audit;
3945 + return profile->audit;
3946 + return AUDIT_NORMAL;
3949 +#endif /* __AA_POLICY_H */
3950 diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
3951 new file mode 100644
3952 index 0000000..5605a3e
3954 +++ b/security/apparmor/include/policy_unpack.h
3957 + * AppArmor security module
3959 + * This file contains AppArmor policy loading interface function definitions.
3961 + * Copyright (C) 1998-2008 Novell/SUSE
3962 + * Copyright 2009-2010 Canonical Ltd.
3964 + * This program is free software; you can redistribute it and/or
3965 + * modify it under the terms of the GNU General Public License as
3966 + * published by the Free Software Foundation, version 2 of the
3970 +#ifndef __POLICY_INTERFACE_H
3971 +#define __POLICY_INTERFACE_H
3973 +struct aa_audit_iface {
3974 + struct aa_audit base;
3977 + const char *name2;
3981 +int aa_audit_iface(struct aa_audit_iface *sa);
3982 +struct aa_profile *aa_unpack(void *udata, size_t size,
3983 + struct aa_audit_iface *sa);
3985 +#endif /* __POLICY_INTERFACE_H */
3986 diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h
3987 new file mode 100644
3988 index 0000000..6c6f271
3990 +++ b/security/apparmor/include/procattr.h
3993 + * AppArmor security module
3995 + * This file contains AppArmor /proc/<pid>/attr/ interface function defintions.
3997 + * Copyright (C) 1998-2008 Novell/SUSE
3998 + * Copyright 2009-2010 Canonical Ltd.
4000 + * This program is free software; you can redistribute it and/or
4001 + * modify it under the terms of the GNU General Public License as
4002 + * published by the Free Software Foundation, version 2 of the
4006 +#ifndef __AA_PROCATTR_H
4007 +#define __AA_PROCATTR_H
4009 +#define AA_DO_TEST 1
4010 +#define AA_ONEXEC 1
4012 +int aa_getprocattr(struct aa_profile *profile, char **string);
4013 +int aa_setprocattr_changehat(char *args, size_t size, int test);
4014 +int aa_setprocattr_changeprofile(char *fqname, int onexec, int test);
4015 +int aa_setprocattr_permipc(char *fqname);
4017 +#endif /* __AA_PROCATTR_H */
4018 diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
4019 new file mode 100644
4020 index 0000000..e8fc079
4022 +++ b/security/apparmor/include/resource.h
4025 + * AppArmor security module
4027 + * This file contains AppArmor resource limits function defintions.
4029 + * Copyright (C) 1998-2008 Novell/SUSE
4030 + * Copyright 2009-2010 Canonical Ltd.
4032 + * This program is free software; you can redistribute it and/or
4033 + * modify it under the terms of the GNU General Public License as
4034 + * published by the Free Software Foundation, version 2 of the
4038 +#ifndef __AA_RESOURCE_H
4039 +#define __AA_RESOURCE_H
4041 +#include <linux/resource.h>
4042 +#include <linux/sched.h>
4046 +/* struct aa_rlimit - rlimits settings for the profile
4047 + * @mask: which hard limits to set
4048 + * @limits: rlimit values that override task limits
4050 + * AppArmor rlimits are used to set confined task rlimits. Only the
4051 + * limits specified in @mask will be controlled by apparmor.
4054 + unsigned int mask;
4055 + struct rlimit limits[RLIM_NLIMITS];
4058 +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
4059 + struct rlimit *new_rlim);
4061 +void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
4063 +static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
4068 +#endif /* __AA_RESOURCE_H */
4069 diff --git a/security/apparmor/include/sid.h b/security/apparmor/include/sid.h
4070 new file mode 100644
4071 index 0000000..020db35
4073 +++ b/security/apparmor/include/sid.h
4076 + * AppArmor security module
4078 + * This file contains AppArmor security identifier (sid) definitions
4080 + * Copyright 2009-2010 Canonical Ltd.
4082 + * This program is free software; you can redistribute it and/or
4083 + * modify it under the terms of the GNU General Public License as
4084 + * published by the Free Software Foundation, version 2 of the
4091 +#include <linux/types.h>
4095 +u32 aa_alloc_sid(void);
4096 +void aa_free_sid(u32 sid);
4098 +#endif /* __AA_SID_H */
4099 diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
4100 new file mode 100644
4101 index 0000000..dbad011
4103 +++ b/security/apparmor/ipc.c
4106 + * AppArmor security module
4108 + * This file contains AppArmor ipc mediation
4110 + * Copyright (C) 1998-2008 Novell/SUSE
4111 + * Copyright 2009-2010 Canonical Ltd.
4113 + * This program is free software; you can redistribute it and/or
4114 + * modify it under the terms of the GNU General Public License as
4115 + * published by the Free Software Foundation, version 2 of the
4119 +#include <linux/gfp.h>
4120 +#include <linux/ptrace.h>
4122 +#include "include/audit.h"
4123 +#include "include/capability.h"
4124 +#include "include/context.h"
4125 +#include "include/policy.h"
4127 +struct aa_audit_ptrace {
4128 + struct aa_audit base;
4130 + pid_t tracer, tracee;
4133 +/* call back to audit ptrace fields */
4134 +static void audit_cb(struct audit_buffer *ab, struct aa_audit *va)
4136 + struct aa_audit_ptrace *sa = container_of(va, struct aa_audit_ptrace,
4138 + audit_log_format(ab, " tracer=%d tracee=%d", sa->tracer, sa->tracee);
4142 + * aa_audit_ptrace - do auditing for ptrace
4143 + * @profile: profile being enforced (NOT NULL)
4144 + * @sa: audit structure (NOT NULL)
4146 + * Returns: %0 or error code
4148 +static int aa_audit_ptrace(struct aa_profile *profile,
4149 + struct aa_audit_ptrace *sa)
4151 + return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa->base, audit_cb);
4155 + * aa_may_ptrace - test if tracer task can trace the tracee
4156 + * @tracer_task: task who will do the tracing (NOT NULL)
4157 + * @tracer: profile of the task doing the tracing (NOT NULL)
4158 + * @tracee: task to be traced
4159 + * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH
4161 + * Returns: %0 else error code if permission denied or error
4163 +int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
4164 + struct aa_profile *tracee, unsigned int mode)
4166 + /* TODO: currently only based on capability, not extended ptrace
4168 + * Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
4171 + if (!tracer || tracer == tracee)
4173 + /* log this capability request */
4174 + return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1);
4178 + * aa_ptrace - do ptrace permission check and auditing
4179 + * @tracer: task doing the tracing
4180 + * @tracee: task being traced
4181 + * @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH
4183 + * Returns: %0 else error code if permission denied or error
4185 +int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
4186 + unsigned int mode)
4189 + * tracer can ptrace tracee when
4190 + * - tracer is unconfined ||
4191 + * - tracer & tracee are in the same namespace &&
4192 + * - tracer is in complain mode
4193 + * - tracer has rules allowing it to trace tracee currently this is:
4194 + * - confined by the same profile ||
4195 + * - tracer profile has CAP_SYS_PTRACE
4198 + struct aa_profile *tracer_p;
4199 + /* cred released below */
4200 + const struct cred *cred = get_task_cred(tracer);
4202 + tracer_p = aa_cred_profile(cred);
4204 + if (!unconfined(tracer_p)) {
4205 + struct aa_audit_ptrace sa = {
4206 + .base.operation = "ptrace",
4207 + .base.gfp_mask = GFP_ATOMIC,
4208 + .tracer = tracer->pid,
4209 + .tracee = tracee->pid,
4211 + /* FIXME: different namespace restriction can be lifted
4212 + * if, namespace are matched to AppArmor namespaces
4214 + struct aa_profile *tracee_p;
4215 + /* lcred released below */
4216 + struct cred *lcred = get_task_cred(tracee);
4217 + tracee_p = aa_cred_profile(lcred);
4219 + sa.base.error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode);
4220 + sa.base.error = aa_audit_ptrace(tracer_p, &sa);
4223 + error = sa.base.error;
4229 diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
4230 new file mode 100644
4231 index 0000000..1e18a44
4233 +++ b/security/apparmor/lib.c
4236 + * AppArmor security module
4238 + * This file contains basic common functions used in AppArmor
4240 + * Copyright (C) 1998-2008 Novell/SUSE
4241 + * Copyright 2009-2010 Canonical Ltd.
4243 + * This program is free software; you can redistribute it and/or
4244 + * modify it under the terms of the GNU General Public License as
4245 + * published by the Free Software Foundation, version 2 of the
4249 +#include <linux/slab.h>
4250 +#include <linux/string.h>
4252 +#include "include/audit.h"
4256 + * aa_split_fqname - split a fqname into a profile and namespace name
4257 + * @fqname: a full qualified name in namespace profile format
4258 + * @ns_name: pointer to portion of the string containing the ns name
4260 + * Returns: profile name or NULL if one is not specified
4262 + * Split a namespace name from a profile name (see policy.c for naming
4263 + * description). If a portion of the name is missing it returns NULL for
4266 + * NOTE: may modifiy the @fqname string. The pointers returned point
4267 + * into the @fqname string.
4269 +char *aa_split_fqname(char *fqname, char **ns_name)
4271 + char *name = strim(fqname);
4274 + if (name[0] == ':') {
4275 + char *split = strchr(&name[1], ':');
4277 + /* overwrite ':' with \0 */
4279 + name = skip_spaces(split + 1);
4281 + /* a ns name without a following profile is allowed */
4283 + *ns_name = &name[1];
4285 + if (name && *name == 0)
4292 + * aa_strneq - compare null terminated @str to a non null terminated substring
4293 + * @str: a null terminated string
4294 + * @sub: a substring, not necessarily null terminated
4295 + * @len: length of @sub to compare
4297 + * The @str string must be full consumed for this to be considered a match
4299 +bool aa_strneq(const char *str, const char *sub, int len)
4301 + int res = strncmp(str, sub, len);
4304 + if (str[len] == 0)
4309 +void aa_info_message(const char *str)
4311 + struct aa_audit sa = {
4312 + .gfp_mask = GFP_KERNEL,
4315 + printk(KERN_INFO "AppArmor: %s\n", str);
4316 + if (audit_enabled)
4317 + aa_audit(AUDIT_APPARMOR_STATUS, NULL, &sa, NULL);
4320 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
4321 new file mode 100644
4322 index 0000000..a0ab74b
4324 +++ b/security/apparmor/lsm.c
4327 + * AppArmor security module
4329 + * This file contains AppArmor LSM hooks.
4331 + * Copyright (C) 1998-2008 Novell/SUSE
4332 + * Copyright 2009-2010 Canonical Ltd.
4334 + * This program is free software; you can redistribute it and/or
4335 + * modify it under the terms of the GNU General Public License as
4336 + * published by the Free Software Foundation, version 2 of the
4340 +#include <linux/security.h>
4341 +#include <linux/moduleparam.h>
4342 +#include <linux/mm.h>
4343 +#include <linux/mman.h>
4344 +#include <linux/mount.h>
4345 +#include <linux/namei.h>
4346 +#include <linux/ptrace.h>
4347 +#include <linux/ctype.h>
4348 +#include <linux/sysctl.h>
4349 +#include <linux/audit.h>
4350 +#include <net/sock.h>
4352 +#include "include/apparmor.h"
4353 +#include "include/apparmorfs.h"
4354 +#include "include/audit.h"
4355 +#include "include/capability.h"
4356 +#include "include/context.h"
4357 +#include "include/file.h"
4358 +#include "include/ipc.h"
4359 +#include "include/net.h"
4360 +#include "include/path.h"
4361 +#include "include/policy.h"
4362 +#include "include/procattr.h"
4364 +/* Flag indicating whether initialization completed */
4365 +int apparmor_initialized;
4368 + * LSM hook functions
4372 + * free the associated aa_task_cxt and put its profiles
4374 +static void apparmor_cred_free(struct cred *cred)
4376 + aa_free_task_context(cred->security);
4377 + cred->security = NULL;
4381 + * allocate the apparmor part of blank credentials
4383 +static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp)
4385 + /* freed by apparmor_cred_free */
4386 + struct aa_task_cxt *cxt = aa_alloc_task_context(gfp);
4390 + cred->security = cxt;
4395 + * prepare new aa_task_cxt for modification by prepare_cred block
4397 +static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
4400 + /* freed by apparmor_cred_free */
4401 + struct aa_task_cxt *cxt = aa_alloc_task_context(gfp);
4405 + aa_dup_task_context(cxt, old->security);
4406 + new->security = cxt;
4411 + * transfer the apparmor data to a blank set of creds
4413 +static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
4415 + const struct aa_task_cxt *old_cxt = old->security;
4416 + struct aa_task_cxt *new_cxt = new->security;
4418 + aa_dup_task_context(new_cxt, old_cxt);
4421 +static int apparmor_ptrace_access_check(struct task_struct *child,
4422 + unsigned int mode)
4426 + rc = cap_ptrace_access_check(child, mode);
4430 + return aa_ptrace(current, child, mode);
4433 +static int apparmor_ptrace_traceme(struct task_struct *parent)
4435 + return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
4438 +/* Derived from security/commoncap.c:cap_capget */
4439 +static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
4440 + kernel_cap_t *inheritable, kernel_cap_t *permitted)
4442 + struct aa_profile *profile;
4443 + const struct cred *cred;
4446 + cred = __task_cred(target);
4447 + profile = aa_cred_profile(cred);
4449 + *effective = cred->cap_effective;
4450 + *inheritable = cred->cap_inheritable;
4451 + *permitted = cred->cap_permitted;
4453 + if (!unconfined(profile))
4454 + *effective = cap_intersect(*effective, profile->caps.allowed);
4455 + rcu_read_unlock();
4460 +static int apparmor_capable(struct task_struct *task, const struct cred *cred,
4461 + int cap, int audit)
4463 + struct aa_profile *profile;
4464 + /* cap_capable returns 0 on success, else -EPERM */
4465 + int error = cap_capable(task, cred, cap, audit);
4467 + profile = aa_cred_profile(cred);
4468 + if (!error && !unconfined(profile))
4469 + error = aa_capable(task, profile, cap, audit);
4474 +static int apparmor_sysctl(struct ctl_table *table, int op)
4477 + struct aa_profile *profile = aa_current_profile();
4479 + if (!unconfined(profile)) {
4480 + char *buffer, *name;
4487 + mask |= MAY_WRITE;
4491 + buffer = (char *)__get_free_page(GFP_KERNEL);
4496 + * TODO: convert this over to using a global or per
4497 + * namespace control instead of a hard coded /proc
4499 + name = sysctl_pathname(table, buffer, PAGE_SIZE);
4500 + if (name && name - buffer >= 5) {
4501 + struct path_cond cond = { 0, S_IFREG };
4503 + memcpy(name, "/proc", 5);
4504 + error = aa_pathstr_perm(profile, "sysctl", name, mask,
4507 + free_page((unsigned long)buffer);
4515 + * common_perm - basic common permission check wrapper fn for paths
4516 + * @op: operation name (NOT NULL)
4517 + * @path: path to check permission of (NOT NULL)
4518 + * @mask: requested permissions mask
4519 + * @cond: conditional info for the permission request (NOT NULL)
4521 + * Returns: %0 else error code if error or permission denied
4523 +static int common_perm(const char *op, struct path *path, u16 mask,
4524 + struct path_cond *cond)
4526 + struct aa_profile *profile;
4529 + profile = __aa_current_profile();
4530 + if (!unconfined(profile))
4531 + error = aa_path_perm(profile, op, path, mask, cond);
4537 + * common_perm_dentry - common permission wrapper when path is dir, dentry
4538 + * @op: operation name (NOT NULL)
4539 + * @dir: directory of the dentry (NOT NULL)
4540 + * @dentry: dentry to check (NOT NULL)
4541 + * @mask: requested permissions mask
4542 + * @cond: conditional info for the permission request (NOT NULL)
4544 + * Returns: %0 else error code if error or permission denied
4546 +static int common_perm_dentry(const char *op, struct path *dir,
4547 + struct dentry *dentry, u16 mask,
4548 + struct path_cond *cond)
4550 + struct path path = { dir->mnt, dentry };
4552 + return common_perm(op, &path, mask, cond);
4556 + * common_perm_rm - common permission wrapper for operations doing rm
4557 + * @op: operation name (NOT NULL)
4558 + * @dir: directory that the dentry is in (NOT NULL)
4559 + * @dentry: dentry being rm'd (NOT NULL)
4560 + * @mask: requested permission mask
4562 + * Returns: %0 else error code if error or permission denied
4564 +static int common_perm_rm(const char *op, struct path *dir,
4565 + struct dentry *dentry, u16 mask)
4567 + struct inode *inode = dentry->d_inode;
4568 + struct path_cond cond = { };
4570 + if (!dir->mnt || !inode || !mediated_filesystem(inode))
4573 + cond.uid = inode->i_uid;
4574 + cond.mode = inode->i_mode;
4576 + return common_perm_dentry(op, dir, dentry, mask, &cond);
4580 + * common_perm_create - common permission wrapper for operations doing create
4581 + * @op: operation name (NOT NULL)
4582 + * @dir: directory that dentry will be created in (NOT NULL)
4583 + * @dentry: dentry to create (NOT NULL)
4584 + * @mask: request permission mask
4585 + * @mode: created file mode
4587 + * Returns: %0 else error code if error or permission denied
4589 +static int common_perm_create(const char *op, struct path *dir,
4590 + struct dentry *dentry, u16 mask, umode_t mode)
4592 + struct path_cond cond = { current_fsuid(), mode };
4594 + if (!dir->mnt || !mediated_filesystem(dir->dentry->d_inode))
4597 + return common_perm_dentry(op, dir, dentry, mask, &cond);
4600 +static int apparmor_path_unlink(struct path *dir, struct dentry *dentry)
4602 + return common_perm_rm("unlink", dir, dentry, AA_MAY_DELETE);
4605 +static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry,
4608 + return common_perm_create("mkdir", dir, dentry, AA_MAY_CREATE, S_IFDIR);
4611 +static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry)
4613 + return common_perm_rm("rmdir", dir, dentry, AA_MAY_DELETE);
4616 +static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
4617 + int mode, unsigned int dev)
4619 + return common_perm_create("mknod", dir, dentry, AA_MAY_CREATE, mode);
4622 +static int apparmor_path_truncate(struct path *path, loff_t length,
4623 + unsigned int time_attrs)
4625 + struct path_cond cond = { path->dentry->d_inode->i_uid,
4626 + path->dentry->d_inode->i_mode
4629 + if (!path->mnt || !mediated_filesystem(path->dentry->d_inode))
4631 + return common_perm("truncate", path, MAY_WRITE, &cond);
4634 +static int apparmor_path_symlink(struct path *dir, struct dentry *dentry,
4635 + const char *old_name)
4637 + return common_perm_create("symlink_create", dir, dentry, AA_MAY_CREATE,
4641 +static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir,
4642 + struct dentry *new_dentry)
4644 + struct aa_profile *profile;
4647 + if (!mediated_filesystem(old_dentry->d_inode))
4650 + profile = aa_current_profile();
4651 + if (!unconfined(profile))
4652 + error = aa_path_link(profile, old_dentry, new_dir, new_dentry);
4656 +static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
4657 + struct path *new_dir, struct dentry *new_dentry)
4659 + struct aa_profile *profile;
4662 + if (!mediated_filesystem(old_dentry->d_inode))
4665 + profile = aa_current_profile();
4666 + if (!unconfined(profile)) {
4667 + struct path old_path = { old_dir->mnt, old_dentry };
4668 + struct path new_path = { new_dir->mnt, new_dentry };
4669 + struct path_cond cond = { old_dentry->d_inode->i_uid,
4670 + old_dentry->d_inode->i_mode
4673 + error = aa_path_perm(profile, "rename_src", &old_path,
4674 + MAY_READ | MAY_WRITE, &cond);
4676 + error = aa_path_perm(profile, "rename_dest", &new_path,
4677 + AA_MAY_CREATE | MAY_WRITE, &cond);
4683 +static int apparmor_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
4686 + struct aa_profile *profile;
4689 + if (!mediated_filesystem(dentry->d_inode))
4692 + profile = aa_current_profile();
4693 + if (!unconfined(profile)) {
4694 + struct path path = { mnt, dentry };
4695 + struct path_cond cond = { dentry->d_inode->i_uid,
4696 + dentry->d_inode->i_mode
4699 + error = aa_path_perm(profile, "chmod", &path, AA_MAY_CHMOD,
4706 +static int apparmor_path_chown(struct path *path, uid_t uid, gid_t gid)
4708 + struct aa_profile *profile;
4711 + if (!mediated_filesystem(path->dentry->d_inode))
4714 + profile = aa_current_profile();
4715 + if (!unconfined(profile)) {
4716 + struct path_cond cond = { path->dentry->d_inode->i_uid,
4717 + path->dentry->d_inode->i_mode
4719 + error = aa_path_perm(profile, "chown", path, AA_MAY_CHOWN,
4726 +static int apparmor_dentry_open(struct file *file, const struct cred *cred)
4728 + struct aa_profile *profile;
4731 + /* If in exec, permission is handled by bprm hooks */
4732 + if (current->in_execve ||
4733 + !mediated_filesystem(file->f_path.dentry->d_inode))
4736 + profile = aa_cred_profile(cred);
4737 + if (!unconfined(profile)) {
4738 + struct aa_file_cxt *fcxt = file->f_security;
4739 + struct inode *inode = file->f_path.dentry->d_inode;
4740 + struct path_cond cond = { inode->i_uid, inode->i_mode };
4742 + error = aa_path_perm(profile, "open", &file->f_path,
4743 + aa_map_file_to_perms(file), &cond);
4744 + /* released by aa_free_file_context */
4745 + fcxt->profile = aa_get_profile(profile);
4746 + /* todo cache actual allowed permissions */
4747 + fcxt->allowed = 0;
4753 +static int apparmor_file_alloc_security(struct file *file)
4755 + /* freed by apparmor_file_free_security */
4756 + file->f_security = aa_alloc_file_context(GFP_KERNEL);
4757 + if (!file->f_security)
4763 +static void apparmor_file_free_security(struct file *file)
4765 + struct aa_file_cxt *cxt = file->f_security;
4767 + aa_free_file_context(cxt);
4770 +static int apparmor_file_permission(struct file *file, int mask)
4773 + * TODO: cache profiles that have revalidated?
4775 + struct aa_file_cxt *fcxt = file->f_security;
4776 + struct aa_profile *profile, *fprofile = fcxt->profile;
4779 + if (!fprofile || !file->f_path.mnt ||
4780 + !mediated_filesystem(file->f_path.dentry->d_inode))
4783 + profile = __aa_current_profile();
4785 +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
4787 + * AppArmor <= 2.4 revalidates files at access time instead
4790 + if (!unconfined(profile) &&
4791 + ((fprofile != profile) || (mask & ~fcxt->allowed)))
4792 + error = aa_file_perm(profile, "file_perm", file, mask);
4798 +static int common_file_perm(const char *op, struct file *file, u16 mask)
4800 + const struct aa_file_cxt *fcxt = file->f_security;
4801 + struct aa_profile *profile, *fprofile = fcxt->profile;
4804 + if (!fprofile || !file->f_path.mnt ||
4805 + !mediated_filesystem(file->f_path.dentry->d_inode))
4808 + profile = aa_current_profile();
4809 + if (!unconfined(profile) && ((fprofile != profile) ||
4810 + (mask & ~fcxt->allowed)))
4811 + error = aa_file_perm(profile, op, file, mask);
4816 +static int apparmor_file_lock(struct file *file, unsigned int cmd)
4818 + u16 mask = AA_MAY_LOCK;
4820 + if (cmd == F_WRLCK)
4821 + mask |= MAY_WRITE;
4823 + return common_file_perm("file_lock", file, mask);
4826 +static int common_mmap(struct file *file, const char *operation,
4827 + unsigned long prot, unsigned long flags)
4829 + struct dentry *dentry;
4832 + if (!file || !file->f_security)
4835 + if (prot & PROT_READ)
4838 + * Private mappings don't require write perms since they don't
4839 + * write back to the files
4841 + if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
4842 + mask |= MAY_WRITE;
4843 + if (prot & PROT_EXEC)
4844 + mask |= AA_EXEC_MMAP;
4846 + dentry = file->f_path.dentry;
4847 + return common_file_perm(operation, file, mask);
4850 +static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
4851 + unsigned long prot, unsigned long flags,
4852 + unsigned long addr, unsigned long addr_only)
4856 + /* do DAC check */
4857 + rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
4858 + if (rc || addr_only)
4861 + return common_mmap(file, "file_mmap", prot, flags);
4864 +static int apparmor_file_mprotect(struct vm_area_struct *vma,
4865 + unsigned long reqprot, unsigned long prot)
4867 + return common_mmap(vma->vm_file, "file_mprotect", prot,
4868 + !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
4871 +static int apparmor_getprocattr(struct task_struct *task, char *name,
4874 + int error = -ENOENT;
4875 + struct aa_profile *profile;
4876 + /* released below */
4877 + const struct cred *cred = get_task_cred(task);
4878 + struct aa_task_cxt *cxt = cred->security;
4879 + profile = aa_cred_profile(cred);
4881 + if (strcmp(name, "current") == 0)
4882 + error = aa_getprocattr(aa_newest_version(cxt->profile),
4884 + else if (strcmp(name, "prev") == 0 && cxt->previous)
4885 + error = aa_getprocattr(aa_newest_version(cxt->previous),
4887 + else if (strcmp(name, "exec") == 0 && cxt->onexec)
4888 + error = aa_getprocattr(aa_newest_version(cxt->onexec),
4898 +static int apparmor_setprocattr(struct task_struct *task, char *name,
4899 + void *value, size_t size)
4901 + char *command, *args;
4905 + if (size == 0 || size >= PAGE_SIZE)
4908 + /* task can only write its own attributes */
4909 + if (current != task)
4913 + args[size] = '\0';
4914 + args = strim(args);
4915 + command = strsep(&args, " ");
4918 + args = skip_spaces(args);
4922 + arg_size = size - (args - (char *) value);
4923 + if (strcmp(name, "current") == 0) {
4924 + if (strcmp(command, "changehat") == 0) {
4925 + error = aa_setprocattr_changehat(args, arg_size,
4927 + } else if (strcmp(command, "permhat") == 0) {
4928 + error = aa_setprocattr_changehat(args, arg_size,
4930 + } else if (strcmp(command, "changeprofile") == 0) {
4931 + error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
4933 + } else if (strcmp(command, "permprofile") == 0) {
4934 + error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
4936 + } else if (strcmp(command, "permipc") == 0) {
4937 + error = aa_setprocattr_permipc(args);
4939 + struct aa_audit sa = {
4940 + .operation = "setprocattr",
4941 + .gfp_mask = GFP_KERNEL,
4945 + return aa_audit(AUDIT_APPARMOR_DENIED, NULL, &sa, NULL);
4947 + } else if (strcmp(name, "exec") == 0) {
4948 + error = aa_setprocattr_changeprofile(args, AA_ONEXEC,
4951 + /* only support the "current" and "exec" process attributes */
4959 +static int apparmor_task_setrlimit(unsigned int resource,
4960 + struct rlimit *new_rlim)
4962 + struct aa_profile *profile = aa_current_profile();
4965 + if (!unconfined(profile))
4966 + error = aa_task_setrlimit(profile, resource, new_rlim);
4971 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
4973 + struct aa_profile *profile;
4979 + profile = __aa_current_profile();
4980 + if (!unconfined(profile))
4981 + error = aa_net_perm(profile, "socket_create", family,
4986 +static int apparmor_socket_post_create(struct socket *sock, int family,
4987 + int type, int protocol, int kern)
4989 + struct sock *sk = sock->sk;
4994 + return aa_revalidate_sk(sk, "socket_post_create");
4997 +static int apparmor_socket_bind(struct socket *sock,
4998 + struct sockaddr *address, int addrlen)
5000 + struct sock *sk = sock->sk;
5002 + return aa_revalidate_sk(sk, "socket_bind");
5005 +static int apparmor_socket_connect(struct socket *sock,
5006 + struct sockaddr *address, int addrlen)
5008 + struct sock *sk = sock->sk;
5010 + return aa_revalidate_sk(sk, "socket_connect");
5013 +static int apparmor_socket_listen(struct socket *sock, int backlog)
5015 + struct sock *sk = sock->sk;
5017 + return aa_revalidate_sk(sk, "socket_listen");
5020 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
5022 + struct sock *sk = sock->sk;
5024 + return aa_revalidate_sk(sk, "socket_accept");
5027 +static int apparmor_socket_sendmsg(struct socket *sock,
5028 + struct msghdr *msg, int size)
5030 + struct sock *sk = sock->sk;
5032 + return aa_revalidate_sk(sk, "socket_sendmsg");
5035 +static int apparmor_socket_recvmsg(struct socket *sock,
5036 + struct msghdr *msg, int size, int flags)
5038 + struct sock *sk = sock->sk;
5040 + return aa_revalidate_sk(sk, "socket_recvmsg");
5043 +static int apparmor_socket_getsockname(struct socket *sock)
5045 + struct sock *sk = sock->sk;
5047 + return aa_revalidate_sk(sk, "socket_getsockname");
5050 +static int apparmor_socket_getpeername(struct socket *sock)
5052 + struct sock *sk = sock->sk;
5054 + return aa_revalidate_sk(sk, "socket_getpeername");
5057 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
5060 + struct sock *sk = sock->sk;
5062 + return aa_revalidate_sk(sk, "socket_getsockopt");
5065 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
5068 + struct sock *sk = sock->sk;
5070 + return aa_revalidate_sk(sk, "socket_setsockopt");
5073 +static int apparmor_socket_shutdown(struct socket *sock, int how)
5075 + struct sock *sk = sock->sk;
5077 + return aa_revalidate_sk(sk, "socket_shutdown");
5080 +static struct security_operations apparmor_ops = {
5081 + .name = "apparmor",
5083 + .ptrace_access_check = apparmor_ptrace_access_check,
5084 + .ptrace_traceme = apparmor_ptrace_traceme,
5085 + .capget = apparmor_capget,
5086 + .sysctl = apparmor_sysctl,
5087 + .capable = apparmor_capable,
5089 + .path_link = apparmor_path_link,
5090 + .path_unlink = apparmor_path_unlink,
5091 + .path_symlink = apparmor_path_symlink,
5092 + .path_mkdir = apparmor_path_mkdir,
5093 + .path_rmdir = apparmor_path_rmdir,
5094 + .path_mknod = apparmor_path_mknod,
5095 + .path_rename = apparmor_path_rename,
5096 + .path_chmod = apparmor_path_chmod,
5097 + .path_chown = apparmor_path_chown,
5098 + .path_truncate = apparmor_path_truncate,
5099 + .dentry_open = apparmor_dentry_open,
5101 + .file_permission = apparmor_file_permission,
5102 + .file_alloc_security = apparmor_file_alloc_security,
5103 + .file_free_security = apparmor_file_free_security,
5104 + .file_mmap = apparmor_file_mmap,
5105 + .file_mprotect = apparmor_file_mprotect,
5106 + .file_lock = apparmor_file_lock,
5108 + .getprocattr = apparmor_getprocattr,
5109 + .setprocattr = apparmor_setprocattr,
5111 + .socket_create = apparmor_socket_create,
5112 + .socket_post_create = apparmor_socket_post_create,
5113 + .socket_bind = apparmor_socket_bind,
5114 + .socket_connect = apparmor_socket_connect,
5115 + .socket_listen = apparmor_socket_listen,
5116 + .socket_accept = apparmor_socket_accept,
5117 + .socket_sendmsg = apparmor_socket_sendmsg,
5118 + .socket_recvmsg = apparmor_socket_recvmsg,
5119 + .socket_getsockname = apparmor_socket_getsockname,
5120 + .socket_getpeername = apparmor_socket_getpeername,
5121 + .socket_getsockopt = apparmor_socket_getsockopt,
5122 + .socket_setsockopt = apparmor_socket_setsockopt,
5123 + .socket_shutdown = apparmor_socket_shutdown,
5125 + .cred_alloc_blank = apparmor_cred_alloc_blank,
5126 + .cred_free = apparmor_cred_free,
5127 + .cred_prepare = apparmor_cred_prepare,
5128 + .cred_transfer = apparmor_cred_transfer,
5130 + .bprm_set_creds = apparmor_bprm_set_creds,
5131 + .bprm_committing_creds = apparmor_bprm_committing_creds,
5132 + .bprm_committed_creds = apparmor_bprm_committed_creds,
5133 + .bprm_secureexec = apparmor_bprm_secureexec,
5135 + .task_setrlimit = apparmor_task_setrlimit,
5139 + * AppArmor sysfs module parameters
5142 +static int param_set_aabool(const char *val, struct kernel_param *kp);
5143 +static int param_get_aabool(char *buffer, struct kernel_param *kp);
5144 +#define param_check_aabool(name, p) __param_check(name, p, int)
5146 +static int param_set_aauint(const char *val, struct kernel_param *kp);
5147 +static int param_get_aauint(char *buffer, struct kernel_param *kp);
5148 +#define param_check_aauint(name, p) __param_check(name, p, int)
5150 +static int param_set_aalockpolicy(const char *val, struct kernel_param *kp);
5151 +static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp);
5152 +#define param_check_aalockpolicy(name, p) __param_check(name, p, int)
5154 +static int param_set_audit(const char *val, struct kernel_param *kp);
5155 +static int param_get_audit(char *buffer, struct kernel_param *kp);
5156 +#define param_check_audit(name, p) __param_check(name, p, int)
5158 +static int param_set_mode(const char *val, struct kernel_param *kp);
5159 +static int param_get_mode(char *buffer, struct kernel_param *kp);
5160 +#define param_check_mode(name, p) __param_check(name, p, int)
5162 +/* Flag values, also controllable via /sys/module/apparmor/parameters
5163 + * We define special types as we want to do additional mediation.
5166 +/* AppArmor global enforcement switch - complain, enforce, kill */
5167 +enum profile_mode aa_g_profile_mode = APPARMOR_ENFORCE;
5168 +module_param_call(mode, param_set_mode, param_get_mode,
5169 + &aa_g_profile_mode, S_IRUSR | S_IWUSR);
5173 +module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR);
5176 +enum audit_mode aa_g_audit;
5177 +module_param_call(audit, param_set_audit, param_get_audit,
5178 + &aa_g_audit, S_IRUSR | S_IWUSR);
5180 +/* Determines if audit header is included in audited messages. This
5181 + * provides more context if the audit daemon is not running
5183 +int aa_g_audit_header;
5184 +module_param_named(audit_header, aa_g_audit_header, aabool,
5185 + S_IRUSR | S_IWUSR);
5187 +/* lock out loading/removal of policy
5188 + * TODO: add in at boot loading of policy, which is the only way to
5189 + * load policy, if lock_policy is set
5191 +int aa_g_lock_policy;
5192 +module_param_named(lock_policy, aa_g_lock_policy, aalockpolicy,
5193 + S_IRUSR | S_IWUSR);
5195 +/* Syscall logging mode */
5196 +int aa_g_logsyscall;
5197 +module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR);
5199 +/* Maximum pathname length before accesses will start getting rejected */
5200 +unsigned int aa_g_path_max = 2 * PATH_MAX;
5201 +module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR | S_IWUSR);
5203 +/* Determines how paranoid loading of policy is and how much verification
5204 + * on the loaded policy is done.
5206 +int aa_g_paranoid_load = 1;
5207 +module_param_named(paranoid_load, aa_g_paranoid_load, aabool,
5208 + S_IRUSR | S_IWUSR);
5210 +/* Boot time disable flag */
5211 +static unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
5212 +module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR);
5214 +static int __init apparmor_enabled_setup(char *str)
5216 + unsigned long enabled;
5217 + int error = strict_strtoul(str, 0, &enabled);
5219 + apparmor_enabled = enabled ? 1 : 0;
5223 +__setup("apparmor=", apparmor_enabled_setup);
5225 +/* set global flag turning off the ability to load policy */
5226 +static int param_set_aalockpolicy(const char *val, struct kernel_param *kp)
5228 + if (!capable(CAP_MAC_ADMIN))
5230 + if (aa_g_lock_policy)
5232 + return param_set_bool(val, kp);
5235 +static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp)
5237 + if (!capable(CAP_MAC_ADMIN))
5239 + return param_get_bool(buffer, kp);
5242 +static int param_set_aabool(const char *val, struct kernel_param *kp)
5244 + if (!capable(CAP_MAC_ADMIN))
5246 + return param_set_bool(val, kp);
5249 +static int param_get_aabool(char *buffer, struct kernel_param *kp)
5251 + if (!capable(CAP_MAC_ADMIN))
5253 + return param_get_bool(buffer, kp);
5256 +static int param_set_aauint(const char *val, struct kernel_param *kp)
5258 + if (!capable(CAP_MAC_ADMIN))
5260 + return param_set_uint(val, kp);
5263 +static int param_get_aauint(char *buffer, struct kernel_param *kp)
5265 + if (!capable(CAP_MAC_ADMIN))
5267 + return param_get_uint(buffer, kp);
5270 +static int param_get_audit(char *buffer, struct kernel_param *kp)
5272 + if (!capable(CAP_MAC_ADMIN))
5275 + if (!apparmor_enabled)
5278 + return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]);
5281 +static int param_set_audit(const char *val, struct kernel_param *kp)
5284 + if (!capable(CAP_MAC_ADMIN))
5287 + if (!apparmor_enabled)
5293 + for (i = 0; i < AUDIT_MAX_INDEX; i++) {
5294 + if (strcmp(val, audit_mode_names[i]) == 0) {
5303 +static int param_get_mode(char *buffer, struct kernel_param *kp)
5305 + if (!capable(CAP_MAC_ADMIN))
5308 + if (!apparmor_enabled)
5311 + return sprintf(buffer, "%s", profile_mode_names[aa_g_profile_mode]);
5314 +static int param_set_mode(const char *val, struct kernel_param *kp)
5317 + if (!capable(CAP_MAC_ADMIN))
5320 + if (!apparmor_enabled)
5326 + for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) {
5327 + if (strcmp(val, profile_mode_names[i]) == 0) {
5328 + aa_g_profile_mode = i;
5337 + * AppArmor init functions
5341 + * set_init_cxt - set a task context and profile on the first task.
5343 + * TODO: allow setting an alternate profile than unconfined
5345 +static int __init set_init_cxt(void)
5347 + struct cred *cred = (struct cred *)current->real_cred;
5348 + struct aa_task_cxt *cxt;
5350 + cxt = aa_alloc_task_context(GFP_KERNEL);
5354 + cxt->profile = aa_get_profile(root_ns->unconfined);
5355 + cred->security = cxt;
5360 +static int __init apparmor_init(void)
5364 + if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
5365 + aa_info_message("AppArmor disabled by boot time parameter\n");
5366 + apparmor_enabled = 0;
5370 + error = aa_alloc_root_ns();
5372 + AA_ERROR("Unable to allocate default profile namespace\n");
5376 + error = set_init_cxt();
5378 + AA_ERROR("Failed to set context on init task\n");
5379 + goto register_security_out;
5382 + error = register_security(&apparmor_ops);
5384 + AA_ERROR("Unable to register AppArmor\n");
5385 + goto register_security_out;
5388 + /* Report that AppArmor successfully initialized */
5389 + apparmor_initialized = 1;
5390 + if (aa_g_profile_mode == APPARMOR_COMPLAIN)
5391 + aa_info_message("AppArmor initialized: complain mode enabled");
5392 + else if (aa_g_profile_mode == APPARMOR_KILL)
5393 + aa_info_message("AppArmor initialized: kill mode enabled");
5395 + aa_info_message("AppArmor initialized");
5399 +register_security_out:
5400 + aa_free_root_ns();
5403 + aa_destroy_aafs();
5405 + apparmor_enabled = 0;
5410 +security_initcall(apparmor_init);
5411 diff --git a/security/apparmor/match.c b/security/apparmor/match.c
5412 new file mode 100644
5413 index 0000000..677d1c2
5415 +++ b/security/apparmor/match.c
5418 + * AppArmor security module
5420 + * This file contains AppArmor dfa based regular expression matching engine
5422 + * Copyright (C) 1998-2008 Novell/SUSE
5423 + * Copyright 2009-2010 Canonical Ltd.
5425 + * This program is free software; you can redistribute it and/or
5426 + * modify it under the terms of the GNU General Public License as
5427 + * published by the Free Software Foundation, version 2 of the
5431 +#include <linux/errno.h>
5432 +#include <linux/kernel.h>
5433 +#include <linux/mm.h>
5434 +#include <linux/slab.h>
5435 +#include <linux/vmalloc.h>
5436 +#include <linux/err.h>
5437 +#include <linux/kref.h>
5439 +#include "include/match.h"
5442 + * free_table - free a table allocated by unpack table
5443 + * @table: table to unpack (MAYBE NULL)
5445 +static void free_table(struct table_header *table)
5450 + if (is_vmalloc_addr(table))
5457 + * unpack_table - unpack a dfa table (one of accept, default, base, next check)
5458 + * @blob: data to unpack
5459 + * @bsize: size of blob
5461 + * Returns: pointer to table else NULL on failure
5463 + * NOTE: must be freed by free_table (not kmalloc)
5465 +static struct table_header *unpack_table(char *blob, size_t bsize)
5467 + struct table_header *table = NULL;
5468 + struct table_header th;
5471 + if (bsize < sizeof(struct table_header))
5474 + /* loaded td_id's start at 1, subtract 1 now to avoid doing
5475 + * it every time we use td_id as an index
5477 + th.td_id = be16_to_cpu(*(u16 *) (blob)) - 1;
5478 + th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
5479 + th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
5480 + blob += sizeof(struct table_header);
5482 + if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
5483 + th.td_flags == YYTD_DATA8))
5486 + tsize = table_size(th.td_lolen, th.td_flags);
5487 + if (bsize < tsize)
5490 + /* freed by free_table */
5491 + table = kmalloc(tsize, GFP_KERNEL);
5493 + table = vmalloc(tsize);
5496 + if (th.td_flags == YYTD_DATA8)
5497 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
5498 + u8, byte_to_byte);
5499 + else if (th.td_flags == YYTD_DATA16)
5500 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
5501 + u16, be16_to_cpu);
5502 + else if (th.td_flags == YYTD_DATA32)
5503 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
5504 + u32, be32_to_cpu);
5512 + free_table(table);
5517 + * verify_dfa - verify that all the transitions and states in the dfa tables
5519 + * @dfa: dfa to test (NOT NULL)
5520 + * @flags: flags controlling what type of accept table are acceptable
5522 + * Assumes dfa has gone through the first pass verification done by unpacking
5523 + * NOTE: this does not valid accept table values
5525 + * Returns: %0 else error code on failure to verify
5527 +static int verify_dfa(struct aa_dfa *dfa, int flags)
5529 + size_t i, state_count, trans_count;
5530 + int error = -EPROTO;
5532 + /* check that required tables exist */
5533 + if (!(dfa->tables[YYTD_ID_DEF] &&
5534 + dfa->tables[YYTD_ID_BASE] &&
5535 + dfa->tables[YYTD_ID_NXT] && dfa->tables[YYTD_ID_CHK]))
5538 + /* accept.size == default.size == base.size */
5539 + state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
5540 + if (ACCEPT1_FLAGS(flags)) {
5541 + if (!dfa->tables[YYTD_ID_ACCEPT])
5543 + if (state_count != dfa->tables[YYTD_ID_ACCEPT]->td_lolen)
5546 + if (ACCEPT2_FLAGS(flags)) {
5547 + if (!dfa->tables[YYTD_ID_ACCEPT2])
5549 + if (state_count != dfa->tables[YYTD_ID_ACCEPT2]->td_lolen)
5552 + if (state_count != dfa->tables[YYTD_ID_DEF]->td_lolen)
5555 + /* next.size == chk.size */
5556 + trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen;
5557 + if (trans_count != dfa->tables[YYTD_ID_CHK]->td_lolen)
5560 + /* if equivalence classes then its table size must be 256 */
5561 + if (dfa->tables[YYTD_ID_EC] &&
5562 + dfa->tables[YYTD_ID_EC]->td_lolen != 256)
5565 + if (flags & DFA_FLAG_VERIFY_STATES) {
5566 + for (i = 0; i < state_count; i++) {
5567 + if (DEFAULT_TABLE(dfa)[i] >= state_count)
5569 + /* TODO: do check that DEF state recursion terminates */
5570 + if (BASE_TABLE(dfa)[i] >= trans_count + 256)
5574 + for (i = 0; i < trans_count; i++) {
5575 + if (NEXT_TABLE(dfa)[i] >= state_count)
5577 + if (CHECK_TABLE(dfa)[i] >= state_count)
5588 + * aa_dfa_free - free a dfa allocated by aa_dfa_unpack
5589 + * @dfa: the dfa to free (MAYBE NULL)
5591 + * Requires: reference count to dfa == 0
5593 +static void aa_dfa_free(struct aa_dfa *dfa)
5598 + for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
5599 + free_table(dfa->tables[i]);
5600 + dfa->tables[i] = NULL;
5607 + * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa)
5608 + * @kr: kref callback for freeing of a dfa (NOT NULL)
5610 +void aa_dfa_free_kref(struct kref *kref)
5612 + struct aa_dfa *dfa = container_of(kref, struct aa_dfa, count);
5617 + * aa_dfa_unpack - unpack the binary tables of a serialized dfa
5618 + * @blob: aligned serialized stream of data to unpack (NOT NULL)
5619 + * @size: size of data to unpack
5620 + * @flags: flags controlling what type of accept tables are acceptable
5622 + * Unpack a dfa that has been serialized. Dfa format and information in
5623 + * Documentation/AppArmor/dfa.txt
5624 + * Assumes the dfa @blob stream has been aligned on a 8 byte boundry
5626 + * Returns: an unpacked dfa ready for matching or ERR_PTR on failure
5628 +struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)
5631 + int error = -ENOMEM;
5632 + char *data = blob;
5633 + struct table_header *table = NULL;
5634 + struct aa_dfa *dfa = kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
5638 + kref_init(&dfa->count);
5642 + /* get dfa table set header */
5643 + if (size < sizeof(struct table_set_header))
5646 + if (ntohl(*(u32 *) data) != YYTH_MAGIC)
5649 + hsize = ntohl(*(u32 *) (data + 4));
5653 + dfa->flags = ntohs(*(u16 *) (data + 12));
5657 + while (size > 0) {
5658 + table = unpack_table(data, size);
5662 + switch (table->td_id) {
5663 + case YYTD_ID_ACCEPT:
5664 + if (!(table->td_flags & ACCEPT1_FLAGS(flags)))
5667 + case YYTD_ID_ACCEPT2:
5668 + if (!(table->td_flags & ACCEPT2_FLAGS(flags)))
5671 + case YYTD_ID_BASE:
5672 + if (table->td_flags != YYTD_DATA32)
5678 + if (table->td_flags != YYTD_DATA16)
5682 + if (table->td_flags != YYTD_DATA8)
5688 + /* check for duplicate table entry */
5689 + if (dfa->tables[table->td_id])
5691 + dfa->tables[table->td_id] = table;
5692 + data += table_size(table->td_lolen, table->td_flags);
5693 + size -= table_size(table->td_lolen, table->td_flags);
5697 + error = verify_dfa(dfa, flags);
5704 + free_table(table);
5706 + return ERR_PTR(error);
5710 + * aa_dfa_match_len - traverse @dfa to find state @str stops at
5711 + * @dfa: the dfa to match @str against (NOT NULL)
5712 + * @start: the state of the dfa to start matching in
5713 + * @str: the string of bytes to match against the dfa (NOT NULL)
5714 + * @len: length of the string of bytes to match
5716 + * aa_dfa_match_len will match @str against the dfa and return the state it
5717 + * finished matching in. The final state can be used to look up the accepting
5718 + * label, or as the start state of a continuing match.
5720 + * This function will happily match again the 0 byte and only finishes
5721 + * when @len input is consumed.
5723 + * Returns: final state reached after input is consumed
5725 +unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
5726 + const char *str, int len)
5728 + u16 *def = DEFAULT_TABLE(dfa);
5729 + u32 *base = BASE_TABLE(dfa);
5730 + u16 *next = NEXT_TABLE(dfa);
5731 + u16 *check = CHECK_TABLE(dfa);
5732 + unsigned int state = start, pos;
5737 + /* current state is <state>, matching character *str */
5738 + if (dfa->tables[YYTD_ID_EC]) {
5739 + /* Equivalence class table defined */
5740 + u8 *equiv = EQUIV_TABLE(dfa);
5741 + /* default is direct to next state */
5742 + for (; len; len--) {
5743 + pos = base[state] + equiv[(u8) *str++];
5744 + if (check[pos] == state)
5745 + state = next[pos];
5747 + state = def[state];
5750 + /* default is direct to next state */
5751 + for (; len; len--) {
5752 + pos = base[state] + (u8) *str++;
5753 + if (check[pos] == state)
5754 + state = next[pos];
5756 + state = def[state];
5764 + * aa_dfa_next_state - traverse @dfa to find state @str stops at
5765 + * @dfa: the dfa to match @str against (NOT NULL)
5766 + * @start: the state of the dfa to start matching in
5767 + * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
5769 + * aa_dfa_next_state will match @str against the dfa and return the state it
5770 + * finished matching in. The final state can be used to look up the accepting
5771 + * label, or as the start state of a continuing match.
5773 + * Returns: final state reached after input is consumed
5775 +unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
5778 + return aa_dfa_match_len(dfa, start, str, strlen(str));
5780 diff --git a/security/apparmor/net.c b/security/apparmor/net.c
5781 new file mode 100644
5782 index 0000000..e9b1d1e
5784 +++ b/security/apparmor/net.c
5787 + * AppArmor security module
5789 + * This file contains AppArmor network mediation
5791 + * Copyright (C) 1998-2008 Novell/SUSE
5792 + * Copyright 2009-2010 Canonical Ltd.
5794 + * This program is free software; you can redistribute it and/or
5795 + * modify it under the terms of the GNU General Public License as
5796 + * published by the Free Software Foundation, version 2 of the
5800 +#include "include/apparmor.h"
5801 +#include "include/audit.h"
5802 +#include "include/context.h"
5803 +#include "include/net.h"
5804 +#include "include/policy.h"
5806 +#include "af_names.h"
5808 +static const char *sock_type_names[] = {
5822 +struct aa_audit_net {
5823 + struct aa_audit base;
5825 + int family, type, protocol;
5829 +/* audit callback for net specific fields */
5830 +static void audit_cb(struct audit_buffer *ab, struct aa_audit *va)
5832 + struct aa_audit_net *sa = container_of(va, struct aa_audit_net, base);
5834 + if (sa->family || sa->type) {
5835 + if (address_family_names[sa->family]) {
5836 + audit_log_format(ab, " family=");
5837 + audit_log_string(ab, address_family_names[sa->family]);
5839 + audit_log_format(ab, " family=\"unknown(%d)\"",
5842 + if (sock_type_names[sa->type]) {
5843 + audit_log_format(ab, " sock_type=");
5844 + audit_log_string(ab, sock_type_names[sa->type]);
5846 + audit_log_format(ab, " sock_type=\"unknown(%d)\"",
5849 + audit_log_format(ab, " protocol=%d", sa->protocol);
5855 + * aa_audit_net - audit network access
5856 + * @profile: profile being enforced (NOT NULL)
5857 + * @sa: audit data (NOT NULL)
5859 + * Returns: %0 or sa->error else other errorcode on failure
5861 +static int aa_audit_net(struct aa_profile *profile, struct aa_audit_net *sa)
5863 + int type = AUDIT_APPARMOR_AUTO;
5865 + if (likely(!sa->base.error)) {
5866 + u16 audit_mask = profile->net.audit[sa->family];
5867 + if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
5868 + !(1 << sa->type & audit_mask)))
5870 + type = AUDIT_APPARMOR_AUDIT;
5872 + u16 quiet_mask = profile->net.quiet[sa->family];
5873 + u16 kill_mask = 0;
5874 + u16 denied = (1 << sa->type) & ~quiet_mask;
5876 + if (denied & kill_mask)
5877 + type = AUDIT_APPARMOR_KILL;
5879 + if ((denied & quiet_mask) &&
5880 + AUDIT_MODE(profile) != AUDIT_NOQUIET &&
5881 + AUDIT_MODE(profile) != AUDIT_ALL)
5882 + return COMPLAIN_MODE(profile) ? 0 : sa->base.error;
5885 + return aa_audit(type, profile, &sa->base, audit_cb);
5889 + * aa_net_perm - very course network access check
5890 + * @profile: profile being enforced (NOT NULL)
5891 + * @operation: name of the operation being checked (NOT NULL)
5892 + * @family: network family
5893 + * @type: network type
5894 + * @protocol: network protocol
5896 + * Returns: %0 else error if permission denied
5898 +int aa_net_perm(struct aa_profile *profile, char *operation,
5899 + int family, int type, int protocol)
5902 + struct aa_audit_net sa = {
5903 + .base.operation = operation,
5904 + .base.gfp_mask = GFP_KERNEL,
5907 + .protocol = protocol,
5910 + if ((family < 0) || (family >= AF_MAX))
5913 + if ((type < 0) || (type >= SOCK_MAX))
5916 + /* unix domain and netlink sockets are handled by ipc */
5917 + if (family == AF_UNIX || family == AF_NETLINK)
5920 + family_mask = profile->net.allowed[family];
5922 + sa.base.error = (family_mask & (1 << type)) ? 0 : -EACCES;
5924 + return aa_audit_net(profile, &sa);
5928 + * aa_revalidate_sk - Revalidate access to a sock
5929 + * @sk: sock being revalidated (NOT NULL)
5930 + * @operation: name of operation being checked (NOT NULL)
5932 + * Returns: %0 else error if permission denied
5934 +int aa_revalidate_sk(struct sock *sk, char *operation)
5936 + struct aa_profile *profile;
5939 + /* aa_revalidate_sk should not be called from interrupt context
5940 + * don't mediate these calls as they are not task related
5942 + if (in_interrupt())
5945 + profile = __aa_current_profile();
5946 + if (!unconfined(profile))
5947 + error = aa_net_perm(profile, operation,
5948 + sk->sk_family, sk->sk_type,
5953 diff --git a/security/apparmor/path.c b/security/apparmor/path.c
5954 new file mode 100644
5955 index 0000000..81ce71d
5957 +++ b/security/apparmor/path.c
5960 + * AppArmor security module
5962 + * This file contains AppArmor function for pathnames
5964 + * Copyright (C) 1998-2008 Novell/SUSE
5965 + * Copyright 2009-2010 Canonical Ltd.
5967 + * This program is free software; you can redistribute it and/or
5968 + * modify it under the terms of the GNU General Public License as
5969 + * published by the Free Software Foundation, version 2 of the
5973 +#include <linux/mnt_namespace.h>
5974 +#include <linux/mount.h>
5975 +#include <linux/namei.h>
5976 +#include <linux/nsproxy.h>
5977 +#include <linux/path.h>
5978 +#include <linux/sched.h>
5979 +#include <linux/slab.h>
5980 +#include <linux/fs_struct.h>
5982 +#include "include/apparmor.h"
5983 +#include "include/path.h"
5984 +#include "include/policy.h"
5987 + * d_namespace_path - lookup a name associated with a given path
5988 + * @path: path to lookup (NOT NULL)
5989 + * @buf: buffer to store path to (NOT NULL)
5990 + * @buflen: length of @buf
5991 + * @name: return pointer for start of path name with in @buf (NOT NULL)
5992 + * @flags: flags controling path lookup
5994 + * Handle path name lookup.
5996 + * Returns: %0 else error code if path lookup fails
5997 + * When no error the path name is returned in @name which points to
5998 + * to a position in @buf
6000 +static int d_namespace_path(struct path *path, char *buf, int buflen,
6001 + char **name, int flags)
6003 + struct path root, tmp;
6005 + int deleted, connected;
6008 + /* Get the root we want to resolve too */
6009 + if (flags & PATH_CHROOT_REL) {
6010 + /* resolve paths relative to chroot */
6011 + read_lock(¤t->fs->lock);
6012 + root = current->fs->root;
6013 + /* released below */
6015 + read_unlock(¤t->fs->lock);
6017 + /* resolve paths relative to namespace */
6018 + root.mnt = current->nsproxy->mnt_ns->root;
6019 + root.dentry = root.mnt->mnt_root;
6020 + /* released below */
6024 + spin_lock(&dcache_lock);
6025 + /* There is a race window between path lookup here and the
6026 + * need to strip the " (deleted) string that __d_path applies
6027 + * Detect the race and relookup the path
6029 + * The stripping of (deleted) is a hack that could be removed
6030 + * with an updated __d_path
6034 + deleted = d_unlinked(path->dentry);
6035 + res = __d_path(path, &tmp, buf, buflen);
6037 + } while (deleted != d_unlinked(path->dentry));
6038 + spin_unlock(&dcache_lock);
6041 + /* handle error conditions - and still allow a partial path to
6044 + if (IS_ERR(res)) {
6045 + error = PTR_ERR(res);
6050 + /* On some filesystems, newly allocated dentries appear to the
6051 + * security_path hooks as a deleted dentry except without an
6052 + * inode allocated.
6054 + * Remove the appended deleted text and return as string for
6055 + * normal mediation, or auditing. The (deleted) string is
6056 + * guarenteed to be added in this case, so just strip it.
6058 + buf[buflen - 11] = 0; /* - (len(" (deleted)") +\0) */
6060 + if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) {
6066 + /* Determine if the path is connected to the expected root */
6067 + connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt;
6069 + /* If the path is not connected, then remove any leading / that
6070 + * __d_path may have returned.
6072 + * specifically directed to connect the path,
6074 + * if in a chroot and doing chroot relative paths and the path
6075 + * resolves to the namespace root (would be connected outside
6076 + * of chroot) and specifically directed to connect paths to
6080 + !(flags & PATH_CONNECT_PATH) &&
6081 + !((flags & PATH_CHROOT_REL) && (flags & PATH_CHROOT_NSCONNECT) &&
6082 + (tmp.mnt == current->nsproxy->mnt_ns->root &&
6083 + tmp.dentry == current->nsproxy->mnt_ns->root->mnt_root))) {
6084 + /* disconnected path, don't return pathname starting with '/' */
6097 + * get_name_to_buffer - get the pathname to a buffer ensure dir / is appended
6098 + * @path: path to get name for (NOT NULL)
6099 + * @flags: flags controlling path lookup
6100 + * @buffer: buffer to put name in (NOT NULL)
6101 + * @size: size of buffer
6102 + * @name: on return contains position of path name in @buffer (NOT NULL)
6104 + * Returns: %0 else error on failure
6106 +static int get_name_to_buffer(struct path *path, int flags, char *buffer,
6107 + int size, char **name)
6109 + int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
6110 + int error = d_namespace_path(path, buffer, size - adjust, name, flags);
6112 + if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0')
6114 + * Append "/" to the pathname. The root directory is a special
6115 + * case; it already ends in slash.
6117 + strcpy(&buffer[size - 2], "/");
6123 + * aa_get_name - compute the pathname of a file
6124 + * @path: path the file (NOT NULL)
6125 + * @flags: flags controling path name generation
6126 + * @buffer: buffer that aa_get_name() allocated (NOT NULL)
6127 + * @name: the generated path name if !error
6129 + * @name is a pointer to the beginning of the pathname (which usually differs
6130 + * from the beginning of the buffer), or NULL. If there is an error @name
6131 + * may contain a partial or invalid name that can be used for audit purposes,
6132 + * but it can not be used for mediation.
6134 + * We need PATH_IS_DIR to indicate whether the file is a directory or not
6135 + * because the file may not yet exist, and so we cannot check the inode's
6138 + * Returns: %0 else error code if could retrieve name
6140 +int aa_get_name(struct path *path, int flags, char **buffer, char **name)
6142 + char *buf, *str = NULL;
6149 + /* freed by caller */
6150 + buf = kmalloc(size, GFP_KERNEL);
6154 + error = get_name_to_buffer(path, flags, buf, size, &str);
6155 + if (!error || (error == -ENOENT) || (error == -ESTALE))
6160 + if (size > aa_g_path_max)
6161 + return -ENAMETOOLONG;
6170 + * sysctl_pathname - generate a pathname for a sysctl
6171 + * @table: sysctl name table (NOT NULL)
6172 + * @buffer: buffer to put name in (NOT NULL)
6173 + * @buflen: length of @buffer
6175 + * Returns: sysctl path name in @buffer or NULL on error
6177 +char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
6181 + buffer += --buflen;
6185 + int namelen = strlen(table->procname);
6187 + if (buflen < namelen + 1)
6189 + buflen -= namelen + 1;
6190 + buffer -= namelen;
6191 + memcpy(buffer, table->procname, namelen);
6193 + table = table->parent;
6198 + memcpy(buffer, "/sys", 4);
6202 diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
6203 new file mode 100644
6204 index 0000000..c4532d6
6206 +++ b/security/apparmor/policy.c
6209 + * AppArmor security module
6211 + * This file contains AppArmor policy manipulation functions
6213 + * Copyright (C) 1998-2008 Novell/SUSE
6214 + * Copyright 2009-2010 Canonical Ltd.
6216 + * This program is free software; you can redistribute it and/or
6217 + * modify it under the terms of the GNU General Public License as
6218 + * published by the Free Software Foundation, version 2 of the
6222 + * AppArmor policy is based around profiles, which contain the rules a
6223 + * task is confined by. Every task in the sytem has a profile attached
6224 + * to it determined either by matching "unconfined" tasks against the
6225 + * visible set of profiles or by following a profiles attachment rules.
6227 + * Each profile exists in a profile namespace which is a container of
6228 + * visible profiles. Each namespace contains a special "unconfined" profile,
6229 + * which doesn't enforce any confinement on a task beyond DAC.
6231 + * Namespace and profile names can be written together in either
6232 + * of two syntaxes.
6233 + * :namespace:profile - used by kernel interfaces for easy detection
6234 + * namespace://profile - used by policy
6236 + * Profile names can not start with : or @ or ^ and may not contain \0
6238 + * Reserved profile names
6239 + * unconfined - special automatically generated unconfined profile
6240 + * inherit - special name to indicate profile inheritance
6241 + * null-XXXX-YYYY - special automically generated learning profiles
6243 + * Namespace names may not start with / or @ and may not contain \0 or :
6244 + * Reserved namespace namespace
6245 + * user-XXXX - user defined profiles
6247 + * a // in a profile or namespace name indicates a hierarcical name with the
6248 + * name before the // being the parent and the name after the child.
6250 + * Profile and namespace hierachies serve two different but similar purposes.
6251 + * The namespace contains the set of visible profiles that are considered
6252 + * for attachment. The hierarchy of namespaces allows for virtualizing
6253 + * the namespace so that for example a chroot can have its own set of profiles
6254 + * which may define some local user namespaces.
6255 + * The profile hierachy severs two distinct purposes,
6256 + * - it allows for sub profiles or hats, which allows an application to run
6257 + * subprograms under its own profile with different restriction than it
6258 + * self, and not have it use the system profile.
6259 + * eg. if a mail program starts an editor, the policy might make the
6260 + * restrictions tighter on the editor tighter than the mail program,
6261 + * and definitely different than general editor restrictions
6262 + * - it allows for binary hierarchy of profiles, so that execution history
6263 + * is preserved. This feature isn't exploited by AppArmor reference policy
6264 + * but is allowed. NOTE: this is currently suboptimal because profile
6265 + * aliasing is not currently implemented so that a profile for each
6266 + * level must be defined.
6267 + * eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started
6270 + * A profile or namespace name that can contain one or more // seperators
6271 + * is refered to as an hname (hierarchical).
6272 + * eg. /bin/bash//bin/ls
6274 + * An fqname is a name that may contain both namespace and profile hnames.
6275 + * eg. :ns:/bin/bash//bin/ls
6278 + * - locking of profile lists is currently fairly coarse. All profile
6279 + * lists within a namespace use the namespace lock.
6280 + * FIXME: move profile lists to using rcu_lists
6283 +#include <linux/slab.h>
6284 +#include <linux/spinlock.h>
6285 +#include <linux/string.h>
6287 +#include "include/apparmor.h"
6288 +#include "include/capability.h"
6289 +#include "include/context.h"
6290 +#include "include/file.h"
6291 +#include "include/ipc.h"
6292 +#include "include/match.h"
6293 +#include "include/path.h"
6294 +#include "include/policy.h"
6295 +#include "include/policy_unpack.h"
6296 +#include "include/resource.h"
6297 +#include "include/sid.h"
6300 +/* root profile namespace */
6301 +struct aa_namespace *root_ns;
6303 +const char *profile_mode_names[] = {
6310 + * hname_tail - find the last component of an hname
6311 + * @name: hname to find the tail component of (NOT NULL)
6313 + * Returns: the tail name component of an hname
6315 +static const char *hname_tail(const char *hname)
6318 + hname = strim((char *)hname);
6319 + for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
6320 + hname = split + 2;
6326 + * policy_init - initialize a policy structure
6327 + * @policy: policy to initialize (NOT NULL)
6328 + * @name: name of the policy, init will make a copy of it (NOT NULL)
6330 +static bool policy_init(struct aa_policy *policy, const char *name)
6332 + /* freed by policy_free */
6333 + policy->hname = kstrdup(name, GFP_KERNEL);
6334 + if (!policy->hname)
6336 + /* base.name is a substring of fqname */
6337 + policy->name = (char *)hname_tail(policy->hname);
6339 + INIT_LIST_HEAD(&policy->list);
6340 + INIT_LIST_HEAD(&policy->profiles);
6341 + kref_init(&policy->count);
6347 + * policy_destroy - free the elements referenced by @policy
6348 + * @policy: policy that is to have its elements freed (NOT NULL)
6350 +static void policy_destroy(struct aa_policy *policy)
6352 + /* still contains profiles -- invalid */
6353 + if (!list_empty(&policy->profiles)) {
6354 + AA_ERROR("%s: internal error, "
6355 + "policy '%s' still contains profiles\n",
6356 + __func__, policy->name);
6359 + if (!list_empty(&policy->list)) {
6360 + AA_ERROR("%s: internal error, policy '%s' still on list\n",
6361 + __func__, policy->name);
6365 + /* don't free name as its a subset of hname */
6366 + kzfree(policy->hname);
6370 + * __policy_find - find a policy by @name on a policy list
6371 + * @head: list to search (NOT NULL)
6372 + * @name: name to search for (NOT NULL)
6374 + * Requires: correct locks for the @head list be held
6376 + * Returns: policy that match @name or NULL if not found
6378 +static struct aa_policy *__policy_find(struct list_head *head, const char *name)
6380 + struct aa_policy *policy;
6382 + list_for_each_entry(policy, head, list) {
6383 + if (!strcmp(policy->name, name))
6390 + * __policy_strn_find - find a policy thats name matches @len chars of @str
6391 + * @head: list to search (NOT NULL)
6392 + * @str: string to search for (NOT NULL)
6393 + * @len: length of match required
6395 + * Requires: correct locks for the @head list be held
6397 + * Returns: policy that match @str or NULL if not found
6399 + * if @len == strlen(@strlen) then this is equiv to __policy_find
6400 + * other wise it allows searching for policy by a partial match of name
6402 +static struct aa_policy *__policy_strn_find(struct list_head *head,
6403 + const char *str, int len)
6405 + struct aa_policy *policy;
6407 + list_for_each_entry(policy, head, list) {
6408 + if (aa_strneq(policy->name, str, len))
6416 + * Routines for AppArmor namespaces
6420 + * aa_alloc_namespace - allocate, initialize and return a new namespace
6421 + * @name: a preallocated name (NOT NULL)
6423 + * Returns: NULL on failure.
6425 +static struct aa_namespace *aa_alloc_namespace(const char *name)
6427 + struct aa_namespace *ns;
6429 + ns = kzalloc(sizeof(*ns), GFP_KERNEL);
6430 + AA_DEBUG("%s(%p)\n", __func__, ns);
6434 + if (!policy_init(&ns->base, name))
6436 + INIT_LIST_HEAD(&ns->sub_ns);
6437 + rwlock_init(&ns->lock);
6440 + * null profile is not added to the profile list,
6441 + * released by aa_free_namespace
6443 + ns->unconfined = aa_alloc_profile("unconfined");
6444 + if (!ns->unconfined)
6445 + goto fail_unconfined;
6447 + ns->unconfined->sid = aa_alloc_sid();
6448 + ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR |
6452 + * released by aa_free_namespace, however aa_remove_namespace breaks
6453 + * the cyclic references (ns->unconfined, and unconfined->ns) and
6454 + * replaces with refs to parent namespace unconfined
6456 + ns->unconfined->ns = aa_get_namespace(ns);
6461 + kzfree(ns->base.name);
6468 + * aa_free_namespace - free a profile namespace
6469 + * @ns: the namespace to free (MAYBE NULL)
6471 + * Requires: All references to the namespace must have been put, if the
6472 + * namespace was referenced by a profile confining a task,
6474 +static void aa_free_namespace(struct aa_namespace *ns)
6479 + policy_destroy(&ns->base);
6480 + aa_put_namespace(ns->parent);
6482 + if (ns->unconfined && ns->unconfined->ns == ns)
6483 + ns->unconfined->ns = NULL;
6485 + aa_put_profile(ns->unconfined);
6490 + * aa_free_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
6491 + * @kr: kref callback for freeing of a namespace (NOT NULL)
6493 +void aa_free_namespace_kref(struct kref *kref)
6495 + aa_free_namespace(container_of(kref, struct aa_namespace, base.count));
6499 + * __aa_find_namespace - find a namespace on a list by @name
6500 + * @head: list to search for namespace on (NOT NULL)
6501 + * @name: name of namespace to look for (NOT NULL)
6503 + * Returns: unrefcounted namespace
6505 + * Requires: ns lock be held
6507 +static struct aa_namespace *__aa_find_namespace(struct list_head *head,
6510 + return (struct aa_namespace *)__policy_find(head, name);
6514 + * aa_find_namespace - look up a profile namespace on the namespace list
6515 + * @root: namespace to search in (NOT NULL)
6516 + * @name: name of namespace to find (NOT NULL)
6518 + * Returns: a pointer to the namespace on the list, or NULL if no namespace
6519 + * called @name exists.
6521 + * refcount released by caller
6523 +struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
6526 + struct aa_namespace *ns = NULL;
6528 + read_lock(&root->lock);
6529 + ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
6530 + read_unlock(&root->lock);
6536 + * aa_prepare_namespace - find an existing or create a new namespace of @name
6537 + * @name: the namespace to find or add (NOT NULL)
6539 + * Returns: refcounted namespace or NULL if failed to create one
6541 +static struct aa_namespace *aa_prepare_namespace(const char *name)
6543 + struct aa_namespace *ns, *root;
6545 + root = aa_current_profile()->ns;
6547 + write_lock(&root->lock);
6549 + /* if name isn't specified the profile is loaded to the current ns */
6551 + /* released by caller */
6552 + ns = aa_get_namespace(root);
6556 + /* try and find the specified ns and if it doesn't exist create it */
6557 + /* released by caller */
6558 + ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
6560 + /* name && namespace not found */
6561 + struct aa_namespace *new_ns;
6562 + write_unlock(&root->lock);
6563 + new_ns = aa_alloc_namespace(name);
6566 + write_lock(&root->lock);
6567 + /* test for race when new_ns was allocated */
6568 + ns = __aa_find_namespace(&root->sub_ns, name);
6570 + /* add parent ref */
6571 + new_ns->parent = aa_get_namespace(root);
6573 + list_add(&new_ns->base.list, &root->sub_ns);
6574 + /* add list ref */
6575 + ns = aa_get_namespace(new_ns);
6577 + /* raced so free the new one */
6578 + aa_free_namespace(new_ns);
6579 + /* get reference on namespace */
6580 + aa_get_namespace(ns);
6584 + write_unlock(&root->lock);
6591 + * __aa_add_profile - add a profile to a list
6592 + * @list: list to add it to (NOT NULL)
6593 + * @profile: the profile to add (NOT NULL)
6595 + * refcount @profile, should be put by __aa_remove_profile
6597 + * Requires: namespace lock be held, or list not be shared
6599 +static void __aa_add_profile(struct list_head *list,
6600 + struct aa_profile *profile)
6602 + list_add(&profile->base.list, list);
6603 + /* get list reference */
6604 + aa_get_profile(profile);
6608 + * __aa_remove_profile - remove a profile from the list it is one
6609 + * @profile: the profile to remove (NOT NULL)
6611 + * remove a profile from the list, warning generally removal should
6612 + * be done with __aa_replace_profile as most profile removals are
6613 + * replacements to the unconfined profile.
6615 + * put @profile list refcount
6617 + * Requires: namespace lock be held, or list not have been live
6619 +static void __aa_remove_profile(struct aa_profile *profile)
6621 + list_del_init(&profile->base.list);
6622 + if (!(profile->flags & PFLAG_NO_LIST_REF))
6623 + /* release list reference */
6624 + aa_put_profile(profile);
6628 + * __aa_replace_profile - replace @old with @new on a list
6629 + * @old: profile to be replaced (NOT NULL)
6630 + * @new: profile to replace @old with (MAYBE NULL)
6632 + * Will duplicaticate and refcount elements that @new inherits from @old
6633 + * and will inherit @old children. If new is NULL it will replace to the
6634 + * unconfined profile for old's namespace.
6636 + * refcount @new for list, put @old list refcount
6638 + * Requires: namespace list lock be held, or list not be shared
6640 +static void __aa_replace_profile(struct aa_profile *old,
6641 + struct aa_profile *new)
6643 + struct aa_policy *policy;
6644 + struct aa_profile *child, *tmp;
6647 + policy = &old->parent->base;
6649 + policy = &old->ns->base;
6652 + /* released when @new is freed */
6653 + new->parent = aa_get_profile(old->parent);
6654 + new->ns = aa_get_namespace(old->ns);
6655 + new->sid = old->sid;
6656 + __aa_add_profile(&policy->profiles, new);
6658 + /* refcount not taken, held via @old refcount */
6659 + new = old->ns->unconfined;
6662 + /* inherit children */
6663 + list_for_each_entry_safe(child, tmp, &old->base.profiles, base.list) {
6664 + aa_put_profile(child->parent);
6665 + child->parent = aa_get_profile(new);
6666 + /* list refcount transfered to @new*/
6667 + list_move(&child->base.list, &new->base.profiles);
6670 + /* released by aa_free_profile */
6671 + old->replacedby = aa_get_profile(new);
6672 + __aa_remove_profile(old);
6676 + * __aa_profile_list_release - remove all profiles on the list and put refs
6677 + * @head: list of profiles (NOT NULL)
6679 + * Requires: namespace lock be held
6681 +static void __aa_profile_list_release(struct list_head *head)
6683 + struct aa_profile *profile, *tmp;
6684 + list_for_each_entry_safe(profile, tmp, head, base.list) {
6685 + /* release any children lists first */
6686 + __aa_profile_list_release(&profile->base.profiles);
6687 + __aa_replace_profile(profile, NULL);
6691 +static void __aa_remove_namespace(struct aa_namespace *ns);
6694 + * __aa_ns_list_release - remove all profile namespaces on the list put refs
6695 + * @head: list of profile namespaces (NOT NULL)
6697 + * Requires: namespace lock be held
6699 +static void __aa_ns_list_release(struct list_head *head)
6701 + struct aa_namespace *ns, *tmp;
6702 + list_for_each_entry_safe(ns, tmp, head, base.list)
6703 + __aa_remove_namespace(ns);
6708 + * aa_destroy_namespace - remove everything contained by @ns
6709 + * @ns: namespace to have it contents removed (NOT NULL)
6711 +static void aa_destroy_namespace(struct aa_namespace *ns)
6716 + write_lock(&ns->lock);
6717 + /* release all profiles in this namespace */
6718 + __aa_profile_list_release(&ns->base.profiles);
6720 + /* release all sub namespaces */
6721 + __aa_ns_list_release(&ns->sub_ns);
6723 + write_unlock(&ns->lock);
6727 + * __aa_remove_namespace - remove a namespace and all its children
6728 + * @ns: namespace to be removed (NOT NULL)
6730 + * Requires: ns->parent->lock be held and ns removed from parent.
6732 +static void __aa_remove_namespace(struct aa_namespace *ns)
6734 + struct aa_profile *unconfined = ns->unconfined;
6736 + /* remove ns from namespace list */
6737 + list_del_init(&ns->base.list);
6740 + * break the ns, unconfined profile cyclic reference and forward
6741 + * all new unconfined profiles requests to the parent namespace
6742 + * This will result in all confined tasks that have a profile
6743 + * being removed, inheriting the parent->unconfined profile.
6746 + ns->unconfined = aa_get_profile(ns->parent->unconfined);
6748 + aa_destroy_namespace(ns);
6750 + /* release original ns->unconfined ref */
6751 + aa_put_profile(unconfined);
6752 + /* release ns->base.list ref, from removal above */
6753 + aa_put_namespace(ns);
6757 + * aa_alloc_root_ns - allocate the root profile namespace
6759 + * Returns: %0 on success else error
6762 +int __init aa_alloc_root_ns(void)
6764 + /* released by aa_free_root_ns - used as list ref*/
6765 + root_ns = aa_alloc_namespace("root");
6773 + * aa_free_root_ns - free the root profile namespace
6775 +void aa_free_root_ns(void)
6777 + struct aa_namespace *ns = root_ns;
6780 + aa_destroy_namespace(ns);
6781 + aa_put_namespace(ns);
6785 + * aa_alloc_profile - allocate, initialize and return a new profile
6786 + * @hname: name of the profile (NOT NULL)
6788 + * Returns: NULL on failure, else refcounted profile
6790 +struct aa_profile *aa_alloc_profile(const char *hname)
6792 + struct aa_profile *profile;
6794 + /* freed by aa_free_profile - usually through aa_put_profile */
6795 + profile = kzalloc(sizeof(*profile), GFP_KERNEL);
6799 + if (!policy_init(&profile->base, hname)) {
6809 + * aa_new_null_profile - create a new null-X learning profile
6810 + * @parent: profile that caused this profile to be created (NOT NULL)
6811 + * @hat: true if the null- learning profile is a hat
6813 + * Create a null- complain mode profile used in learning mode. The name of
6814 + * the profile is unique and follows the format of parent//null-sid.
6816 + * null profiles are added to the profile list but the list does not
6817 + * hold a count on them so that they are automatically released when
6820 + * Returns: new profile else NULL on failure
6822 +struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
6824 + struct aa_profile *profile = NULL;
6826 + u32 sid = aa_alloc_sid();
6829 + name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, GFP_KERNEL);
6832 + sprintf(name, "%s//null-%x", parent->base.hname, sid);
6834 + profile = aa_alloc_profile(name);
6839 + profile->sid = sid;
6840 + profile->mode = APPARMOR_COMPLAIN;
6841 + profile->flags = PFLAG_NULL | PFLAG_NO_LIST_REF;
6843 + profile->flags |= PFLAG_HAT;
6845 + /* released on aa_free_profile */
6846 + profile->parent = aa_get_profile(parent);
6847 + profile->ns = aa_get_namespace(parent->ns);
6849 + write_lock(&profile->ns->lock);
6850 + __aa_add_profile(&parent->base.profiles, profile);
6851 + write_unlock(&profile->ns->lock);
6861 + * aa_free_profile - free a profile
6862 + * @profile: the profile to free (MAYBE NULL)
6864 + * Free a profile, its hats and null_profile. All references to the profile,
6865 + * its hats and null_profile must have been put.
6867 + * If the profile was referenced from a task context, aa_free_profile() will
6868 + * be called from an rcu callback routine, so we must not sleep here.
6870 +static void aa_free_profile(struct aa_profile *profile)
6872 + AA_DEBUG("%s(%p)\n", __func__, profile);
6877 + if (!list_empty(&profile->base.list)) {
6878 + AA_ERROR("%s: internal error, "
6879 + "profile '%s' still on ns list\n",
6880 + __func__, profile->base.name);
6884 + /* free children profiles */
6885 + policy_destroy(&profile->base);
6886 + aa_put_profile(profile->parent);
6888 + aa_put_namespace(profile->ns);
6890 + aa_free_file_rules(&profile->file);
6891 + aa_free_cap_rules(&profile->caps);
6892 + aa_free_net_rules(&profile->net);
6893 + aa_free_rlimit_rules(&profile->rlimits);
6895 + aa_free_sid(profile->sid);
6896 + aa_put_dfa(profile->xmatch);
6898 + if (profile->replacedby)
6899 + aa_put_profile(profile->replacedby);
6905 + * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile)
6906 + * @kr: kref callback for freeing of a profile (NOT NULL)
6908 +void aa_free_profile_kref(struct kref *kref)
6910 + struct aa_profile *p = container_of(kref, struct aa_profile,
6913 + aa_free_profile(p);
6916 +/* TODO: profile count accounting - setup in remove */
6919 + * __aa_find_child - find a profile on @head list with a name matching @name
6920 + * @head: list to search (NOT NULL)
6921 + * @name: name of profile (NOT NULL)
6923 + * Requires: ns lock protecting list be held
6925 + * Returns: unrefcounted profile ptr, or NULL if not found
6927 +static struct aa_profile *__aa_find_child(struct list_head *head,
6930 + return (struct aa_profile *)__policy_find(head, name);
6934 + * __aa_strn_find_child - find a profile on @head list using substring of @name
6935 + * @head: list to search (NOT NULL)
6936 + * @name: name of profile (NOT NULL)
6937 + * @len: length of @name substring to match
6939 + * Requires: ns lock protecting list be held
6941 + * Returns: unrefcounted profile ptr, or NULL if not found
6943 +static struct aa_profile *__aa_strn_find_child(struct list_head *head,
6944 + const char *name, int len)
6946 + return (struct aa_profile *)__policy_strn_find(head, name, len);
6950 + * aa_find_child - find a profile by @name in @parent
6951 + * @parent: profile to search (NOT NULL)
6952 + * @name: profile name to search for (NOT NULL)
6954 + * Returns: a ref counted profile or NULL if not found
6956 +struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
6958 + struct aa_profile *profile;
6960 + read_lock(&parent->ns->lock);
6961 + profile = aa_get_profile(__aa_find_child(&parent->base.profiles, name));
6962 + read_unlock(&parent->ns->lock);
6968 + * __aa_find_parent - lookup the parent of a profile of name @hname
6969 + * @ns: namespace to lookup profile in (NOT NULL)
6970 + * @hname: hierarchical profile name to find parent of (NOT NULL)
6972 + * Lookups up the parent of a fully qualified profile name, the profile
6973 + * that matches hname does not need to exist, in general this
6974 + * is used to load a new profile.
6976 + * Requires: ns->lock be held
6978 + * Returns: unrefcounted policy or NULL if not found
6980 +static struct aa_policy *__aa_find_parent(struct aa_namespace *ns,
6981 + const char *hname)
6983 + struct aa_policy *policy;
6984 + struct aa_profile *profile = NULL;
6987 + policy = &ns->base;
6989 + for (split = strstr(hname, "//"); split;) {
6990 + profile = __aa_strn_find_child(&policy->profiles, hname,
6994 + policy = &profile->base;
6995 + hname = split + 2;
6996 + split = strstr(hname, "//");
7000 + return &profile->base;
7004 + * __aa_find_profile - lookup the profile matching @hname
7005 + * @base: base list to start looking up profile name from (NOT NULL)
7006 + * @hname: hierarchical profile name (NOT NULL)
7008 + * Requires: ns->lock be held
7010 + * Returns: unrefcounted profile pointer or NULL if not found
7012 + * Do a relative name lookup, recursing through profile tree.
7014 +static struct aa_profile *__aa_find_profile(struct aa_policy *base,
7015 + const char *hname)
7017 + struct aa_profile *profile = NULL;
7020 + for (split = strstr(hname, "//"); split;) {
7021 + profile = __aa_strn_find_child(&base->profiles, hname,
7026 + base = &profile->base;
7027 + hname = split + 2;
7028 + split = strstr(hname, "//");
7031 + profile = __aa_find_child(&base->profiles, hname);
7037 + * aa_find_profile_by_name - find a profile by its full or partial name
7038 + * @ns: the namespace to start from
7039 + * @hname: name to do lookup on. Does not contain namespace prefix
7041 + * Returns: refcounted profile or NULL if not found
7043 +struct aa_profile *aa_find_profile(struct aa_namespace *ns, const char *hname)
7045 + struct aa_profile *profile;
7047 + read_lock(&ns->lock);
7048 + profile = aa_get_profile(__aa_find_profile(&ns->base, hname));
7049 + read_unlock(&ns->lock);
7054 + * replacement_allowed - test to see if replacement is allowed
7055 + * @profile: profile to test if it can be replaced (MAYBE NULL)
7056 + * @sa: audit data (NOT NULL)
7057 + * @add_only: true if replacement shouldn't be allowed but addition is okay
7059 + * Returns: %1 if replacement allowed else %0
7061 +static bool replacement_allowed(struct aa_profile *profile,
7062 + struct aa_audit_iface *sa,
7066 + if (profile->flags & PFLAG_IMMUTABLE) {
7067 + sa->base.info = "cannot replace immutible profile";
7068 + sa->base.error = -EPERM;
7070 + } else if (add_only) {
7071 + sa->base.info = "profile already exists";
7072 + sa->base.error = -EEXIST;
7080 + * __add_new_profile - simple wrapper around __aa_add_profile
7081 + * @ns: namespace that profile is being added to (NOT NULL)
7082 + * @policy: the policy container to add the profile to (NOT NULL)
7083 + * @profile: profile to add (NOT NULL)
7085 + * add a profile to a list and do other required basic allocations
7087 +static void __add_new_profile(struct aa_namespace *ns,
7088 + struct aa_policy *policy,
7089 + struct aa_profile *profile)
7091 + if (policy != &ns->base)
7092 + /* released on profile replacement or aa_free_profile */
7093 + profile->parent = aa_get_profile((struct aa_profile *) policy);
7094 + __aa_add_profile(&policy->profiles, profile);
7095 + /* released on aa_free_profile */
7096 + profile->sid = aa_alloc_sid();
7097 + profile->ns = aa_get_namespace(ns);
7101 + * aa_interface_replace_profiles - replace profile(s) on the profile list
7102 + * @udata: serialized data stream (NOT NULL)
7103 + * @size: size of the serialized data stream
7104 + * @add_only: true if only doing addition, no replacement allowed
7106 + * unpack and replace a profile on the profile list and uses of that profile
7107 + * by any aa_task_cxt. If the profile does not exist on the profile list
7110 + * Returns: size of data consumed else error code on failure.
7112 +ssize_t aa_interface_replace_profiles(void *udata, size_t size, bool add_only)
7114 + struct aa_policy *policy;
7115 + struct aa_profile *old_profile = NULL, *new_profile = NULL;
7116 + struct aa_profile *rename_profile = NULL;
7117 + struct aa_namespace *ns;
7119 + struct aa_audit_iface sa = {
7120 + .base.operation = "profile_replace",
7121 + .base.gfp_mask = GFP_ATOMIC,
7124 + /* check if loading policy is locked out */
7125 + if (aa_g_lock_policy) {
7126 + sa.base.info = "policy locked";
7127 + sa.base.error = -EACCES;
7131 + /* released below */
7132 + new_profile = aa_unpack(udata, size, &sa);
7133 + if (IS_ERR(new_profile)) {
7134 + sa.base.error = PTR_ERR(new_profile);
7138 + /* released below */
7139 + ns = aa_prepare_namespace(sa.name2);
7141 + sa.base.info = "failed to prepare namespace";
7142 + sa.base.error = -ENOMEM;
7146 + sa.name = new_profile->base.hname;
7148 + write_lock(&ns->lock);
7149 + /* no ref on policy only use inside lock */
7150 + policy = __aa_find_parent(ns, new_profile->base.hname);
7153 + sa.base.info = "parent does not exist";
7154 + sa.base.error = -ENOENT;
7158 + old_profile = __aa_find_child(&policy->profiles,
7159 + new_profile->base.name);
7160 + /* released below */
7161 + aa_get_profile(old_profile);
7163 + if (new_profile->rename) {
7164 + rename_profile = __aa_find_profile(&ns->base,
7165 + new_profile->rename);
7166 + /* released below */
7167 + aa_get_profile(rename_profile);
7169 + if (!rename_profile) {
7170 + sa.base.info = "profile to rename does not exist";
7171 + sa.name = new_profile->rename;
7172 + sa.base.error = -ENOENT;
7177 + if (!replacement_allowed(old_profile, &sa, add_only))
7180 + if (!replacement_allowed(rename_profile, &sa, add_only))
7184 + if (!old_profile && !rename_profile)
7185 + sa.base.operation = "profile_load";
7187 + error = aa_audit_iface(&sa);
7189 + /* rename field must be cleared as it is shared with replaced-by */
7190 + if (new_profile->rename) {
7191 + kzfree(new_profile->rename);
7192 + new_profile->rename = NULL;
7197 + __aa_replace_profile(old_profile, new_profile);
7198 + if (rename_profile)
7199 + __aa_replace_profile(rename_profile, new_profile);
7200 + if (!(old_profile || rename_profile))
7201 + __add_new_profile(ns, policy, new_profile);
7203 + write_unlock(&ns->lock);
7206 + aa_put_namespace(ns);
7207 + aa_put_profile(rename_profile);
7208 + aa_put_profile(old_profile);
7209 + aa_put_profile(new_profile);
7215 + error = aa_audit_iface(&sa);
7220 + * aa_interface_remove_profiles - remove profile(s) from the system
7221 + * @fqname: name of the profile or namespace to remove (NOT NULL)
7222 + * @size: size of the name
7224 + * Remove a profile or sub namespace from the current namespace, so that
7225 + * they can not be found anymore and mark them as replaced by unconfined
7227 + * NOTE: removing confinement does not restore rlimits to preconfinemnet values
7229 + * Returns: size of data consume else error code if fails
7231 +ssize_t aa_interface_remove_profiles(char *fqname, size_t size)
7233 + struct aa_namespace *root, *ns = NULL;
7234 + struct aa_profile *profile = NULL;
7235 + struct aa_audit_iface sa = {
7236 + .base.operation = "profile_remove",
7237 + .base.gfp_mask = GFP_ATOMIC,
7239 + const char *name = fqname;
7242 + /* check if loading policy is locked out */
7243 + if (aa_g_lock_policy) {
7244 + sa.base.info = "policy locked";
7245 + sa.base.error = -EACCES;
7249 + if (*fqname == 0) {
7250 + sa.base.info = "no profile specified";
7251 + sa.base.error = -ENOENT;
7255 + /* ref count held by cred */
7256 + root = aa_current_profile()->ns;
7258 + if (fqname[0] == ':') {
7260 + name = aa_split_fqname(fqname, &ns_name);
7262 + /* released below */
7263 + ns = aa_find_namespace(root, ns_name);
7265 + /* released below */
7266 + ns = aa_get_namespace(root);
7269 + sa.base.info = "namespace does not exist";
7270 + sa.base.error = -ENOENT;
7274 + sa.name2 = ns->base.name;
7275 + write_lock(&ns->lock);
7277 + /* remove namespace - can only happen if fqname[0] == ':' */
7278 + __aa_remove_namespace(ns);
7280 + /* remove profile */
7281 + profile = aa_get_profile(__aa_find_profile(&ns->base, name));
7284 + sa.base.error = -ENOENT;
7285 + sa.base.info = "profile does not exist";
7286 + goto fail_ns_lock;
7288 + sa.name = profile->base.hname;
7289 + __aa_profile_list_release(&profile->base.profiles);
7290 + __aa_replace_profile(profile, NULL);
7292 + write_unlock(&ns->lock);
7294 + /* don't fail removal if audit fails */
7295 + (void) aa_audit_iface(&sa);
7296 + aa_put_namespace(ns);
7297 + aa_put_profile(profile);
7301 + write_unlock(&ns->lock);
7302 + aa_put_namespace(ns);
7305 + error = aa_audit_iface(&sa);
7308 diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
7309 new file mode 100644
7310 index 0000000..20bdf9c
7312 +++ b/security/apparmor/policy_unpack.c
7315 + * AppArmor security module
7317 + * This file contains AppArmor functions for unpacking policy loaded from
7320 + * Copyright (C) 1998-2008 Novell/SUSE
7321 + * Copyright 2009-2010 Canonical Ltd.
7323 + * This program is free software; you can redistribute it and/or
7324 + * modify it under the terms of the GNU General Public License as
7325 + * published by the Free Software Foundation, version 2 of the
7328 + * AppArmor uses a serialized binary format for loading policy.
7329 + * The policy format is documented in Documentation/???
7330 + * All policy is validated all before it is used.
7333 +#include <asm/unaligned.h>
7334 +#include <linux/ctype.h>
7335 +#include <linux/errno.h>
7337 +#include "include/apparmor.h"
7338 +#include "include/audit.h"
7339 +#include "include/context.h"
7340 +#include "include/match.h"
7341 +#include "include/policy.h"
7342 +#include "include/policy_unpack.h"
7343 +#include "include/sid.h"
7346 + * The AppArmor interface treats data as a type byte followed by the
7347 + * actual data. The interface has the notion of a a named entry
7348 + * which has a name (AA_NAME typecode followed by name string) followed by
7349 + * the entries typecode and data. Named types allow for optional
7350 + * elements and extensions to be added and tested for without breaking
7351 + * backwards compatability.
7359 + AA_NAME, /* same as string except it is items name */
7371 + * aa_ext is the read of the buffer containing the serialized profile. The
7372 + * data is copied into a kernel buffer in apparmorfs and then handed off to
7373 + * the unpack routines.
7378 + void *pos; /* pointer to current position in the buffer */
7382 +/* audit callback for unpack fields */
7383 +static void audit_cb(struct audit_buffer *ab, struct aa_audit *va)
7385 + struct aa_audit_iface *sa = container_of(va, struct aa_audit_iface,
7389 + audit_log_format(ab, " name=");
7390 + audit_log_string(ab, sa->name);
7393 + audit_log_format(ab, " namespace=");
7394 + audit_log_string(ab, sa->name2);
7396 + if (sa->base.error && sa->pos)
7397 + audit_log_format(ab, " offset=%ld", sa->pos);
7401 + * aa_audit_iface - do audit message for policy unpacking/load/replace/remove
7402 + * @sa: audit date to send to audit (NOT NULL)
7404 + * Returns: %0 or error
7406 +int aa_audit_iface(struct aa_audit_iface *sa)
7408 + struct aa_profile *profile;
7409 + const struct cred *cred = get_current_cred();
7411 + profile = aa_cred_profile(cred);
7412 + error = aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa->base, audit_cb);
7417 +/* test if read will be in packed data bounds */
7418 +static bool aa_inbounds(struct aa_ext *e, size_t size)
7420 + return (size <= e->end - e->pos);
7424 + * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
7425 + * @e: serialized data read head
7426 + * @chunk: start address for chunk of data
7428 + * Returns: the size of chunk found with the read head at the end of the chunk.
7430 +static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk)
7434 + if (!aa_inbounds(e, sizeof(u16)))
7436 + size = le16_to_cpu(get_unaligned((u16 *) e->pos));
7437 + e->pos += sizeof(u16);
7438 + if (!aa_inbounds(e, size))
7445 +/* unpack control byte */
7446 +static bool unpack_X(struct aa_ext *e, enum aa_code code)
7448 + if (!aa_inbounds(e, 1))
7450 + if (*(u8 *) e->pos != code)
7457 + * unpack_nameX - check is the next element is of type X with a name of @name
7458 + * @e: serialized data extent information (NOT NULL)
7459 + * @code: type code
7460 + * @name: name to match to the serialized element. (MAYBE NULL)
7462 + * check that the next serialized data element is of type X and has a tag
7463 + * name @name. If @name is specified then there must be a matching
7464 + * name element in the stream. If @name is NULL any name element will be
7465 + * skipped and only the typecode will be tested.
7466 + * returns 1 on success (both type code and name tests match) and the read
7467 + * head is advanced past the headers
7469 + * Returns: 0 if either match failes, the read head does not move
7471 +static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
7474 + * May need to reset pos if name or type doesn't match
7476 + void *pos = e->pos;
7478 + * Check for presence of a tagname, and if present name size
7479 + * AA_NAME tag value is a u16.
7481 + if (unpack_X(e, AA_NAME)) {
7483 + size_t size = unpack_u16_chunk(e, &tag);
7484 + /* if a name is specified it must match. otherwise skip tag */
7485 + if (name && (!size || strcmp(name, tag)))
7487 + } else if (name) {
7488 + /* if a name is specified and there is no name tag fail */
7492 + /* now check if type code matches */
7493 + if (unpack_X(e, code))
7501 +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
7503 + if (unpack_nameX(e, AA_U16, name)) {
7504 + if (!aa_inbounds(e, sizeof(u16)))
7507 + *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
7508 + e->pos += sizeof(u16);
7514 +static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
7516 + if (unpack_nameX(e, AA_U32, name)) {
7517 + if (!aa_inbounds(e, sizeof(u32)))
7520 + *data = le32_to_cpu(get_unaligned((u32 *) e->pos));
7521 + e->pos += sizeof(u32);
7527 +static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name)
7529 + if (unpack_nameX(e, AA_U64, name)) {
7530 + if (!aa_inbounds(e, sizeof(u64)))
7533 + *data = le64_to_cpu(get_unaligned((u64 *) e->pos));
7534 + e->pos += sizeof(u64);
7540 +static size_t unpack_array(struct aa_ext *e, const char *name)
7542 + if (unpack_nameX(e, AA_ARRAY, name)) {
7544 + if (!aa_inbounds(e, sizeof(u16)))
7546 + size = (int)le16_to_cpu(get_unaligned((u16 *) e->pos));
7547 + e->pos += sizeof(u16);
7553 +static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
7555 + if (unpack_nameX(e, AA_BLOB, name)) {
7557 + if (!aa_inbounds(e, sizeof(u32)))
7559 + size = le32_to_cpu(get_unaligned((u32 *) e->pos));
7560 + e->pos += sizeof(u32);
7561 + if (aa_inbounds(e, (size_t) size)) {
7570 +static int unpack_str(struct aa_ext *e, const char **string, const char *name)
7574 + void *pos = e->pos;
7576 + if (unpack_nameX(e, AA_STRING, name)) {
7577 + size = unpack_u16_chunk(e, &src_str);
7579 + /* strings are null terminated, length is size - 1 */
7580 + if (src_str[size - 1] != 0)
7582 + *string = src_str;
7592 +static int unpack_strdup(struct aa_ext *e, char **string, const char *name)
7595 + void *pos = e->pos;
7596 + int res = unpack_str(e, &tmp, name);
7602 + *string = kmemdup(tmp, res, GFP_KERNEL);
7611 +static bool verify_accept(struct aa_dfa *dfa, int flags)
7615 + /* verify accept permissions */
7616 + for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
7617 + int mode = ACCEPT_TABLE(dfa)[i];
7619 + if (mode & ~DFA_VALID_PERM_MASK)
7622 + if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK)
7629 + * unpack_dfa - unpack a file rule dfa
7630 + * @e: serialized data extent information
7632 + * returns dfa or ERR_PTR or NULL if no dfa
7634 +static struct aa_dfa *unpack_dfa(struct aa_ext *e)
7636 + char *blob = NULL;
7638 + struct aa_dfa *dfa = NULL;
7640 + size = unpack_blob(e, &blob, "aadfa");
7643 + * The dfa is aligned with in the blob to 8 bytes
7644 + * from the beginning of the stream.
7646 + size_t sz = blob - (char *)e->start;
7647 + size_t pad = ALIGN(sz, 8) - sz;
7648 + int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
7649 + TO_ACCEPT2_FLAG(YYTD_DATA32);
7652 + if (aa_g_paranoid_load)
7653 + flags |= DFA_FLAG_VERIFY_STATES;
7655 + dfa = aa_dfa_unpack(blob + pad, size - pad, flags);
7657 + if (!IS_ERR(dfa) && !verify_accept(dfa, flags))
7665 + return ERR_PTR(-EPROTO);
7668 +static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
7670 + void *pos = e->pos;
7672 + /* exec table is optional */
7673 + if (unpack_nameX(e, AA_STRUCT, "xtable")) {
7676 + size = unpack_array(e, NULL);
7677 + /* currently 4 exec bits and entries 0-3 are reserved iupcx */
7678 + if (size > 16 - 4)
7680 + profile->file.trans.table = kzalloc(sizeof(char *) * size,
7682 + if (!profile->file.trans.table)
7685 + profile->file.trans.size = size;
7686 + for (i = 0; i < size; i++) {
7688 + int c, j, size = unpack_strdup(e, &str, NULL);
7691 + profile->file.trans.table[i] = str;
7692 + /* verify that name doesn't start with space */
7693 + if (isspace(*str))
7696 + /* count internal # of internal \0 */
7697 + for (c = j = 0; j < size - 2; j++) {
7701 + if (*str == ':') {
7702 + /* beginning with : requires an embedded \0 */
7705 + /* first character after : must be valid */
7709 + /* fail - all other cases with embedded \0 */
7712 + if (!unpack_nameX(e, AA_ARRAYEND, NULL))
7714 + if (!unpack_nameX(e, AA_STRUCTEND, NULL))
7720 + aa_free_domain_entries(&profile->file.trans);
7725 +static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
7727 + void *pos = e->pos;
7729 + /* rlimits are optional */
7730 + if (unpack_nameX(e, AA_STRUCT, "rlimits")) {
7733 + if (!unpack_u32(e, &tmp, NULL))
7735 + profile->rlimits.mask = tmp;
7737 + size = unpack_array(e, NULL);
7738 + if (size > RLIM_NLIMITS)
7740 + for (i = 0; i < size; i++) {
7742 + if (!unpack_u64(e, &tmp, NULL))
7744 + profile->rlimits.limits[i].rlim_max = tmp;
7746 + if (!unpack_nameX(e, AA_ARRAYEND, NULL))
7748 + if (!unpack_nameX(e, AA_STRUCTEND, NULL))
7759 + * unpack_profile - unpack a serialized profile
7760 + * @e: serialized data extent information
7761 + * @sa: audit struct for the operation
7763 + * NOTE: unpack profile sets audit struct if there is a failure
7765 +static struct aa_profile *unpack_profile(struct aa_ext *e,
7766 + struct aa_audit_iface *sa)
7768 + struct aa_profile *profile = NULL;
7769 + const char *name = NULL;
7771 + int i, error = -EPROTO;
7772 + kernel_cap_t tmpcap;
7776 + /* check that we have the right struct being passed */
7777 + if (!unpack_nameX(e, AA_STRUCT, "profile"))
7779 + if (!unpack_str(e, &name, NULL))
7782 + profile = aa_alloc_profile(name);
7784 + return ERR_PTR(-ENOMEM);
7786 + /* profile renaming is optional */
7787 + (void) unpack_str(e, &profile->rename, "rename");
7789 + /* xmatch is optional and may be NULL */
7790 + profile->xmatch = unpack_dfa(e);
7791 + if (IS_ERR(profile->xmatch)) {
7792 + error = PTR_ERR(profile->xmatch);
7793 + profile->xmatch = NULL;
7796 + /* xmatch_len is not optional if xmatch is set */
7797 + if (profile->xmatch) {
7798 + if (!unpack_u32(e, &tmp, NULL))
7800 + profile->xmatch_len = tmp;
7803 + /* per profile debug flags (complain, audit) */
7804 + if (!unpack_nameX(e, AA_STRUCT, "flags"))
7806 + if (!unpack_u32(e, &tmp, NULL))
7809 + profile->flags |= PFLAG_HAT;
7810 + if (!unpack_u32(e, &tmp, NULL))
7813 + profile->mode = APPARMOR_COMPLAIN;
7814 + if (!unpack_u32(e, &tmp, NULL))
7817 + profile->audit = AUDIT_ALL;
7819 + if (!unpack_nameX(e, AA_STRUCTEND, NULL))
7822 + /* path_flags is optional */
7823 + unpack_u32(e, &profile->path_flags, "path_flags");
7824 + profile->path_flags |= profile->flags & PFLAG_MEDIATE_DELETED;
7826 + /* mmap_min_addr is optional */
7827 + if (unpack_u64(e, &tmp64, "mmap_min_addr")) {
7828 + profile->mmap_min_addr = (unsigned long)tmp64;
7829 + if (((u64) profile->mmap_min_addr) == tmp64) {
7830 + profile->flags |= PFLAG_MMAP_MIN_ADDR;
7832 + sa->base.info = "invalid set mmap_min_addr";
7837 + if (!unpack_u32(e, &(profile->caps.allowed.cap[0]), NULL))
7839 + if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL))
7841 + if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL))
7843 + if (!unpack_u32(e, &tmpcap.cap[0], NULL))
7846 + if (unpack_nameX(e, AA_STRUCT, "caps64")) {
7847 + /* optional upper half of 64 bit caps */
7848 + if (!unpack_u32(e, &(profile->caps.allowed.cap[1]), NULL))
7850 + if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL))
7852 + if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL))
7854 + if (!unpack_u32(e, &(tmpcap.cap[1]), NULL))
7856 + if (!unpack_nameX(e, AA_STRUCTEND, NULL))
7860 + if (unpack_nameX(e, AA_STRUCT, "capsx")) {
7861 + /* optional extended caps mediation mask */
7862 + if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL))
7864 + if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
7868 + if (!unpack_rlimits(e, profile))
7871 + size = unpack_array(e, "net_allowed_af");
7873 + if (size > AF_MAX)
7876 + for (i = 0; i < size; i++) {
7877 + if (!unpack_u16(e, &profile->net.allowed[i], NULL))
7879 + if (!unpack_u16(e, &profile->net.audit[i], NULL))
7881 + if (!unpack_u16(e, &profile->net.quiet[i], NULL))
7884 + if (!unpack_nameX(e, AA_ARRAYEND, NULL))
7887 + * allow unix domain and netlink sockets they are handled
7891 + profile->net.allowed[AF_UNIX] = 0xffff;
7892 + profile->net.allowed[AF_NETLINK] = 0xffff;
7894 + /* get file rules */
7895 + profile->file.dfa = unpack_dfa(e);
7896 + if (IS_ERR(profile->file.dfa)) {
7897 + error = PTR_ERR(profile->file.dfa);
7898 + profile->file.dfa = NULL;
7902 + if (!unpack_u32(e, &profile->file.start, "dfa_start"))
7903 + /* default start state */
7904 + profile->file.start = DFA_START;
7906 + if (!unpack_trans_table(e, profile))
7909 + if (!unpack_nameX(e, AA_STRUCTEND, NULL))
7915 + sa->name = name ? name : "unknown";
7916 + if (!sa->base.info)
7917 + sa->base.info = "failed to unpack profile";
7919 + aa_put_profile(profile);
7921 + return ERR_PTR(error);
7925 + * aa_verify_head - unpack serialized stream header
7926 + * @e: serialized data read head
7927 + * @operation: operation header is being verified for
7929 + * Returns: error or 0 if header is good
7931 +static int aa_verify_header(struct aa_ext *e, struct aa_audit_iface *sa)
7933 + /* get the interface version */
7934 + if (!unpack_u32(e, &e->version, "version")) {
7935 + sa->base.info = "invalid profile format";
7936 + aa_audit_iface(sa);
7937 + return -EPROTONOSUPPORT;
7940 + /* check that the interface version is currently supported */
7941 + if (e->version != 5) {
7942 + sa->base.info = "unsupported interface version";
7943 + aa_audit_iface(sa);
7944 + return -EPROTONOSUPPORT;
7947 + /* read the namespace if present */
7948 + if (!unpack_str(e, &sa->name2, "namespace"))
7955 + * verify_profile - Do post unpack analysis to verify profile consistency
7956 + * @profile: profile to verify
7958 + * Returns: 0 if passes verification else error
7960 +static bool verify_xindex(int xindex, int table_size)
7963 + xtype = xindex & AA_X_TYPE_MASK;
7964 + index = xindex & AA_X_INDEX_MASK;
7965 + if (xtype == AA_X_TABLE && index > table_size)
7970 +/* verify dfa xindexes are in range of transition tables */
7971 +static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
7974 + for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
7975 + if (!verify_xindex(dfa_user_xindex(dfa, i), table_size))
7977 + if (!verify_xindex(dfa_other_xindex(dfa, i), table_size))
7983 +static int verify_profile(struct aa_profile *profile, struct aa_audit_iface *sa)
7985 + if (aa_g_paranoid_load) {
7986 + if (profile->file.dfa &&
7987 + !verify_dfa_xindex(profile->file.dfa,
7988 + profile->file.trans.size)) {
7989 + sa->base.info = "Invalid named transition";
7998 + * aa_unpack - unpack packed binary profile data loaded from user space
7999 + * @udata: user data copied to kmem (NOT NULL)
8000 + * @size: the size of the user data
8001 + * @sa: audit struct for unpacking (NOT NULL)
8003 + * Unpack user data and return refcounted allocated profile or ERR_PTR
8005 + * Returns: profile else error pointer if fails to unpack
8007 +struct aa_profile *aa_unpack(void *udata, size_t size,
8008 + struct aa_audit_iface *sa)
8010 + struct aa_profile *profile;
8012 + struct aa_ext e = {
8014 + .end = udata + size,
8018 + error = aa_verify_header(&e, sa);
8020 + return ERR_PTR(error);
8022 + profile = unpack_profile(&e, sa);
8023 + if (IS_ERR(profile))
8024 + sa->pos = e.pos - e.start;
8026 + error = verify_profile(profile, sa);
8028 + aa_put_profile(profile);
8029 + profile = ERR_PTR(error);
8032 + /* return refcount */
8035 diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
8036 new file mode 100644
8037 index 0000000..4991f9d
8039 +++ b/security/apparmor/procattr.c
8042 + * AppArmor security module
8044 + * This file contains AppArmor /proc/<pid>/attr/ interface functions
8046 + * Copyright (C) 1998-2008 Novell/SUSE
8047 + * Copyright 2009-2010 Canonical Ltd.
8049 + * This program is free software; you can redistribute it and/or
8050 + * modify it under the terms of the GNU General Public License as
8051 + * published by the Free Software Foundation, version 2 of the
8055 +#include "include/apparmor.h"
8056 +#include "include/policy.h"
8057 +#include "include/domain.h"
8060 + * aa_getprocattr - Return the profile information for @profile
8061 + * @profile: the profile to print profile info about (NOT NULL)
8062 + * @string: the string that will contain the profile and namespace info (!NULL)
8064 + * Returns: length of @string on success else error on failure
8066 + * Requires: profile != NULL
8068 + * Creates a string containing the namespace_name://profile_name for
8071 + * Returns: size of string placed in @string else error code on failure
8073 +int aa_getprocattr(struct aa_profile *profile, char **string)
8076 + int len = 0, mode_len, name_len, ns_len = 0;
8077 + const char *mode_str = profile_mode_names[profile->mode];
8078 + struct aa_namespace *ns = profile->ns;
8081 + mode_len = strlen(mode_str) + 3; /* + 3 for _() */
8082 + name_len = strlen(profile->base.hname);
8083 + if (ns != root_ns)
8084 + ns_len = strlen(ns->base.name) + 3; /*+ 3 for :// */
8085 + len = mode_len + ns_len + name_len + 1; /*+ 1 for \n */
8086 + s = str = kmalloc(len + 1, GFP_ATOMIC); /* + 1 \0 */
8091 + sprintf(s, "%s://", ns->base.name);
8094 + if (profile->flags & PFLAG_UNCONFINED)
8095 + sprintf(s, "%s\n", profile->base.hname);
8097 + sprintf(s, "%s (%s)\n", profile->base.hname, mode_str);
8100 + /* NOTE: len does not include \0 of string, not saved as part of file */
8105 + * split_token_from_name - separate a string of form <token>^<name>
8106 + * @op: operation name (NOT NULL)
8107 + * @args: string to parse (NOT NULL)
8108 + * @token: stores returned parsed token value (NOT NULL)
8110 + * Returns: start position of name after token else NULL on failure
8112 +static char *split_token_from_name(const char *op, char *args, u64 * token)
8116 + *token = simple_strtoull(args, &name, 16);
8117 + if ((name == args) || *name != '^') {
8118 + AA_ERROR("%s: Invalid input '%s'", op, args);
8119 + return ERR_PTR(-EINVAL);
8122 + name++; /* skip ^ */
8129 + * aa_setprocattr_chagnehat - handle procattr interface to change_hat
8130 + * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL)
8131 + * @size: size of the args
8132 + * @test: true if this is a test of change_hat permissions
8134 + * Returns: %0 or error code if change_hat fails
8136 +int aa_setprocattr_changehat(char *args, size_t size, int test)
8140 + const char *hats[16]; /* current hard limit on # of names */
8143 + hat = split_token_from_name("change_hat", args, &token);
8145 + return PTR_ERR(hat);
8147 + if (!hat && !token) {
8148 + AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
8153 + /* set up hat name vector, args guarenteed null terminated
8156 + char *end = args + size;
8157 + for (count = 0; (hat < end) && count < 16; ++count) {
8158 + char *next = hat + strlen(hat) + 1;
8159 + hats[count] = hat;
8164 + AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
8165 + __func__, token, hat ? hat : NULL);
8167 + return aa_change_hat(hats, count, token, test);
8171 + * aa_setprocattr_changeprofile - handle procattr interface to changeprofile
8172 + * @fqname: args received from writting to /proc/<pid>/attr/current (NOT NULL)
8173 + * @onexec: true if change_profile should be delayed until exec
8174 + * @test: true if this is a test of change_profile permissions
8176 + * Returns: %0 or error code if change_profile fails
8178 +int aa_setprocattr_changeprofile(char *fqname, int onexec, int test)
8180 + char *name, *ns_name;
8182 + name = aa_split_fqname(fqname, &ns_name);
8183 + return aa_change_profile(ns_name, name, onexec, test);
8186 +int aa_setprocattr_permipc(char *fqname)
8188 + /* TODO: add ipc permission querying */
8191 diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
8192 new file mode 100644
8193 index 0000000..b330102
8195 +++ b/security/apparmor/resource.c
8198 + * AppArmor security module
8200 + * This file contains AppArmor resource mediation and attachment
8202 + * Copyright (C) 1998-2008 Novell/SUSE
8203 + * Copyright 2009-2010 Canonical Ltd.
8205 + * This program is free software; you can redistribute it and/or
8206 + * modify it under the terms of the GNU General Public License as
8207 + * published by the Free Software Foundation, version 2 of the
8211 +#include <linux/audit.h>
8213 +#include "include/audit.h"
8214 +#include "include/resource.h"
8215 +#include "include/policy.h"
8217 +struct aa_audit_resource {
8218 + struct aa_audit base;
8223 +/* audit callback for resource specific fields */
8224 +static void audit_cb(struct audit_buffer *ab, struct aa_audit *va)
8226 + struct aa_audit_resource *sa = container_of(va,
8227 + struct aa_audit_resource,
8231 + audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
8235 + * aa_audit_resource - audit setting resource limit
8236 + * @profile: profile being enforced (NOT NULL)
8237 + * @sa: audit data (NOT NULL)
8239 + * Returns: 0 or sa->error else other error code on failure
8241 +static int aa_audit_resource(struct aa_profile *profile,
8242 + struct aa_audit_resource *sa)
8244 + return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa->base, audit_cb);
8248 + * aa_task_setrlimit - test permission to set an rlimit
8249 + * @profile - profile confining the task (NOT NULL)
8250 + * @resource - the resource being set
8251 + * @new_rlim - the new resource limit (NOT NULL)
8253 + * Control raising the processes hard limit.
8255 + * Returns: 0 or error code if setting resource failed
8257 +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
8258 + struct rlimit *new_rlim)
8260 + struct aa_audit_resource sa = {
8261 + .base.operation = "setrlimit",
8262 + .base.gfp_mask = GFP_KERNEL,
8263 + .rlimit = resource + 1,
8267 + if (profile->rlimits.mask & (1 << resource) &&
8268 + new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
8269 + sa.base.error = -EACCES;
8271 + error = aa_audit_resource(profile, &sa);
8278 + * __aa_transition_rlimits - apply new profile rlimits
8279 + * @old: old profile on task (MAYBE NULL)
8280 + * @new: new profile with rlimits to apply (NOT NULL)
8282 +void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new)
8284 + unsigned int mask = 0;
8285 + struct rlimit *rlim, *initrlim;
8288 + /* for any rlimits the profile controlled reset the soft limit
8289 + * to the less of the tasks hard limit and the init tasks soft limit
8291 + if (old && old->rlimits.mask) {
8292 + for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
8293 + if (old->rlimits.mask & mask) {
8294 + rlim = current->signal->rlim + i;
8295 + initrlim = init_task.signal->rlim + i;
8296 + rlim->rlim_cur = min(rlim->rlim_max,
8297 + initrlim->rlim_cur);
8302 + /* set any new hard limits as dictated by the new profile */
8303 + if (!(new && new->rlimits.mask))
8305 + for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
8306 + if (!(new->rlimits.mask & mask))
8309 + rlim = current->signal->rlim + i;
8310 + rlim->rlim_max = min(rlim->rlim_max,
8311 + new->rlimits.limits[i].rlim_max);
8312 + /* soft limit should not exceed hard limit */
8313 + rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
8316 diff --git a/security/apparmor/sid.c b/security/apparmor/sid.c
8317 new file mode 100644
8318 index 0000000..e0b76de
8320 +++ b/security/apparmor/sid.c
8323 + * AppArmor security module
8325 + * This file contains AppArmor security identifier (sid) manipulation fns
8327 + * Copyright 2009-2010 Canonical Ltd.
8329 + * This program is free software; you can redistribute it and/or
8330 + * modify it under the terms of the GNU General Public License as
8331 + * published by the Free Software Foundation, version 2 of the
8335 + * AppArmor allocates a unique sid for every profile loaded. If a profile
8336 + * is replaced it receive the sid of the profile it is replacing.
8338 + * The sid value of 0 is invalid.
8341 +#include <linux/spinlock.h>
8342 +#include <linux/errno.h>
8343 +#include <linux/err.h>
8345 +#include "include/sid.h"
8347 +/* global counter from which sids are allocated */
8348 +static u16 global_sid;
8349 +static DEFINE_SPINLOCK(sid_lock);
8351 +/* TODO FIXME: add sid to profile mapping, and sid recycling */
8354 + * aa_alloc_sid - allocate a new sid for a profile
8356 +u32 aa_alloc_sid(void)
8361 + * TODO FIXME: sid recycling - part of profile mapping table
8363 + spin_lock(&sid_lock);
8364 + sid = (++global_sid);
8365 + spin_unlock(&sid_lock);
8370 + * aa_free_sid - free a sid
8371 + * @sid: sid to free
8373 +void aa_free_sid(u32 sid)