]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-apparmor.patch
- vserver for 2.6.36 + two delta patches
[packages/kernel.git] / kernel-apparmor.patch
CommitLineData
76514441
AM
1From 3f980257e048429a1f0a5dbce0b027a93c0781cc Mon Sep 17 00:00:00 2001
2From: John Johansen <john.johansen@canonical.com>
3Date: Wed, 4 Aug 2010 04:42:50 -0700
4Subject: [PATCH] AppArmor: security module v2.6 + compat patches as of 29-07-2010 (security-next)
5
6AppArmor v2.6 module as synced to security-next 29-07-2010 backported to
72.6.35 + AppArmor 2.4 compatibility patches.
8
9Signed-off-by: John Johansen <john.johansen@canonical.com>
10---
11 Documentation/apparmor.txt | 40 +
12 Documentation/kernel-parameters.txt | 8 +
13 MAINTAINERS | 8 +
14 include/linux/lsm_audit.h | 31 +
15 security/Kconfig | 6 +
16 security/Makefile | 2 +
17 security/apparmor/.gitignore | 5 +
18 security/apparmor/Kconfig | 40 +
19 security/apparmor/Makefile | 30 +
20 security/apparmor/apparmorfs-24.c | 287 +++++++
21 security/apparmor/apparmorfs.c | 253 ++++++
22 security/apparmor/audit.c | 215 ++++++
23 security/apparmor/capability.c | 141 ++++
24 security/apparmor/context.c | 216 ++++++
25 security/apparmor/domain.c | 823 ++++++++++++++++++++
26 security/apparmor/file.c | 457 +++++++++++
27 security/apparmor/include/apparmor.h | 92 +++
28 security/apparmor/include/apparmorfs.h | 26 +
29 security/apparmor/include/audit.h | 123 +++
30 security/apparmor/include/capability.h | 45 ++
31 security/apparmor/include/context.h | 154 ++++
32 security/apparmor/include/domain.h | 36 +
33 security/apparmor/include/file.h | 217 ++++++
34 security/apparmor/include/ipc.h | 28 +
35 security/apparmor/include/match.h | 132 ++++
36 security/apparmor/include/net.h | 40 +
37 security/apparmor/include/path.h | 31 +
38 security/apparmor/include/policy.h | 308 ++++++++
39 security/apparmor/include/policy_unpack.h | 20 +
40 security/apparmor/include/procattr.h | 26 +
41 security/apparmor/include/resource.h | 46 ++
42 security/apparmor/include/sid.h | 24 +
43 security/apparmor/ipc.c | 114 +++
44 security/apparmor/lib.c | 133 ++++
45 security/apparmor/lsm.c | 1051 +++++++++++++++++++++++++
46 security/apparmor/match.c | 370 +++++++++
47 security/apparmor/net.c | 169 ++++
48 security/apparmor/path.c | 235 ++++++
49 security/apparmor/policy.c | 1185 +++++++++++++++++++++++++++++
50 security/apparmor/policy_unpack.c | 740 ++++++++++++++++++
51 security/apparmor/policy_unpack.c.rej | 11 +
52 security/apparmor/procattr.c | 170 ++++
53 security/apparmor/resource.c | 134 ++++
54 security/apparmor/sid.c | 55 ++
55 44 files changed, 8277 insertions(+), 0 deletions(-)
56 create mode 100644 Documentation/apparmor.txt
57 create mode 100644 security/apparmor/.gitignore
58 create mode 100644 security/apparmor/Kconfig
59 create mode 100644 security/apparmor/Makefile
60 create mode 100644 security/apparmor/apparmorfs-24.c
61 create mode 100644 security/apparmor/apparmorfs.c
62 create mode 100644 security/apparmor/audit.c
63 create mode 100644 security/apparmor/capability.c
64 create mode 100644 security/apparmor/context.c
65 create mode 100644 security/apparmor/domain.c
66 create mode 100644 security/apparmor/file.c
67 create mode 100644 security/apparmor/include/apparmor.h
68 create mode 100644 security/apparmor/include/apparmorfs.h
69 create mode 100644 security/apparmor/include/audit.h
70 create mode 100644 security/apparmor/include/capability.h
71 create mode 100644 security/apparmor/include/context.h
72 create mode 100644 security/apparmor/include/domain.h
73 create mode 100644 security/apparmor/include/file.h
74 create mode 100644 security/apparmor/include/ipc.h
75 create mode 100644 security/apparmor/include/match.h
76 create mode 100644 security/apparmor/include/net.h
77 create mode 100644 security/apparmor/include/path.h
78 create mode 100644 security/apparmor/include/policy.h
79 create mode 100644 security/apparmor/include/policy_unpack.h
80 create mode 100644 security/apparmor/include/procattr.h
81 create mode 100644 security/apparmor/include/resource.h
82 create mode 100644 security/apparmor/include/sid.h
83 create mode 100644 security/apparmor/ipc.c
84 create mode 100644 security/apparmor/lib.c
85 create mode 100644 security/apparmor/lsm.c
86 create mode 100644 security/apparmor/match.c
87 create mode 100644 security/apparmor/net.c
88 create mode 100644 security/apparmor/path.c
89 create mode 100644 security/apparmor/policy.c
90 create mode 100644 security/apparmor/policy_unpack.c
91 create mode 100644 security/apparmor/policy_unpack.c.rej
92 create mode 100644 security/apparmor/procattr.c
93 create mode 100644 security/apparmor/resource.c
94 create mode 100644 security/apparmor/sid.c
95
96diff --git a/Documentation/apparmor.txt b/Documentation/apparmor.txt
97new file mode 100644
98index 0000000..6240438
99--- /dev/null
100+++ b/Documentation/apparmor.txt
101@@ -0,0 +1,40 @@
102+--- What is AppArmor? ---
103+
104+AppArmor is MAC style security extension for the Linux kernel. It implements
105+a task centered policy, with task "profiles" being created and loaded
106+from user space. Tasks on the system that do not have a profile defined for
107+them run in an unconfined state which is equivalent to standard Linux DAC
108+permissions.
109+
110+--- How to enable/disable ---
111+
112+set CONFIG_SECURITY_APPARMOR=y
113+
114+If AppArmor should be selected as the default security module then
115+ set CONFIG_DEFAULT_SECURITY="apparmor"
116+ and CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
117+
118+Build the kernel
119+
120+If AppArmor is not the default security module it can be enabled by passing
121+security=apparmor on the kernel's command line.
122+
123+If AppArmor is the default security module it can be disabled by passing
124+apparmor=0, security=XXXX (where XXX is valid security module), on the
125+kernel's command line
126+
127+For AppArmor to enforce any restrictions beyond standard Linux DAC permissions
128+policy must be loaded into the kernel from user space (see the Documentation
129+and tools links).
130+
131+--- Documentation ---
132+
133+Documentation can be found on the wiki.
134+
135+--- Links ---
136+
137+Mailing List - apparmor@lists.ubuntu.com
138+Wiki - http://apparmor.wiki.kernel.org/
139+User space tools - https://launchpad.net/apparmor
140+Kernel module - git://git.kernel.org/pub/scm/linux/kernel/git/jj/apparmor-dev.git
141+
142diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
143index 2b2407d..b61f89f 100644
144--- a/Documentation/kernel-parameters.txt
145+++ b/Documentation/kernel-parameters.txt
146@@ -93,6 +93,7 @@ parameter is applicable:
147 Documentation/scsi/.
148 SECURITY Different security models are enabled.
149 SELINUX SELinux support is enabled.
150+ APPARMOR AppArmor support is enabled.
151 SERIAL Serial support is enabled.
152 SH SuperH architecture is enabled.
153 SMP The kernel is an SMP kernel.
154@@ -2312,6 +2313,13 @@ and is between 256 and 4096 characters. It is defined in the file
155 If enabled at boot time, /selinux/disable can be used
156 later to disable prior to initial policy load.
157
158+ apparmor= [APPARMOR] Disable or enable AppArmor at boot time
159+ Format: { "0" | "1" }
160+ See security/apparmor/Kconfig help text
161+ 0 -- disable.
162+ 1 -- enable.
163+ Default value is set via kernel config option.
164+
165 serialnumber [BUGS=X86-32]
2380c486 166
76514441
AM
167 shapers= [NET]
168diff --git a/MAINTAINERS b/MAINTAINERS
169index 02f75fc..a8d5851 100644
170--- a/MAINTAINERS
171+++ b/MAINTAINERS
172@@ -5061,6 +5061,14 @@ S: Supported
173 F: include/linux/selinux*
174 F: security/selinux/
175
176+APPARMOR SECURITY MODULE
177+M: John Johansen <john.johansen@canonical.com>
178+L: apparmor@lists.ubuntu.com (subscribers-only, general discussion)
179+W: apparmor.wiki.kernel.org
180+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jj/apparmor-dev.git
181+S: Supported
182+F: security/apparmor/
183+
184 SENSABLE PHANTOM
185 M: Jiri Slaby <jirislaby@gmail.com>
186 S: Maintained
187diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
188index 6907251..3474e45 100644
189--- a/include/linux/lsm_audit.h
190+++ b/include/linux/lsm_audit.h
191@@ -94,6 +94,37 @@ struct common_audit_data {
192 int result;
193 } selinux_audit_data;
194 #endif
195+#ifdef CONFIG_SECURITY_APPARMOR
196+ struct {
197+ int error;
198+ int op;
199+ int type;
200+ void *profile;
201+ const char *name;
202+ const char *info;
203+ union {
204+ void *target;
205+ struct {
206+ long pos;
207+ void *target;
208+ } iface;
209+ struct {
210+ int rlim;
211+ unsigned long max;
212+ } rlim;
213+ struct {
214+ const char *target;
215+ u32 request;
216+ u32 denied;
217+ uid_t ouid;
218+ } fs;
219+ struct {
220+ int type, protocol;
221+ struct sock *sk;
222+ } net;
223+ };
224+ } apparmor_audit_data;
225+#endif
226 };
227 /* these callback will be implemented by a specific LSM */
228 void (*lsm_pre_audit)(struct audit_buffer *, void *);
ceaf2cfb
AM
229diff --git a/security/Kconfig b/security/Kconfig
230index 226b955..bd72ae6 100644
231--- a/security/Kconfig
232+++ b/security/Kconfig
233@@ -140,6 +140,7 @@ config LSM_MMAP_MIN_ADDR
0eaba94d
AM
234 source security/selinux/Kconfig
235 source security/smack/Kconfig
236 source security/tomoyo/Kconfig
237+source security/apparmor/Kconfig
238
239 source security/integrity/ima/Kconfig
240
ceaf2cfb
AM
241@@ -148,6 +149,7 @@ choice
242 default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX
243 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
244 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
245+ default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
246 default DEFAULT_SECURITY_DAC
247
248 help
249@@ -163,6 +165,9 @@ choice
250 config DEFAULT_SECURITY_TOMOYO
251 bool "TOMOYO" if SECURITY_TOMOYO=y
252
253+ config DEFAULT_SECURITY_APPARMOR
254+ bool "AppArmor" if SECURITY_APPARMOR=y
255+
256 config DEFAULT_SECURITY_DAC
257 bool "Unix Discretionary Access Controls"
258
259@@ -173,6 +178,7 @@ config DEFAULT_SECURITY
260 default "selinux" if DEFAULT_SECURITY_SELINUX
261 default "smack" if DEFAULT_SECURITY_SMACK
262 default "tomoyo" if DEFAULT_SECURITY_TOMOYO
263+ default "apparmor" if DEFAULT_SECURITY_APPARMOR
264 default "" if DEFAULT_SECURITY_DAC
265
266 endmenu
267diff --git a/security/Makefile b/security/Makefile
268index da20a19..8bb0fe9 100644
269--- a/security/Makefile
270+++ b/security/Makefile
271@@ -6,6 +6,7 @@ obj-$(CONFIG_KEYS) += keys/
272 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
273 subdir-$(CONFIG_SECURITY_SMACK) += smack
274 subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
275+subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
276
277 # always enable default capabilities
278 obj-y += commoncap.o
279@@ -19,6 +20,7 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
280 obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
281 obj-$(CONFIG_AUDIT) += lsm_audit.o
282 obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
283+obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o
284 obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
285
286 # Object integrity file lists
287diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
288new file mode 100644
289index 0000000..0a0a99f
290--- /dev/null
291+++ b/security/apparmor/.gitignore
292@@ -0,0 +1,5 @@
293+#
294+# Generated include files
295+#
296+af_names.h
297+capability_names.h
298diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
299new file mode 100644
76514441 300index 0000000..fdf3022
ceaf2cfb
AM
301--- /dev/null
302+++ b/security/apparmor/Kconfig
303@@ -0,0 +1,40 @@
304+config SECURITY_APPARMOR
305+ bool "AppArmor support"
306+ depends on SECURITY
307+ select AUDIT
308+ select SECURITY_PATH
309+ select SECURITYFS
310+ select SECURITY_NETWORK
311+ default n
312+ help
313+ This enables the AppArmor security module.
314+ Required userspace tools (if they are not included in your
315+ distribution) and further information may be found at
76514441 316+ http://apparmor.wiki.kernel.org
ceaf2cfb
AM
317+
318+ If you are unsure how to answer this question, answer N.
319+
320+config SECURITY_APPARMOR_BOOTPARAM_VALUE
321+ int "AppArmor boot parameter default value"
322+ depends on SECURITY_APPARMOR
323+ range 0 1
324+ default 1
325+ help
326+ This option sets the default value for the kernel parameter
327+ 'apparmor', which allows AppArmor to be enabled or disabled
328+ at boot. If this option is set to 0 (zero), the AppArmor
329+ kernel parameter will default to 0, disabling AppArmor at
76514441 330+ boot. If this option is set to 1 (one), the AppArmor
ceaf2cfb 331+ kernel parameter will default to 1, enabling AppArmor at
76514441 332+ boot.
ceaf2cfb
AM
333+
334+ If you are unsure how to answer this question, answer 1.
335+
336+config SECURITY_APPARMOR_COMPAT_24
337+ bool "Enable AppArmor 2.4 compatability"
338+ depends on SECURITY_APPARMOR
339+ default y
340+ help
341+ This option enables compatability with AppArmor 2.4. It is
342+ recommended if compatability with older versions of AppArmor
343+ is desired.
344diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
345new file mode 100644
76514441 346index 0000000..e5e8968
ceaf2cfb
AM
347--- /dev/null
348+++ b/security/apparmor/Makefile
76514441 349@@ -0,0 +1,30 @@
ceaf2cfb
AM
350+# Makefile for AppArmor Linux Security Module
351+#
352+obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
353+
354+apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
355+ path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
356+ resource.o sid.o file.o net.o
357+
358+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
359+
360+clean-files: capability_names.h af_names.h
361+
362+quiet_cmd_make-caps = GEN $@
363+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 "};" >> $@
364+
365+quiet_cmd_make-af = GEN $@
366+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 "};" >> $@
367+
76514441
AM
368+quiet_cmd_make-rlim = GEN $@
369+cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@
370+
ceaf2cfb
AM
371+$(obj)/capability.o : $(obj)/capability_names.h
372+$(obj)/net.o : $(obj)/af_names.h
76514441 373+$(obj)/resource.o : $(obj)/rlim_names.h
ceaf2cfb
AM
374+$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
375+ $(call cmd,make-caps)
376+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
377+ $(call cmd,make-af)
76514441
AM
378+$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
379+ $(call cmd,make-rlim)
ceaf2cfb
AM
380diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
381new file mode 100644
76514441 382index 0000000..dc8c744
ceaf2cfb
AM
383--- /dev/null
384+++ b/security/apparmor/apparmorfs-24.c
76514441 385@@ -0,0 +1,287 @@
9474138d
AM
386+/*
387+ * AppArmor security module
388+ *
ceaf2cfb 389+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
9474138d
AM
390+ *
391+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 392+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
393+ *
394+ * This program is free software; you can redistribute it and/or
395+ * modify it under the terms of the GNU General Public License as
396+ * published by the Free Software Foundation, version 2 of the
397+ * License.
ceaf2cfb
AM
398+ *
399+ *
400+ * This file contain functions providing an interface for <= AppArmor 2.4
401+ * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
402+ * being set (see Makefile).
9474138d
AM
403+ */
404+
405+#include <linux/security.h>
406+#include <linux/vmalloc.h>
407+#include <linux/module.h>
408+#include <linux/seq_file.h>
409+#include <linux/uaccess.h>
410+#include <linux/namei.h>
2380c486 411+
9474138d
AM
412+#include "include/apparmor.h"
413+#include "include/audit.h"
414+#include "include/context.h"
415+#include "include/policy.h"
9474138d 416+
ceaf2cfb
AM
417+
418+/* apparmor/matching */
419+static ssize_t aa_matching_read(struct file *file, char __user *buf,
420+ size_t size, loff_t *ppos)
421+{
422+ const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
423+ "user::other";
424+
425+ return simple_read_from_buffer(buf, size, ppos, matching,
426+ sizeof(matching) - 1);
427+}
428+
429+const struct file_operations aa_fs_matching_fops = {
430+ .read = aa_matching_read,
431+};
432+
433+/* apparmor/features */
434+static ssize_t aa_features_read(struct file *file, char __user *buf,
435+ size_t size, loff_t *ppos)
436+{
437+ const char features[] = "file=3.1 capability=2.0 network=1.0 "
438+ "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
439+
440+ return simple_read_from_buffer(buf, size, ppos, features,
441+ sizeof(features) - 1);
442+}
443+
444+const struct file_operations aa_fs_features_fops = {
445+ .read = aa_features_read,
446+};
ceaf2cfb
AM
447+
448+/**
449+ * __next_namespace - find the next namespace to list
450+ * @root: root namespace to stop search at (NOT NULL)
451+ * @ns: current ns position (NOT NULL)
452+ *
453+ * Find the next namespace from @ns under @root and handle all locking needed
454+ * while switching current namespace.
455+ *
456+ * Returns: next namespace or NULL if at last namespace under @root
457+ * NOTE: will not unlock root->lock
458+ */
459+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
460+ struct aa_namespace *ns)
9474138d 461+{
ceaf2cfb 462+ struct aa_namespace *parent;
9474138d 463+
ceaf2cfb
AM
464+ /* is next namespace a child */
465+ if (!list_empty(&ns->sub_ns)) {
466+ struct aa_namespace *next;
467+ next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
468+ read_lock(&next->lock);
469+ return next;
470+ }
471+
472+ /* check if the next ns is a sibling, parent, gp, .. */
473+ parent = ns->parent;
474+ while (parent) {
475+ read_unlock(&ns->lock);
476+ list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
477+ read_lock(&ns->lock);
478+ return ns;
479+ }
480+ if (parent == root)
481+ return NULL;
482+ ns = parent;
483+ parent = parent->parent;
484+ }
485+
486+ return NULL;
9474138d
AM
487+}
488+
ceaf2cfb
AM
489+/**
490+ * __first_profile - find the first profile in a namespace
491+ * @root: namespace that is root of profiles being displayed (NOT NULL)
492+ * @ns: namespace to start in (NOT NULL)
493+ *
494+ * Returns: unrefcounted profile or NULL if no profile
495+ */
76514441
AM
496+static struct aa_profile *__first_profile(struct aa_namespace *root,
497+ struct aa_namespace *ns)
9474138d 498+{
ceaf2cfb
AM
499+ for ( ; ns; ns = __next_namespace(root, ns)) {
500+ if (!list_empty(&ns->base.profiles))
501+ return list_first_entry(&ns->base.profiles,
502+ struct aa_profile, base.list);
9474138d 503+ }
ceaf2cfb 504+ return NULL;
9474138d
AM
505+}
506+
ceaf2cfb
AM
507+/**
508+ * __next_profile - step to the next profile in a profile tree
509+ * @profile: current profile in tree (NOT NULL)
510+ *
511+ * Perform a depth first taversal on the profile tree in a namespace
512+ *
513+ * Returns: next profile or NULL if done
514+ * Requires: profile->ns.lock to be held
515+ */
516+static struct aa_profile *__next_profile(struct aa_profile *p)
9474138d 517+{
ceaf2cfb
AM
518+ struct aa_profile *parent;
519+ struct aa_namespace *ns = p->ns;
9474138d 520+
ceaf2cfb
AM
521+ /* is next profile a child */
522+ if (!list_empty(&p->base.profiles))
523+ return list_first_entry(&p->base.profiles, typeof(*p),
524+ base.list);
9474138d 525+
ceaf2cfb
AM
526+ /* is next profile a sibling, parent sibling, gp, subling, .. */
527+ parent = p->parent;
528+ while (parent) {
529+ list_for_each_entry_continue(p, &parent->base.profiles,
530+ base.list)
531+ return p;
532+ p = parent;
533+ parent = parent->parent;
534+ }
9474138d 535+
ceaf2cfb
AM
536+ /* is next another profile in the namespace */
537+ list_for_each_entry_continue(p, &ns->base.profiles, base.list)
538+ return p;
9474138d 539+
ceaf2cfb 540+ return NULL;
9474138d
AM
541+}
542+
ceaf2cfb
AM
543+/**
544+ * next_profile - step to the next profile in where ever it may be
545+ * @root: root namespace (NOT NULL)
546+ * @profile: current profile (NOT NULL)
547+ *
548+ * Returns: next profile or NULL if there isn't one
549+ */
550+static struct aa_profile *next_profile(struct aa_namespace *root,
551+ struct aa_profile *profile)
9474138d 552+{
ceaf2cfb
AM
553+ struct aa_profile *next = __next_profile(profile);
554+ if (next)
555+ return next;
9474138d 556+
ceaf2cfb
AM
557+ /* finished all profiles in namespace move to next namespace */
558+ return __first_profile(root, __next_namespace(root, profile->ns));
559+}
9474138d 560+
ceaf2cfb
AM
561+/**
562+ * p_start - start a depth first traversal of profile tree
563+ * @f: seq_file to fill
564+ * @pos: current position
565+ *
566+ * Returns: first profile under current namespace or NULL if none found
567+ *
568+ * acquires first ns->lock
569+ */
570+static void *p_start(struct seq_file *f, loff_t *pos)
571+ __acquires(root->lock)
9474138d 572+{
ceaf2cfb
AM
573+ struct aa_profile *profile = NULL;
574+ struct aa_namespace *root = aa_current_profile()->ns;
575+ loff_t l = *pos;
576+ f->private = aa_get_namespace(root);
9474138d 577+
9474138d 578+
ceaf2cfb
AM
579+ /* find the first profile */
580+ read_lock(&root->lock);
581+ profile = __first_profile(root, root);
9474138d 582+
ceaf2cfb
AM
583+ /* skip to position */
584+ for (; profile && l > 0; l--)
585+ profile = next_profile(root, profile);
9474138d 586+
ceaf2cfb 587+ return profile;
9474138d
AM
588+}
589+
ceaf2cfb
AM
590+/**
591+ * p_next - read the next profile entry
592+ * @f: seq_file to fill
593+ * @p: profile previously returned
594+ * @pos: current position
595+ *
596+ * Returns: next profile after @p or NULL if none
597+ *
598+ * may acquire/release locks in namespace tree as necessary
599+ */
600+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
9474138d 601+{
ceaf2cfb
AM
602+ struct aa_profile *profile = p;
603+ struct aa_namespace *root = f->private;
604+ (*pos)++;
9474138d 605+
ceaf2cfb
AM
606+ return next_profile(root, profile);
607+}
9474138d 608+
ceaf2cfb
AM
609+/**
610+ * p_stop - stop depth first traversal
611+ * @f: seq_file we are filling
612+ * @p: the last profile writen
613+ *
614+ * Release all locking done by p_start/p_next on namespace tree
615+ */
616+static void p_stop(struct seq_file *f, void *p)
617+ __releases(root->lock)
618+{
619+ struct aa_profile *profile = p;
620+ struct aa_namespace *root = f->private, *ns;
9474138d 621+
ceaf2cfb
AM
622+ if (profile) {
623+ for (ns = profile->ns; ns && ns != root; ns = ns->parent)
624+ read_unlock(&ns->lock);
625+ }
626+ read_unlock(&root->lock);
627+ aa_put_namespace(root);
9474138d
AM
628+}
629+
ceaf2cfb 630+/**
76514441 631+ * seq_show_profile - show a profile entry
ceaf2cfb
AM
632+ * @f: seq_file to file
633+ * @p: current position (profile) (NOT NULL)
634+ *
635+ * Returns: error on failure
636+ */
637+static int seq_show_profile(struct seq_file *f, void *p)
9474138d 638+{
ceaf2cfb
AM
639+ struct aa_profile *profile = (struct aa_profile *)p;
640+ struct aa_namespace *root = f->private;
9474138d 641+
ceaf2cfb 642+ if (profile->ns != root)
76514441 643+ seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
ceaf2cfb
AM
644+ seq_printf(f, "%s (%s)\n", profile->base.hname,
645+ COMPLAIN_MODE(profile) ? "complain" : "enforce");
9474138d 646+
ceaf2cfb 647+ return 0;
9474138d
AM
648+}
649+
ceaf2cfb
AM
650+static const struct seq_operations aa_fs_profiles_op = {
651+ .start = p_start,
652+ .next = p_next,
653+ .stop = p_stop,
654+ .show = seq_show_profile,
9474138d
AM
655+};
656+
76514441
AM
657+static int profiles_open(struct inode *inode, struct file *file)
658+{
659+ return seq_open(file, &aa_fs_profiles_op);
660+}
661+
662+static int profiles_release(struct inode *inode, struct file *file)
663+{
664+ return seq_release(inode, file);
665+}
666+
667+const struct file_operations aa_fs_profiles_fops = {
668+ .open = profiles_open,
669+ .read = seq_read,
670+ .llseek = seq_lseek,
671+ .release = profiles_release,
672+};
673diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
674new file mode 100644
675index 0000000..0e27449
676--- /dev/null
677+++ b/security/apparmor/apparmorfs.c
678@@ -0,0 +1,253 @@
679+/*
680+ * AppArmor security module
681+ *
682+ * This file contains AppArmor /sys/kernel/security/apparmor interface functions
683+ *
684+ * Copyright (C) 1998-2008 Novell/SUSE
685+ * Copyright 2009-2010 Canonical Ltd.
686+ *
687+ * This program is free software; you can redistribute it and/or
688+ * modify it under the terms of the GNU General Public License as
689+ * published by the Free Software Foundation, version 2 of the
690+ * License.
691+ */
692+
693+#include <linux/security.h>
694+#include <linux/vmalloc.h>
695+#include <linux/module.h>
696+#include <linux/seq_file.h>
697+#include <linux/uaccess.h>
698+#include <linux/namei.h>
699+
700+#include "include/apparmor.h"
701+#include "include/apparmorfs.h"
702+#include "include/audit.h"
703+#include "include/context.h"
704+#include "include/policy.h"
705+
706+/**
707+ * aa_simple_write_to_buffer - common routine for getting policy from user
708+ * @op: operation doing the user buffer copy
709+ * @userbuf: user buffer to copy data from (NOT NULL)
710+ * @alloc_size: size of user buffer
711+ * @copy_size: size of data to copy from user buffer
712+ * @pos: position write is at in the file (NOT NULL)
713+ *
714+ * Returns: kernel buffer containing copy of user buffer data or an
715+ * ERR_PTR on failure.
716+ */
717+static char *aa_simple_write_to_buffer(int op, const char __user *userbuf,
718+ size_t alloc_size, size_t copy_size,
719+ loff_t *pos)
720+{
721+ char *data;
722+
723+ if (*pos != 0)
724+ /* only writes from pos 0, that is complete writes */
725+ return ERR_PTR(-ESPIPE);
726+
727+ /*
728+ * Don't allow profile load/replace/remove from profiles that don't
729+ * have CAP_MAC_ADMIN
730+ */
731+ if (!aa_may_manage_policy(op))
732+ return ERR_PTR(-EACCES);
733+
734+ /* freed by caller to simple_write_to_buffer */
735+ data = kvmalloc(alloc_size);
736+ if (data == NULL)
737+ return ERR_PTR(-ENOMEM);
738+
739+ if (copy_from_user(data, userbuf, copy_size)) {
740+ kvfree(data);
741+ return ERR_PTR(-EFAULT);
742+ }
743+
744+ return data;
745+}
746+
747+
748+/* .load file hook fn to load policy */
749+static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
750+ loff_t *pos)
751+{
752+ char *data;
753+ ssize_t error;
754+
755+ data = aa_simple_write_to_buffer(OP_PROF_LOAD, buf, size, size, pos);
756+
757+ error = PTR_ERR(data);
758+ if (!IS_ERR(data)) {
759+ error = aa_replace_profiles(data, size, PROF_ADD);
760+ kvfree(data);
761+ }
762+
763+ return error;
764+}
765+
766+static const struct file_operations aa_fs_profile_load = {
767+ .write = profile_load
768+};
769+
770+/* .replace file hook fn to load and/or replace policy */
771+static ssize_t profile_replace(struct file *f, const char __user *buf,
772+ size_t size, loff_t *pos)
773+{
774+ char *data;
775+ ssize_t error;
776+
777+ data = aa_simple_write_to_buffer(OP_PROF_REPL, buf, size, size, pos);
778+ error = PTR_ERR(data);
779+ if (!IS_ERR(data)) {
780+ error = aa_replace_profiles(data, size, PROF_REPLACE);
781+ kvfree(data);
782+ }
783+
784+ return error;
785+}
786+
787+static const struct file_operations aa_fs_profile_replace = {
788+ .write = profile_replace
789+};
790+
791+/* .remove file hook fn to remove loaded policy */
792+static ssize_t profile_remove(struct file *f, const char __user *buf,
793+ size_t size, loff_t *pos)
794+{
795+ char *data;
796+ ssize_t error;
797+
798+ /*
799+ * aa_remove_profile needs a null terminated string so 1 extra
800+ * byte is allocated and the copied data is null terminated.
801+ */
802+ data = aa_simple_write_to_buffer(OP_PROF_RM, buf, size + 1, size, pos);
9474138d 803+
76514441
AM
804+ error = PTR_ERR(data);
805+ if (!IS_ERR(data)) {
806+ data[size] = 0;
807+ error = aa_remove_profiles(data, size);
808+ kvfree(data);
809+ }
810+
811+ return error;
9474138d
AM
812+}
813+
76514441
AM
814+static const struct file_operations aa_fs_profile_remove = {
815+ .write = profile_remove
9474138d
AM
816+};
817+
ceaf2cfb
AM
818+/** Base file system setup **/
819+
76514441 820+static struct dentry *aa_fs_dentry __initdata;
9474138d 821+
76514441 822+static void __init aafs_remove(const char *name)
9474138d
AM
823+{
824+ struct dentry *dentry;
825+
ceaf2cfb 826+ dentry = lookup_one_len(name, aa_fs_dentry, strlen(name));
9474138d
AM
827+ if (!IS_ERR(dentry)) {
828+ securityfs_remove(dentry);
829+ dput(dentry);
830+ }
831+}
832+
ceaf2cfb
AM
833+/**
834+ * aafs_create - create an entry in the apparmor filesystem
76514441 835+ * @name: name of the entry (NOT NULL)
ceaf2cfb 836+ * @mask: file permission mask of the file
76514441 837+ * @fops: file operations for the file (NOT NULL)
ceaf2cfb
AM
838+ *
839+ * Used aafs_remove to remove entries created with this fn.
840+ */
76514441
AM
841+static int __init aafs_create(const char *name, int mask,
842+ const struct file_operations *fops)
9474138d
AM
843+{
844+ struct dentry *dentry;
845+
ceaf2cfb 846+ dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry,
9474138d
AM
847+ NULL, fops);
848+
849+ return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
850+}
851+
ceaf2cfb
AM
852+/**
853+ * aa_destroy_aafs - cleanup and free aafs
854+ *
855+ * releases dentries allocated by aa_create_aafs
856+ */
76514441 857+void __init aa_destroy_aafs(void)
9474138d 858+{
ceaf2cfb 859+ if (aa_fs_dentry) {
9474138d
AM
860+ aafs_remove(".remove");
861+ aafs_remove(".replace");
862+ aafs_remove(".load");
ceaf2cfb 863+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
76514441 864+ aafs_remove("profiles");
9474138d
AM
865+ aafs_remove("matching");
866+ aafs_remove("features");
ceaf2cfb
AM
867+#endif
868+ securityfs_remove(aa_fs_dentry);
869+ aa_fs_dentry = NULL;
9474138d
AM
870+ }
871+}
872+
ceaf2cfb
AM
873+/**
874+ * aa_create_aafs - create the apparmor security filesystem
875+ *
876+ * dentries created here are released by aa_destroy_aafs
877+ *
878+ * Returns: error on failure
879+ */
76514441 880+int __init aa_create_aafs(void)
9474138d
AM
881+{
882+ int error;
883+
884+ if (!apparmor_initialized)
885+ return 0;
886+
ceaf2cfb 887+ if (aa_fs_dentry) {
9474138d
AM
888+ AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
889+ return -EEXIST;
890+ }
891+
ceaf2cfb
AM
892+ aa_fs_dentry = securityfs_create_dir("apparmor", NULL);
893+ if (IS_ERR(aa_fs_dentry)) {
894+ error = PTR_ERR(aa_fs_dentry);
895+ aa_fs_dentry = NULL;
9474138d
AM
896+ goto error;
897+ }
ceaf2cfb
AM
898+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
899+ error = aafs_create("matching", 0444, &aa_fs_matching_fops);
9474138d
AM
900+ if (error)
901+ goto error;
ceaf2cfb 902+ error = aafs_create("features", 0444, &aa_fs_features_fops);
9474138d
AM
903+ if (error)
904+ goto error;
ceaf2cfb
AM
905+#endif
906+ error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
9474138d
AM
907+ if (error)
908+ goto error;
ceaf2cfb 909+ error = aafs_create(".load", 0640, &aa_fs_profile_load);
9474138d
AM
910+ if (error)
911+ goto error;
ceaf2cfb 912+ error = aafs_create(".replace", 0640, &aa_fs_profile_replace);
9474138d
AM
913+ if (error)
914+ goto error;
ceaf2cfb 915+ error = aafs_create(".remove", 0640, &aa_fs_profile_remove);
9474138d
AM
916+ if (error)
917+ goto error;
918+
919+ /* TODO: add support for apparmorfs_null and apparmorfs_mnt */
920+
921+ /* Report that AppArmor fs is enabled */
ceaf2cfb 922+ aa_info_message("AppArmor Filesystem Enabled");
9474138d
AM
923+ return 0;
924+
925+error:
ceaf2cfb 926+ aa_destroy_aafs();
9474138d 927+ AA_ERROR("Error creating AppArmor securityfs\n");
9474138d
AM
928+ return error;
929+}
930+
ceaf2cfb
AM
931+fs_initcall(aa_create_aafs);
932diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
933new file mode 100644
76514441 934index 0000000..96502b2
ceaf2cfb
AM
935--- /dev/null
936+++ b/security/apparmor/audit.c
76514441 937@@ -0,0 +1,215 @@
9474138d
AM
938+/*
939+ * AppArmor security module
940+ *
941+ * This file contains AppArmor auditing functions
942+ *
943+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 944+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
945+ *
946+ * This program is free software; you can redistribute it and/or
947+ * modify it under the terms of the GNU General Public License as
948+ * published by the Free Software Foundation, version 2 of the
949+ * License.
950+ */
951+
952+#include <linux/audit.h>
953+#include <linux/socket.h>
954+
955+#include "include/apparmor.h"
956+#include "include/audit.h"
957+#include "include/policy.h"
958+
76514441
AM
959+const char *op_table[] = {
960+ "null",
961+
962+ "sysctl",
963+ "capable",
964+
965+ "unlink",
966+ "mkdir",
967+ "rmdir",
968+ "mknod",
969+ "truncate",
970+ "link",
971+ "symlink",
972+ "rename_src",
973+ "rename_dest",
974+ "chmod",
975+ "chown",
976+ "getattr",
977+ "open",
978+
979+ "file_perm",
980+ "file_lock",
981+ "file_mmap",
982+ "file_mprotect",
983+
984+ "create",
985+ "post_create",
986+ "bind",
987+ "connect",
988+ "listen",
989+ "accept",
990+ "sendmsg",
991+ "recvmsg",
992+ "getsockname",
993+ "getpeername",
994+ "getsockopt",
995+ "setsockopt",
996+ "socket_shutdown",
997+
998+ "ptrace",
999+
1000+ "exec",
1001+ "change_hat",
1002+ "change_profile",
1003+ "change_onexec",
1004+
1005+ "setprocattr",
1006+ "setrlimit",
1007+
1008+ "profile_replace",
1009+ "profile_load",
1010+ "profile_remove"
1011+};
1012+
9474138d
AM
1013+const char *audit_mode_names[] = {
1014+ "normal",
1015+ "quiet_denied",
ceaf2cfb 1016+ "quiet",
9474138d
AM
1017+ "noquiet",
1018+ "all"
1019+};
1020+
ceaf2cfb 1021+static char *aa_audit_type[] = {
76514441
AM
1022+ "AUDIT",
1023+ "ALLOWED",
1024+ "DENIED",
1025+ "HINT",
1026+ "STATUS",
1027+ "ERROR",
1028+ "KILLED"
9474138d
AM
1029+};
1030+
1031+/*
ceaf2cfb
AM
1032+ * Currently AppArmor auditing is fed straight into the audit framework.
1033+ *
9474138d 1034+ * TODO:
ceaf2cfb
AM
1035+ * netlink interface for complain mode
1036+ * user auditing, - send user auditing to netlink interface
9474138d
AM
1037+ * system control of whether user audit messages go to system log
1038+ */
ceaf2cfb
AM
1039+
1040+/**
76514441
AM
1041+ * audit_base - core AppArmor function.
1042+ * @ab: audit buffer to fill (NOT NULL)
1043+ * @ca: audit structure containing data to audit (NOT NULL)
ceaf2cfb 1044+ *
76514441 1045+ * Record common AppArmor audit data from @sa
ceaf2cfb 1046+ */
76514441 1047+static void audit_pre(struct audit_buffer *ab, void *ca)
9474138d 1048+{
76514441
AM
1049+ struct common_audit_data *sa = ca;
1050+ struct task_struct *tsk = sa->tsk ? sa->tsk : current;
9474138d 1051+
ceaf2cfb 1052+ if (aa_g_audit_header) {
76514441
AM
1053+ audit_log_format(ab, "apparmor=");
1054+ audit_log_string(ab, aa_audit_type[sa->aad.type]);
ceaf2cfb 1055+ }
9474138d 1056+
76514441 1057+ if (sa->aad.op) {
ceaf2cfb 1058+ audit_log_format(ab, " operation=");
76514441 1059+ audit_log_string(ab, op_table[sa->aad.op]);
ceaf2cfb 1060+ }
9474138d 1061+
76514441 1062+ if (sa->aad.info) {
ceaf2cfb 1063+ audit_log_format(ab, " info=");
76514441
AM
1064+ audit_log_string(ab, sa->aad.info);
1065+ if (sa->aad.error)
1066+ audit_log_format(ab, " error=%d", sa->aad.error);
9474138d
AM
1067+ }
1068+
76514441
AM
1069+ if (sa->aad.profile) {
1070+ struct aa_profile *profile = sa->aad.profile;
ceaf2cfb
AM
1071+ pid_t pid;
1072+ rcu_read_lock();
76514441 1073+ pid = tsk->real_parent->pid;
ceaf2cfb 1074+ rcu_read_unlock();
9474138d 1075+ audit_log_format(ab, " parent=%d", pid);
ceaf2cfb 1076+ if (profile->ns != root_ns) {
9474138d 1077+ audit_log_format(ab, " namespace=");
ceaf2cfb 1078+ audit_log_untrustedstring(ab, profile->ns->base.hname);
9474138d 1079+ }
76514441
AM
1080+ audit_log_format(ab, " profile=");
1081+ audit_log_untrustedstring(ab, profile->base.hname);
9474138d
AM
1082+ }
1083+
76514441
AM
1084+ if (sa->aad.name) {
1085+ audit_log_format(ab, " name=");
1086+ audit_log_untrustedstring(ab, sa->aad.name);
1087+ }
1088+}
9474138d 1089+
76514441
AM
1090+/**
1091+ * aa_audit_msg - Log a message to the audit subsystem
1092+ * @sa: audit event structure (NOT NULL)
1093+ * @cb: optional callback fn for type specific fields (MAYBE NULL)
1094+ */
1095+void aa_audit_msg(int type, struct common_audit_data *sa,
1096+ void (*cb) (struct audit_buffer *, void *))
1097+{
1098+ sa->aad.type = type;
1099+ sa->lsm_pre_audit = audit_pre;
1100+ sa->lsm_post_audit = cb;
1101+ common_lsm_audit(sa);
9474138d
AM
1102+}
1103+
1104+/**
76514441 1105+ * aa_audit - Log a profile based audit event to the audit subsystem
9474138d 1106+ * @type: audit type for the message
76514441
AM
1107+ * @profile: profile to check against (NOT NULL)
1108+ * @gfp: allocation flags to use
1109+ * @sa: audit event (NOT NULL)
1110+ * @cb: optional callback fn for type specific fields (MAYBE NULL)
ceaf2cfb
AM
1111+ *
1112+ * Handle default message switching based off of audit mode flags
1113+ *
1114+ * Returns: error on failure
9474138d 1115+ */
76514441
AM
1116+int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
1117+ struct common_audit_data *sa,
1118+ void (*cb) (struct audit_buffer *, void *))
9474138d 1119+{
76514441 1120+ BUG_ON(!profile);
9474138d
AM
1121+
1122+ if (type == AUDIT_APPARMOR_AUTO) {
76514441 1123+ if (likely(!sa->aad.error)) {
ceaf2cfb 1124+ if (AUDIT_MODE(profile) != AUDIT_ALL)
5e665963 1125+ return 0;
9474138d 1126+ type = AUDIT_APPARMOR_AUDIT;
ceaf2cfb 1127+ } else if (COMPLAIN_MODE(profile))
9474138d
AM
1128+ type = AUDIT_APPARMOR_ALLOWED;
1129+ else
1130+ type = AUDIT_APPARMOR_DENIED;
1131+ }
ceaf2cfb 1132+ if (AUDIT_MODE(profile) == AUDIT_QUIET ||
9474138d 1133+ (type == AUDIT_APPARMOR_DENIED &&
ceaf2cfb 1134+ AUDIT_MODE(profile) == AUDIT_QUIET))
76514441
AM
1135+ return sa->aad.error;
1136+
1137+ if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
1138+ type = AUDIT_APPARMOR_KILL;
1139+
1140+ if (!unconfined(profile))
1141+ sa->aad.profile = profile;
1142+
1143+ aa_audit_msg(type, sa, cb);
9474138d 1144+
76514441
AM
1145+ if (sa->aad.type == AUDIT_APPARMOR_KILL)
1146+ (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current);
1147+
1148+ if (sa->aad.type == AUDIT_APPARMOR_ALLOWED)
1149+ return complain_error(sa->aad.error);
1150+
1151+ return sa->aad.error;
ceaf2cfb
AM
1152+}
1153diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
1154new file mode 100644
76514441 1155index 0000000..9982c48
ceaf2cfb
AM
1156--- /dev/null
1157+++ b/security/apparmor/capability.c
76514441 1158@@ -0,0 +1,141 @@
9474138d
AM
1159+/*
1160+ * AppArmor security module
1161+ *
1162+ * This file contains AppArmor capability mediation functions
1163+ *
1164+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 1165+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
1166+ *
1167+ * This program is free software; you can redistribute it and/or
1168+ * modify it under the terms of the GNU General Public License as
1169+ * published by the Free Software Foundation, version 2 of the
1170+ * License.
1171+ */
1172+
1173+#include <linux/capability.h>
1174+#include <linux/errno.h>
1175+#include <linux/gfp.h>
1176+
1177+#include "include/apparmor.h"
1178+#include "include/capability.h"
1179+#include "include/context.h"
1180+#include "include/policy.h"
1181+#include "include/audit.h"
1182+
1183+/*
1184+ * Table of capability names: we generate it from capabilities.h.
1185+ */
1186+#include "capability_names.h"
1187+
1188+struct audit_cache {
ceaf2cfb 1189+ struct aa_profile *profile;
9474138d
AM
1190+ kernel_cap_t caps;
1191+};
1192+
1193+static DEFINE_PER_CPU(struct audit_cache, audit_cache);
1194+
ceaf2cfb
AM
1195+/**
1196+ * audit_cb - call back for capability components of audit struct
1197+ * @ab - audit buffer (NOT NULL)
1198+ * @va - audit struct to audit data from (NOT NULL)
1199+ */
76514441 1200+static void audit_cb(struct audit_buffer *ab, void *va)
9474138d 1201+{
76514441
AM
1202+ struct common_audit_data *sa = va;
1203+ audit_log_format(ab, " capname=");
1204+ audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
9474138d
AM
1205+}
1206+
ceaf2cfb 1207+/**
76514441
AM
1208+ * audit_caps - audit a capability
1209+ * @profile: profile confining task (NOT NULL)
1210+ * @task: task capability test was performed against (NOT NULL)
1211+ * @cap: capability tested
1212+ * @error: error code returned by test
ceaf2cfb
AM
1213+ *
1214+ * Do auditing of capability and handle, audit/complain/kill modes switching
1215+ * and duplicate message elimination.
1216+ *
76514441 1217+ * Returns: 0 or sa->error on success, error code on failure
ceaf2cfb 1218+ */
76514441
AM
1219+static int audit_caps(struct aa_profile *profile, struct task_struct *task,
1220+ int cap, int error)
9474138d
AM
1221+{
1222+ struct audit_cache *ent;
1223+ int type = AUDIT_APPARMOR_AUTO;
76514441
AM
1224+ struct common_audit_data sa;
1225+ COMMON_AUDIT_DATA_INIT(&sa, CAP);
1226+ sa.tsk = task;
1227+ sa.u.cap = cap;
1228+ sa.aad.op = OP_CAPABLE;
1229+ sa.aad.error = error;
1230+
1231+ if (likely(!error)) {
9474138d 1232+ /* test if auditing is being forced */
ceaf2cfb 1233+ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
76514441 1234+ !cap_raised(profile->caps.audit, cap)))
9474138d 1235+ return 0;
5e665963 1236+ type = AUDIT_APPARMOR_AUDIT;
76514441
AM
1237+ } else if (KILL_MODE(profile) ||
1238+ cap_raised(profile->caps.kill, cap)) {
9474138d 1239+ type = AUDIT_APPARMOR_KILL;
76514441 1240+ } else if (cap_raised(profile->caps.quiet, cap) &&
ceaf2cfb
AM
1241+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
1242+ AUDIT_MODE(profile) != AUDIT_ALL) {
9474138d 1243+ /* quiet auditing */
76514441 1244+ return error;
9474138d
AM
1245+ }
1246+
1247+ /* Do simple duplicate message elimination */
1248+ ent = &get_cpu_var(audit_cache);
76514441 1249+ if (profile == ent->profile && cap_raised(ent->caps, cap)) {
ceaf2cfb
AM
1250+ put_cpu_var(audit_cache);
1251+ if (COMPLAIN_MODE(profile))
76514441
AM
1252+ return complain_error(error);
1253+ return error;
9474138d 1254+ } else {
ceaf2cfb
AM
1255+ aa_put_profile(ent->profile);
1256+ ent->profile = aa_get_profile(profile);
76514441 1257+ cap_raise(ent->caps, cap);
9474138d
AM
1258+ }
1259+ put_cpu_var(audit_cache);
1260+
76514441 1261+ return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb);
9474138d
AM
1262+}
1263+
ceaf2cfb 1264+/**
76514441 1265+ * profile_capable - test if profile allows use of capability @cap
ceaf2cfb
AM
1266+ * @profile: profile being enforced (NOT NULL, NOT unconfined)
1267+ * @cap: capability to test if allowed
1268+ *
1269+ * Returns: 0 if allowed else -EPERM
1270+ */
76514441 1271+static int profile_capable(struct aa_profile *profile, int cap)
9474138d 1272+{
76514441 1273+ return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM;
9474138d
AM
1274+}
1275+
1276+/**
1277+ * aa_capable - test permission to use capability
76514441
AM
1278+ * @task: task doing capability test against (NOT NULL)
1279+ * @profile: profile confining @task (NOT NULL)
9474138d
AM
1280+ * @cap: capability to be tested
1281+ * @audit: whether an audit record should be generated
1282+ *
1283+ * Look up capability in profile capability set.
ceaf2cfb
AM
1284+ *
1285+ * Returns: 0 on success, or else an error code.
9474138d
AM
1286+ */
1287+int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
1288+ int audit)
1289+{
76514441 1290+ int error = profile_capable(profile, cap);
9474138d
AM
1291+
1292+ if (!audit) {
ceaf2cfb 1293+ if (COMPLAIN_MODE(profile))
76514441 1294+ return complain_error(error);
9474138d
AM
1295+ return error;
1296+ }
1297+
76514441 1298+ return audit_caps(profile, task, cap, error);
9474138d 1299+}
ceaf2cfb
AM
1300diff --git a/security/apparmor/context.c b/security/apparmor/context.c
1301new file mode 100644
76514441 1302index 0000000..8a9b502
ceaf2cfb
AM
1303--- /dev/null
1304+++ b/security/apparmor/context.c
76514441 1305@@ -0,0 +1,216 @@
9474138d
AM
1306+/*
1307+ * AppArmor security module
1308+ *
1309+ * This file contains AppArmor functions used to manipulate object security
1310+ * contexts.
1311+ *
1312+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 1313+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
1314+ *
1315+ * This program is free software; you can redistribute it and/or
1316+ * modify it under the terms of the GNU General Public License as
1317+ * published by the Free Software Foundation, version 2 of the
1318+ * License.
ceaf2cfb
AM
1319+ *
1320+ *
1321+ * AppArmor sets confinement on every task, via the the aa_task_cxt and
76514441 1322+ * the aa_task_cxt.profile, both of which are required and are not allowed
ceaf2cfb
AM
1323+ * to be NULL. The aa_task_cxt is not reference counted and is unique
1324+ * to each cred (which is reference count). The profile pointed to by
1325+ * the task_cxt is reference counted.
1326+ *
1327+ * TODO
1328+ * If a task uses change_hat it currently does not return to the old
1329+ * cred or task context but instead creates a new one. Ideally the task
1330+ * should return to the previous cred if it has not been modified.
1331+ *
9474138d
AM
1332+ */
1333+
1334+#include "include/context.h"
1335+#include "include/policy.h"
1336+
ceaf2cfb 1337+/**
76514441 1338+ * aa_alloc_task_context - allocate a new task_cxt
ceaf2cfb
AM
1339+ * @flags: gfp flags for allocation
1340+ *
1341+ * Returns: allocated buffer or NULL on failure
1342+ */
1343+struct aa_task_cxt *aa_alloc_task_context(gfp_t flags)
9474138d 1344+{
ceaf2cfb 1345+ return kzalloc(sizeof(struct aa_task_cxt), flags);
9474138d
AM
1346+}
1347+
ceaf2cfb
AM
1348+/**
1349+ * aa_free_task_context - free a task_cxt
1350+ * @cxt: task_cxt to free (MAYBE NULL)
1351+ */
1352+void aa_free_task_context(struct aa_task_cxt *cxt)
9474138d
AM
1353+{
1354+ if (cxt) {
ceaf2cfb
AM
1355+ aa_put_profile(cxt->profile);
1356+ aa_put_profile(cxt->previous);
1357+ aa_put_profile(cxt->onexec);
9474138d 1358+
ceaf2cfb 1359+ kzfree(cxt);
9474138d
AM
1360+ }
1361+}
1362+
9474138d 1363+/**
ceaf2cfb
AM
1364+ * aa_dup_task_context - duplicate a task context, incrementing reference counts
1365+ * @new: a blank task context (NOT NULL)
1366+ * @old: the task context to copy (NOT NULL)
9474138d 1367+ */
ceaf2cfb 1368+void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
9474138d 1369+{
ceaf2cfb
AM
1370+ *new = *old;
1371+ aa_get_profile(new->profile);
1372+ aa_get_profile(new->previous);
1373+ aa_get_profile(new->onexec);
9474138d
AM
1374+}
1375+
1376+/**
76514441
AM
1377+ * aa_replace_current_profile - replace the current tasks profiles
1378+ * @profile: new profile (NOT NULL)
9474138d 1379+ *
76514441 1380+ * Returns: 0 or error on failure
9474138d 1381+ */
76514441 1382+int aa_replace_current_profile(struct aa_profile *profile)
9474138d 1383+{
76514441
AM
1384+ struct aa_task_cxt *cxt = current_cred()->security;
1385+ struct cred *new;
1386+ BUG_ON(!profile);
1387+
ceaf2cfb 1388+ if (cxt->profile == profile)
76514441 1389+ return 0;
9474138d 1390+
76514441
AM
1391+ new = prepare_creds();
1392+ if (!new)
1393+ return -ENOMEM;
1394+
1395+ cxt = new->security;
ceaf2cfb
AM
1396+ if (unconfined(profile) || (cxt->profile->ns != profile->ns)) {
1397+ /* if switching to unconfined or a different profile namespace
1398+ * clear out context state
1399+ */
1400+ aa_put_profile(cxt->previous);
1401+ aa_put_profile(cxt->onexec);
1402+ cxt->previous = NULL;
1403+ cxt->onexec = NULL;
1404+ cxt->token = 0;
9474138d 1405+ }
76514441
AM
1406+ /* be careful switching cxt->profile, when racing replacement it
1407+ * is possible that cxt->profile->replacedby is the reference keeping
1408+ * @profile valid, so make sure to get its reference before dropping
1409+ * the reference on cxt->profile */
1410+ aa_get_profile(profile);
ceaf2cfb 1411+ aa_put_profile(cxt->profile);
76514441 1412+ cxt->profile = profile;
9474138d
AM
1413+
1414+ commit_creds(new);
1415+ return 0;
1416+}
1417+
ceaf2cfb
AM
1418+/**
1419+ * aa_set_current_onexec - set the tasks change_profile to happen onexec
76514441 1420+ * @profile: system profile to set at exec (MAYBE NULL to clear value)
ceaf2cfb
AM
1421+ *
1422+ * Returns: 0 or error on failure
1423+ */
1424+int aa_set_current_onexec(struct aa_profile *profile)
9474138d 1425+{
ceaf2cfb 1426+ struct aa_task_cxt *cxt;
9474138d
AM
1427+ struct cred *new = prepare_creds();
1428+ if (!new)
1429+ return -ENOMEM;
1430+
1431+ cxt = new->security;
76514441 1432+ aa_get_profile(profile);
ceaf2cfb 1433+ aa_put_profile(cxt->onexec);
76514441 1434+ cxt->onexec = profile;
9474138d
AM
1435+
1436+ commit_creds(new);
1437+ return 0;
1438+}
1439+
ceaf2cfb
AM
1440+/**
1441+ * aa_set_current_hat - set the current tasks hat
1442+ * @profile: profile to set as the current hat (NOT NULL)
1443+ * @token: token value that must be specified to change from the hat
1444+ *
1445+ * Do switch of tasks hat. If the task is currently in a hat
1446+ * validate the token to match.
1447+ *
1448+ * Returns: 0 or error on failure
9474138d
AM
1449+ */
1450+int aa_set_current_hat(struct aa_profile *profile, u64 token)
1451+{
ceaf2cfb 1452+ struct aa_task_cxt *cxt;
9474138d
AM
1453+ struct cred *new = prepare_creds();
1454+ if (!new)
1455+ return -ENOMEM;
ceaf2cfb 1456+ BUG_ON(!profile);
9474138d
AM
1457+
1458+ cxt = new->security;
ceaf2cfb 1459+ if (!cxt->previous) {
76514441 1460+ /* transfer refcount */
ceaf2cfb
AM
1461+ cxt->previous = cxt->profile;
1462+ cxt->token = token;
1463+ } else if (cxt->token == token) {
1464+ aa_put_profile(cxt->profile);
9474138d
AM
1465+ } else {
1466+ /* previous_profile && cxt->token != token */
1467+ abort_creds(new);
1468+ return -EACCES;
1469+ }
ceaf2cfb 1470+ cxt->profile = aa_get_profile(aa_newest_version(profile));
9474138d 1471+ /* clear exec on switching context */
ceaf2cfb
AM
1472+ aa_put_profile(cxt->onexec);
1473+ cxt->onexec = NULL;
9474138d
AM
1474+
1475+ commit_creds(new);
1476+ return 0;
1477+}
1478+
ceaf2cfb
AM
1479+/**
1480+ * aa_restore_previous_profile - exit from hat context restoring the profile
1481+ * @token: the token that must be matched to exit hat context
1482+ *
1483+ * Attempt to return out of a hat to the previous profile. The token
1484+ * must match the stored token value.
1485+ *
1486+ * Returns: 0 or error of failure
9474138d
AM
1487+ */
1488+int aa_restore_previous_profile(u64 token)
1489+{
ceaf2cfb 1490+ struct aa_task_cxt *cxt;
9474138d
AM
1491+ struct cred *new = prepare_creds();
1492+ if (!new)
1493+ return -ENOMEM;
1494+
1495+ cxt = new->security;
ceaf2cfb 1496+ if (cxt->token != token) {
9474138d
AM
1497+ abort_creds(new);
1498+ return -EACCES;
1499+ }
1500+ /* ignore restores when there is no saved profile */
ceaf2cfb 1501+ if (!cxt->previous) {
9474138d
AM
1502+ abort_creds(new);
1503+ return 0;
1504+ }
1505+
ceaf2cfb
AM
1506+ aa_put_profile(cxt->profile);
1507+ cxt->profile = aa_newest_version(cxt->previous);
1508+ BUG_ON(!cxt->profile);
1509+ if (unlikely(cxt->profile != cxt->previous)) {
1510+ aa_get_profile(cxt->profile);
1511+ aa_put_profile(cxt->previous);
9474138d
AM
1512+ }
1513+ /* clear exec && prev information when restoring to previous context */
ceaf2cfb
AM
1514+ cxt->previous = NULL;
1515+ cxt->token = 0;
1516+ aa_put_profile(cxt->onexec);
1517+ cxt->onexec = NULL;
9474138d
AM
1518+
1519+ commit_creds(new);
1520+ return 0;
1521+}
ceaf2cfb
AM
1522diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
1523new file mode 100644
76514441 1524index 0000000..08bbe63
ceaf2cfb
AM
1525--- /dev/null
1526+++ b/security/apparmor/domain.c
76514441 1527@@ -0,0 +1,823 @@
9474138d
AM
1528+/*
1529+ * AppArmor security module
1530+ *
1531+ * This file contains AppArmor policy attachment and domain transitions
1532+ *
1533+ * Copyright (C) 2002-2008 Novell/SUSE
ceaf2cfb 1534+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
1535+ *
1536+ * This program is free software; you can redistribute it and/or
1537+ * modify it under the terms of the GNU General Public License as
1538+ * published by the Free Software Foundation, version 2 of the
1539+ * License.
1540+ */
1541+
1542+#include <linux/errno.h>
1543+#include <linux/fdtable.h>
1544+#include <linux/file.h>
1545+#include <linux/mount.h>
9474138d
AM
1546+#include <linux/syscalls.h>
1547+#include <linux/tracehook.h>
5e665963 1548+#include <linux/personality.h>
9474138d
AM
1549+
1550+#include "include/audit.h"
1551+#include "include/apparmorfs.h"
1552+#include "include/context.h"
1553+#include "include/domain.h"
1554+#include "include/file.h"
1555+#include "include/ipc.h"
1556+#include "include/match.h"
1557+#include "include/path.h"
1558+#include "include/policy.h"
1559+
1560+/**
1561+ * aa_free_domain_entries - free entries in a domain table
ceaf2cfb 1562+ * @domain: the domain table to free (MAYBE NULL)
9474138d
AM
1563+ */
1564+void aa_free_domain_entries(struct aa_domain *domain)
1565+{
1566+ int i;
ceaf2cfb
AM
1567+ if (domain) {
1568+ if (!domain->table)
1569+ return;
9474138d 1570+
ceaf2cfb
AM
1571+ for (i = 0; i < domain->size; i++)
1572+ kzfree(domain->table[i]);
1573+ kzfree(domain->table);
1574+ domain->table = NULL;
1575+ }
9474138d
AM
1576+}
1577+
ceaf2cfb 1578+/**
76514441 1579+ * may_change_ptraced_domain - check if can change profile on ptraced task
ceaf2cfb
AM
1580+ * @task: task we want to change profile of (NOT NULL)
1581+ * @to_profile: profile to change to (NOT NULL)
1582+ *
1583+ * Check if the task is ptraced and if so if the tracing task is allowed
9474138d 1584+ * to trace the new domain
ceaf2cfb
AM
1585+ *
1586+ * Returns: %0 or error if change not allowed
9474138d 1587+ */
76514441
AM
1588+static int may_change_ptraced_domain(struct task_struct *task,
1589+ struct aa_profile *to_profile)
9474138d
AM
1590+{
1591+ struct task_struct *tracer;
1592+ struct cred *cred = NULL;
1593+ struct aa_profile *tracerp = NULL;
1594+ int error = 0;
1595+
1596+ rcu_read_lock();
1597+ tracer = tracehook_tracer_task(task);
ceaf2cfb
AM
1598+ if (tracer) {
1599+ /* released below */
1600+ cred = get_task_cred(tracer);
1601+ tracerp = aa_cred_profile(cred);
1602+ }
9474138d
AM
1603+ rcu_read_unlock();
1604+
ceaf2cfb
AM
1605+ /* not ptraced */
1606+ if (!tracer || unconfined(tracerp))
1607+ goto out;
9474138d
AM
1608+
1609+ error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
ceaf2cfb
AM
1610+
1611+out:
1612+ if (cred)
1613+ put_cred(cred);
9474138d
AM
1614+
1615+ return error;
1616+}
1617+
1618+/**
ceaf2cfb
AM
1619+ * change_profile_perms - find permissions for change_profile
1620+ * @profile: the current profile (NOT NULL)
1621+ * @ns: the namespace being switched to (NOT NULL)
1622+ * @name: the name of the profile to change to (NOT NULL)
76514441
AM
1623+ * @request: requested perms
1624+ * @start: state to start matching in
ceaf2cfb
AM
1625+ *
1626+ * Returns: permission set
9474138d
AM
1627+ */
1628+static struct file_perms change_profile_perms(struct aa_profile *profile,
1629+ struct aa_namespace *ns,
76514441
AM
1630+ const char *name, u32 request,
1631+ unsigned int start)
9474138d
AM
1632+{
1633+ struct file_perms perms;
ceaf2cfb 1634+ struct path_cond cond = { };
9474138d
AM
1635+ unsigned int state;
1636+
ceaf2cfb 1637+ if (unconfined(profile)) {
76514441 1638+ perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC;
9474138d 1639+ perms.audit = perms.quiet = perms.kill = 0;
9474138d 1640+ return perms;
5e665963
AM
1641+ } else if (!profile->file.dfa) {
1642+ return nullperms;
9474138d 1643+ } else if ((ns == profile->ns)) {
76514441
AM
1644+ /* try matching against rules with out namespace prepended */
1645+ aa_str_perms(profile->file.dfa, start, name, &cond, &perms);
1646+ if (COMBINED_PERM_MASK(perms) & request)
9474138d
AM
1647+ return perms;
1648+ }
1649+
1650+ /* try matching with namespace name and then profile */
76514441
AM
1651+ state = aa_dfa_match(profile->file.dfa, start, ns->base.name);
1652+ state = aa_dfa_match_len(profile->file.dfa, state, ":", 1);
1653+ aa_str_perms(profile->file.dfa, state, name, &cond, &perms);
1654+
1655+ return perms;
9474138d
AM
1656+}
1657+
ceaf2cfb 1658+/**
76514441 1659+ * __attach_match_ - find an attachment match
ceaf2cfb
AM
1660+ * @name - to match against (NOT NULL)
1661+ * @head - profile list to walk (NOT NULL)
1662+ *
1663+ * Do a linear search on the profiles in the list. There is a matching
76514441 1664+ * preference where an exact match is preferred over a name which uses
ceaf2cfb 1665+ * expressions to match, and matching expressions with the greatest
76514441 1666+ * xmatch_len are preferred.
ceaf2cfb
AM
1667+ *
1668+ * Requires: @head not be shared or have appropriate locks held
1669+ *
1670+ * Returns: profile or NULL if no match found
1671+ */
76514441
AM
1672+static struct aa_profile *__attach_match(const char *name,
1673+ struct list_head *head)
ceaf2cfb
AM
1674+{
1675+ int len = 0;
1676+ struct aa_profile *profile, *candidate = NULL;
1677+
1678+ list_for_each_entry(profile, head, base.list) {
1679+ if (profile->flags & PFLAG_NULL)
1680+ continue;
1681+ if (profile->xmatch && profile->xmatch_len > len) {
1682+ unsigned int state = aa_dfa_match(profile->xmatch,
1683+ DFA_START, name);
76514441 1684+ u32 perm = dfa_user_allow(profile->xmatch, state);
ceaf2cfb
AM
1685+ /* any accepting state means a valid match. */
1686+ if (perm & MAY_EXEC) {
1687+ candidate = profile;
1688+ len = profile->xmatch_len;
1689+ }
1690+ } else if (!strcmp(profile->base.name, name))
1691+ /* exact non-re match, no more searching required */
1692+ return profile;
1693+ }
1694+
1695+ return candidate;
1696+}
1697+
1698+/**
76514441 1699+ * find_attach - do attachment search for unconfined processes
ceaf2cfb
AM
1700+ * @ns: the current namespace (NOT NULL)
1701+ * @list: list to search (NOT NULL)
1702+ * @name: the executable name to match against (NOT NULL)
1703+ *
1704+ * Returns: profile or NULL if no match found
1705+ */
76514441
AM
1706+static struct aa_profile *find_attach(struct aa_namespace *ns,
1707+ struct list_head *list, const char *name)
ceaf2cfb
AM
1708+{
1709+ struct aa_profile *profile;
1710+
1711+ read_lock(&ns->lock);
76514441 1712+ profile = aa_get_profile(__attach_match(name, list));
ceaf2cfb
AM
1713+ read_unlock(&ns->lock);
1714+
1715+ return profile;
1716+}
1717+
1718+/**
1719+ * separate_fqname - separate the namespace and profile names
1720+ * @fqname: the fqname name to split (NOT NULL)
1721+ * @ns_name: the namespace name if it exists (NOT NULL)
1722+ *
1723+ * This is the xtable equivalent routine of aa_split_fqname. It finds the
1724+ * split in an xtable fqname which contains an embedded \0 instead of a :
1725+ * if a namespace is specified. This is done so the xtable is constant and
76514441 1726+ * isn't re-split on every lookup.
ceaf2cfb
AM
1727+ *
1728+ * Either the profile or namespace name may be optional but if the namespace
1729+ * is specified the profile name termination must be present. This results
1730+ * in the following possible encodings:
1731+ * profile_name\0
1732+ * :ns_name\0profile_name\0
1733+ * :ns_name\0\0
1734+ *
76514441 1735+ * NOTE: the xtable fqname is pre-validated at load time in unpack_trans_table
ceaf2cfb
AM
1736+ *
1737+ * Returns: profile name if it is specified else NULL
1738+ */
1739+static const char *separate_fqname(const char *fqname, const char **ns_name)
9474138d 1740+{
ceaf2cfb
AM
1741+ const char *name;
1742+
1743+ if (fqname[0] == ':') {
76514441
AM
1744+ /* In this case there is guaranteed to be two \0 terminators
1745+ * in the string. They are verified at load time by
1746+ * by unpack_trans_table
1747+ */
ceaf2cfb
AM
1748+ *ns_name = fqname + 1; /* skip : */
1749+ name = *ns_name + strlen(*ns_name) + 1;
1750+ if (!*name)
1751+ name = NULL;
1752+ } else {
1753+ *ns_name = NULL;
1754+ name = fqname;
9474138d 1755+ }
ceaf2cfb
AM
1756+
1757+ return name;
1758+}
1759+
1760+static const char *next_name(int xtype, const char *name)
1761+{
9474138d
AM
1762+ return NULL;
1763+}
1764+
ceaf2cfb 1765+/**
76514441
AM
1766+ * x_table_lookup - lookup an x transition name via transition table
1767+ * @profile: current profile (NOT NULL)
ceaf2cfb
AM
1768+ * @xindex: index into x transition table
1769+ *
76514441 1770+ * Returns: refcounted profile, or NULL on failure (MAYBE NULL)
9474138d 1771+ */
76514441 1772+static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
9474138d
AM
1773+{
1774+ struct aa_profile *new_profile = NULL;
ceaf2cfb 1775+ struct aa_namespace *ns = profile->ns;
76514441 1776+ u32 xtype = xindex & AA_X_TYPE_MASK;
9474138d 1777+ int index = xindex & AA_X_INDEX_MASK;
76514441 1778+ const char *name;
9474138d 1779+
76514441
AM
1780+ /* index is guaranteed to be in range, validated at load time */
1781+ for (name = profile->file.trans.table[index]; !new_profile && name;
1782+ name = next_name(xtype, name)) {
9474138d
AM
1783+ struct aa_namespace *new_ns;
1784+ const char *xname = NULL;
1785+
1786+ new_ns = NULL;
1787+ if (xindex & AA_X_CHILD) {
ceaf2cfb 1788+ /* release by caller */
9474138d 1789+ new_profile = aa_find_child(profile, name);
9474138d
AM
1790+ continue;
1791+ } else if (*name == ':') {
1792+ /* switching namespace */
ceaf2cfb
AM
1793+ const char *ns_name;
1794+ xname = name = separate_fqname(name, &ns_name);
1795+ if (!xname)
9474138d 1796+ /* no name so use profile name */
ceaf2cfb 1797+ xname = profile->base.hname;
9474138d
AM
1798+ if (*ns_name == '@') {
1799+ /* TODO: variable support */
1800+ ;
1801+ }
ceaf2cfb
AM
1802+ /* released below */
1803+ new_ns = aa_find_namespace(ns, ns_name);
9474138d
AM
1804+ if (!new_ns)
1805+ continue;
1806+ } else if (*name == '@') {
1807+ /* TODO: variable support */
ceaf2cfb 1808+ continue;
9474138d 1809+ } else {
76514441 1810+ /* basic namespace lookup */
9474138d
AM
1811+ xname = name;
1812+ }
1813+
ceaf2cfb 1814+ /* released by caller */
76514441 1815+ new_profile = aa_lookup_profile(new_ns ? new_ns : ns, xname);
9474138d
AM
1816+ aa_put_namespace(new_ns);
1817+ }
1818+
ceaf2cfb 1819+ /* released by caller */
9474138d
AM
1820+ return new_profile;
1821+}
1822+
ceaf2cfb 1823+/**
76514441
AM
1824+ * x_to_profile - get target profile for a given xindex
1825+ * @profile: current profile (NOT NULL)
1826+ * @name: name to lookup (NOT NULL)
1827+ * @xindex: index into x transition table
1828+ *
1829+ * find profile for a transition index
1830+ *
1831+ * Returns: refcounted profile or NULL if not found available
1832+ */
1833+static struct aa_profile *x_to_profile(struct aa_profile *profile,
1834+ const char *name, u32 xindex)
1835+{
1836+ struct aa_profile *new_profile = NULL;
1837+ struct aa_namespace *ns = profile->ns;
1838+ u32 xtype = xindex & AA_X_TYPE_MASK;
1839+
1840+ switch (xtype) {
1841+ case AA_X_NONE:
1842+ /* fail exec unless ix || ux fallback - handled by caller */
1843+ return NULL;
1844+ case AA_X_NAME:
1845+ if (xindex & AA_X_CHILD)
1846+ /* released by caller */
1847+ new_profile = find_attach(ns, &profile->base.profiles,
1848+ name);
1849+ else
1850+ /* released by caller */
1851+ new_profile = find_attach(ns, &ns->base.profiles,
1852+ name);
1853+ break;
1854+ case AA_X_TABLE:
1855+ /* released by caller */
1856+ new_profile = x_table_lookup(profile, xindex);
1857+ break;
1858+ }
1859+
1860+ /* released by caller */
1861+ return new_profile;
1862+}
1863+
1864+/**
ceaf2cfb
AM
1865+ * apparmor_bprm_set_creds - set the new creds on the bprm struct
1866+ * @bprm: binprm for the exec (NOT NULL)
1867+ *
1868+ * Returns: %0 or error on failure
1869+ */
9474138d
AM
1870+int apparmor_bprm_set_creds(struct linux_binprm *bprm)
1871+{
ceaf2cfb 1872+ struct aa_task_cxt *cxt;
9474138d
AM
1873+ struct aa_profile *profile, *new_profile = NULL;
1874+ struct aa_namespace *ns;
1875+ char *buffer = NULL;
ceaf2cfb 1876+ unsigned int state;
76514441 1877+ struct file_perms perms = {};
ceaf2cfb
AM
1878+ struct path_cond cond = {
1879+ bprm->file->f_path.dentry->d_inode->i_uid,
1880+ bprm->file->f_path.dentry->d_inode->i_mode
1881+ };
76514441
AM
1882+ const char *name = NULL, *target = NULL, *info = NULL;
1883+ int error = cap_bprm_set_creds(bprm);
1884+ if (error)
1885+ return error;
9474138d
AM
1886+
1887+ if (bprm->cred_prepared)
1888+ return 0;
1889+
9474138d
AM
1890+ cxt = bprm->cred->security;
1891+ BUG_ON(!cxt);
1892+
76514441 1893+ profile = aa_get_profile(aa_newest_version(cxt->profile));
ceaf2cfb
AM
1894+ /*
1895+ * get the namespace from the replacement profile as replacement
1896+ * can change the namespace
1897+ */
1898+ ns = profile->ns;
1899+ state = profile->file.start;
9474138d 1900+
76514441
AM
1901+ /* buffer freed below, name is pointer into buffer */
1902+ error = aa_get_name(&bprm->file->f_path, profile->path_flags, &buffer,
1903+ &name);
1904+ if (error) {
ceaf2cfb
AM
1905+ if (profile->flags &
1906+ (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED))
76514441
AM
1907+ error = 0;
1908+ info = "Exec failed name resolution";
1909+ name = bprm->filename;
9474138d
AM
1910+ goto audit;
1911+ }
1912+
76514441
AM
1913+ /* Test for onexec first as onexec directives override other
1914+ * x transitions.
1915+ */
ceaf2cfb 1916+ if (unconfined(profile)) {
76514441
AM
1917+ /* unconfined task */
1918+ if (cxt->onexec)
1919+ /* change_profile on exec already been granted */
1920+ new_profile = aa_get_profile(cxt->onexec);
1921+ else
1922+ new_profile = find_attach(ns, &ns->base.profiles, name);
9474138d
AM
1923+ if (!new_profile)
1924+ goto cleanup;
1925+ goto apply;
76514441
AM
1926+ }
1927+
1928+ /* find exec permissions for name */
1929+ state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms);
1930+ if (cxt->onexec) {
1931+ struct file_perms cp;
1932+ info = "change_profile onexec";
1933+ if (!(perms.allow & AA_MAY_ONEXEC))
1934+ goto audit;
1935+
1936+ /* test if this exec can be paired with change_profile onexec.
1937+ * onexec permission is linked to exec with a standard pairing
1938+ * exec\0change_profile
ceaf2cfb 1939+ */
76514441
AM
1940+ state = aa_dfa_null_transition(profile->file.dfa, state);
1941+ cp = change_profile_perms(profile, cxt->onexec->ns, name,
1942+ AA_MAY_ONEXEC, state);
1943+
1944+ if (!(cp.allow & AA_MAY_ONEXEC))
1945+ goto audit;
1946+ new_profile = aa_get_profile(aa_newest_version(cxt->onexec));
1947+ goto apply;
1948+ }
1949+
1950+ if (perms.allow & MAY_EXEC) {
1951+ /* exec permission determine how to transition */
1952+ new_profile = x_to_profile(profile, name, perms.xindex);
ceaf2cfb 1953+ if (!new_profile) {
76514441
AM
1954+ if (perms.xindex & AA_X_INHERIT) {
1955+ /* (p|c|n)ix - don't change profile but do
1956+ * use the newest version, which was picked
1957+ * up above when getting profile
1958+ */
1959+ info = "ix fallback";
1960+ new_profile = aa_get_profile(profile);
9474138d 1961+ goto x_clear;
76514441 1962+ } else if (perms.xindex & AA_X_UNCONFINED) {
9474138d 1963+ new_profile = aa_get_profile(ns->unconfined);
76514441 1964+ info = "ux fallback";
9474138d 1965+ } else {
76514441
AM
1966+ error = -ENOENT;
1967+ info = "profile not found";
9474138d
AM
1968+ }
1969+ }
ceaf2cfb 1970+ } else if (COMPLAIN_MODE(profile)) {
76514441 1971+ /* no exec permission - are we in learning mode */
ceaf2cfb 1972+ new_profile = aa_new_null_profile(profile, 0);
ceaf2cfb 1973+ if (!new_profile) {
76514441
AM
1974+ error = -ENOMEM;
1975+ info = "could not create null profile";
1976+ } else {
1977+ error = -EACCES;
1978+ target = new_profile->base.hname;
1979+ }
1980+ perms.xindex |= AA_X_UNSAFE;
1981+ } else
1982+ /* fail exec */
1983+ error = -EACCES;
9474138d
AM
1984+
1985+ if (!new_profile)
1986+ goto audit;
1987+
9474138d
AM
1988+ if (bprm->unsafe & LSM_UNSAFE_SHARE) {
1989+ /* FIXME: currently don't mediate shared state */
1990+ ;
1991+ }
1992+
1993+ if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
76514441
AM
1994+ error = may_change_ptraced_domain(current, new_profile);
1995+ if (error) {
1996+ aa_put_profile(new_profile);
9474138d 1997+ goto audit;
76514441 1998+ }
9474138d
AM
1999+ }
2000+
2001+ /* Determine if secure exec is needed.
2002+ * Can be at this point for the following reasons:
2003+ * 1. unconfined switching to confined
2004+ * 2. confined switching to different confinement
2005+ * 3. confined switching to unconfined
2006+ *
2007+ * Cases 2 and 3 are marked as requiring secure exec
2008+ * (unless policy specified "unsafe exec")
2009+ *
2010+ * bprm->unsafe is used to cache the AA_X_UNSAFE permission
2011+ * to avoid having to recompute in secureexec
2012+ */
76514441
AM
2013+ if (!(perms.xindex & AA_X_UNSAFE)) {
2014+ AA_DEBUG("scrubbing environment variables for %s profile=%s\n",
2015+ name, new_profile->base.hname);
9474138d 2016+ bprm->unsafe |= AA_SECURE_X_NEEDED;
ceaf2cfb 2017+ }
9474138d 2018+apply:
76514441 2019+ target = new_profile->base.hname;
9474138d
AM
2020+ /* when transitioning profiles clear unsafe personality bits */
2021+ bprm->per_clear |= PER_CLEAR_ON_SETID;
2022+
76514441 2023+x_clear:
ceaf2cfb
AM
2024+ aa_put_profile(cxt->profile);
2025+ /* transfer new profile reference will be released when cxt is freed */
2026+ cxt->profile = new_profile;
9474138d 2027+
76514441 2028+ /* clear out all temporary/transitional state from the context */
ceaf2cfb
AM
2029+ aa_put_profile(cxt->previous);
2030+ aa_put_profile(cxt->onexec);
2031+ cxt->previous = NULL;
2032+ cxt->onexec = NULL;
2033+ cxt->token = 0;
9474138d
AM
2034+
2035+audit:
76514441
AM
2036+ error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
2037+ name, target, cond.uid, info, error);
9474138d
AM
2038+
2039+cleanup:
76514441 2040+ aa_put_profile(profile);
9474138d
AM
2041+ kfree(buffer);
2042+
76514441 2043+ return error;
9474138d
AM
2044+}
2045+
ceaf2cfb
AM
2046+/**
2047+ * apparmor_bprm_secureexec - determine if secureexec is needed
2048+ * @bprm: binprm for exec (NOT NULL)
2049+ *
2050+ * Returns: %1 if secureexec is needed else %0
2051+ */
9474138d
AM
2052+int apparmor_bprm_secureexec(struct linux_binprm *bprm)
2053+{
2054+ int ret = cap_bprm_secureexec(bprm);
2055+
2056+ /* the decision to use secure exec is computed in set_creds
ceaf2cfb 2057+ * and stored in bprm->unsafe.
9474138d
AM
2058+ */
2059+ if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
2060+ ret = 1;
2061+
2062+ return ret;
2063+}
2064+
ceaf2cfb
AM
2065+/**
2066+ * apparmor_bprm_committing_creds - do task cleanup on committing new creds
2067+ * @bprm: binprm for the exec (NOT NULL)
9474138d 2068+ */
ceaf2cfb 2069+void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
9474138d 2070+{
ceaf2cfb
AM
2071+ struct aa_profile *profile = __aa_current_profile();
2072+ struct aa_task_cxt *new_cxt = bprm->cred->security;
9474138d 2073+
ceaf2cfb
AM
2074+ /* bail out if unconfined or not changing profile */
2075+ if ((new_cxt->profile == profile) ||
2076+ (unconfined(new_cxt->profile)))
2077+ return;
9474138d
AM
2078+
2079+ current->pdeath_signal = 0;
2080+
2081+ /* reset soft limits and set hard limits for the new profile */
ceaf2cfb 2082+ __aa_transition_rlimits(profile, new_cxt->profile);
2380c486 2083+}
2380c486 2084+
ceaf2cfb
AM
2085+/**
2086+ * apparmor_bprm_commited_cred - do cleanup after new creds committed
2087+ * @bprm: binprm for the exec (NOT NULL)
2088+ */
9474138d
AM
2089+void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
2090+{
2091+ /* TODO: cleanup signals - ipc mediation */
2092+ return;
2093+}
2380c486 2094+
ceaf2cfb
AM
2095+/*
2096+ * Functions for self directed profile change
2097+ */
2098+
2099+/**
2100+ * new_compound_name - create an hname with @n2 appended to @n1
2101+ * @n1: base of hname (NOT NULL)
2102+ * @n2: name to append (NOT NULL)
2103+ *
2104+ * Returns: new name or NULL on error
2105+ */
2106+static char *new_compound_name(const char *n1, const char *n2)
2107+{
2108+ char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
2109+ if (name)
2110+ sprintf(name, "%s//%s", n1, n2);
2111+ return name;
2112+}
2113+
9474138d
AM
2114+/**
2115+ * aa_change_hat - change hat to/from subprofile
76514441 2116+ * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0)
ceaf2cfb 2117+ * @count: number of hat names in @hats
9474138d
AM
2118+ * @token: magic value to validate the hat change
2119+ * @permtest: true if this is just a permission test
2120+ *
ceaf2cfb
AM
2121+ * Change to the first profile specified in @hats that exists, and store
2122+ * the @hat_magic in the current task context. If the count == 0 and the
2123+ * @token matches that stored in the current task context, return to the
2124+ * top level profile.
2125+ *
9474138d
AM
2126+ * Returns %0 on success, error otherwise.
2127+ */
ceaf2cfb 2128+int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
9474138d
AM
2129+{
2130+ const struct cred *cred;
ceaf2cfb 2131+ struct aa_task_cxt *cxt;
9474138d 2132+ struct aa_profile *profile, *previous_profile, *hat = NULL;
0eaba94d 2133+ char *name = NULL;
ceaf2cfb 2134+ int i;
76514441
AM
2135+ struct file_perms perms = {};
2136+ const char *target = NULL, *info = NULL;
2137+ int error = 0;
2380c486 2138+
ceaf2cfb
AM
2139+ /* released below */
2140+ cred = get_current_cred();
9474138d 2141+ cxt = cred->security;
ceaf2cfb
AM
2142+ profile = aa_cred_profile(cred);
2143+ previous_profile = cxt->previous;
2380c486 2144+
ceaf2cfb 2145+ if (unconfined(profile)) {
76514441
AM
2146+ info = "unconfined";
2147+ error = -EPERM;
9474138d
AM
2148+ goto audit;
2149+ }
2380c486 2150+
ceaf2cfb
AM
2151+ if (count) {
2152+ /* attempting to change into a new hat or switch to a sibling */
2153+ struct aa_profile *root;
2154+ root = PROFILE_IS_HAT(profile) ? profile->parent : profile;
2380c486 2155+
ceaf2cfb
AM
2156+ /* find first matching hat */
2157+ for (i = 0; i < count && !hat; i++)
2158+ /* released below */
2159+ hat = aa_find_child(root, hats[i]);
9474138d 2160+ if (!hat) {
ceaf2cfb 2161+ if (!COMPLAIN_MODE(root) || permtest) {
ceaf2cfb 2162+ if (list_empty(&root->base.profiles))
76514441 2163+ error = -ECHILD;
ceaf2cfb 2164+ else
76514441 2165+ error = -ENOENT;
0eaba94d 2166+ goto out;
ceaf2cfb
AM
2167+ }
2168+
2169+ /*
2170+ * In complain mode and failed to match any hats.
76514441 2171+ * Audit the failure is based off of the first hat
ceaf2cfb
AM
2172+ * supplied. This is done due how userspace
2173+ * interacts with change_hat.
2174+ *
2175+ * TODO: Add logging of all failed hats
2176+ */
2177+
2178+ /* freed below */
2179+ name = new_compound_name(root->base.hname, hats[0]);
76514441 2180+ target = name;
ceaf2cfb
AM
2181+ /* released below */
2182+ hat = aa_new_null_profile(profile, 1);
9474138d 2183+ if (!hat) {
76514441
AM
2184+ info = "failed null profile create";
2185+ error = -ENOMEM;
9474138d
AM
2186+ goto audit;
2187+ }
0eaba94d 2188+ } else {
76514441 2189+ target = hat->base.hname;
0eaba94d 2190+ if (!PROFILE_IS_HAT(hat)) {
76514441
AM
2191+ info = "target not hat";
2192+ error = -EPERM;
0eaba94d
AM
2193+ goto audit;
2194+ }
9474138d 2195+ }
2380c486 2196+
76514441
AM
2197+ error = may_change_ptraced_domain(current, hat);
2198+ if (error) {
2199+ info = "ptraced";
2200+ error = -EPERM;
9474138d
AM
2201+ goto audit;
2202+ }
2203+
2204+ if (!permtest) {
76514441
AM
2205+ error = aa_set_current_hat(hat, token);
2206+ if (error == -EACCES)
2207+ /* kill task in case of brute force attacks */
2208+ perms.kill = AA_MAY_CHANGEHAT;
2209+ else if (name && !error)
0eaba94d 2210+ /* reset error for learning of new hats */
76514441 2211+ error = -ENOENT;
9474138d 2212+ }
0eaba94d 2213+ } else if (previous_profile) {
ceaf2cfb
AM
2214+ /* Return to saved profile. Kill task if restore fails
2215+ * to avoid brute force attacks
2216+ */
76514441
AM
2217+ target = previous_profile->base.hname;
2218+ error = aa_restore_previous_profile(token);
2219+ perms.kill = AA_MAY_CHANGEHAT;
ceaf2cfb
AM
2220+ } else
2221+ /* ignore restores when there is no saved profile */
2222+ goto out;
9474138d
AM
2223+
2224+audit:
2225+ if (!permtest)
76514441
AM
2226+ error = aa_audit_file(profile, &perms, GFP_KERNEL,
2227+ OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL,
2228+ target, 0, info, error);
9474138d 2229+
9474138d
AM
2230+out:
2231+ aa_put_profile(hat);
0eaba94d 2232+ kfree(name);
ceaf2cfb 2233+ put_cred(cred);
9474138d 2234+
76514441 2235+ return error;
9474138d
AM
2236+}
2237+
2238+/**
2239+ * aa_change_profile - perform a one-way profile transition
76514441
AM
2240+ * @ns_name: name of the profile namespace to change to (MAYBE NULL)
2241+ * @hname: name of profile to change to (MAYBE NULL)
9474138d
AM
2242+ * @onexec: whether this transition is to take place immediately or at exec
2243+ * @permtest: true if this is just a permission test
2380c486 2244+ *
9474138d 2245+ * Change to new profile @name. Unlike with hats, there is no way
76514441
AM
2246+ * to change back. If @name isn't specified the current profile name is
2247+ * used.
2248+ * If @onexec then the transition is delayed until
9474138d 2249+ * the next exec.
2380c486 2250+ *
9474138d 2251+ * Returns %0 on success, error otherwise.
2380c486 2252+ */
76514441 2253+int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
ceaf2cfb 2254+ bool permtest)
9474138d
AM
2255+{
2256+ const struct cred *cred;
ceaf2cfb 2257+ struct aa_task_cxt *cxt;
9474138d
AM
2258+ struct aa_profile *profile, *target = NULL;
2259+ struct aa_namespace *ns = NULL;
76514441
AM
2260+ struct file_perms perms = {};
2261+ const char *name = NULL, *info = NULL;
2262+ int op, error = 0;
2263+ u32 request;
2380c486 2264+
ceaf2cfb 2265+ if (!hname && !ns_name)
9474138d 2266+ return -EINVAL;
2380c486 2267+
76514441
AM
2268+ if (onexec) {
2269+ request = AA_MAY_ONEXEC;
2270+ op = OP_CHANGE_ONEXEC;
2271+ } else {
2272+ request = AA_MAY_CHANGE_PROFILE;
2273+ op = OP_CHANGE_PROFILE;
2274+ }
9474138d 2275+
ceaf2cfb 2276+ cred = get_current_cred();
9474138d 2277+ cxt = cred->security;
ceaf2cfb 2278+ profile = aa_cred_profile(cred);
9474138d
AM
2279+
2280+ if (ns_name) {
ceaf2cfb
AM
2281+ /* released below */
2282+ ns = aa_find_namespace(profile->ns, ns_name);
9474138d
AM
2283+ if (!ns) {
2284+ /* we don't create new namespace in complain mode */
76514441
AM
2285+ name = ns_name;
2286+ info = "namespace not found";
2287+ error = -ENOENT;
9474138d
AM
2288+ goto audit;
2289+ }
76514441 2290+ } else
ceaf2cfb
AM
2291+ /* released below */
2292+ ns = aa_get_namespace(profile->ns);
9474138d
AM
2293+
2294+ /* if the name was not specified, use the name of the current profile */
ceaf2cfb
AM
2295+ if (!hname) {
2296+ if (unconfined(profile))
2297+ hname = ns->unconfined->base.hname;
9474138d 2298+ else
ceaf2cfb 2299+ hname = profile->base.hname;
9474138d 2300+ }
9474138d 2301+
76514441
AM
2302+ perms = change_profile_perms(profile, ns, hname, request,
2303+ profile->file.start);
2304+ if (!(perms.allow & request)) {
2305+ error = -EACCES;
9474138d
AM
2306+ goto audit;
2307+ }
2308+
ceaf2cfb 2309+ /* released below */
76514441 2310+ target = aa_lookup_profile(ns, hname);
9474138d 2311+ if (!target) {
76514441
AM
2312+ info = "profile not found";
2313+ error = -ENOENT;
ceaf2cfb 2314+ if (permtest || !COMPLAIN_MODE(profile))
9474138d 2315+ goto audit;
76514441 2316+ /* released below */
ceaf2cfb
AM
2317+ target = aa_new_null_profile(profile, 0);
2318+ if (!target) {
76514441
AM
2319+ info = "failed null profile create";
2320+ error = -ENOMEM;
ceaf2cfb
AM
2321+ goto audit;
2322+ }
9474138d 2323+ }
ceaf2cfb 2324+
9474138d 2325+ /* check if tracing task is allowed to trace target domain */
76514441
AM
2326+ error = may_change_ptraced_domain(current, target);
2327+ if (error) {
2328+ info = "ptrace prevents transition";
9474138d
AM
2329+ goto audit;
2330+ }
2331+
2332+ if (permtest)
2333+ goto audit;
2334+
2335+ if (onexec)
76514441 2336+ error = aa_set_current_onexec(target);
9474138d 2337+ else
76514441 2338+ error = aa_replace_current_profile(target);
2380c486 2339+
9474138d
AM
2340+audit:
2341+ if (!permtest)
76514441
AM
2342+ error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request,
2343+ name, hname, 0, info, error);
9474138d
AM
2344+
2345+ aa_put_namespace(ns);
2346+ aa_put_profile(target);
ceaf2cfb 2347+ put_cred(cred);
9474138d 2348+
76514441 2349+ return error;
9474138d 2350+}
ceaf2cfb
AM
2351diff --git a/security/apparmor/file.c b/security/apparmor/file.c
2352new file mode 100644
76514441 2353index 0000000..7312db7
ceaf2cfb
AM
2354--- /dev/null
2355+++ b/security/apparmor/file.c
76514441 2356@@ -0,0 +1,457 @@
2380c486 2357+/*
9474138d
AM
2358+ * AppArmor security module
2359+ *
2360+ * This file contains AppArmor mediation of files
2361+ *
2362+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 2363+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
2364+ *
2365+ * This program is free software; you can redistribute it and/or
2366+ * modify it under the terms of the GNU General Public License as
2367+ * published by the Free Software Foundation, version 2 of the
2368+ * License.
2380c486 2369+ */
2380c486 2370+
9474138d
AM
2371+#include "include/apparmor.h"
2372+#include "include/audit.h"
2373+#include "include/file.h"
2374+#include "include/match.h"
2375+#include "include/path.h"
2376+#include "include/policy.h"
2377+
2378+struct file_perms nullperms;
2379+
76514441 2380+
ceaf2cfb 2381+/**
76514441
AM
2382+ * audit_file_mask - convert mask to permission string
2383+ * @buffer: buffer to write string to (NOT NULL)
ceaf2cfb 2384+ * @mask: permission mask to convert
ceaf2cfb 2385+ */
76514441 2386+static void audit_file_mask(struct audit_buffer *ab, u32 mask)
9474138d 2387+{
76514441
AM
2388+ char str[10];
2389+
2390+ char *m = str;
9474138d
AM
2391+
2392+ if (mask & AA_EXEC_MMAP)
2393+ *m++ = 'm';
76514441 2394+ if (mask & (MAY_READ | AA_MAY_META_READ))
9474138d 2395+ *m++ = 'r';
76514441
AM
2396+ if (mask & (MAY_WRITE | AA_MAY_META_WRITE | AA_MAY_CHMOD |
2397+ AA_MAY_CHOWN))
9474138d
AM
2398+ *m++ = 'w';
2399+ else if (mask & MAY_APPEND)
2400+ *m++ = 'a';
ceaf2cfb
AM
2401+ if (mask & AA_MAY_CREATE)
2402+ *m++ = 'c';
2403+ if (mask & AA_MAY_DELETE)
2404+ *m++ = 'd';
9474138d
AM
2405+ if (mask & AA_MAY_LINK)
2406+ *m++ = 'l';
2407+ if (mask & AA_MAY_LOCK)
2408+ *m++ = 'k';
ceaf2cfb 2409+ if (mask & MAY_EXEC)
9474138d 2410+ *m++ = 'x';
76514441 2411+ *m = '\0';
2380c486 2412+
ceaf2cfb 2413+ audit_log_string(ab, str);
9474138d 2414+}
2380c486 2415+
ceaf2cfb
AM
2416+/**
2417+ * file_audit_cb - call back for file specific audit fields
2418+ * @ab: audit_buffer (NOT NULL)
2419+ * @va: audit struct to audit values of (NOT NULL)
2420+ */
76514441 2421+static void file_audit_cb(struct audit_buffer *ab, void *va)
9474138d 2422+{
76514441
AM
2423+ struct common_audit_data *sa = va;
2424+ uid_t fsuid = current_fsuid();
2380c486 2425+
76514441 2426+ if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
ceaf2cfb 2427+ audit_log_format(ab, " requested_mask=");
76514441 2428+ audit_file_mask(ab, sa->aad.fs.request);
ceaf2cfb 2429+ }
76514441 2430+ if (sa->aad.fs.denied & AA_AUDIT_FILE_MASK) {
ceaf2cfb 2431+ audit_log_format(ab, " denied_mask=");
76514441 2432+ audit_file_mask(ab, sa->aad.fs.denied);
ceaf2cfb 2433+ }
76514441 2434+ if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
9474138d 2435+ audit_log_format(ab, " fsuid=%d", fsuid);
76514441 2436+ audit_log_format(ab, " ouid=%d", sa->aad.fs.ouid);
9474138d 2437+ }
2380c486 2438+
76514441
AM
2439+ if (sa->aad.fs.target) {
2440+ audit_log_format(ab, " target=");
2441+ audit_log_untrustedstring(ab, sa->aad.fs.target);
9474138d
AM
2442+ }
2443+}
2380c486 2444+
ceaf2cfb
AM
2445+/**
2446+ * aa_audit_file - handle the auditing of file operations
2447+ * @profile: the profile being enforced (NOT NULL)
76514441
AM
2448+ * @perms: the permissions computed for the request (NOT NULL)
2449+ * @gfp: allocation flags
2450+ * @op: operation being mediated
2451+ * @request: permissions requested
2452+ * @name: name of object being mediated (MAYBE NULL)
2453+ * @target: name of target (MAYBE NULL)
2454+ * @ouid: object uid
2455+ * @info: extra information message (MAYBE NULL)
2456+ * @error: 0 if operation allowed else failure error code
ceaf2cfb
AM
2457+ *
2458+ * Returns: %0 or error on failure
2459+ */
76514441
AM
2460+int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
2461+ gfp_t gfp, int op, u32 request, const char *name,
2462+ const char *target, uid_t ouid, const char *info, int error)
9474138d
AM
2463+{
2464+ int type = AUDIT_APPARMOR_AUTO;
76514441
AM
2465+ struct common_audit_data sa;
2466+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
2467+ sa.aad.op = op,
2468+ sa.aad.fs.request = request;
2469+ sa.aad.name = name;
2470+ sa.aad.fs.target = target;
2471+ sa.aad.fs.ouid = ouid;
2472+ sa.aad.info = info;
2473+ sa.aad.error = error;
2474+
2475+ if (likely(!sa.aad.error)) {
2476+ u32 mask = perms->audit;
2380c486 2477+
ceaf2cfb 2478+ if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
9474138d 2479+ mask = 0xffff;
2380c486 2480+
9474138d 2481+ /* mask off perms that are not being force audited */
76514441 2482+ sa.aad.fs.request &= mask;
2380c486 2483+
76514441 2484+ if (likely(!sa.aad.fs.request))
9474138d 2485+ return 0;
5e665963 2486+ type = AUDIT_APPARMOR_AUDIT;
9474138d 2487+ } else {
ceaf2cfb 2488+ /* only report permissions that were denied */
76514441 2489+ sa.aad.fs.request = sa.aad.fs.request & ~perms->allow;
2380c486 2490+
76514441 2491+ if (sa.aad.fs.request & perms->kill)
9474138d 2492+ type = AUDIT_APPARMOR_KILL;
2380c486 2493+
ceaf2cfb 2494+ /* quiet known rejects, assumes quiet and kill do not overlap */
76514441 2495+ if ((sa.aad.fs.request & perms->quiet) &&
ceaf2cfb
AM
2496+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
2497+ AUDIT_MODE(profile) != AUDIT_ALL)
76514441 2498+ sa.aad.fs.request &= ~perms->quiet;
2380c486 2499+
76514441
AM
2500+ if (!sa.aad.fs.request)
2501+ return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
9474138d 2502+ }
76514441
AM
2503+
2504+ sa.aad.fs.denied = sa.aad.fs.request & ~perms->allow;
2505+ return aa_audit(type, profile, gfp, &sa, file_audit_cb);
2506+}
2507+
2508+/**
2509+ * map_old_perms - map old file perms layout to the new layout
2510+ * @old: permission set in old mapping
2511+ *
2512+ * Returns: new permission mapping
2513+ */
2514+static u32 map_old_perms(u32 old)
2515+{
2516+ u32 new = old & 0xf;
2517+ if (old & MAY_READ)
2518+ new |= AA_MAY_META_READ;
2519+ if (old & MAY_WRITE)
2520+ new |= AA_MAY_META_WRITE | AA_MAY_CREATE | AA_MAY_DELETE |
2521+ AA_MAY_CHMOD | AA_MAY_CHOWN;
2522+ if (old & 0x10)
2523+ new |= AA_MAY_LINK;
2524+ /* the old mapping lock and link_subset flags where overlaid
2525+ * and use was determined by part of a pair that they were in
2526+ */
2527+ if (old & 0x20)
2528+ new |= AA_MAY_LOCK | AA_LINK_SUBSET;
2529+ if (old & 0x40) /* AA_EXEC_MMAP */
2530+ new |= AA_EXEC_MMAP;
2531+
2532+ new |= AA_MAY_META_READ;
2533+
2534+ return new;
9474138d 2535+}
2380c486 2536+
ceaf2cfb 2537+/**
76514441 2538+ * compute_perms - convert dfa compressed perms to internal perms
ceaf2cfb
AM
2539+ * @dfa: dfa to compute perms for (NOT NULL)
2540+ * @state: state in dfa
2541+ * @cond: conditions to consider (NOT NULL)
2542+ *
2543+ * TODO: convert from dfa + state to permission entry, do computation conversion
2544+ * at load time.
2545+ *
2546+ * Returns: computed permission set
2547+ */
76514441
AM
2548+static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state,
2549+ struct path_cond *cond)
9474138d
AM
2550+{
2551+ struct file_perms perms;
2380c486 2552+
ceaf2cfb
AM
2553+ /* FIXME: change over to new dfa format
2554+ * currently file perms are encoded in the dfa, new format
2555+ * splits the permissions from the dfa. This mapping can be
2556+ * done at profile load
2557+ */
9474138d 2558+ perms.kill = 0;
2380c486 2559+
9474138d 2560+ if (current_fsuid() == cond->uid) {
76514441
AM
2561+ perms.allow = map_old_perms(dfa_user_allow(dfa, state));
2562+ perms.audit = map_old_perms(dfa_user_audit(dfa, state));
2563+ perms.quiet = map_old_perms(dfa_user_quiet(dfa, state));
9474138d
AM
2564+ perms.xindex = dfa_user_xindex(dfa, state);
2565+ } else {
76514441
AM
2566+ perms.allow = map_old_perms(dfa_other_allow(dfa, state));
2567+ perms.audit = map_old_perms(dfa_other_audit(dfa, state));
2568+ perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
9474138d
AM
2569+ perms.xindex = dfa_other_xindex(dfa, state);
2570+ }
2380c486 2571+
9474138d 2572+ /* change_profile wasn't determined by ownership in old mapping */
5e665963 2573+ if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
76514441 2574+ perms.allow |= AA_MAY_CHANGE_PROFILE;
2380c486 2575+
9474138d
AM
2576+ return perms;
2577+}
2380c486 2578+
ceaf2cfb
AM
2579+/**
2580+ * aa_str_perms - find permission that match @name
76514441 2581+ * @dfa: to match against (MAYBE NULL)
ceaf2cfb
AM
2582+ * @state: state to start matching in
2583+ * @name: string to match against dfa (NOT NULL)
2584+ * @cond: conditions to consider for permission set computation (NOT NULL)
76514441 2585+ * @perms: Returns - the permissions found when matching @name
ceaf2cfb 2586+ *
76514441 2587+ * Returns: the final state in @dfa when beginning @start and walking @name
ceaf2cfb 2588+ */
76514441
AM
2589+unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
2590+ const char *name, struct path_cond *cond,
2591+ struct file_perms *perms)
9474138d
AM
2592+{
2593+ unsigned int state;
76514441
AM
2594+ if (!dfa) {
2595+ *perms = nullperms;
2596+ return DFA_NOMATCH;
2597+ }
2380c486 2598+
9474138d 2599+ state = aa_dfa_match(dfa, start, name);
76514441 2600+ *perms = compute_perms(dfa, state, cond);
2380c486 2601+
76514441 2602+ return state;
9474138d 2603+}
2380c486 2604+
ceaf2cfb 2605+/**
76514441
AM
2606+ * is_deleted - test if a file has been completely unlinked
2607+ * @dentry: dentry of file to test for deletion (NOT NULL)
ceaf2cfb 2608+ *
76514441 2609+ * Returns: %1 if deleted else %0
ceaf2cfb 2610+ */
76514441 2611+static inline bool is_deleted(struct dentry *dentry)
9474138d 2612+{
76514441
AM
2613+ if (d_unlinked(dentry) && dentry->d_inode->i_nlink == 0)
2614+ return 1;
2615+ return 0;
9474138d 2616+}
2380c486 2617+
ceaf2cfb
AM
2618+/**
2619+ * aa_path_perm - do permissions check & audit for @path
76514441 2620+ * @op: operation being checked
ceaf2cfb 2621+ * @profile: profile being enforced (NOT NULL)
ceaf2cfb 2622+ * @path: path to check permissions of (NOT NULL)
76514441 2623+ * @flags: any additional path flags beyond what the profile specifies
ceaf2cfb
AM
2624+ * @request: requested permissions
2625+ * @cond: conditional info for this request (NOT NULL)
2626+ *
2627+ * Returns: %0 else error if access denied or other error
2628+ */
76514441
AM
2629+int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
2630+ int flags, u32 request, struct path_cond *cond)
9474138d 2631+{
76514441
AM
2632+ char *buffer = NULL;
2633+ struct file_perms perms = {};
2634+ const char *name, *info = NULL;
2635+ int error;
2636+
2637+ flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
2638+ error = aa_get_name(path, flags, &buffer, &name);
2639+ if (error) {
2640+ if (error == -ENOENT && is_deleted(path->dentry)) {
2641+ /* Access to open files that are deleted are
2642+ * give a pass (implicit delegation)
2643+ */
2644+ error = 0;
2645+ perms.allow = request;
2646+ } else if (error == -ENOENT)
2647+ info = "Failed name lookup - deleted entry";
2648+ else if (error == -ESTALE)
2649+ info = "Failed name lookup - disconnected path";
2650+ else if (error == -ENAMETOOLONG)
2651+ info = "Failed name lookup - name too long";
9474138d 2652+ else
76514441 2653+ info = "Failed name lookup";
9474138d 2654+ } else {
76514441
AM
2655+ aa_str_perms(profile->file.dfa, profile->file.start, name, cond,
2656+ &perms);
2657+ if (request & ~perms.allow)
2658+ error = -EACCES;
9474138d 2659+ }
76514441
AM
2660+ error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request, name,
2661+ NULL, cond->uid, info, error);
9474138d 2662+ kfree(buffer);
2380c486 2663+
76514441 2664+ return error;
9474138d 2665+}
2380c486 2666+
ceaf2cfb
AM
2667+/**
2668+ * xindex_is_subset - helper for aa_path_link
2669+ * @link: link permission set
2670+ * @target: target permission set
2671+ *
2672+ * test target x permissions are equal OR a subset of link x permissions
2673+ * this is done as part of the subset test, where a hardlink must have
2674+ * a subset of permissions that the target has.
2675+ *
2676+ * Returns: %1 if subset else %0
2677+ */
76514441 2678+static inline bool xindex_is_subset(u32 link, u32 target)
ceaf2cfb
AM
2679+{
2680+ if (((link & ~AA_X_UNSAFE) != (target & ~AA_X_UNSAFE)) ||
2681+ ((link & AA_X_UNSAFE) && !(target & AA_X_UNSAFE)))
2682+ return 0;
2683+
2684+ return 1;
2685+}
2686+
2687+/**
2688+ * aa_path_link - Handle hard link permission check
2689+ * @profile: the profile being enforced (NOT NULL)
2690+ * @old_dentry: the target dentry (NOT NULL)
2691+ * @new_dir: directory the new link will be created in (NOT NULL)
2692+ * @new_dentry: the link being created (NOT NULL)
2693+ *
2694+ * Handle the permission test for a link & target pair. Permission
2695+ * is encoded as a pair where the link permission is determined
2696+ * first, and if allowed, the target is tested. The target test
2697+ * is done from the point of the link match (not start of DFA)
2698+ * making the target permission dependent on the link permission match.
2699+ *
2700+ * The subset test if required forces that permissions granted
2701+ * on link are a subset of the permission granted to target.
2702+ *
2703+ * Returns: %0 if allowed else error
2704+ */
9474138d
AM
2705+int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
2706+ struct path *new_dir, struct dentry *new_dentry)
2707+{
2708+ struct path link = { new_dir->mnt, new_dentry };
2709+ struct path target = { new_dir->mnt, old_dentry };
ceaf2cfb
AM
2710+ struct path_cond cond = {
2711+ old_dentry->d_inode->i_uid,
2712+ old_dentry->d_inode->i_mode
2713+ };
9474138d 2714+ char *buffer = NULL, *buffer2 = NULL;
76514441
AM
2715+ const char *lname, *tname = NULL, *info = NULL;
2716+ struct file_perms lperms, perms;
2717+ u32 request = AA_MAY_LINK;
9474138d 2718+ unsigned int state;
76514441
AM
2719+ int error;
2720+
2721+ lperms = nullperms;
2380c486 2722+
ceaf2cfb 2723+ /* buffer freed below, lname is pointer in buffer */
76514441
AM
2724+ error = aa_get_name(&link, profile->path_flags, &buffer, &lname);
2725+ if (error)
9474138d 2726+ goto audit;
2380c486 2727+
ceaf2cfb 2728+ /* buffer2 freed below, tname is pointer in buffer2 */
76514441
AM
2729+ error = aa_get_name(&target, profile->path_flags, &buffer2, &tname);
2730+ if (error)
9474138d 2731+ goto audit;
2380c486 2732+
76514441 2733+ error = -EACCES;
ceaf2cfb 2734+ /* aa_str_perms - handles the case of the dfa being NULL */
76514441
AM
2735+ state = aa_str_perms(profile->file.dfa, profile->file.start, lname,
2736+ &cond, &lperms);
2380c486 2737+
76514441 2738+ if (!(lperms.allow & AA_MAY_LINK))
9474138d 2739+ goto audit;
2380c486 2740+
9474138d 2741+ /* test to see if target can be paired with link */
76514441
AM
2742+ state = aa_dfa_null_transition(profile->file.dfa, state);
2743+ aa_str_perms(profile->file.dfa, state, tname, &cond, &perms);
2744+
2745+ /* force audit/quiet masks for link are stored in the second entry
2746+ * in the link pair.
2747+ */
2748+ lperms.audit = perms.audit;
2749+ lperms.quiet = perms.quiet;
2750+ lperms.kill = perms.kill;
2751+
2752+ if (!(perms.allow & AA_MAY_LINK)) {
2753+ info = "target restricted";
9474138d
AM
2754+ goto audit;
2755+ }
2380c486 2756+
9474138d 2757+ /* done if link subset test is not required */
76514441 2758+ if (!(perms.allow & AA_LINK_SUBSET))
ceaf2cfb 2759+ goto done_tests;
2380c486 2760+
9474138d
AM
2761+ /* Do link perm subset test requiring allowed permission on link are a
2762+ * subset of the allowed permissions on target.
2763+ */
76514441
AM
2764+ aa_str_perms(profile->file.dfa, profile->file.start, tname, &cond,
2765+ &perms);
2380c486 2766+
9474138d 2767+ /* AA_MAY_LINK is not considered in the subset test */
76514441
AM
2768+ request = lperms.allow & ~AA_MAY_LINK;
2769+ lperms.allow &= perms.allow | AA_MAY_LINK;
9474138d 2770+
76514441
AM
2771+ request |= AA_AUDIT_FILE_MASK & (lperms.allow & ~perms.allow);
2772+ if (request & ~lperms.allow) {
ceaf2cfb 2773+ goto audit;
76514441
AM
2774+ } else if ((lperms.allow & MAY_EXEC) &&
2775+ !xindex_is_subset(lperms.xindex, perms.xindex)) {
2776+ lperms.allow &= ~MAY_EXEC;
2777+ request |= MAY_EXEC;
2778+ info = "link not subset of target";
ceaf2cfb 2779+ goto audit;
9474138d 2780+ }
2380c486 2781+
ceaf2cfb 2782+done_tests:
76514441 2783+ error = 0;
ceaf2cfb 2784+
9474138d 2785+audit:
76514441
AM
2786+ error = aa_audit_file(profile, &lperms, GFP_KERNEL, OP_LINK, request,
2787+ lname, tname, cond.uid, info, error);
9474138d
AM
2788+ kfree(buffer);
2789+ kfree(buffer2);
2380c486 2790+
76514441 2791+ return error;
9474138d 2792+}
2380c486 2793+
ceaf2cfb 2794+/**
76514441
AM
2795+ * aa_file_perm - do permission revalidation check & audit for @file
2796+ * @op: operation being checked
ceaf2cfb 2797+ * @profile: profile being enforced (NOT NULL)
76514441 2798+ * @file: file to revalidate access permissions on (NOT NULL)
ceaf2cfb 2799+ * @request: requested permissions
ceaf2cfb 2800+ *
76514441 2801+ * Returns: %0 if access allowed else error
ceaf2cfb 2802+ */
76514441
AM
2803+int aa_file_perm(int op, struct aa_profile *profile, struct file *file,
2804+ u32 request)
9474138d 2805+{
ceaf2cfb
AM
2806+ struct path_cond cond = {
2807+ .uid = file->f_path.dentry->d_inode->i_uid,
2808+ .mode = file->f_path.dentry->d_inode->i_mode
2809+ };
2380c486 2810+
76514441
AM
2811+ return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED,
2812+ request, &cond);
2380c486 2813+}
ceaf2cfb
AM
2814diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
2815new file mode 100644
76514441 2816index 0000000..38ccaea
ceaf2cfb
AM
2817--- /dev/null
2818+++ b/security/apparmor/include/apparmor.h
76514441 2819@@ -0,0 +1,92 @@
9474138d
AM
2820+/*
2821+ * AppArmor security module
2822+ *
2823+ * This file contains AppArmor basic global and lib definitions
2824+ *
2825+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 2826+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
2827+ *
2828+ * This program is free software; you can redistribute it and/or
2829+ * modify it under the terms of the GNU General Public License as
2830+ * published by the Free Software Foundation, version 2 of the
2831+ * License.
2832+ */
2380c486 2833+
9474138d
AM
2834+#ifndef __APPARMOR_H
2835+#define __APPARMOR_H
2380c486 2836+
9474138d 2837+#include <linux/fs.h>
2380c486 2838+
ceaf2cfb
AM
2839+#include "match.h"
2840+
76514441 2841+/* Control parameters settable through module/boot flags */
ceaf2cfb
AM
2842+extern enum audit_mode aa_g_audit;
2843+extern int aa_g_audit_header;
2844+extern int aa_g_debug;
2845+extern int aa_g_lock_policy;
2846+extern int aa_g_logsyscall;
2847+extern int aa_g_paranoid_load;
2848+extern unsigned int aa_g_path_max;
2380c486 2849+
9474138d
AM
2850+/*
2851+ * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
2852+ * which is not related to profile accesses.
2853+ */
2380c486 2854+
9474138d
AM
2855+#define AA_DEBUG(fmt, args...) \
2856+ do { \
ceaf2cfb 2857+ if (aa_g_debug && printk_ratelimit()) \
9474138d
AM
2858+ printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
2859+ } while (0)
2380c486 2860+
9474138d
AM
2861+#define AA_ERROR(fmt, args...) \
2862+ do { \
2863+ if (printk_ratelimit()) \
2864+ printk(KERN_ERR "AppArmor: " fmt, ##args); \
2865+ } while (0)
2866+
2867+/* Flag indicating whether initialization completed */
76514441 2868+extern int apparmor_initialized __initdata;
2380c486 2869+
9474138d 2870+/* fn's in lib */
ceaf2cfb 2871+char *aa_split_fqname(char *args, char **ns_name);
ceaf2cfb 2872+void aa_info_message(const char *str);
76514441
AM
2873+void *kvmalloc(size_t size);
2874+void kvfree(void *buffer);
2875+
2876+
2877+/**
2878+ * aa_strneq - compare null terminated @str to a non null terminated substring
2879+ * @str: a null terminated string
2880+ * @sub: a substring, not necessarily null terminated
2881+ * @len: length of @sub to compare
2882+ *
2883+ * The @str string must be full consumed for this to be considered a match
2884+ */
2885+static inline bool aa_strneq(const char *str, const char *sub, int len)
2886+{
2887+ return !strncmp(str, sub, len) && !str[len];
2888+}
ceaf2cfb
AM
2889+
2890+/**
2891+ * aa_dfa_null_transition - step to next state after null character
2892+ * @dfa: the dfa to match against
2893+ * @start: the state of the dfa to start matching in
ceaf2cfb
AM
2894+ *
2895+ * aa_dfa_null_transition transitions to the next state after a null
2896+ * character which is not used in standard matching and is only
76514441 2897+ * used to separate pairs.
ceaf2cfb
AM
2898+ */
2899+static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
76514441 2900+ unsigned int start)
ceaf2cfb 2901+{
76514441
AM
2902+ /* the null transition only needs the string's null terminator byte */
2903+ return aa_dfa_match_len(dfa, start, "", 1);
ceaf2cfb 2904+}
2380c486 2905+
ceaf2cfb 2906+static inline bool mediated_filesystem(struct inode *inode)
2380c486 2907+{
9474138d 2908+ return !(inode->i_sb->s_flags & MS_NOUSER);
2380c486
JR
2909+}
2910+
ceaf2cfb
AM
2911+#endif /* __APPARMOR_H */
2912diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
2913new file mode 100644
76514441 2914index 0000000..14f955c
ceaf2cfb
AM
2915--- /dev/null
2916+++ b/security/apparmor/include/apparmorfs.h
76514441 2917@@ -0,0 +1,26 @@
ceaf2cfb
AM
2918+/*
2919+ * AppArmor security module
2920+ *
2921+ * This file contains AppArmor filesystem definitions.
2922+ *
2923+ * Copyright (C) 1998-2008 Novell/SUSE
2924+ * Copyright 2009-2010 Canonical Ltd.
2925+ *
2926+ * This program is free software; you can redistribute it and/or
2927+ * modify it under the terms of the GNU General Public License as
2928+ * published by the Free Software Foundation, version 2 of the
2929+ * License.
2930+ */
2931+
2932+#ifndef __AA_APPARMORFS_H
2933+#define __AA_APPARMORFS_H
2934+
76514441 2935+extern void __init aa_destroy_aafs(void);
ceaf2cfb
AM
2936+
2937+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
2938+extern const struct file_operations aa_fs_matching_fops;
2939+extern const struct file_operations aa_fs_features_fops;
76514441 2940+extern const struct file_operations aa_fs_profiles_fops;
ceaf2cfb 2941+#endif
2380c486 2942+
ceaf2cfb
AM
2943+#endif /* __AA_APPARMORFS_H */
2944diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
2945new file mode 100644
76514441 2946index 0000000..1951786
ceaf2cfb
AM
2947--- /dev/null
2948+++ b/security/apparmor/include/audit.h
76514441 2949@@ -0,0 +1,123 @@
9474138d
AM
2950+/*
2951+ * AppArmor security module
2952+ *
2953+ * This file contains AppArmor auditing function definitions.
2954+ *
2955+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 2956+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
2957+ *
2958+ * This program is free software; you can redistribute it and/or
2959+ * modify it under the terms of the GNU General Public License as
2960+ * published by the Free Software Foundation, version 2 of the
2961+ * License.
2962+ */
2380c486 2963+
9474138d
AM
2964+#ifndef __AA_AUDIT_H
2965+#define __AA_AUDIT_H
2380c486 2966+
9474138d
AM
2967+#include <linux/audit.h>
2968+#include <linux/fs.h>
76514441 2969+#include <linux/lsm_audit.h>
9474138d
AM
2970+#include <linux/sched.h>
2971+#include <linux/slab.h>
2380c486 2972+
76514441
AM
2973+#include "file.h"
2974+
9474138d 2975+struct aa_profile;
2380c486 2976+
9474138d
AM
2977+extern const char *audit_mode_names[];
2978+#define AUDIT_MAX_INDEX 5
2380c486 2979+
9474138d 2980+#define AUDIT_APPARMOR_AUTO 0 /* auto choose audit message type */
2380c486 2981+
9474138d
AM
2982+enum audit_mode {
2983+ AUDIT_NORMAL, /* follow normal auditing of accesses */
2984+ AUDIT_QUIET_DENIED, /* quiet all denied access messages */
2985+ AUDIT_QUIET, /* quiet all messages */
2986+ AUDIT_NOQUIET, /* do not quiet audit messages */
2987+ AUDIT_ALL /* audit all accesses */
2380c486
JR
2988+};
2989+
76514441
AM
2990+enum audit_type {
2991+ AUDIT_APPARMOR_AUDIT,
2992+ AUDIT_APPARMOR_ALLOWED,
2993+ AUDIT_APPARMOR_DENIED,
2994+ AUDIT_APPARMOR_HINT,
2995+ AUDIT_APPARMOR_STATUS,
2996+ AUDIT_APPARMOR_ERROR,
2997+ AUDIT_APPARMOR_KILL
9474138d 2998+};
2380c486 2999+
76514441
AM
3000+extern const char *op_table[];
3001+enum aa_ops {
3002+ OP_NULL,
3003+
3004+ OP_SYSCTL,
3005+ OP_CAPABLE,
3006+
3007+ OP_UNLINK,
3008+ OP_MKDIR,
3009+ OP_RMDIR,
3010+ OP_MKNOD,
3011+ OP_TRUNC,
3012+ OP_LINK,
3013+ OP_SYMLINK,
3014+ OP_RENAME_SRC,
3015+ OP_RENAME_DEST,
3016+ OP_CHMOD,
3017+ OP_CHOWN,
3018+ OP_GETATTR,
3019+ OP_OPEN,
3020+
3021+ OP_FPERM,
3022+ OP_FLOCK,
3023+ OP_FMMAP,
3024+ OP_FMPROT,
3025+
3026+ OP_CREATE,
3027+ OP_POST_CREATE,
3028+ OP_BIND,
3029+ OP_CONNECT,
3030+ OP_LISTEN,
3031+ OP_ACCEPT,
3032+ OP_SENDMSG,
3033+ OP_RECVMSG,
3034+ OP_GETSOCKNAME,
3035+ OP_GETPEERNAME,
3036+ OP_GETSOCKOPT,
3037+ OP_SETSOCKOPT,
3038+ OP_SOCK_SHUTDOWN,
3039+
3040+ OP_PTRACE,
3041+
3042+ OP_EXEC,
3043+ OP_CHANGE_HAT,
3044+ OP_CHANGE_PROFILE,
3045+ OP_CHANGE_ONEXEC,
3046+
3047+ OP_SETPROCATTR,
3048+ OP_SETRLIMIT,
3049+
3050+ OP_PROF_REPL,
3051+ OP_PROF_LOAD,
3052+ OP_PROF_RM,
3053+};
3054+
3055+
3056+/* define a short hand for apparmor_audit_data portion of common_audit_data */
3057+#define aad apparmor_audit_data
3058+
3059+void aa_audit_msg(int type, struct common_audit_data *sa,
3060+ void (*cb) (struct audit_buffer *, void *));
3061+int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
3062+ struct common_audit_data *sa,
3063+ void (*cb) (struct audit_buffer *, void *));
3064+
3065+static inline int complain_error(int error)
3066+{
3067+ if (error == -EPERM || error == -EACCES)
3068+ return 0;
3069+ return error;
3070+}
ceaf2cfb
AM
3071+
3072+#endif /* __AA_AUDIT_H */
3073diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
3074new file mode 100644
76514441 3075index 0000000..c24d295
ceaf2cfb
AM
3076--- /dev/null
3077+++ b/security/apparmor/include/capability.h
9474138d
AM
3078@@ -0,0 +1,45 @@
3079+/*
3080+ * AppArmor security module
3081+ *
3082+ * This file contains AppArmor capability mediation definitions.
3083+ *
3084+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 3085+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
3086+ *
3087+ * This program is free software; you can redistribute it and/or
3088+ * modify it under the terms of the GNU General Public License as
3089+ * published by the Free Software Foundation, version 2 of the
3090+ * License.
3091+ */
3092+
3093+#ifndef __AA_CAPABILITY_H
3094+#define __AA_CAPABILITY_H
3095+
3096+#include <linux/sched.h>
3097+
3098+struct aa_profile;
3099+
3100+/* aa_caps - confinement data for capabilities
ceaf2cfb
AM
3101+ * @allowed: capabilities mask
3102+ * @audit: caps that are to be audited
3103+ * @quiet: caps that should not be audited
3104+ * @kill: caps that when requested will result in the task being killed
3105+ * @extended: caps that are subject finer grained mediation
9474138d
AM
3106+ */
3107+struct aa_caps {
76514441 3108+ kernel_cap_t allow;
9474138d
AM
3109+ kernel_cap_t audit;
3110+ kernel_cap_t quiet;
3111+ kernel_cap_t kill;
ceaf2cfb 3112+ kernel_cap_t extended;
2380c486
JR
3113+};
3114+
9474138d
AM
3115+int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
3116+ int audit);
2380c486 3117+
9474138d 3118+static inline void aa_free_cap_rules(struct aa_caps *caps)
2380c486 3119+{
9474138d 3120+ /* NOP */
2380c486
JR
3121+}
3122+
ceaf2cfb
AM
3123+#endif /* __AA_CAPBILITY_H */
3124diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h
3125new file mode 100644
76514441 3126index 0000000..a9cbee4
ceaf2cfb
AM
3127--- /dev/null
3128+++ b/security/apparmor/include/context.h
3129@@ -0,0 +1,154 @@
9474138d
AM
3130+/*
3131+ * AppArmor security module
3132+ *
3133+ * This file contains AppArmor contexts used to associate "labels" to objects.
3134+ *
3135+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 3136+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
3137+ *
3138+ * This program is free software; you can redistribute it and/or
3139+ * modify it under the terms of the GNU General Public License as
3140+ * published by the Free Software Foundation, version 2 of the
3141+ * License.
3142+ */
2380c486 3143+
9474138d
AM
3144+#ifndef __AA_CONTEXT_H
3145+#define __AA_CONTEXT_H
2380c486 3146+
9474138d
AM
3147+#include <linux/cred.h>
3148+#include <linux/slab.h>
3149+#include <linux/sched.h>
2380c486 3150+
9474138d
AM
3151+#include "policy.h"
3152+
9474138d 3153+/* struct aa_file_cxt - the AppArmor context the file was opened in
9474138d 3154+ * @perms: the permission the file was opened with
76514441
AM
3155+ *
3156+ * The file_cxt could currently be directly stored in file->f_security
3157+ * as the profile reference is now stored in the f_cred. However the
3158+ * cxt struct will expand in the future so we keep the struct.
9474138d
AM
3159+ */
3160+struct aa_file_cxt {
76514441 3161+ u16 allow;
9474138d
AM
3162+};
3163+
ceaf2cfb
AM
3164+/**
3165+ * aa_alloc_file_context - allocate file_cxt
3166+ * @gfp: gfp flags for allocation
3167+ *
3168+ * Returns: file_cxt or NULL on failure
3169+ */
9474138d 3170+static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp)
2380c486 3171+{
9474138d 3172+ return kzalloc(sizeof(struct aa_file_cxt), gfp);
2380c486
JR
3173+}
3174+
ceaf2cfb
AM
3175+/**
3176+ * aa_free_file_context - free a file_cxt
3177+ * @cxt: file_cxt to free (MAYBE_NULL)
3178+ */
9474138d 3179+static inline void aa_free_file_context(struct aa_file_cxt *cxt)
2380c486 3180+{
76514441 3181+ if (cxt)
ceaf2cfb 3182+ kzfree(cxt);
9474138d 3183+}
2380c486 3184+
ceaf2cfb
AM
3185+/**
3186+ * struct aa_task_cxt - primary label for confined tasks
3187+ * @profile: the current profile (NOT NULL)
3188+ * @exec: profile to transition to on next exec (MAYBE NULL)
3189+ * @previous: profile the task may return to (MAYBE NULL)
9474138d 3190+ * @token: magic value the task must know for returning to @previous_profile
2380c486 3191+ *
9474138d
AM
3192+ * Contains the task's current profile (which could change due to
3193+ * change_hat). Plus the hat_magic needed during change_hat.
ceaf2cfb
AM
3194+ *
3195+ * TODO: make so a task can be confined by a stack of contexts
2380c486 3196+ */
ceaf2cfb 3197+struct aa_task_cxt {
9474138d
AM
3198+ struct aa_profile *profile;
3199+ struct aa_profile *onexec;
3200+ struct aa_profile *previous;
3201+ u64 token;
3202+};
2380c486 3203+
ceaf2cfb
AM
3204+struct aa_task_cxt *aa_alloc_task_context(gfp_t flags);
3205+void aa_free_task_context(struct aa_task_cxt *cxt);
3206+void aa_dup_task_context(struct aa_task_cxt *new,
3207+ const struct aa_task_cxt *old);
76514441 3208+int aa_replace_current_profile(struct aa_profile *profile);
ceaf2cfb 3209+int aa_set_current_onexec(struct aa_profile *profile);
9474138d
AM
3210+int aa_set_current_hat(struct aa_profile *profile, u64 token);
3211+int aa_restore_previous_profile(u64 cookie);
2380c486 3212+
9474138d
AM
3213+/**
3214+ * __aa_task_is_confined - determine if @task has any confinement
ceaf2cfb 3215+ * @task: task to check confinement of (NOT NULL)
9474138d 3216+ *
ceaf2cfb 3217+ * If @task != current needs to be called in RCU safe critical section
9474138d 3218+ */
ceaf2cfb 3219+static inline bool __aa_task_is_confined(struct task_struct *task)
2380c486 3220+{
ceaf2cfb 3221+ struct aa_task_cxt *cxt = __task_cred(task)->security;
2380c486 3222+
ceaf2cfb
AM
3223+ BUG_ON(!cxt || !cxt->profile);
3224+ if (unconfined(aa_newest_version(cxt->profile)))
3225+ return 0;
2380c486 3226+
ceaf2cfb 3227+ return 1;
2380c486
JR
3228+}
3229+
ceaf2cfb
AM
3230+/**
3231+ * aa_cred_profile - obtain cred's profiles
3232+ * @cred: cred to obtain profiles from (NOT NULL)
3233+ *
3234+ * Returns: confining profile
3235+ *
3236+ * does NOT increment reference count
3237+ */
3238+static inline struct aa_profile *aa_cred_profile(const struct cred *cred)
2380c486 3239+{
ceaf2cfb
AM
3240+ struct aa_task_cxt *cxt = cred->security;
3241+ BUG_ON(!cxt || !cxt->profile);
3242+ return aa_newest_version(cxt->profile);
9474138d 3243+}
2380c486 3244+
ceaf2cfb
AM
3245+/**
3246+ * __aa_current_profile - find the current tasks confining profile
3247+ *
3248+ * Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
3249+ *
3250+ * This fn will not update the tasks cred to the most up to date version
3251+ * of the profile so it is safe to call when inside of locks.
3252+ */
3253+static inline struct aa_profile *__aa_current_profile(void)
2380c486 3254+{
ceaf2cfb 3255+ return aa_cred_profile(current_cred());
2380c486
JR
3256+}
3257+
ceaf2cfb
AM
3258+/**
3259+ * aa_current_profile - find the current tasks confining profile and do updates
3260+ *
3261+ * Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
3262+ *
3263+ * This fn will update the tasks cred structure if the profile has been
3264+ * replaced. Not safe to call inside locks
3265+ */
9474138d 3266+static inline struct aa_profile *aa_current_profile(void)
2380c486 3267+{
ceaf2cfb
AM
3268+ const struct aa_task_cxt *cxt = current_cred()->security;
3269+ struct aa_profile *profile;
3270+ BUG_ON(!cxt || !cxt->profile);
2380c486 3271+
ceaf2cfb
AM
3272+ profile = aa_newest_version(cxt->profile);
3273+ /*
3274+ * Whether or not replacement succeeds, use newest profile so
3275+ * there is no need to update it after replacement.
3276+ */
3277+ if (unlikely((cxt->profile != profile)))
76514441 3278+ aa_replace_current_profile(profile);
2380c486 3279+
ceaf2cfb
AM
3280+ return profile;
3281+}
9474138d 3282+
ceaf2cfb
AM
3283+#endif /* __AA_CONTEXT_H */
3284diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
3285new file mode 100644
76514441 3286index 0000000..de04464
ceaf2cfb
AM
3287--- /dev/null
3288+++ b/security/apparmor/include/domain.h
3289@@ -0,0 +1,36 @@
9474138d
AM
3290+/*
3291+ * AppArmor security module
3292+ *
3293+ * This file contains AppArmor security domain transition function definitions.
3294+ *
3295+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 3296+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
3297+ *
3298+ * This program is free software; you can redistribute it and/or
3299+ * modify it under the terms of the GNU General Public License as
3300+ * published by the Free Software Foundation, version 2 of the
3301+ * License.
2380c486 3302+ */
2380c486 3303+
9474138d
AM
3304+#include <linux/binfmts.h>
3305+#include <linux/types.h>
3306+
3307+#ifndef __AA_DOMAIN_H
3308+#define __AA_DOMAIN_H
3309+
3310+struct aa_domain {
3311+ int size;
3312+ char **table;
3313+};
3314+
3315+int apparmor_bprm_set_creds(struct linux_binprm *bprm);
3316+int apparmor_bprm_secureexec(struct linux_binprm *bprm);
ceaf2cfb 3317+void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
9474138d
AM
3318+void apparmor_bprm_committed_creds(struct linux_binprm *bprm);
3319+
3320+void aa_free_domain_entries(struct aa_domain *domain);
ceaf2cfb 3321+int aa_change_hat(const char *hats[], int count, u64 token, bool permtest);
76514441 3322+int aa_change_profile(const char *ns_name, const char *name, bool onexec,
ceaf2cfb
AM
3323+ bool permtest);
3324+
3325+#endif /* __AA_DOMAIN_H */
3326diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
3327new file mode 100644
76514441 3328index 0000000..be36fea
ceaf2cfb
AM
3329--- /dev/null
3330+++ b/security/apparmor/include/file.h
76514441 3331@@ -0,0 +1,217 @@
9474138d
AM
3332+/*
3333+ * AppArmor security module
3334+ *
3335+ * This file contains AppArmor file mediation function definitions.
3336+ *
3337+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 3338+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
3339+ *
3340+ * This program is free software; you can redistribute it and/or
3341+ * modify it under the terms of the GNU General Public License as
3342+ * published by the Free Software Foundation, version 2 of the
3343+ * License.
3344+ */
3345+
3346+#ifndef __AA_FILE_H
3347+#define __AA_FILE_H
3348+
3349+#include <linux/path.h>
3350+
9474138d
AM
3351+#include "domain.h"
3352+#include "match.h"
3353+
3354+struct aa_profile;
3355+
3356+/*
3357+ * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags
3358+ * for profile permissions
3359+ */
76514441
AM
3360+#define AA_MAY_CREATE 0x0010
3361+#define AA_MAY_DELETE 0x0020
3362+#define AA_MAY_META_WRITE 0x0040
3363+#define AA_MAY_META_READ 0x0080
9474138d 3364+
76514441
AM
3365+#define AA_MAY_CHMOD 0x0100
3366+#define AA_MAY_CHOWN 0x0200
3367+#define AA_MAY_LOCK 0x0400
3368+#define AA_EXEC_MMAP 0x0800
2380c486 3369+
76514441
AM
3370+#define AA_MAY_LINK 0x1000
3371+#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */
3372+#define AA_MAY_ONEXEC 0x40000000 /* exec allows onexec */
3373+#define AA_MAY_CHANGE_PROFILE 0x80000000
3374+#define AA_MAY_CHANGEHAT 0x80000000 /* ctrl auditing only */
2380c486 3375+
9474138d 3376+#define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\
76514441
AM
3377+ AA_MAY_CREATE | AA_MAY_DELETE | \
3378+ AA_MAY_META_READ | AA_MAY_META_WRITE | \
3379+ AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \
3380+ AA_EXEC_MMAP | AA_MAY_LINK)
2380c486 3381+
9474138d
AM
3382+/*
3383+ * The xindex is broken into 3 parts
3384+ * - index - an index into either the exec name table or the variable table
3385+ * - exec type - which determines how the executable name and index are used
3386+ * - flags - which modify how the destination name is applied
3387+ */
3388+#define AA_X_INDEX_MASK 0x03ff
2380c486 3389+
9474138d 3390+#define AA_X_TYPE_MASK 0x0c00
ceaf2cfb 3391+#define AA_X_TYPE_SHIFT 10
9474138d
AM
3392+#define AA_X_NONE 0x0000
3393+#define AA_X_NAME 0x0400 /* use executable name px */
3394+#define AA_X_TABLE 0x0800 /* use a specified name ->n# */
2380c486 3395+
9474138d
AM
3396+#define AA_X_UNSAFE 0x1000
3397+#define AA_X_CHILD 0x2000 /* make >AA_X_NONE apply to children */
3398+#define AA_X_INHERIT 0x4000
3399+#define AA_X_UNCONFINED 0x8000
2380c486 3400+
9474138d
AM
3401+/* AA_SECURE_X_NEEDED - is passed in the bprm->unsafe field */
3402+#define AA_SECURE_X_NEEDED 0x8000
2380c486 3403+
76514441 3404+/* need to make conditional which ones are being set */
9474138d
AM
3405+struct path_cond {
3406+ uid_t uid;
3407+ umode_t mode;
3408+};
2380c486 3409+
76514441
AM
3410+/* struct file_perms - file permission
3411+ * @allow: mask of permissions that are allowed
9474138d
AM
3412+ * @audit: mask of permissions to force an audit message for
3413+ * @quiet: mask of permissions to quiet audit messages for
3414+ * @kill: mask of permissions that when matched will kill the task
76514441 3415+ * @xindex: exec transition index if @allow contains MAY_EXEC
2380c486 3416+ *
9474138d 3417+ * The @audit and @queit mask should be mutually exclusive.
2380c486 3418+ */
9474138d 3419+struct file_perms {
76514441
AM
3420+ u32 allow;
3421+ u32 audit;
3422+ u32 quiet;
3423+ u32 kill;
9474138d 3424+ u16 xindex;
9474138d 3425+};
2380c486 3426+
9474138d 3427+extern struct file_perms nullperms;
2380c486 3428+
76514441 3429+#define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill)
2380c486 3430+
9474138d
AM
3431+/* FIXME: split perms from dfa and match this to description
3432+ * also add delegation info.
2380c486 3433+ */
9474138d
AM
3434+static inline u16 dfa_map_xindex(u16 mask)
3435+{
3436+ u16 old_index = (mask >> 10) & 0xf;
3437+ u16 index = 0;
3438+
9474138d
AM
3439+ if (mask & 0x100)
3440+ index |= AA_X_UNSAFE;
3441+ if (mask & 0x200)
3442+ index |= AA_X_INHERIT;
5e665963
AM
3443+ if (mask & 0x80)
3444+ index |= AA_X_UNCONFINED;
9474138d
AM
3445+
3446+ if (old_index == 1) {
3447+ index |= AA_X_UNCONFINED;
3448+ } else if (old_index == 2) {
3449+ index |= AA_X_NAME;
3450+ } else if (old_index == 3) {
3451+ index |= AA_X_NAME | AA_X_CHILD;
2380c486 3452+ } else {
9474138d
AM
3453+ index |= AA_X_TABLE;
3454+ index |= old_index - 4;
2380c486 3455+ }
9474138d
AM
3456+
3457+ return index;
2380c486
JR
3458+}
3459+
9474138d
AM
3460+/*
3461+ * map old dfa inline permissions to new format
3462+ */
76514441
AM
3463+#define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \
3464+ ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
ceaf2cfb
AM
3465+#define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f)
3466+#define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f)
9474138d
AM
3467+#define dfa_user_xindex(dfa, state) \
3468+ (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff))
3469+
76514441
AM
3470+#define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \
3471+ 0x7f) | \
3472+ ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
ceaf2cfb
AM
3473+#define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f)
3474+#define dfa_other_quiet(dfa, state) \
3475+ ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f)
9474138d
AM
3476+#define dfa_other_xindex(dfa, state) \
3477+ dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
3478+
76514441
AM
3479+int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
3480+ gfp_t gfp, int op, u32 request, const char *name,
3481+ const char *target, uid_t ouid, const char *info, int error);
9474138d 3482+
2380c486 3483+/**
9474138d
AM
3484+ * struct aa_file_rules - components used for file rule permissions
3485+ * @dfa: dfa to match path names and conditionals against
3486+ * @perms: permission table indexed by the matched state accept entry of @dfa
3487+ * @trans: transition table for indexed by named x transitions
3488+ *
3489+ * File permission are determined by matching a path against @dfa and then
3490+ * then using the value of the accept entry for the matching state as
3491+ * an index into @perms. If a named exec transition is required it is
3492+ * looked up in the transition table.
2380c486 3493+ */
9474138d 3494+struct aa_file_rules {
ceaf2cfb 3495+ unsigned int start;
9474138d
AM
3496+ struct aa_dfa *dfa;
3497+ /* struct perms perms; */
3498+ struct aa_domain trans;
3499+ /* TODO: add delegate table */
3500+};
3501+
76514441
AM
3502+unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
3503+ const char *name, struct path_cond *cond,
3504+ struct file_perms *perms);
2380c486 3505+
76514441
AM
3506+int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
3507+ int flags, u32 request, struct path_cond *cond);
9474138d
AM
3508+
3509+int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
3510+ struct path *new_dir, struct dentry *new_dentry);
3511+
76514441
AM
3512+int aa_file_perm(int op, struct aa_profile *profile, struct file *file,
3513+ u32 request);
9474138d 3514+
9474138d 3515+static inline void aa_free_file_rules(struct aa_file_rules *rules)
2380c486 3516+{
ceaf2cfb 3517+ aa_put_dfa(rules->dfa);
9474138d 3518+ aa_free_domain_entries(&rules->trans);
2380c486
JR
3519+}
3520+
9474138d
AM
3521+#define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40))
3522+
3523+/* from namei.c */
9474138d 3524+#define MAP_OPEN_FLAGS(x) ((((x) + 1) & O_ACCMODE) ? (x) + 1 : (x))
ceaf2cfb
AM
3525+
3526+/**
3527+ * aa_map_file_perms - map file flags to AppArmor permissions
3528+ * @file: open file to map flags to AppArmor permissions
3529+ *
3530+ * Returns: apparmor permission set for the file
9474138d 3531+ */
76514441 3532+static inline u32 aa_map_file_to_perms(struct file *file)
2380c486 3533+{
9474138d 3534+ int flags = MAP_OPEN_FLAGS(file->f_flags);
76514441 3535+ u32 perms = ACC_FMODE(file->f_mode);
9474138d
AM
3536+
3537+ if ((flags & O_APPEND) && (perms & MAY_WRITE))
3538+ perms = (perms & ~MAY_WRITE) | MAY_APPEND;
3539+ /* trunc implies write permission */
3540+ if (flags & O_TRUNC)
3541+ perms |= MAY_WRITE;
3542+ if (flags & O_CREAT)
3543+ perms |= AA_MAY_CREATE;
3544+
3545+ return perms;
2380c486
JR
3546+}
3547+
ceaf2cfb
AM
3548+#endif /* __AA_FILE_H */
3549diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h
3550new file mode 100644
3551index 0000000..aeda0fb
3552--- /dev/null
3553+++ b/security/apparmor/include/ipc.h
9474138d 3554@@ -0,0 +1,28 @@
2380c486 3555+/*
9474138d 3556+ * AppArmor security module
2380c486 3557+ *
9474138d 3558+ * This file contains AppArmor ipc mediation function definitions.
2380c486 3559+ *
9474138d 3560+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 3561+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
3562+ *
3563+ * This program is free software; you can redistribute it and/or
3564+ * modify it under the terms of the GNU General Public License as
3565+ * published by the Free Software Foundation, version 2 of the
3566+ * License.
2380c486
JR
3567+ */
3568+
9474138d
AM
3569+#ifndef __AA_IPC_H
3570+#define __AA_IPC_H
2380c486 3571+
9474138d 3572+#include <linux/sched.h>
2380c486 3573+
9474138d 3574+struct aa_profile;
2380c486 3575+
9474138d
AM
3576+int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
3577+ struct aa_profile *tracee, unsigned int mode);
2380c486 3578+
9474138d
AM
3579+int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
3580+ unsigned int mode);
2380c486 3581+
ceaf2cfb
AM
3582+#endif /* __AA_IPC_H */
3583diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
3584new file mode 100644
76514441 3585index 0000000..734a6d3
ceaf2cfb
AM
3586--- /dev/null
3587+++ b/security/apparmor/include/match.h
76514441 3588@@ -0,0 +1,132 @@
9474138d
AM
3589+/*
3590+ * AppArmor security module
3591+ *
3592+ * This file contains AppArmor policy dfa matching engine definitions.
3593+ *
3594+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 3595+ * Copyright 2009-2010 Canonical Ltd.
2380c486 3596+ *
9474138d
AM
3597+ * This program is free software; you can redistribute it and/or
3598+ * modify it under the terms of the GNU General Public License as
3599+ * published by the Free Software Foundation, version 2 of the
3600+ * License.
2380c486 3601+ */
2380c486 3602+
9474138d
AM
3603+#ifndef __AA_MATCH_H
3604+#define __AA_MATCH_H
2380c486 3605+
76514441
AM
3606+#include <linux/workqueue.h>
3607+
9474138d
AM
3608+#define DFA_NOMATCH 0
3609+#define DFA_START 1
3610+
3611+#define DFA_VALID_PERM_MASK 0xffffffff
3612+#define DFA_VALID_PERM2_MASK 0xffffffff
2380c486 3613+
2380c486 3614+/**
9474138d
AM
3615+ * The format used for transition tables is based on the GNU flex table
3616+ * file format (--tables-file option; see Table File Format in the flex
3617+ * info pages and the flex sources for documentation). The magic number
3618+ * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
3619+ * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
3620+ * slightly differently (see the apparmor-parser package).
2380c486 3621+ */
2380c486 3622+
9474138d 3623+#define YYTH_MAGIC 0x1B5E783D
ceaf2cfb 3624+#define YYTH_DEF_RECURSE 0x1 /* DEF Table is recursive */
2380c486 3625+
9474138d 3626+struct table_set_header {
ceaf2cfb
AM
3627+ u32 th_magic; /* YYTH_MAGIC */
3628+ u32 th_hsize;
3629+ u32 th_ssize;
3630+ u16 th_flags;
3631+ char th_version[];
9474138d 3632+};
2380c486 3633+
ceaf2cfb
AM
3634+/* The YYTD_ID are one less than flex table mappings. The flex id
3635+ * has 1 subtracted at table load time, this allows us to directly use the
3636+ * ID's as indexes.
3637+ */
3638+#define YYTD_ID_ACCEPT 0
3639+#define YYTD_ID_BASE 1
3640+#define YYTD_ID_CHK 2
3641+#define YYTD_ID_DEF 3
3642+#define YYTD_ID_EC 4
3643+#define YYTD_ID_META 5
3644+#define YYTD_ID_ACCEPT2 6
3645+#define YYTD_ID_NXT 7
3646+#define YYTD_ID_TSIZE 8
2380c486 3647+
9474138d
AM
3648+#define YYTD_DATA8 1
3649+#define YYTD_DATA16 2
3650+#define YYTD_DATA32 4
ceaf2cfb
AM
3651+#define YYTD_DATA64 8
3652+
3653+/* Each ACCEPT2 table gets 6 dedicated flags, YYTD_DATAX define the
3654+ * first flags
3655+ */
3656+#define ACCEPT1_FLAGS(X) ((X) & 0x3f)
3657+#define ACCEPT2_FLAGS(X) ACCEPT1_FLAGS((X) >> YYTD_ID_ACCEPT2)
3658+#define TO_ACCEPT1_FLAG(X) ACCEPT1_FLAGS(X)
3659+#define TO_ACCEPT2_FLAG(X) (ACCEPT1_FLAGS(X) << YYTD_ID_ACCEPT2)
3660+#define DFA_FLAG_VERIFY_STATES 0x1000
2380c486 3661+
9474138d 3662+struct table_header {
ceaf2cfb
AM
3663+ u16 td_id;
3664+ u16 td_flags;
3665+ u32 td_hilen;
3666+ u32 td_lolen;
3667+ char td_data[];
9474138d 3668+};
2380c486 3669+
ceaf2cfb
AM
3670+#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF]->td_data))
3671+#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE]->td_data))
3672+#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT]->td_data))
3673+#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK]->td_data))
3674+#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC]->td_data))
3675+#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT]->td_data))
3676+#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2]->td_data))
2380c486 3677+
9474138d 3678+struct aa_dfa {
ceaf2cfb
AM
3679+ struct kref count;
3680+ u16 flags;
3681+ struct table_header *tables[YYTD_ID_TSIZE];
9474138d 3682+};
2380c486 3683+
9474138d 3684+#define byte_to_byte(X) (X)
2380c486 3685+
9474138d
AM
3686+#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
3687+ do { \
3688+ typeof(LEN) __i; \
3689+ TYPE *__t = (TYPE *) TABLE; \
3690+ TYPE *__b = (TYPE *) BLOB; \
3691+ for (__i = 0; __i < LEN; __i++) { \
3692+ __t[__i] = NTOHX(__b[__i]); \
3693+ } \
3694+ } while (0)
2380c486 3695+
9474138d 3696+static inline size_t table_size(size_t len, size_t el_size)
2380c486 3697+{
9474138d 3698+ return ALIGN(sizeof(struct table_header) + len * el_size, 8);
2380c486
JR
3699+}
3700+
ceaf2cfb 3701+struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
9474138d
AM
3702+unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
3703+ const char *str, int len);
3704+unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
3705+ const char *str);
ceaf2cfb
AM
3706+void aa_dfa_free_kref(struct kref *kref);
3707+
3708+/**
3709+ * aa_put_dfa - put a dfa refcount
3710+ * @dfa: dfa to put refcount (MAYBE NULL)
3711+ *
76514441 3712+ * Requires: if @dfa != NULL that a valid refcount be held
ceaf2cfb
AM
3713+ */
3714+static inline void aa_put_dfa(struct aa_dfa *dfa)
3715+{
3716+ if (dfa)
3717+ kref_put(&dfa->count, aa_dfa_free_kref);
3718+}
9474138d
AM
3719+
3720+#endif /* __AA_MATCH_H */
ceaf2cfb
AM
3721diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
3722new file mode 100644
76514441 3723index 0000000..3c7d599
ceaf2cfb
AM
3724--- /dev/null
3725+++ b/security/apparmor/include/net.h
9474138d 3726@@ -0,0 +1,40 @@
2380c486 3727+/*
9474138d
AM
3728+ * AppArmor security module
3729+ *
3730+ * This file contains AppArmor network mediation definitions.
2380c486 3731+ *
9474138d 3732+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 3733+ * Copyright 2009-2010 Canonical Ltd.
2380c486 3734+ *
9474138d
AM
3735+ * This program is free software; you can redistribute it and/or
3736+ * modify it under the terms of the GNU General Public License as
3737+ * published by the Free Software Foundation, version 2 of the
3738+ * License.
2380c486 3739+ */
2380c486 3740+
9474138d
AM
3741+#ifndef __AA_NET_H
3742+#define __AA_NET_H
2380c486 3743+
9474138d 3744+#include <net/sock.h>
2380c486 3745+
9474138d
AM
3746+/* struct aa_net - network confinement data
3747+ * @allowed: basic network families permissions
3748+ * @audit_network: which network permissions to force audit
3749+ * @quiet_network: which network permissions to quiet rejects
3750+ */
3751+struct aa_net {
76514441 3752+ u16 allow[AF_MAX];
9474138d
AM
3753+ u16 audit[AF_MAX];
3754+ u16 quiet[AF_MAX];
3755+};
2380c486 3756+
76514441
AM
3757+extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
3758+ int type, int protocol, struct sock *sk);
3759+extern int aa_revalidate_sk(int op, struct sock *sk);
2380c486 3760+
9474138d
AM
3761+static inline void aa_free_net_rules(struct aa_net *new)
3762+{
3763+ /* NOP */
3764+}
2380c486 3765+
ceaf2cfb
AM
3766+#endif /* __AA_NET_H */
3767diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
3768new file mode 100644
76514441 3769index 0000000..27b327a
ceaf2cfb
AM
3770--- /dev/null
3771+++ b/security/apparmor/include/path.h
3772@@ -0,0 +1,31 @@
9474138d
AM
3773+/*
3774+ * AppArmor security module
3775+ *
3776+ * This file contains AppArmor basic path manipulation function definitions.
3777+ *
3778+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 3779+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
3780+ *
3781+ * This program is free software; you can redistribute it and/or
3782+ * modify it under the terms of the GNU General Public License as
3783+ * published by the Free Software Foundation, version 2 of the
3784+ * License.
3785+ */
2380c486 3786+
9474138d
AM
3787+#ifndef __AA_PATH_H
3788+#define __AA_PATH_H
3789+
ceaf2cfb
AM
3790+
3791+enum path_flags {
3792+ PATH_IS_DIR = 0x1, /* path is a directory */
3793+ PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */
3794+ PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */
3795+ PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */
3796+
76514441 3797+ PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */
ceaf2cfb
AM
3798+ PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */
3799+};
3800+
76514441 3801+int aa_get_name(struct path *path, int flags, char **buffer, const char **name);
9474138d 3802+
ceaf2cfb
AM
3803+#endif /* __AA_PATH_H */
3804diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
3805new file mode 100644
76514441 3806index 0000000..6776929
ceaf2cfb
AM
3807--- /dev/null
3808+++ b/security/apparmor/include/policy.h
76514441 3809@@ -0,0 +1,308 @@
9474138d
AM
3810+/*
3811+ * AppArmor security module
3812+ *
3813+ * This file contains AppArmor policy definitions.
2380c486 3814+ *
9474138d 3815+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 3816+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
3817+ *
3818+ * This program is free software; you can redistribute it and/or
3819+ * modify it under the terms of the GNU General Public License as
3820+ * published by the Free Software Foundation, version 2 of the
3821+ * License.
2380c486 3822+ */
2380c486 3823+
9474138d
AM
3824+#ifndef __AA_POLICY_H
3825+#define __AA_POLICY_H
2380c486 3826+
9474138d
AM
3827+#include <linux/capability.h>
3828+#include <linux/cred.h>
3829+#include <linux/kref.h>
3830+#include <linux/sched.h>
3831+#include <linux/slab.h>
3832+#include <linux/socket.h>
2380c486 3833+
9474138d
AM
3834+#include "apparmor.h"
3835+#include "audit.h"
3836+#include "capability.h"
3837+#include "domain.h"
3838+#include "file.h"
3839+#include "net.h"
3840+#include "resource.h"
2380c486 3841+
9474138d
AM
3842+extern const char *profile_mode_names[];
3843+#define APPARMOR_NAMES_MAX_INDEX 3
2380c486 3844+
76514441
AM
3845+#define COMPLAIN_MODE(_profile) \
3846+ ((aa_g_profile_mode == APPARMOR_COMPLAIN) || \
3847+ ((_profile)->mode == APPARMOR_COMPLAIN))
2380c486 3848+
76514441
AM
3849+#define KILL_MODE(_profile) \
3850+ ((aa_g_profile_mode == APPARMOR_KILL) || \
3851+ ((_profile)->mode == APPARMOR_KILL))
2380c486 3852+
76514441 3853+#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT)
2380c486 3854+
9474138d
AM
3855+/*
3856+ * FIXME: currently need a clean way to replace and remove profiles as a
3857+ * set. It should be done at the namespace level.
3858+ * Either, with a set of profiles loaded at the namespace level or via
3859+ * a mark and remove marked interface.
3860+ */
3861+enum profile_mode {
ceaf2cfb
AM
3862+ APPARMOR_ENFORCE, /* enforce access rules */
3863+ APPARMOR_COMPLAIN, /* allow and log access violations */
3864+ APPARMOR_KILL, /* kill task on access violation */
9474138d 3865+};
2380c486 3866+
9474138d
AM
3867+enum profile_flags {
3868+ PFLAG_HAT = 1, /* profile is a hat */
76514441 3869+ PFLAG_UNCONFINED = 2, /* profile is an unconfined profile */
9474138d
AM
3870+ PFLAG_NULL = 4, /* profile is null learning profile */
3871+ PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */
3872+ PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */
76514441 3873+ PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */
9474138d 3874+ PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */
ceaf2cfb
AM
3875+ PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */
3876+
76514441 3877+ /* These flags must correspond with PATH_flags */
ceaf2cfb 3878+ PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */
9474138d 3879+};
2380c486 3880+
9474138d 3881+struct aa_profile;
2380c486 3882+
ceaf2cfb 3883+/* struct aa_policy - common part of both namespaces and profiles
9474138d 3884+ * @name: name of the object
ceaf2cfb 3885+ * @hname - The hierarchical name
9474138d 3886+ * @count: reference count of the obj
ceaf2cfb 3887+ * @list: list policy object is on
9474138d
AM
3888+ * @profiles: head of the profiles list contained in the object
3889+ */
ceaf2cfb 3890+struct aa_policy {
9474138d 3891+ char *name;
ceaf2cfb 3892+ char *hname;
9474138d 3893+ struct kref count;
9474138d
AM
3894+ struct list_head list;
3895+ struct list_head profiles;
3896+};
2380c486 3897+
9474138d
AM
3898+/* struct aa_ns_acct - accounting of profiles in namespace
3899+ * @max_size: maximum space allowed for all profiles in namespace
3900+ * @max_count: maximum number of profiles that can be in this namespace
3901+ * @size: current size of profiles
3902+ * @count: current count of profiles (includes null profiles)
3903+ */
3904+struct aa_ns_acct {
3905+ int max_size;
3906+ int max_count;
3907+ int size;
3908+ int count;
3909+};
2380c486 3910+
9474138d 3911+/* struct aa_namespace - namespace for a set of profiles
ceaf2cfb
AM
3912+ * @base: common policy
3913+ * @parent: parent of namespace
3914+ * @lock: lock for modifying the object
9474138d 3915+ * @acct: accounting for the namespace
9474138d 3916+ * @unconfined: special unconfined profile for the namespace
ceaf2cfb 3917+ * @sub_ns: list of namespaces under the current namespace.
9474138d
AM
3918+ *
3919+ * An aa_namespace defines the set profiles that are searched to determine
3920+ * which profile to attach to a task. Profiles can not be shared between
76514441
AM
3921+ * aa_namespaces and profile names within a namespace are guaranteed to be
3922+ * unique. When profiles in separate namespaces have the same name they
9474138d
AM
3923+ * are NOT considered to be equivalent.
3924+ *
ceaf2cfb
AM
3925+ * Namespaces are hierarchical and only namespaces and profiles below the
3926+ * current namespace are visible.
3927+ *
9474138d
AM
3928+ * Namespace names must be unique and can not contain the characters :/\0
3929+ *
76514441
AM
3930+ * FIXME TODO: add vserver support of namespaces (can it all be done in
3931+ * userspace?)
9474138d
AM
3932+ */
3933+struct aa_namespace {
ceaf2cfb
AM
3934+ struct aa_policy base;
3935+ struct aa_namespace *parent;
3936+ rwlock_t lock;
9474138d 3937+ struct aa_ns_acct acct;
9474138d 3938+ struct aa_profile *unconfined;
ceaf2cfb 3939+ struct list_head sub_ns;
9474138d 3940+};
2380c486 3941+
9474138d 3942+/* struct aa_profile - basic confinement data
76514441 3943+ * @base - base components of the profile (name, refcount, lists, lock ...)
ceaf2cfb 3944+ * @parent: parent of profile
9474138d 3945+ * @ns: namespace the profile is in
76514441
AM
3946+ * @replacedby: is set to the profile that replaced this profile
3947+ * @rename: optional profile name that this profile renamed
9474138d 3948+ * @xmatch: optional extended matching for unconfined executables names
ceaf2cfb 3949+ * @xmatch_len: xmatch prefix len, used to determine xmatch priority
9474138d
AM
3950+ * @sid: the unique security id number of this profile
3951+ * @audit: the auditing mode of the profile
3952+ * @mode: the enforcement mode of the profile
3953+ * @flags: flags controlling profile behavior
ceaf2cfb 3954+ * @path_flags: flags controlling path generation behavior
9474138d
AM
3955+ * @size: the memory consumed by this profiles rules
3956+ * @file: The set of rules governing basic file access and domain transitions
3957+ * @caps: capabilities for the profile
3958+ * @net: network controls for the profile
3959+ * @rlimits: rlimits for the profile
3960+ *
3961+ * The AppArmor profile contains the basic confinement data. Each profile
76514441 3962+ * has a name, and exists in a namespace. The @name and @exec_match are
9474138d 3963+ * used to determine profile attachment against unconfined tasks. All other
76514441 3964+ * attachments are determined by profile X transition rules.
9474138d
AM
3965+ *
3966+ * The @replacedby field is write protected by the profile lock. Reads
3967+ * are assumed to be atomic, and are done without locking.
3968+ *
76514441 3969+ * Profiles have a hierarchy where hats and children profiles keep
9474138d
AM
3970+ * a reference to their parent.
3971+ *
3972+ * Profile names can not begin with a : and can not contain the \0
3973+ * character. If a profile name begins with / it will be considered when
3974+ * determining profile attachment on "unconfined" tasks.
3975+ */
3976+struct aa_profile {
ceaf2cfb 3977+ struct aa_policy base;
9474138d 3978+ struct aa_profile *parent;
9474138d 3979+
ceaf2cfb 3980+ struct aa_namespace *ns;
76514441
AM
3981+ struct aa_profile *replacedby;
3982+ const char *rename;
3983+
9474138d
AM
3984+ struct aa_dfa *xmatch;
3985+ int xmatch_len;
3986+ u32 sid;
3987+ enum audit_mode audit;
3988+ enum profile_mode mode;
3989+ u32 flags;
ceaf2cfb 3990+ u32 path_flags;
9474138d
AM
3991+ int size;
3992+
3993+ struct aa_file_rules file;
3994+ struct aa_caps caps;
3995+ struct aa_net net;
3996+ struct aa_rlimit rlimits;
3997+};
2380c486 3998+
ceaf2cfb
AM
3999+extern struct aa_namespace *root_ns;
4000+extern enum profile_mode aa_g_profile_mode;
2380c486 4001+
ceaf2cfb 4002+void aa_add_profile(struct aa_policy *common, struct aa_profile *profile);
2380c486 4003+
76514441
AM
4004+bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view);
4005+const char *aa_ns_name(struct aa_namespace *parent, struct aa_namespace *child);
ceaf2cfb
AM
4006+int aa_alloc_root_ns(void);
4007+void aa_free_root_ns(void);
4008+void aa_free_namespace_kref(struct kref *kref);
2380c486 4009+
ceaf2cfb
AM
4010+struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
4011+ const char *name);
2380c486 4012+
ceaf2cfb 4013+static inline struct aa_policy *aa_get_common(struct aa_policy *c)
2380c486 4014+{
9474138d
AM
4015+ if (c)
4016+ kref_get(&c->count);
2380c486 4017+
9474138d 4018+ return c;
2380c486
JR
4019+}
4020+
ceaf2cfb
AM
4021+/**
4022+ * aa_get_namespace - increment references count on @ns
4023+ * @ns: namespace to increment reference count of (MAYBE NULL)
4024+ *
76514441 4025+ * Returns: pointer to @ns, if @ns is NULL returns NULL
ceaf2cfb
AM
4026+ * Requires: @ns must be held with valid refcount when called
4027+ */
9474138d 4028+static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
2380c486 4029+{
9474138d
AM
4030+ if (ns)
4031+ kref_get(&(ns->base.count));
2380c486 4032+
9474138d 4033+ return ns;
2380c486
JR
4034+}
4035+
ceaf2cfb
AM
4036+/**
4037+ * aa_put_namespace - decrement refcount on @ns
76514441 4038+ * @ns: namespace to put reference of
ceaf2cfb 4039+ *
76514441 4040+ * Decrement reference count of @ns and if no longer in use free it
ceaf2cfb 4041+ */
9474138d 4042+static inline void aa_put_namespace(struct aa_namespace *ns)
2380c486 4043+{
9474138d 4044+ if (ns)
ceaf2cfb 4045+ kref_put(&ns->base.count, aa_free_namespace_kref);
9474138d
AM
4046+}
4047+
ceaf2cfb
AM
4048+struct aa_profile *aa_alloc_profile(const char *name);
4049+struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat);
4050+void aa_free_profile_kref(struct kref *kref);
9474138d 4051+struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
76514441 4052+struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *name);
9474138d 4053+struct aa_profile *aa_match_profile(struct aa_namespace *ns, const char *name);
ceaf2cfb 4054+
76514441
AM
4055+ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace);
4056+ssize_t aa_remove_profiles(char *name, size_t size);
4057+
4058+#define PROF_ADD 1
4059+#define PROF_REPLACE 0
ceaf2cfb
AM
4060+
4061+#define unconfined(X) ((X)->flags & PFLAG_UNCONFINED)
4062+
4063+/**
4064+ * aa_newest_version - find the newest version of @profile
4065+ * @profile: the profile to check for newer versions of (NOT NULL)
4066+ *
4067+ * Returns: newest version of @profile, if @profile is the newest version
4068+ * return @profile.
4069+ *
4070+ * NOTE: the profile returned is not refcounted, The refcount on @profile
4071+ * must be held until the caller decides what to do with the returned newest
4072+ * version.
4073+ */
4074+static inline struct aa_profile *aa_newest_version(struct aa_profile *profile)
9474138d 4075+{
76514441
AM
4076+ while (profile->replacedby)
4077+ profile = profile->replacedby;
ceaf2cfb 4078+
9474138d 4079+ return profile;
2380c486
JR
4080+}
4081+
9474138d
AM
4082+/**
4083+ * aa_get_profile - increment refcount on profile @p
ceaf2cfb
AM
4084+ * @p: profile (MAYBE NULL)
4085+ *
4086+ * Returns: pointer to @p if @p is NULL will return NULL
4087+ * Requires: @p must be held with valid refcount when called
9474138d
AM
4088+ */
4089+static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
2380c486 4090+{
9474138d
AM
4091+ if (p)
4092+ kref_get(&(p->base.count));
2380c486 4093+
9474138d 4094+ return p;
2380c486
JR
4095+}
4096+
9474138d
AM
4097+/**
4098+ * aa_put_profile - decrement refcount on profile @p
ceaf2cfb 4099+ * @p: profile (MAYBE NULL)
9474138d
AM
4100+ */
4101+static inline void aa_put_profile(struct aa_profile *p)
2380c486 4102+{
9474138d 4103+ if (p)
ceaf2cfb 4104+ kref_put(&p->base.count, aa_free_profile_kref);
2380c486
JR
4105+}
4106+
ceaf2cfb 4107+static inline int AUDIT_MODE(struct aa_profile *profile)
2380c486 4108+{
ceaf2cfb
AM
4109+ if (aa_g_audit != AUDIT_NORMAL)
4110+ return aa_g_audit;
76514441
AM
4111+
4112+ return profile->audit;
2380c486
JR
4113+}
4114+
76514441
AM
4115+bool aa_may_manage_policy(int op);
4116+
ceaf2cfb
AM
4117+#endif /* __AA_POLICY_H */
4118diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
4119new file mode 100644
76514441 4120index 0000000..a2dccca
ceaf2cfb
AM
4121--- /dev/null
4122+++ b/security/apparmor/include/policy_unpack.h
76514441 4123@@ -0,0 +1,20 @@
9474138d
AM
4124+/*
4125+ * AppArmor security module
4126+ *
4127+ * This file contains AppArmor policy loading interface function definitions.
4128+ *
4129+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 4130+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
4131+ *
4132+ * This program is free software; you can redistribute it and/or
4133+ * modify it under the terms of the GNU General Public License as
4134+ * published by the Free Software Foundation, version 2 of the
4135+ * License.
4136+ */
2380c486 4137+
9474138d
AM
4138+#ifndef __POLICY_INTERFACE_H
4139+#define __POLICY_INTERFACE_H
2380c486 4140+
76514441 4141+struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns);
2380c486 4142+
ceaf2cfb
AM
4143+#endif /* __POLICY_INTERFACE_H */
4144diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h
4145new file mode 100644
76514441 4146index 0000000..544aa6b
ceaf2cfb
AM
4147--- /dev/null
4148+++ b/security/apparmor/include/procattr.h
9474138d
AM
4149@@ -0,0 +1,26 @@
4150+/*
4151+ * AppArmor security module
4152+ *
76514441 4153+ * This file contains AppArmor /proc/<pid>/attr/ interface function definitions.
9474138d
AM
4154+ *
4155+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 4156+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
4157+ *
4158+ * This program is free software; you can redistribute it and/or
4159+ * modify it under the terms of the GNU General Public License as
4160+ * published by the Free Software Foundation, version 2 of the
4161+ * License.
4162+ */
2380c486 4163+
9474138d
AM
4164+#ifndef __AA_PROCATTR_H
4165+#define __AA_PROCATTR_H
2380c486 4166+
9474138d 4167+#define AA_DO_TEST 1
ceaf2cfb
AM
4168+#define AA_ONEXEC 1
4169+
4170+int aa_getprocattr(struct aa_profile *profile, char **string);
4171+int aa_setprocattr_changehat(char *args, size_t size, int test);
76514441 4172+int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test);
ceaf2cfb
AM
4173+int aa_setprocattr_permipc(char *fqname);
4174+
4175+#endif /* __AA_PROCATTR_H */
4176diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
4177new file mode 100644
76514441 4178index 0000000..3c88be9
ceaf2cfb
AM
4179--- /dev/null
4180+++ b/security/apparmor/include/resource.h
76514441 4181@@ -0,0 +1,46 @@
9474138d
AM
4182+/*
4183+ * AppArmor security module
4184+ *
76514441 4185+ * This file contains AppArmor resource limits function definitions.
9474138d
AM
4186+ *
4187+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 4188+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
4189+ *
4190+ * This program is free software; you can redistribute it and/or
4191+ * modify it under the terms of the GNU General Public License as
4192+ * published by the Free Software Foundation, version 2 of the
4193+ * License.
4194+ */
2380c486 4195+
9474138d
AM
4196+#ifndef __AA_RESOURCE_H
4197+#define __AA_RESOURCE_H
2380c486 4198+
9474138d
AM
4199+#include <linux/resource.h>
4200+#include <linux/sched.h>
2380c486 4201+
9474138d 4202+struct aa_profile;
2380c486 4203+
76514441 4204+/* struct aa_rlimit - rlimit settings for the profile
9474138d
AM
4205+ * @mask: which hard limits to set
4206+ * @limits: rlimit values that override task limits
4207+ *
4208+ * AppArmor rlimits are used to set confined task rlimits. Only the
4209+ * limits specified in @mask will be controlled by apparmor.
4210+ */
4211+struct aa_rlimit {
4212+ unsigned int mask;
4213+ struct rlimit limits[RLIM_NLIMITS];
4214+};
2380c486 4215+
76514441 4216+int aa_map_resource(int resource);
9474138d
AM
4217+int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
4218+ struct rlimit *new_rlim);
4219+
4220+void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
4221+
4222+static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
4223+{
4224+ /* NOP */
2380c486
JR
4225+}
4226+
ceaf2cfb
AM
4227+#endif /* __AA_RESOURCE_H */
4228diff --git a/security/apparmor/include/sid.h b/security/apparmor/include/sid.h
4229new file mode 100644
4230index 0000000..020db35
4231--- /dev/null
4232+++ b/security/apparmor/include/sid.h
4233@@ -0,0 +1,24 @@
9474138d
AM
4234+/*
4235+ * AppArmor security module
4236+ *
4237+ * This file contains AppArmor security identifier (sid) definitions
4238+ *
ceaf2cfb 4239+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
4240+ *
4241+ * This program is free software; you can redistribute it and/or
4242+ * modify it under the terms of the GNU General Public License as
4243+ * published by the Free Software Foundation, version 2 of the
4244+ * License.
4245+ */
4246+
4247+#ifndef __AA_SID_H
4248+#define __AA_SID_H
4249+
4250+#include <linux/types.h>
4251+
4252+struct aa_profile;
4253+
ceaf2cfb 4254+u32 aa_alloc_sid(void);
9474138d 4255+void aa_free_sid(u32 sid);
2380c486 4256+
ceaf2cfb
AM
4257+#endif /* __AA_SID_H */
4258diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
4259new file mode 100644
76514441 4260index 0000000..9013a78
ceaf2cfb
AM
4261--- /dev/null
4262+++ b/security/apparmor/ipc.c
76514441 4263@@ -0,0 +1,114 @@
9474138d
AM
4264+/*
4265+ * AppArmor security module
4266+ *
4267+ * This file contains AppArmor ipc mediation
4268+ *
4269+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 4270+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
4271+ *
4272+ * This program is free software; you can redistribute it and/or
4273+ * modify it under the terms of the GNU General Public License as
4274+ * published by the Free Software Foundation, version 2 of the
4275+ * License.
4276+ */
2380c486 4277+
9474138d
AM
4278+#include <linux/gfp.h>
4279+#include <linux/ptrace.h>
2380c486 4280+
9474138d
AM
4281+#include "include/audit.h"
4282+#include "include/capability.h"
4283+#include "include/context.h"
4284+#include "include/policy.h"
2380c486 4285+
9474138d 4286+/* call back to audit ptrace fields */
76514441 4287+static void audit_cb(struct audit_buffer *ab, void *va)
9474138d 4288+{
76514441
AM
4289+ struct common_audit_data *sa = va;
4290+ audit_log_format(ab, " target=");
4291+ audit_log_untrustedstring(ab, sa->aad.target);
2380c486
JR
4292+}
4293+
ceaf2cfb
AM
4294+/**
4295+ * aa_audit_ptrace - do auditing for ptrace
4296+ * @profile: profile being enforced (NOT NULL)
76514441
AM
4297+ * @target: profile being traced (NOT NULL)
4298+ * @error: error condition
ceaf2cfb
AM
4299+ *
4300+ * Returns: %0 or error code
4301+ */
9474138d 4302+static int aa_audit_ptrace(struct aa_profile *profile,
76514441 4303+ struct aa_profile *target, int error)
2380c486 4304+{
76514441
AM
4305+ struct common_audit_data sa;
4306+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
4307+ sa.aad.op = OP_PTRACE;
4308+ sa.aad.target = target;
4309+ sa.aad.error = error;
4310+
4311+ return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
4312+ audit_cb);
2380c486
JR
4313+}
4314+
ceaf2cfb
AM
4315+/**
4316+ * aa_may_ptrace - test if tracer task can trace the tracee
4317+ * @tracer_task: task who will do the tracing (NOT NULL)
4318+ * @tracer: profile of the task doing the tracing (NOT NULL)
4319+ * @tracee: task to be traced
4320+ * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH
4321+ *
4322+ * Returns: %0 else error code if permission denied or error
4323+ */
9474138d
AM
4324+int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
4325+ struct aa_profile *tracee, unsigned int mode)
2380c486 4326+{
9474138d
AM
4327+ /* TODO: currently only based on capability, not extended ptrace
4328+ * rules,
4329+ * Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
4330+ */
4331+
76514441 4332+ if (unconfined(tracer) || tracer == tracee)
9474138d
AM
4333+ return 0;
4334+ /* log this capability request */
4335+ return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1);
2380c486
JR
4336+}
4337+
ceaf2cfb
AM
4338+/**
4339+ * aa_ptrace - do ptrace permission check and auditing
76514441
AM
4340+ * @tracer: task doing the tracing (NOT NULL)
4341+ * @tracee: task being traced (NOT NULL)
ceaf2cfb
AM
4342+ * @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH
4343+ *
4344+ * Returns: %0 else error code if permission denied or error
4345+ */
9474138d
AM
4346+int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
4347+ unsigned int mode)
2380c486 4348+{
9474138d
AM
4349+ /*
4350+ * tracer can ptrace tracee when
4351+ * - tracer is unconfined ||
9474138d
AM
4352+ * - tracer is in complain mode
4353+ * - tracer has rules allowing it to trace tracee currently this is:
4354+ * - confined by the same profile ||
4355+ * - tracer profile has CAP_SYS_PTRACE
4356+ */
4357+
4358+ struct aa_profile *tracer_p;
ceaf2cfb
AM
4359+ /* cred released below */
4360+ const struct cred *cred = get_task_cred(tracer);
2380c486 4361+ int error = 0;
ceaf2cfb
AM
4362+ tracer_p = aa_cred_profile(cred);
4363+
4364+ if (!unconfined(tracer_p)) {
ceaf2cfb
AM
4365+ /* lcred released below */
4366+ struct cred *lcred = get_task_cred(tracee);
76514441 4367+ struct aa_profile *tracee_p = aa_cred_profile(lcred);
2380c486 4368+
76514441
AM
4369+ error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode);
4370+ error = aa_audit_ptrace(tracer_p, tracee_p, error);
2380c486 4371+
ceaf2cfb 4372+ put_cred(lcred);
2380c486 4373+ }
9474138d 4374+ put_cred(cred);
2380c486 4375+
2380c486
JR
4376+ return error;
4377+}
ceaf2cfb
AM
4378diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
4379new file mode 100644
76514441 4380index 0000000..6e85cdb
ceaf2cfb
AM
4381--- /dev/null
4382+++ b/security/apparmor/lib.c
76514441 4383@@ -0,0 +1,133 @@
9474138d
AM
4384+/*
4385+ * AppArmor security module
4386+ *
4387+ * This file contains basic common functions used in AppArmor
4388+ *
4389+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 4390+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
4391+ *
4392+ * This program is free software; you can redistribute it and/or
4393+ * modify it under the terms of the GNU General Public License as
4394+ * published by the Free Software Foundation, version 2 of the
4395+ * License.
4396+ */
2380c486 4397+
9474138d
AM
4398+#include <linux/slab.h>
4399+#include <linux/string.h>
76514441 4400+#include <linux/vmalloc.h>
2380c486 4401+
9474138d 4402+#include "include/audit.h"
2380c486 4403+
2380c486 4404+
ceaf2cfb
AM
4405+/**
4406+ * aa_split_fqname - split a fqname into a profile and namespace name
76514441
AM
4407+ * @fqname: a full qualified name in namespace profile format (NOT NULL)
4408+ * @ns_name: pointer to portion of the string containing the ns name (NOT NULL)
ceaf2cfb
AM
4409+ *
4410+ * Returns: profile name or NULL if one is not specified
4411+ *
4412+ * Split a namespace name from a profile name (see policy.c for naming
4413+ * description). If a portion of the name is missing it returns NULL for
4414+ * that portion.
4415+ *
76514441 4416+ * NOTE: may modify the @fqname string. The pointers returned point
ceaf2cfb
AM
4417+ * into the @fqname string.
4418+ */
4419+char *aa_split_fqname(char *fqname, char **ns_name)
9474138d 4420+{
ceaf2cfb 4421+ char *name = strim(fqname);
2380c486 4422+
ceaf2cfb
AM
4423+ *ns_name = NULL;
4424+ if (name[0] == ':') {
4425+ char *split = strchr(&name[1], ':');
4426+ if (split) {
4427+ /* overwrite ':' with \0 */
4428+ *split = 0;
4429+ name = skip_spaces(split + 1);
4430+ } else
4431+ /* a ns name without a following profile is allowed */
4432+ name = NULL;
4433+ *ns_name = &name[1];
2380c486 4434+ }
ceaf2cfb 4435+ if (name && *name == 0)
9474138d 4436+ name = NULL;
2380c486 4437+
9474138d 4438+ return name;
2380c486
JR
4439+}
4440+
9474138d 4441+/**
76514441
AM
4442+ * aa_info_message - log a none profile related status message
4443+ * @str: message to log
4444+ */
4445+void aa_info_message(const char *str)
4446+{
4447+ if (audit_enabled) {
4448+ struct common_audit_data sa;
4449+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
4450+ sa.aad.info = str;
4451+ aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
4452+ }
4453+ printk(KERN_INFO "AppArmor: %s\n", str);
4454+}
4455+
4456+/**
4457+ * kvmalloc - do allocation preferring kmalloc but falling back to vmalloc
4458+ * @size: size of allocation
9474138d 4459+ *
76514441
AM
4460+ * Return: allocated buffer or NULL if failed
4461+ *
4462+ * It is possible that policy being loaded from the user is larger than
4463+ * what can be allocated by kmalloc, in those cases fall back to vmalloc.
9474138d 4464+ */
76514441 4465+void *kvmalloc(size_t size)
9474138d 4466+{
76514441
AM
4467+ void *buffer = NULL;
4468+
4469+ if (size == 0)
4470+ return NULL;
4471+
4472+ /* do not attempt kmalloc if we need more than 16 pages at once */
4473+ if (size <= (16*PAGE_SIZE))
4474+ buffer = kmalloc(size, GFP_NOIO | __GFP_NOWARN);
4475+ if (!buffer) {
4476+ /* see kvfree for why size must be at least work_struct size
4477+ * when allocated via vmalloc
4478+ */
4479+ if (size < sizeof(struct work_struct))
4480+ size = sizeof(struct work_struct);
4481+ buffer = vmalloc(size);
4482+ }
4483+ return buffer;
9474138d 4484+}
2380c486 4485+
76514441
AM
4486+/**
4487+ * do_vfree - workqueue routine for freeing vmalloced memory
4488+ * @work: data to be freed
4489+ *
4490+ * The work_struct is overlaid to the data being freed, as at the point
4491+ * the work is scheduled the data is no longer valid, be its freeing
4492+ * needs to be delayed until safe.
4493+ */
4494+static void do_vfree(struct work_struct *work)
9474138d 4495+{
76514441 4496+ vfree(work);
2380c486 4497+}
ceaf2cfb 4498+
76514441
AM
4499+/**
4500+ * kvfree - free an allocation do by kvmalloc
4501+ * @buffer: buffer to free (MAYBE_NULL)
4502+ *
4503+ * Free a buffer allocated by kvmalloc
4504+ */
4505+void kvfree(void *buffer)
4506+{
4507+ if (is_vmalloc_addr(buffer)) {
4508+ /* Data is no longer valid so just use the allocated space
4509+ * as the work_struct
4510+ */
4511+ struct work_struct *work = (struct work_struct *) buffer;
4512+ INIT_WORK(work, do_vfree);
4513+ schedule_work(work);
4514+ } else
4515+ kfree(buffer);
4516+}
ceaf2cfb
AM
4517diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
4518new file mode 100644
76514441 4519index 0000000..e8d0821
ceaf2cfb
AM
4520--- /dev/null
4521+++ b/security/apparmor/lsm.c
76514441 4522@@ -0,0 +1,1051 @@
9474138d
AM
4523+/*
4524+ * AppArmor security module
4525+ *
4526+ * This file contains AppArmor LSM hooks.
4527+ *
4528+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 4529+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
4530+ *
4531+ * This program is free software; you can redistribute it and/or
4532+ * modify it under the terms of the GNU General Public License as
4533+ * published by the Free Software Foundation, version 2 of the
4534+ * License.
4535+ */
2380c486 4536+
9474138d
AM
4537+#include <linux/security.h>
4538+#include <linux/moduleparam.h>
4539+#include <linux/mm.h>
4540+#include <linux/mman.h>
4541+#include <linux/mount.h>
4542+#include <linux/namei.h>
4543+#include <linux/ptrace.h>
4544+#include <linux/ctype.h>
4545+#include <linux/sysctl.h>
4546+#include <linux/audit.h>
4547+#include <net/sock.h>
4548+
4549+#include "include/apparmor.h"
4550+#include "include/apparmorfs.h"
4551+#include "include/audit.h"
4552+#include "include/capability.h"
4553+#include "include/context.h"
4554+#include "include/file.h"
4555+#include "include/ipc.h"
4556+#include "include/net.h"
4557+#include "include/path.h"
4558+#include "include/policy.h"
4559+#include "include/procattr.h"
4560+
4561+/* Flag indicating whether initialization completed */
76514441 4562+int apparmor_initialized __initdata;
9474138d 4563+
9474138d
AM
4564+/*
4565+ * LSM hook functions
4566+ */
4567+
4568+/*
ceaf2cfb
AM
4569+ * free the associated aa_task_cxt and put its profiles
4570+ */
4571+static void apparmor_cred_free(struct cred *cred)
4572+{
4573+ aa_free_task_context(cred->security);
4574+ cred->security = NULL;
4575+}
4576+
4577+/*
4578+ * allocate the apparmor part of blank credentials
4579+ */
4580+static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp)
4581+{
4582+ /* freed by apparmor_cred_free */
4583+ struct aa_task_cxt *cxt = aa_alloc_task_context(gfp);
4584+ if (!cxt)
4585+ return -ENOMEM;
4586+
4587+ cred->security = cxt;
4588+ return 0;
4589+}
4590+
4591+/*
4592+ * prepare new aa_task_cxt for modification by prepare_cred block
9474138d
AM
4593+ */
4594+static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
4595+ gfp_t gfp)
2380c486 4596+{
ceaf2cfb
AM
4597+ /* freed by apparmor_cred_free */
4598+ struct aa_task_cxt *cxt = aa_alloc_task_context(gfp);
9474138d
AM
4599+ if (!cxt)
4600+ return -ENOMEM;
ceaf2cfb
AM
4601+
4602+ aa_dup_task_context(cxt, old->security);
9474138d
AM
4603+ new->security = cxt;
4604+ return 0;
2380c486
JR
4605+}
4606+
9474138d 4607+/*
ceaf2cfb 4608+ * transfer the apparmor data to a blank set of creds
9474138d 4609+ */
ceaf2cfb 4610+static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
2380c486 4611+{
ceaf2cfb
AM
4612+ const struct aa_task_cxt *old_cxt = old->security;
4613+ struct aa_task_cxt *new_cxt = new->security;
2380c486 4614+
ceaf2cfb
AM
4615+ aa_dup_task_context(new_cxt, old_cxt);
4616+}
9474138d 4617+
ceaf2cfb
AM
4618+static int apparmor_ptrace_access_check(struct task_struct *child,
4619+ unsigned int mode)
2380c486 4620+{
76514441
AM
4621+ int error = cap_ptrace_access_check(child, mode);
4622+ if (error)
4623+ return error;
ceaf2cfb 4624+
9474138d 4625+ return aa_ptrace(current, child, mode);
2380c486
JR
4626+}
4627+
9474138d 4628+static int apparmor_ptrace_traceme(struct task_struct *parent)
2380c486 4629+{
76514441
AM
4630+ int error = cap_ptrace_traceme(parent);
4631+ if (error)
4632+ return error;
4633+
9474138d 4634+ return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
2380c486
JR
4635+}
4636+
9474138d
AM
4637+/* Derived from security/commoncap.c:cap_capget */
4638+static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
4639+ kernel_cap_t *inheritable, kernel_cap_t *permitted)
2380c486
JR
4640+{
4641+ struct aa_profile *profile;
9474138d 4642+ const struct cred *cred;
2380c486 4643+
9474138d
AM
4644+ rcu_read_lock();
4645+ cred = __task_cred(target);
ceaf2cfb 4646+ profile = aa_cred_profile(cred);
2380c486 4647+
ceaf2cfb 4648+ *effective = cred->cap_effective;
9474138d 4649+ *inheritable = cred->cap_inheritable;
ceaf2cfb 4650+ *permitted = cred->cap_permitted;
2380c486 4651+
76514441
AM
4652+ if (!unconfined(profile)) {
4653+ *effective = cap_intersect(*effective, profile->caps.allow);
4654+ *permitted = cap_intersect(*permitted, profile->caps.allow);
4655+ }
9474138d 4656+ rcu_read_unlock();
2380c486 4657+
9474138d 4658+ return 0;
2380c486
JR
4659+}
4660+
9474138d
AM
4661+static int apparmor_capable(struct task_struct *task, const struct cred *cred,
4662+ int cap, int audit)
2380c486 4663+{
9474138d
AM
4664+ struct aa_profile *profile;
4665+ /* cap_capable returns 0 on success, else -EPERM */
4666+ int error = cap_capable(task, cred, cap, audit);
76514441
AM
4667+ if (!error) {
4668+ profile = aa_cred_profile(cred);
4669+ if (!unconfined(profile))
4670+ error = aa_capable(task, profile, cap, audit);
9474138d 4671+ }
9474138d 4672+ return error;
2380c486
JR
4673+}
4674+
ceaf2cfb
AM
4675+/**
4676+ * common_perm - basic common permission check wrapper fn for paths
76514441 4677+ * @op: operation being checked
ceaf2cfb
AM
4678+ * @path: path to check permission of (NOT NULL)
4679+ * @mask: requested permissions mask
4680+ * @cond: conditional info for the permission request (NOT NULL)
4681+ *
4682+ * Returns: %0 else error code if error or permission denied
4683+ */
76514441 4684+static int common_perm(int op, struct path *path, u32 mask,
9474138d 4685+ struct path_cond *cond)
2380c486
JR
4686+{
4687+ struct aa_profile *profile;
9474138d 4688+ int error = 0;
2380c486 4689+
ceaf2cfb
AM
4690+ profile = __aa_current_profile();
4691+ if (!unconfined(profile))
76514441 4692+ error = aa_path_perm(op, profile, path, 0, mask, cond);
2380c486 4693+
9474138d 4694+ return error;
2380c486
JR
4695+}
4696+
ceaf2cfb 4697+/**
76514441
AM
4698+ * common_perm_dir_dentry - common permission wrapper when path is dir, dentry
4699+ * @op: operation being checked
ceaf2cfb
AM
4700+ * @dir: directory of the dentry (NOT NULL)
4701+ * @dentry: dentry to check (NOT NULL)
4702+ * @mask: requested permissions mask
4703+ * @cond: conditional info for the permission request (NOT NULL)
4704+ *
4705+ * Returns: %0 else error code if error or permission denied
4706+ */
76514441
AM
4707+static int common_perm_dir_dentry(int op, struct path *dir,
4708+ struct dentry *dentry, u32 mask,
4709+ struct path_cond *cond)
2380c486 4710+{
9474138d 4711+ struct path path = { dir->mnt, dentry };
2380c486 4712+
9474138d 4713+ return common_perm(op, &path, mask, cond);
2380c486
JR
4714+}
4715+
ceaf2cfb 4716+/**
76514441
AM
4717+ * common_perm_mnt_dentry - common permission wrapper when mnt, dentry
4718+ * @op: operation being checked
4719+ * @mnt: mount point of dentry (NOT NULL)
4720+ * @dentry: dentry to check (NOT NULL)
4721+ * @mask: requested permissions mask
4722+ *
4723+ * Returns: %0 else error code if error or permission denied
4724+ */
4725+static int common_perm_mnt_dentry(int op, struct vfsmount *mnt,
4726+ struct dentry *dentry, u32 mask)
4727+{
4728+ struct path path = { mnt, dentry };
4729+ struct path_cond cond = { dentry->d_inode->i_uid,
4730+ dentry->d_inode->i_mode
4731+ };
4732+
4733+ return common_perm(op, &path, mask, &cond);
4734+}
4735+
4736+/**
ceaf2cfb 4737+ * common_perm_rm - common permission wrapper for operations doing rm
76514441 4738+ * @op: operation being checked
ceaf2cfb
AM
4739+ * @dir: directory that the dentry is in (NOT NULL)
4740+ * @dentry: dentry being rm'd (NOT NULL)
4741+ * @mask: requested permission mask
4742+ *
4743+ * Returns: %0 else error code if error or permission denied
4744+ */
76514441
AM
4745+static int common_perm_rm(int op, struct path *dir,
4746+ struct dentry *dentry, u32 mask)
2380c486 4747+{
9474138d 4748+ struct inode *inode = dentry->d_inode;
ceaf2cfb 4749+ struct path_cond cond = { };
2380c486 4750+
76514441 4751+ if (!inode || !dir->mnt || !mediated_filesystem(inode))
2380c486
JR
4752+ return 0;
4753+
9474138d
AM
4754+ cond.uid = inode->i_uid;
4755+ cond.mode = inode->i_mode;
2380c486 4756+
76514441 4757+ return common_perm_dir_dentry(op, dir, dentry, mask, &cond);
2380c486
JR
4758+}
4759+
ceaf2cfb
AM
4760+/**
4761+ * common_perm_create - common permission wrapper for operations doing create
76514441 4762+ * @op: operation being checked
ceaf2cfb
AM
4763+ * @dir: directory that dentry will be created in (NOT NULL)
4764+ * @dentry: dentry to create (NOT NULL)
4765+ * @mask: request permission mask
4766+ * @mode: created file mode
4767+ *
4768+ * Returns: %0 else error code if error or permission denied
4769+ */
76514441
AM
4770+static int common_perm_create(int op, struct path *dir, struct dentry *dentry,
4771+ u32 mask, umode_t mode)
2380c486 4772+{
9474138d
AM
4773+ struct path_cond cond = { current_fsuid(), mode };
4774+
4775+ if (!dir->mnt || !mediated_filesystem(dir->dentry->d_inode))
4776+ return 0;
2380c486 4777+
76514441 4778+ return common_perm_dir_dentry(op, dir, dentry, mask, &cond);
2380c486
JR
4779+}
4780+
9474138d 4781+static int apparmor_path_unlink(struct path *dir, struct dentry *dentry)
2380c486 4782+{
76514441 4783+ return common_perm_rm(OP_UNLINK, dir, dentry, AA_MAY_DELETE);
2380c486
JR
4784+}
4785+
9474138d
AM
4786+static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry,
4787+ int mode)
2380c486 4788+{
76514441
AM
4789+ return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE,
4790+ S_IFDIR);
2380c486
JR
4791+}
4792+
9474138d
AM
4793+static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry)
4794+{
76514441 4795+ return common_perm_rm(OP_RMDIR, dir, dentry, AA_MAY_DELETE);
9474138d
AM
4796+}
4797+
4798+static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
4799+ int mode, unsigned int dev)
4800+{
76514441 4801+ return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode);
9474138d
AM
4802+}
4803+
4804+static int apparmor_path_truncate(struct path *path, loff_t length,
4805+ unsigned int time_attrs)
4806+{
4807+ struct path_cond cond = { path->dentry->d_inode->i_uid,
ceaf2cfb
AM
4808+ path->dentry->d_inode->i_mode
4809+ };
9474138d
AM
4810+
4811+ if (!path->mnt || !mediated_filesystem(path->dentry->d_inode))
4812+ return 0;
76514441
AM
4813+
4814+ return common_perm(OP_TRUNC, path, MAY_WRITE | AA_MAY_META_WRITE,
4815+ &cond);
9474138d
AM
4816+}
4817+
4818+static int apparmor_path_symlink(struct path *dir, struct dentry *dentry,
ceaf2cfb 4819+ const char *old_name)
2380c486 4820+{
76514441 4821+ return common_perm_create(OP_SYMLINK, dir, dentry, AA_MAY_CREATE,
9474138d 4822+ S_IFLNK);
2380c486
JR
4823+}
4824+
9474138d
AM
4825+static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir,
4826+ struct dentry *new_dentry)
2380c486
JR
4827+{
4828+ struct aa_profile *profile;
4829+ int error = 0;
4830+
9474138d 4831+ if (!mediated_filesystem(old_dentry->d_inode))
2380c486
JR
4832+ return 0;
4833+
ceaf2cfb
AM
4834+ profile = aa_current_profile();
4835+ if (!unconfined(profile))
9474138d 4836+ error = aa_path_link(profile, old_dentry, new_dir, new_dentry);
2380c486
JR
4837+ return error;
4838+}
4839+
9474138d 4840+static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
ceaf2cfb 4841+ struct path *new_dir, struct dentry *new_dentry)
2380c486 4842+{
9474138d
AM
4843+ struct aa_profile *profile;
4844+ int error = 0;
2380c486 4845+
9474138d 4846+ if (!mediated_filesystem(old_dentry->d_inode))
2380c486
JR
4847+ return 0;
4848+
ceaf2cfb
AM
4849+ profile = aa_current_profile();
4850+ if (!unconfined(profile)) {
9474138d
AM
4851+ struct path old_path = { old_dir->mnt, old_dentry };
4852+ struct path new_path = { new_dir->mnt, new_dentry };
4853+ struct path_cond cond = { old_dentry->d_inode->i_uid,
ceaf2cfb
AM
4854+ old_dentry->d_inode->i_mode
4855+ };
9474138d 4856+
76514441
AM
4857+ error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0,
4858+ MAY_READ | AA_MAY_META_READ | MAY_WRITE |
4859+ AA_MAY_META_WRITE | AA_MAY_DELETE,
4860+ &cond);
9474138d 4861+ if (!error)
76514441
AM
4862+ error = aa_path_perm(OP_RENAME_DEST, profile, &new_path,
4863+ 0, MAY_WRITE | AA_MAY_META_WRITE |
4864+ AA_MAY_CREATE, &cond);
ceaf2cfb
AM
4865+
4866+ }
4867+ return error;
4868+}
4869+
4870+static int apparmor_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
4871+ mode_t mode)
4872+{
ceaf2cfb
AM
4873+ if (!mediated_filesystem(dentry->d_inode))
4874+ return 0;
4875+
76514441 4876+ return common_perm_mnt_dentry(OP_CHMOD, mnt, dentry, AA_MAY_CHMOD);
ceaf2cfb
AM
4877+}
4878+
4879+static int apparmor_path_chown(struct path *path, uid_t uid, gid_t gid)
4880+{
76514441
AM
4881+ struct path_cond cond = { path->dentry->d_inode->i_uid,
4882+ path->dentry->d_inode->i_mode
4883+ };
ceaf2cfb
AM
4884+
4885+ if (!mediated_filesystem(path->dentry->d_inode))
4886+ return 0;
4887+
76514441
AM
4888+ return common_perm(OP_CHOWN, path, AA_MAY_CHOWN, &cond);
4889+}
ceaf2cfb 4890+
76514441
AM
4891+static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
4892+{
4893+ if (!mediated_filesystem(dentry->d_inode))
4894+ return 0;
4895+
4896+ return common_perm_mnt_dentry(OP_GETATTR, mnt, dentry,
4897+ AA_MAY_META_READ);
2380c486
JR
4898+}
4899+
9474138d 4900+static int apparmor_dentry_open(struct file *file, const struct cred *cred)
2380c486 4901+{
76514441 4902+ struct aa_file_cxt *fcxt = file->f_security;
9474138d
AM
4903+ struct aa_profile *profile;
4904+ int error = 0;
ceaf2cfb 4905+
76514441
AM
4906+ if (!mediated_filesystem(file->f_path.dentry->d_inode))
4907+ return 0;
4908+
4909+ /* If in exec, permission is handled by bprm hooks.
4910+ * Cache permissions granted by the previous exec check, with
4911+ * implicit read and executable mmap which are required to
4912+ * actually execute the image.
4913+ */
4914+ if (current->in_execve) {
4915+ fcxt->allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP;
9474138d 4916+ return 0;
76514441 4917+ }
2380c486 4918+
ceaf2cfb
AM
4919+ profile = aa_cred_profile(cred);
4920+ if (!unconfined(profile)) {
ceaf2cfb 4921+ struct inode *inode = file->f_path.dentry->d_inode;
9474138d 4922+ struct path_cond cond = { inode->i_uid, inode->i_mode };
2380c486 4923+
76514441 4924+ error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0,
9474138d 4925+ aa_map_file_to_perms(file), &cond);
76514441
AM
4926+ /* todo cache full allowed permissions set and state */
4927+ fcxt->allow = aa_map_file_to_perms(file);
9474138d 4928+ }
2380c486 4929+
9474138d 4930+ return error;
2380c486
JR
4931+}
4932+
9474138d 4933+static int apparmor_file_alloc_security(struct file *file)
2380c486 4934+{
ceaf2cfb 4935+ /* freed by apparmor_file_free_security */
9474138d
AM
4936+ file->f_security = aa_alloc_file_context(GFP_KERNEL);
4937+ if (!file->f_security)
4938+ return -ENOMEM;
4939+ return 0;
2380c486 4940+
2380c486
JR
4941+}
4942+
9474138d 4943+static void apparmor_file_free_security(struct file *file)
2380c486 4944+{
9474138d 4945+ struct aa_file_cxt *cxt = file->f_security;
2380c486 4946+
9474138d 4947+ aa_free_file_context(cxt);
2380c486
JR
4948+}
4949+
76514441 4950+static int common_file_perm(int op, struct file *file, u32 mask)
2380c486 4951+{
9474138d 4952+ struct aa_file_cxt *fcxt = file->f_security;
76514441 4953+ struct aa_profile *profile, *fprofile = aa_cred_profile(file->f_cred);
9474138d 4954+ int error = 0;
2380c486 4955+
76514441
AM
4956+ BUG_ON(!fprofile);
4957+
4958+ if (!file->f_path.mnt ||
9474138d
AM
4959+ !mediated_filesystem(file->f_path.dentry->d_inode))
4960+ return 0;
4961+
ceaf2cfb
AM
4962+ profile = __aa_current_profile();
4963+
76514441
AM
4964+ /* revalidate access, if task is unconfined, or the cached cred
4965+ * doesn't match or if the request is for more permissions than
4966+ * was granted.
4967+ *
4968+ * Note: the test for !unconfined(fprofile) is to handle file
4969+ * delegation from unconfined tasks
ceaf2cfb 4970+ */
76514441
AM
4971+ if (!unconfined(profile) && !unconfined(fprofile) &&
4972+ ((fprofile != profile) || (mask & ~fcxt->allow)))
4973+ error = aa_file_perm(op, profile, file, mask);
9474138d
AM
4974+
4975+ return error;
2380c486
JR
4976+}
4977+
76514441 4978+static int apparmor_file_permission(struct file *file, int mask)
2380c486 4979+{
76514441 4980+ return common_file_perm(OP_FPERM, file, mask);
2380c486
JR
4981+}
4982+
9474138d 4983+static int apparmor_file_lock(struct file *file, unsigned int cmd)
2380c486 4984+{
76514441 4985+ u32 mask = AA_MAY_LOCK;
2380c486 4986+
9474138d
AM
4987+ if (cmd == F_WRLCK)
4988+ mask |= MAY_WRITE;
4989+
76514441 4990+ return common_file_perm(OP_FLOCK, file, mask);
2380c486
JR
4991+}
4992+
76514441
AM
4993+static int common_mmap(int op, struct file *file, unsigned long prot,
4994+ unsigned long flags)
2380c486 4995+{
9474138d
AM
4996+ struct dentry *dentry;
4997+ int mask = 0;
2380c486 4998+
9474138d
AM
4999+ if (!file || !file->f_security)
5000+ return 0;
5001+
5002+ if (prot & PROT_READ)
5003+ mask |= MAY_READ;
ceaf2cfb
AM
5004+ /*
5005+ * Private mappings don't require write perms since they don't
5006+ * write back to the files
5007+ */
9474138d
AM
5008+ if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
5009+ mask |= MAY_WRITE;
5010+ if (prot & PROT_EXEC)
5011+ mask |= AA_EXEC_MMAP;
5012+
5013+ dentry = file->f_path.dentry;
76514441 5014+ return common_file_perm(op, file, mask);
2380c486
JR
5015+}
5016+
9474138d
AM
5017+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
5018+ unsigned long prot, unsigned long flags,
5019+ unsigned long addr, unsigned long addr_only)
2380c486 5020+{
ceaf2cfb
AM
5021+ int rc = 0;
5022+
5023+ /* do DAC check */
5024+ rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
5025+ if (rc || addr_only)
5026+ return rc;
2380c486 5027+
76514441 5028+ return common_mmap(OP_FMMAP, file, prot, flags);
2380c486
JR
5029+}
5030+
9474138d
AM
5031+static int apparmor_file_mprotect(struct vm_area_struct *vma,
5032+ unsigned long reqprot, unsigned long prot)
2380c486 5033+{
76514441 5034+ return common_mmap(OP_FMPROT, vma->vm_file, prot,
ceaf2cfb 5035+ !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
2380c486
JR
5036+}
5037+
5038+static int apparmor_getprocattr(struct task_struct *task, char *name,
5039+ char **value)
5040+{
9474138d 5041+ int error = -ENOENT;
ceaf2cfb
AM
5042+ struct aa_profile *profile;
5043+ /* released below */
5044+ const struct cred *cred = get_task_cred(task);
5045+ struct aa_task_cxt *cxt = cred->security;
5046+ profile = aa_cred_profile(cred);
5047+
5048+ if (strcmp(name, "current") == 0)
5049+ error = aa_getprocattr(aa_newest_version(cxt->profile),
5050+ value);
5051+ else if (strcmp(name, "prev") == 0 && cxt->previous)
5052+ error = aa_getprocattr(aa_newest_version(cxt->previous),
5053+ value);
5054+ else if (strcmp(name, "exec") == 0 && cxt->onexec)
5055+ error = aa_getprocattr(aa_newest_version(cxt->onexec),
5056+ value);
5057+ else
5058+ error = -EINVAL;
2380c486 5059+
9474138d 5060+ put_cred(cred);
2380c486
JR
5061+
5062+ return error;
5063+}
5064+
5065+static int apparmor_setprocattr(struct task_struct *task, char *name,
5066+ void *value, size_t size)
5067+{
76514441 5068+ char *command, *args = value;
ceaf2cfb 5069+ size_t arg_size;
2380c486
JR
5070+ int error;
5071+
76514441 5072+ if (size == 0)
2380c486 5073+ return -EINVAL;
76514441
AM
5074+ /* args points to a PAGE_SIZE buffer, AppArmor requires that
5075+ * the buffer must be null terminated or have size <= PAGE_SIZE -1
5076+ * so that AppArmor can null terminate them
5077+ */
5078+ if (args[size - 1] != '\0') {
5079+ if (size == PAGE_SIZE)
5080+ return -EINVAL;
5081+ args[size] = '\0';
5082+ }
9474138d
AM
5083+
5084+ /* task can only write its own attributes */
5085+ if (current != task)
5086+ return -EACCES;
5087+
2380c486 5088+ args = value;
ceaf2cfb 5089+ args = strim(args);
2380c486
JR
5090+ command = strsep(&args, " ");
5091+ if (!args)
5092+ return -EINVAL;
ceaf2cfb 5093+ args = skip_spaces(args);
2380c486
JR
5094+ if (!*args)
5095+ return -EINVAL;
5096+
ceaf2cfb 5097+ arg_size = size - (args - (char *) value);
9474138d
AM
5098+ if (strcmp(name, "current") == 0) {
5099+ if (strcmp(command, "changehat") == 0) {
ceaf2cfb
AM
5100+ error = aa_setprocattr_changehat(args, arg_size,
5101+ !AA_DO_TEST);
9474138d 5102+ } else if (strcmp(command, "permhat") == 0) {
ceaf2cfb
AM
5103+ error = aa_setprocattr_changehat(args, arg_size,
5104+ AA_DO_TEST);
9474138d 5105+ } else if (strcmp(command, "changeprofile") == 0) {
ceaf2cfb 5106+ error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
9474138d
AM
5107+ !AA_DO_TEST);
5108+ } else if (strcmp(command, "permprofile") == 0) {
ceaf2cfb 5109+ error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
9474138d
AM
5110+ AA_DO_TEST);
5111+ } else if (strcmp(command, "permipc") == 0) {
5112+ error = aa_setprocattr_permipc(args);
5113+ } else {
76514441
AM
5114+ struct common_audit_data sa;
5115+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
5116+ sa.aad.op = OP_SETPROCATTR;
5117+ sa.aad.info = name;
5118+ sa.aad.error = -EINVAL;
5119+ return aa_audit(AUDIT_APPARMOR_DENIED, NULL, GFP_KERNEL,
5120+ &sa, NULL);
2380c486 5121+ }
9474138d 5122+ } else if (strcmp(name, "exec") == 0) {
ceaf2cfb 5123+ error = aa_setprocattr_changeprofile(args, AA_ONEXEC,
9474138d 5124+ !AA_DO_TEST);
2380c486 5125+ } else {
9474138d 5126+ /* only support the "current" and "exec" process attributes */
2380c486
JR
5127+ return -EINVAL;
5128+ }
2380c486
JR
5129+ if (!error)
5130+ error = size;
5131+ return error;
5132+}
5133+
5134+static int apparmor_task_setrlimit(unsigned int resource,
5135+ struct rlimit *new_rlim)
5136+{
ceaf2cfb 5137+ struct aa_profile *profile = aa_current_profile();
2380c486
JR
5138+ int error = 0;
5139+
ceaf2cfb 5140+ if (!unconfined(profile))
2380c486 5141+ error = aa_task_setrlimit(profile, resource, new_rlim);
2380c486
JR
5142+
5143+ return error;
5144+}
5145+
ceaf2cfb
AM
5146+static int apparmor_socket_create(int family, int type, int protocol, int kern)
5147+{
9474138d
AM
5148+ struct aa_profile *profile;
5149+ int error = 0;
2380c486 5150+
9474138d
AM
5151+ if (kern)
5152+ return 0;
2380c486 5153+
ceaf2cfb
AM
5154+ profile = __aa_current_profile();
5155+ if (!unconfined(profile))
76514441
AM
5156+ error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
5157+ NULL);
9474138d 5158+ return error;
2380c486
JR
5159+}
5160+
9474138d
AM
5161+static int apparmor_socket_bind(struct socket *sock,
5162+ struct sockaddr *address, int addrlen)
2380c486 5163+{
9474138d 5164+ struct sock *sk = sock->sk;
2380c486 5165+
76514441 5166+ return aa_revalidate_sk(OP_BIND, sk);
2380c486
JR
5167+}
5168+
9474138d 5169+static int apparmor_socket_connect(struct socket *sock,
ceaf2cfb 5170+ struct sockaddr *address, int addrlen)
9474138d
AM
5171+{
5172+ struct sock *sk = sock->sk;
2380c486 5173+
76514441 5174+ return aa_revalidate_sk(OP_CONNECT, sk);
9474138d 5175+}
2380c486 5176+
9474138d
AM
5177+static int apparmor_socket_listen(struct socket *sock, int backlog)
5178+{
5179+ struct sock *sk = sock->sk;
2380c486 5180+
76514441 5181+ return aa_revalidate_sk(OP_LISTEN, sk);
9474138d 5182+}
2380c486 5183+
9474138d
AM
5184+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
5185+{
5186+ struct sock *sk = sock->sk;
2380c486 5187+
76514441 5188+ return aa_revalidate_sk(OP_ACCEPT, sk);
9474138d 5189+}
2380c486 5190+
9474138d 5191+static int apparmor_socket_sendmsg(struct socket *sock,
ceaf2cfb 5192+ struct msghdr *msg, int size)
2380c486 5193+{
9474138d
AM
5194+ struct sock *sk = sock->sk;
5195+
76514441 5196+ return aa_revalidate_sk(OP_SENDMSG, sk);
2380c486
JR
5197+}
5198+
9474138d
AM
5199+static int apparmor_socket_recvmsg(struct socket *sock,
5200+ struct msghdr *msg, int size, int flags)
2380c486 5201+{
9474138d 5202+ struct sock *sk = sock->sk;
2380c486 5203+
76514441 5204+ return aa_revalidate_sk(OP_RECVMSG, sk);
2380c486
JR
5205+}
5206+
9474138d 5207+static int apparmor_socket_getsockname(struct socket *sock)
2380c486 5208+{
9474138d
AM
5209+ struct sock *sk = sock->sk;
5210+
76514441 5211+ return aa_revalidate_sk(OP_GETSOCKNAME, sk);
2380c486
JR
5212+}
5213+
9474138d 5214+static int apparmor_socket_getpeername(struct socket *sock)
2380c486 5215+{
9474138d 5216+ struct sock *sk = sock->sk;
2380c486 5217+
76514441 5218+ return aa_revalidate_sk(OP_GETPEERNAME, sk);
2380c486
JR
5219+}
5220+
9474138d 5221+static int apparmor_socket_getsockopt(struct socket *sock, int level,
ceaf2cfb 5222+ int optname)
2380c486 5223+{
9474138d 5224+ struct sock *sk = sock->sk;
2380c486 5225+
76514441 5226+ return aa_revalidate_sk(OP_GETSOCKOPT, sk);
2380c486
JR
5227+}
5228+
9474138d 5229+static int apparmor_socket_setsockopt(struct socket *sock, int level,
ceaf2cfb 5230+ int optname)
9474138d
AM
5231+{
5232+ struct sock *sk = sock->sk;
2380c486 5233+
76514441 5234+ return aa_revalidate_sk(OP_SETSOCKOPT, sk);
9474138d 5235+}
2380c486 5236+
9474138d 5237+static int apparmor_socket_shutdown(struct socket *sock, int how)
2380c486 5238+{
9474138d 5239+ struct sock *sk = sock->sk;
2380c486 5240+
76514441 5241+ return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
9474138d 5242+}
2380c486 5243+
9474138d
AM
5244+static struct security_operations apparmor_ops = {
5245+ .name = "apparmor",
2380c486 5246+
ceaf2cfb 5247+ .ptrace_access_check = apparmor_ptrace_access_check,
9474138d
AM
5248+ .ptrace_traceme = apparmor_ptrace_traceme,
5249+ .capget = apparmor_capget,
9474138d 5250+ .capable = apparmor_capable,
9474138d
AM
5251+
5252+ .path_link = apparmor_path_link,
5253+ .path_unlink = apparmor_path_unlink,
5254+ .path_symlink = apparmor_path_symlink,
5255+ .path_mkdir = apparmor_path_mkdir,
5256+ .path_rmdir = apparmor_path_rmdir,
5257+ .path_mknod = apparmor_path_mknod,
5258+ .path_rename = apparmor_path_rename,
ceaf2cfb
AM
5259+ .path_chmod = apparmor_path_chmod,
5260+ .path_chown = apparmor_path_chown,
9474138d
AM
5261+ .path_truncate = apparmor_path_truncate,
5262+ .dentry_open = apparmor_dentry_open,
76514441 5263+ .inode_getattr = apparmor_inode_getattr,
2380c486 5264+
9474138d
AM
5265+ .file_permission = apparmor_file_permission,
5266+ .file_alloc_security = apparmor_file_alloc_security,
5267+ .file_free_security = apparmor_file_free_security,
5268+ .file_mmap = apparmor_file_mmap,
5269+ .file_mprotect = apparmor_file_mprotect,
5270+ .file_lock = apparmor_file_lock,
2380c486 5271+
9474138d
AM
5272+ .getprocattr = apparmor_getprocattr,
5273+ .setprocattr = apparmor_setprocattr,
2380c486 5274+
9474138d 5275+ .socket_create = apparmor_socket_create,
9474138d
AM
5276+ .socket_bind = apparmor_socket_bind,
5277+ .socket_connect = apparmor_socket_connect,
5278+ .socket_listen = apparmor_socket_listen,
5279+ .socket_accept = apparmor_socket_accept,
5280+ .socket_sendmsg = apparmor_socket_sendmsg,
5281+ .socket_recvmsg = apparmor_socket_recvmsg,
5282+ .socket_getsockname = apparmor_socket_getsockname,
5283+ .socket_getpeername = apparmor_socket_getpeername,
5284+ .socket_getsockopt = apparmor_socket_getsockopt,
5285+ .socket_setsockopt = apparmor_socket_setsockopt,
5286+ .socket_shutdown = apparmor_socket_shutdown,
2380c486 5287+
ceaf2cfb 5288+ .cred_alloc_blank = apparmor_cred_alloc_blank,
9474138d
AM
5289+ .cred_free = apparmor_cred_free,
5290+ .cred_prepare = apparmor_cred_prepare,
ceaf2cfb 5291+ .cred_transfer = apparmor_cred_transfer,
2380c486 5292+
9474138d 5293+ .bprm_set_creds = apparmor_bprm_set_creds,
ceaf2cfb 5294+ .bprm_committing_creds = apparmor_bprm_committing_creds,
9474138d
AM
5295+ .bprm_committed_creds = apparmor_bprm_committed_creds,
5296+ .bprm_secureexec = apparmor_bprm_secureexec,
2380c486 5297+
9474138d
AM
5298+ .task_setrlimit = apparmor_task_setrlimit,
5299+};
2380c486 5300+
9474138d
AM
5301+/*
5302+ * AppArmor sysfs module parameters
5303+ */
2380c486 5304+
9474138d
AM
5305+static int param_set_aabool(const char *val, struct kernel_param *kp);
5306+static int param_get_aabool(char *buffer, struct kernel_param *kp);
5307+#define param_check_aabool(name, p) __param_check(name, p, int)
2380c486 5308+
9474138d
AM
5309+static int param_set_aauint(const char *val, struct kernel_param *kp);
5310+static int param_get_aauint(char *buffer, struct kernel_param *kp);
5311+#define param_check_aauint(name, p) __param_check(name, p, int)
2380c486 5312+
9474138d
AM
5313+static int param_set_aalockpolicy(const char *val, struct kernel_param *kp);
5314+static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp);
5315+#define param_check_aalockpolicy(name, p) __param_check(name, p, int)
2380c486 5316+
9474138d
AM
5317+static int param_set_audit(const char *val, struct kernel_param *kp);
5318+static int param_get_audit(char *buffer, struct kernel_param *kp);
5319+#define param_check_audit(name, p) __param_check(name, p, int)
2380c486 5320+
9474138d
AM
5321+static int param_set_mode(const char *val, struct kernel_param *kp);
5322+static int param_get_mode(char *buffer, struct kernel_param *kp);
5323+#define param_check_mode(name, p) __param_check(name, p, int)
2380c486 5324+
9474138d
AM
5325+/* Flag values, also controllable via /sys/module/apparmor/parameters
5326+ * We define special types as we want to do additional mediation.
5327+ */
2380c486 5328+
9474138d 5329+/* AppArmor global enforcement switch - complain, enforce, kill */
ceaf2cfb 5330+enum profile_mode aa_g_profile_mode = APPARMOR_ENFORCE;
9474138d 5331+module_param_call(mode, param_set_mode, param_get_mode,
ceaf2cfb 5332+ &aa_g_profile_mode, S_IRUSR | S_IWUSR);
2380c486 5333+
9474138d 5334+/* Debug mode */
ceaf2cfb
AM
5335+int aa_g_debug;
5336+module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR);
2380c486 5337+
9474138d 5338+/* Audit mode */
ceaf2cfb 5339+enum audit_mode aa_g_audit;
9474138d 5340+module_param_call(audit, param_set_audit, param_get_audit,
ceaf2cfb 5341+ &aa_g_audit, S_IRUSR | S_IWUSR);
2380c486 5342+
9474138d
AM
5343+/* Determines if audit header is included in audited messages. This
5344+ * provides more context if the audit daemon is not running
5345+ */
76514441 5346+int aa_g_audit_header = 1;
ceaf2cfb 5347+module_param_named(audit_header, aa_g_audit_header, aabool,
9474138d 5348+ S_IRUSR | S_IWUSR);
2380c486 5349+
9474138d
AM
5350+/* lock out loading/removal of policy
5351+ * TODO: add in at boot loading of policy, which is the only way to
5352+ * load policy, if lock_policy is set
2380c486 5353+ */
ceaf2cfb
AM
5354+int aa_g_lock_policy;
5355+module_param_named(lock_policy, aa_g_lock_policy, aalockpolicy,
9474138d 5356+ S_IRUSR | S_IWUSR);
2380c486 5357+
9474138d 5358+/* Syscall logging mode */
ceaf2cfb
AM
5359+int aa_g_logsyscall;
5360+module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR);
2380c486 5361+
9474138d 5362+/* Maximum pathname length before accesses will start getting rejected */
ceaf2cfb
AM
5363+unsigned int aa_g_path_max = 2 * PATH_MAX;
5364+module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR | S_IWUSR);
5365+
5366+/* Determines how paranoid loading of policy is and how much verification
5367+ * on the loaded policy is done.
5368+ */
5369+int aa_g_paranoid_load = 1;
5370+module_param_named(paranoid_load, aa_g_paranoid_load, aabool,
5371+ S_IRUSR | S_IWUSR);
2380c486 5372+
9474138d 5373+/* Boot time disable flag */
9474138d 5374+static unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
ceaf2cfb 5375+module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR);
2380c486 5376+
9474138d 5377+static int __init apparmor_enabled_setup(char *str)
2380c486 5378+{
ceaf2cfb
AM
5379+ unsigned long enabled;
5380+ int error = strict_strtoul(str, 0, &enabled);
5381+ if (!error)
5382+ apparmor_enabled = enabled ? 1 : 0;
9474138d 5383+ return 1;
2380c486 5384+}
ceaf2cfb 5385+
9474138d 5386+__setup("apparmor=", apparmor_enabled_setup);
2380c486 5387+
ceaf2cfb 5388+/* set global flag turning off the ability to load policy */
9474138d 5389+static int param_set_aalockpolicy(const char *val, struct kernel_param *kp)
2380c486 5390+{
ceaf2cfb 5391+ if (!capable(CAP_MAC_ADMIN))
9474138d 5392+ return -EPERM;
ceaf2cfb 5393+ if (aa_g_lock_policy)
9474138d
AM
5394+ return -EACCES;
5395+ return param_set_bool(val, kp);
2380c486
JR
5396+}
5397+
9474138d 5398+static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp)
2380c486 5399+{
ceaf2cfb 5400+ if (!capable(CAP_MAC_ADMIN))
9474138d
AM
5401+ return -EPERM;
5402+ return param_get_bool(buffer, kp);
2380c486
JR
5403+}
5404+
9474138d 5405+static int param_set_aabool(const char *val, struct kernel_param *kp)
2380c486 5406+{
ceaf2cfb 5407+ if (!capable(CAP_MAC_ADMIN))
9474138d
AM
5408+ return -EPERM;
5409+ return param_set_bool(val, kp);
2380c486
JR
5410+}
5411+
9474138d 5412+static int param_get_aabool(char *buffer, struct kernel_param *kp)
2380c486 5413+{
ceaf2cfb 5414+ if (!capable(CAP_MAC_ADMIN))
9474138d
AM
5415+ return -EPERM;
5416+ return param_get_bool(buffer, kp);
2380c486
JR
5417+}
5418+
9474138d 5419+static int param_set_aauint(const char *val, struct kernel_param *kp)
2380c486 5420+{
ceaf2cfb 5421+ if (!capable(CAP_MAC_ADMIN))
9474138d
AM
5422+ return -EPERM;
5423+ return param_set_uint(val, kp);
2380c486
JR
5424+}
5425+
9474138d 5426+static int param_get_aauint(char *buffer, struct kernel_param *kp)
2380c486 5427+{
ceaf2cfb 5428+ if (!capable(CAP_MAC_ADMIN))
9474138d
AM
5429+ return -EPERM;
5430+ return param_get_uint(buffer, kp);
2380c486
JR
5431+}
5432+
9474138d
AM
5433+static int param_get_audit(char *buffer, struct kernel_param *kp)
5434+{
ceaf2cfb 5435+ if (!capable(CAP_MAC_ADMIN))
9474138d 5436+ return -EPERM;
2380c486 5437+
9474138d
AM
5438+ if (!apparmor_enabled)
5439+ return -EINVAL;
2380c486 5440+
ceaf2cfb 5441+ return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]);
2380c486
JR
5442+}
5443+
9474138d 5444+static int param_set_audit(const char *val, struct kernel_param *kp)
2380c486 5445+{
9474138d 5446+ int i;
ceaf2cfb 5447+ if (!capable(CAP_MAC_ADMIN))
9474138d 5448+ return -EPERM;
2380c486 5449+
9474138d
AM
5450+ if (!apparmor_enabled)
5451+ return -EINVAL;
2380c486 5452+
9474138d
AM
5453+ if (!val)
5454+ return -EINVAL;
2380c486 5455+
9474138d
AM
5456+ for (i = 0; i < AUDIT_MAX_INDEX; i++) {
5457+ if (strcmp(val, audit_mode_names[i]) == 0) {
ceaf2cfb 5458+ aa_g_audit = i;
9474138d 5459+ return 0;
2380c486 5460+ }
2380c486 5461+ }
2380c486 5462+
9474138d 5463+ return -EINVAL;
2380c486
JR
5464+}
5465+
9474138d 5466+static int param_get_mode(char *buffer, struct kernel_param *kp)
2380c486 5467+{
ceaf2cfb 5468+ if (!capable(CAP_MAC_ADMIN))
9474138d 5469+ return -EPERM;
2380c486 5470+
9474138d
AM
5471+ if (!apparmor_enabled)
5472+ return -EINVAL;
2380c486 5473+
ceaf2cfb 5474+ return sprintf(buffer, "%s", profile_mode_names[aa_g_profile_mode]);
2380c486
JR
5475+}
5476+
9474138d 5477+static int param_set_mode(const char *val, struct kernel_param *kp)
2380c486 5478+{
9474138d 5479+ int i;
ceaf2cfb 5480+ if (!capable(CAP_MAC_ADMIN))
9474138d 5481+ return -EPERM;
2380c486 5482+
9474138d
AM
5483+ if (!apparmor_enabled)
5484+ return -EINVAL;
2380c486 5485+
9474138d
AM
5486+ if (!val)
5487+ return -EINVAL;
2380c486 5488+
9474138d
AM
5489+ for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) {
5490+ if (strcmp(val, profile_mode_names[i]) == 0) {
ceaf2cfb 5491+ aa_g_profile_mode = i;
9474138d
AM
5492+ return 0;
5493+ }
5494+ }
2380c486 5495+
9474138d 5496+ return -EINVAL;
2380c486
JR
5497+}
5498+
9474138d
AM
5499+/*
5500+ * AppArmor init functions
2380c486 5501+ */
2380c486 5502+
ceaf2cfb
AM
5503+/**
5504+ * set_init_cxt - set a task context and profile on the first task.
5505+ *
5506+ * TODO: allow setting an alternate profile than unconfined
5507+ */
5508+static int __init set_init_cxt(void)
9474138d 5509+{
ceaf2cfb
AM
5510+ struct cred *cred = (struct cred *)current->real_cred;
5511+ struct aa_task_cxt *cxt;
2380c486 5512+
9474138d
AM
5513+ cxt = aa_alloc_task_context(GFP_KERNEL);
5514+ if (!cxt)
5515+ return -ENOMEM;
2380c486 5516+
ceaf2cfb 5517+ cxt->profile = aa_get_profile(root_ns->unconfined);
9474138d 5518+ cred->security = cxt;
2380c486 5519+
9474138d 5520+ return 0;
2380c486
JR
5521+}
5522+
9474138d 5523+static int __init apparmor_init(void)
2380c486 5524+{
9474138d 5525+ int error;
2380c486 5526+
9474138d 5527+ if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
76514441 5528+ aa_info_message("AppArmor disabled by boot time parameter");
9474138d
AM
5529+ apparmor_enabled = 0;
5530+ return 0;
5531+ }
2380c486 5532+
ceaf2cfb 5533+ error = aa_alloc_root_ns();
9474138d
AM
5534+ if (error) {
5535+ AA_ERROR("Unable to allocate default profile namespace\n");
5536+ goto alloc_out;
5537+ }
2380c486 5538+
9474138d
AM
5539+ error = set_init_cxt();
5540+ if (error) {
5541+ AA_ERROR("Failed to set context on init task\n");
ceaf2cfb 5542+ goto register_security_out;
9474138d 5543+ }
2380c486 5544+
9474138d
AM
5545+ error = register_security(&apparmor_ops);
5546+ if (error) {
5547+ AA_ERROR("Unable to register AppArmor\n");
5548+ goto register_security_out;
5549+ }
2380c486 5550+
9474138d
AM
5551+ /* Report that AppArmor successfully initialized */
5552+ apparmor_initialized = 1;
ceaf2cfb
AM
5553+ if (aa_g_profile_mode == APPARMOR_COMPLAIN)
5554+ aa_info_message("AppArmor initialized: complain mode enabled");
5555+ else if (aa_g_profile_mode == APPARMOR_KILL)
5556+ aa_info_message("AppArmor initialized: kill mode enabled");
9474138d 5557+ else
ceaf2cfb 5558+ aa_info_message("AppArmor initialized");
2380c486 5559+
9474138d 5560+ return error;
2380c486 5561+
9474138d 5562+register_security_out:
ceaf2cfb 5563+ aa_free_root_ns();
2380c486 5564+
9474138d 5565+alloc_out:
ceaf2cfb 5566+ aa_destroy_aafs();
2380c486 5567+
9474138d
AM
5568+ apparmor_enabled = 0;
5569+ return error;
2380c486 5570+
2380c486
JR
5571+}
5572+
9474138d 5573+security_initcall(apparmor_init);
ceaf2cfb
AM
5574diff --git a/security/apparmor/match.c b/security/apparmor/match.c
5575new file mode 100644
76514441 5576index 0000000..0248bb3
ceaf2cfb
AM
5577--- /dev/null
5578+++ b/security/apparmor/match.c
76514441 5579@@ -0,0 +1,370 @@
9474138d
AM
5580+/*
5581+ * AppArmor security module
2380c486 5582+ *
9474138d
AM
5583+ * This file contains AppArmor dfa based regular expression matching engine
5584+ *
5585+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 5586+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
5587+ *
5588+ * This program is free software; you can redistribute it and/or
5589+ * modify it under the terms of the GNU General Public License as
5590+ * published by the Free Software Foundation, version 2 of the
5591+ * License.
2380c486 5592+ */
2380c486 5593+
9474138d 5594+#include <linux/errno.h>
ceaf2cfb 5595+#include <linux/kernel.h>
0eaba94d 5596+#include <linux/mm.h>
ceaf2cfb 5597+#include <linux/slab.h>
0eaba94d 5598+#include <linux/vmalloc.h>
ceaf2cfb
AM
5599+#include <linux/err.h>
5600+#include <linux/kref.h>
2380c486 5601+
76514441 5602+#include "include/apparmor.h"
9474138d 5603+#include "include/match.h"
2380c486 5604+
ceaf2cfb 5605+/**
ceaf2cfb 5606+ * unpack_table - unpack a dfa table (one of accept, default, base, next check)
76514441 5607+ * @blob: data to unpack (NOT NULL)
ceaf2cfb
AM
5608+ * @bsize: size of blob
5609+ *
5610+ * Returns: pointer to table else NULL on failure
5611+ *
76514441 5612+ * NOTE: must be freed by kvfree (not kmalloc)
ceaf2cfb
AM
5613+ */
5614+static struct table_header *unpack_table(char *blob, size_t bsize)
9474138d
AM
5615+{
5616+ struct table_header *table = NULL;
5617+ struct table_header th;
5618+ size_t tsize;
2380c486 5619+
9474138d
AM
5620+ if (bsize < sizeof(struct table_header))
5621+ goto out;
2380c486 5622+
ceaf2cfb
AM
5623+ /* loaded td_id's start at 1, subtract 1 now to avoid doing
5624+ * it every time we use td_id as an index
5625+ */
5626+ th.td_id = be16_to_cpu(*(u16 *) (blob)) - 1;
9474138d
AM
5627+ th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
5628+ th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
5629+ blob += sizeof(struct table_header);
2380c486 5630+
9474138d 5631+ if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
ceaf2cfb 5632+ th.td_flags == YYTD_DATA8))
9474138d 5633+ goto out;
2380c486 5634+
9474138d
AM
5635+ tsize = table_size(th.td_lolen, th.td_flags);
5636+ if (bsize < tsize)
5637+ goto out;
2380c486 5638+
76514441
AM
5639+ /* Pad table allocation for next/check by 256 entries to remain
5640+ * backwards compatible with old (buggy) tools and remain safe without
5641+ * run time checks
5642+ */
5643+ if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK)
5644+ tsize += 256 * th.td_flags;
5645+
5646+ table = kvmalloc(tsize);
9474138d 5647+ if (table) {
76514441
AM
5648+ /* ensure the pad is clear, else there will be errors */
5649+ memset(table, 0, tsize);
9474138d
AM
5650+ *table = th;
5651+ if (th.td_flags == YYTD_DATA8)
5652+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
5653+ u8, byte_to_byte);
5654+ else if (th.td_flags == YYTD_DATA16)
5655+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
5656+ u16, be16_to_cpu);
ceaf2cfb 5657+ else if (th.td_flags == YYTD_DATA32)
9474138d
AM
5658+ UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
5659+ u32, be32_to_cpu);
ceaf2cfb
AM
5660+ else
5661+ goto fail;
9474138d 5662+ }
2380c486 5663+
9474138d 5664+out:
76514441
AM
5665+ /* if table was vmalloced make sure the page tables are synced
5666+ * before it is used, as it goes live to all cpus.
5667+ */
5668+ if (is_vmalloc_addr(table))
5669+ vm_unmap_aliases();
9474138d 5670+ return table;
ceaf2cfb 5671+fail:
76514441 5672+ kvfree(table);
ceaf2cfb
AM
5673+ return NULL;
5674+}
5675+
5676+/**
76514441 5677+ * verify_dfa - verify that transitions and states in the tables are in bounds.
ceaf2cfb
AM
5678+ * @dfa: dfa to test (NOT NULL)
5679+ * @flags: flags controlling what type of accept table are acceptable
5680+ *
5681+ * Assumes dfa has gone through the first pass verification done by unpacking
5682+ * NOTE: this does not valid accept table values
5683+ *
5684+ * Returns: %0 else error code on failure to verify
5685+ */
5686+static int verify_dfa(struct aa_dfa *dfa, int flags)
5687+{
5688+ size_t i, state_count, trans_count;
5689+ int error = -EPROTO;
5690+
5691+ /* check that required tables exist */
5692+ if (!(dfa->tables[YYTD_ID_DEF] &&
5693+ dfa->tables[YYTD_ID_BASE] &&
5694+ dfa->tables[YYTD_ID_NXT] && dfa->tables[YYTD_ID_CHK]))
5695+ goto out;
5696+
5697+ /* accept.size == default.size == base.size */
5698+ state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
5699+ if (ACCEPT1_FLAGS(flags)) {
5700+ if (!dfa->tables[YYTD_ID_ACCEPT])
5701+ goto out;
5702+ if (state_count != dfa->tables[YYTD_ID_ACCEPT]->td_lolen)
5703+ goto out;
5704+ }
5705+ if (ACCEPT2_FLAGS(flags)) {
5706+ if (!dfa->tables[YYTD_ID_ACCEPT2])
5707+ goto out;
5708+ if (state_count != dfa->tables[YYTD_ID_ACCEPT2]->td_lolen)
5709+ goto out;
5710+ }
5711+ if (state_count != dfa->tables[YYTD_ID_DEF]->td_lolen)
5712+ goto out;
5713+
5714+ /* next.size == chk.size */
5715+ trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen;
5716+ if (trans_count != dfa->tables[YYTD_ID_CHK]->td_lolen)
5717+ goto out;
5718+
5719+ /* if equivalence classes then its table size must be 256 */
5720+ if (dfa->tables[YYTD_ID_EC] &&
5721+ dfa->tables[YYTD_ID_EC]->td_lolen != 256)
5722+ goto out;
5723+
5724+ if (flags & DFA_FLAG_VERIFY_STATES) {
76514441 5725+ int warning = 0;
ceaf2cfb
AM
5726+ for (i = 0; i < state_count; i++) {
5727+ if (DEFAULT_TABLE(dfa)[i] >= state_count)
5728+ goto out;
5729+ /* TODO: do check that DEF state recursion terminates */
76514441
AM
5730+ if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
5731+ if (warning)
5732+ continue;
5733+ printk(KERN_WARNING "AppArmor DFA next/check "
5734+ "upper bounds error fixed, upgrade "
5735+ "user space tools \n");
5736+ warning = 1;
5737+ } else if (BASE_TABLE(dfa)[i] >= trans_count) {
5738+ printk(KERN_ERR "AppArmor DFA next/check upper "
5739+ "bounds error\n");
ceaf2cfb 5740+ goto out;
76514441 5741+ }
ceaf2cfb
AM
5742+ }
5743+
5744+ for (i = 0; i < trans_count; i++) {
5745+ if (NEXT_TABLE(dfa)[i] >= state_count)
5746+ goto out;
5747+ if (CHECK_TABLE(dfa)[i] >= state_count)
5748+ goto out;
5749+ }
5750+ }
5751+
5752+ error = 0;
5753+out:
5754+ return error;
5755+}
5756+
5757+/**
76514441 5758+ * dfa_free - free a dfa allocated by aa_dfa_unpack
ceaf2cfb
AM
5759+ * @dfa: the dfa to free (MAYBE NULL)
5760+ *
5761+ * Requires: reference count to dfa == 0
5762+ */
76514441 5763+static void dfa_free(struct aa_dfa *dfa)
ceaf2cfb
AM
5764+{
5765+ if (dfa) {
5766+ int i;
5767+
5768+ for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
76514441 5769+ kvfree(dfa->tables[i]);
ceaf2cfb
AM
5770+ dfa->tables[i] = NULL;
5771+ }
76514441 5772+ kfree(dfa);
ceaf2cfb 5773+ }
ceaf2cfb
AM
5774+}
5775+
5776+/**
5777+ * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa)
5778+ * @kr: kref callback for freeing of a dfa (NOT NULL)
5779+ */
5780+void aa_dfa_free_kref(struct kref *kref)
5781+{
5782+ struct aa_dfa *dfa = container_of(kref, struct aa_dfa, count);
76514441 5783+ dfa_free(dfa);
9474138d 5784+}
2380c486 5785+
ceaf2cfb
AM
5786+/**
5787+ * aa_dfa_unpack - unpack the binary tables of a serialized dfa
5788+ * @blob: aligned serialized stream of data to unpack (NOT NULL)
5789+ * @size: size of data to unpack
5790+ * @flags: flags controlling what type of accept tables are acceptable
5791+ *
76514441
AM
5792+ * Unpack a dfa that has been serialized. To find information on the dfa
5793+ * format look in Documentation/apparmor.txt
ceaf2cfb
AM
5794+ * Assumes the dfa @blob stream has been aligned on a 8 byte boundry
5795+ *
5796+ * Returns: an unpacked dfa ready for matching or ERR_PTR on failure
5797+ */
5798+struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)
9474138d 5799+{
ceaf2cfb 5800+ int hsize;
9474138d 5801+ int error = -ENOMEM;
ceaf2cfb
AM
5802+ char *data = blob;
5803+ struct table_header *table = NULL;
5804+ struct aa_dfa *dfa = kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
5805+ if (!dfa)
5806+ goto fail;
5807+
5808+ kref_init(&dfa->count);
5809+
5810+ error = -EPROTO;
2380c486 5811+
9474138d
AM
5812+ /* get dfa table set header */
5813+ if (size < sizeof(struct table_set_header))
5814+ goto fail;
2380c486 5815+
ceaf2cfb 5816+ if (ntohl(*(u32 *) data) != YYTH_MAGIC)
9474138d 5817+ goto fail;
2380c486 5818+
ceaf2cfb 5819+ hsize = ntohl(*(u32 *) (data + 4));
9474138d
AM
5820+ if (size < hsize)
5821+ goto fail;
2380c486 5822+
ceaf2cfb
AM
5823+ dfa->flags = ntohs(*(u16 *) (data + 12));
5824+ data += hsize;
9474138d 5825+ size -= hsize;
2380c486 5826+
9474138d 5827+ while (size > 0) {
ceaf2cfb 5828+ table = unpack_table(data, size);
9474138d
AM
5829+ if (!table)
5830+ goto fail;
2380c486 5831+
9474138d
AM
5832+ switch (table->td_id) {
5833+ case YYTD_ID_ACCEPT:
ceaf2cfb
AM
5834+ if (!(table->td_flags & ACCEPT1_FLAGS(flags)))
5835+ goto fail;
5836+ break;
9474138d 5837+ case YYTD_ID_ACCEPT2:
ceaf2cfb
AM
5838+ if (!(table->td_flags & ACCEPT2_FLAGS(flags)))
5839+ goto fail;
5840+ break;
9474138d 5841+ case YYTD_ID_BASE:
9474138d
AM
5842+ if (table->td_flags != YYTD_DATA32)
5843+ goto fail;
5844+ break;
5845+ case YYTD_ID_DEF:
5846+ case YYTD_ID_NXT:
5847+ case YYTD_ID_CHK:
9474138d
AM
5848+ if (table->td_flags != YYTD_DATA16)
5849+ goto fail;
5850+ break;
5851+ case YYTD_ID_EC:
9474138d
AM
5852+ if (table->td_flags != YYTD_DATA8)
5853+ goto fail;
5854+ break;
5855+ default:
9474138d
AM
5856+ goto fail;
5857+ }
ceaf2cfb
AM
5858+ /* check for duplicate table entry */
5859+ if (dfa->tables[table->td_id])
5860+ goto fail;
5861+ dfa->tables[table->td_id] = table;
5862+ data += table_size(table->td_lolen, table->td_flags);
9474138d 5863+ size -= table_size(table->td_lolen, table->td_flags);
ceaf2cfb 5864+ table = NULL;
2380c486
JR
5865+ }
5866+
ceaf2cfb
AM
5867+ error = verify_dfa(dfa, flags);
5868+ if (error)
5869+ goto fail;
2380c486 5870+
ceaf2cfb 5871+ return dfa;
2380c486 5872+
ceaf2cfb 5873+fail:
76514441
AM
5874+ kvfree(table);
5875+ dfa_free(dfa);
ceaf2cfb 5876+ return ERR_PTR(error);
2380c486
JR
5877+}
5878+
2380c486 5879+/**
9474138d 5880+ * aa_dfa_match_len - traverse @dfa to find state @str stops at
ceaf2cfb 5881+ * @dfa: the dfa to match @str against (NOT NULL)
9474138d 5882+ * @start: the state of the dfa to start matching in
ceaf2cfb 5883+ * @str: the string of bytes to match against the dfa (NOT NULL)
9474138d 5884+ * @len: length of the string of bytes to match
2380c486 5885+ *
9474138d
AM
5886+ * aa_dfa_match_len will match @str against the dfa and return the state it
5887+ * finished matching in. The final state can be used to look up the accepting
5888+ * label, or as the start state of a continuing match.
5889+ *
5890+ * This function will happily match again the 0 byte and only finishes
5891+ * when @len input is consumed.
ceaf2cfb
AM
5892+ *
5893+ * Returns: final state reached after input is consumed
2380c486 5894+ */
9474138d
AM
5895+unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
5896+ const char *str, int len)
2380c486 5897+{
9474138d
AM
5898+ u16 *def = DEFAULT_TABLE(dfa);
5899+ u32 *base = BASE_TABLE(dfa);
5900+ u16 *next = NEXT_TABLE(dfa);
5901+ u16 *check = CHECK_TABLE(dfa);
5902+ unsigned int state = start, pos;
2380c486 5903+
9474138d 5904+ if (state == 0)
2380c486 5905+ return 0;
2380c486 5906+
9474138d 5907+ /* current state is <state>, matching character *str */
ceaf2cfb
AM
5908+ if (dfa->tables[YYTD_ID_EC]) {
5909+ /* Equivalence class table defined */
9474138d 5910+ u8 *equiv = EQUIV_TABLE(dfa);
ceaf2cfb 5911+ /* default is direct to next state */
9474138d 5912+ for (; len; len--) {
ceaf2cfb 5913+ pos = base[state] + equiv[(u8) *str++];
9474138d
AM
5914+ if (check[pos] == state)
5915+ state = next[pos];
5916+ else
5917+ state = def[state];
2380c486
JR
5918+ }
5919+ } else {
ceaf2cfb 5920+ /* default is direct to next state */
9474138d 5921+ for (; len; len--) {
ceaf2cfb 5922+ pos = base[state] + (u8) *str++;
9474138d
AM
5923+ if (check[pos] == state)
5924+ state = next[pos];
5925+ else
5926+ state = def[state];
5927+ }
2380c486 5928+ }
ceaf2cfb 5929+
9474138d 5930+ return state;
2380c486
JR
5931+}
5932+
9474138d
AM
5933+/**
5934+ * aa_dfa_next_state - traverse @dfa to find state @str stops at
ceaf2cfb 5935+ * @dfa: the dfa to match @str against (NOT NULL)
9474138d 5936+ * @start: the state of the dfa to start matching in
ceaf2cfb 5937+ * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
9474138d
AM
5938+ *
5939+ * aa_dfa_next_state will match @str against the dfa and return the state it
5940+ * finished matching in. The final state can be used to look up the accepting
5941+ * label, or as the start state of a continuing match.
ceaf2cfb
AM
5942+ *
5943+ * Returns: final state reached after input is consumed
9474138d
AM
5944+ */
5945+unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
5946+ const char *str)
5947+{
5948+ return aa_dfa_match_len(dfa, start, str, strlen(str));
2380c486 5949+}
ceaf2cfb
AM
5950diff --git a/security/apparmor/net.c b/security/apparmor/net.c
5951new file mode 100644
76514441 5952index 0000000..7c36e82
ceaf2cfb
AM
5953--- /dev/null
5954+++ b/security/apparmor/net.c
76514441 5955@@ -0,0 +1,169 @@
9474138d
AM
5956+/*
5957+ * AppArmor security module
5958+ *
5959+ * This file contains AppArmor network mediation
5960+ *
5961+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 5962+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
5963+ *
5964+ * This program is free software; you can redistribute it and/or
5965+ * modify it under the terms of the GNU General Public License as
5966+ * published by the Free Software Foundation, version 2 of the
5967+ * License.
5968+ */
2380c486 5969+
9474138d
AM
5970+#include "include/apparmor.h"
5971+#include "include/audit.h"
5972+#include "include/context.h"
5973+#include "include/net.h"
5974+#include "include/policy.h"
2380c486 5975+
9474138d 5976+#include "af_names.h"
2380c486 5977+
9474138d
AM
5978+static const char *sock_type_names[] = {
5979+ "unknown(0)",
5980+ "stream",
5981+ "dgram",
5982+ "raw",
5983+ "rdm",
5984+ "seqpacket",
5985+ "dccp",
5986+ "unknown(7)",
5987+ "unknown(8)",
5988+ "unknown(9)",
5989+ "packet",
5990+};
2380c486 5991+
ceaf2cfb 5992+/* audit callback for net specific fields */
76514441 5993+static void audit_cb(struct audit_buffer *ab, void *va)
9474138d 5994+{
76514441 5995+ struct common_audit_data *sa = va;
2380c486 5996+
76514441
AM
5997+ audit_log_format(ab, " family=");
5998+ if (address_family_names[sa->u.net.family]) {
5999+ audit_log_string(ab, address_family_names[sa->u.net.family]);
6000+ } else {
6001+ audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family);
2380c486 6002+ }
ceaf2cfb 6003+
76514441
AM
6004+ audit_log_format(ab, " sock_type=");
6005+ if (sock_type_names[sa->aad.net.type]) {
6006+ audit_log_string(ab, sock_type_names[sa->aad.net.type]);
6007+ } else {
6008+ audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type);
6009+ }
6010+
6011+ audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
2380c486
JR
6012+}
6013+
ceaf2cfb 6014+/**
76514441 6015+ * audit_net - audit network access
ceaf2cfb 6016+ * @profile: profile being enforced (NOT NULL)
76514441
AM
6017+ * @op: operation being checked
6018+ * @family: network family
6019+ * @type: network type
6020+ * @protocol: network protocol
6021+ * @sk: socket auditing is being applied to
6022+ * @error: error code for failure else 0
ceaf2cfb
AM
6023+ *
6024+ * Returns: %0 or sa->error else other errorcode on failure
6025+ */
76514441
AM
6026+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
6027+ int protocol, struct sock *sk, int error)
2380c486 6028+{
76514441
AM
6029+ int audit_type = AUDIT_APPARMOR_AUTO;
6030+ struct common_audit_data sa;
6031+ if (sk) {
6032+ COMMON_AUDIT_DATA_INIT(&sa, NET);
6033+ } else {
6034+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
6035+ }
6036+ /* todo fill in socket addr info */
6037+
6038+ sa.aad.op = op,
6039+ sa.u.net.family = family;
6040+ sa.u.net.sk = sk;
6041+ sa.aad.net.type = type;
6042+ sa.aad.net.protocol = protocol;
2380c486 6043+
76514441
AM
6044+ if (likely(!sa.aad.error)) {
6045+ u16 audit_mask = profile->net.audit[sa.u.net.family];
ceaf2cfb 6046+ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
76514441 6047+ !(1 << sa.aad.net.type & audit_mask)))
9474138d 6048+ return 0;
76514441 6049+ audit_type = AUDIT_APPARMOR_AUDIT;
9474138d 6050+ } else {
76514441 6051+ u16 quiet_mask = profile->net.quiet[sa.u.net.family];
9474138d 6052+ u16 kill_mask = 0;
76514441 6053+ u16 denied = (1 << sa.aad.net.type) & ~quiet_mask;
9474138d
AM
6054+
6055+ if (denied & kill_mask)
76514441 6056+ audit_type = AUDIT_APPARMOR_KILL;
9474138d
AM
6057+
6058+ if ((denied & quiet_mask) &&
ceaf2cfb
AM
6059+ AUDIT_MODE(profile) != AUDIT_NOQUIET &&
6060+ AUDIT_MODE(profile) != AUDIT_ALL)
76514441 6061+ return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
2380c486 6062+ }
9474138d 6063+
76514441 6064+ return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
2380c486
JR
6065+}
6066+
ceaf2cfb
AM
6067+/**
6068+ * aa_net_perm - very course network access check
76514441 6069+ * @op: operation being checked
ceaf2cfb 6070+ * @profile: profile being enforced (NOT NULL)
ceaf2cfb
AM
6071+ * @family: network family
6072+ * @type: network type
6073+ * @protocol: network protocol
6074+ *
6075+ * Returns: %0 else error if permission denied
6076+ */
76514441
AM
6077+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
6078+ int protocol, struct sock *sk)
2380c486 6079+{
9474138d 6080+ u16 family_mask;
76514441 6081+ int error;
2380c486 6082+
9474138d
AM
6083+ if ((family < 0) || (family >= AF_MAX))
6084+ return -EINVAL;
2380c486 6085+
9474138d
AM
6086+ if ((type < 0) || (type >= SOCK_MAX))
6087+ return -EINVAL;
2380c486 6088+
9474138d
AM
6089+ /* unix domain and netlink sockets are handled by ipc */
6090+ if (family == AF_UNIX || family == AF_NETLINK)
6091+ return 0;
2380c486 6092+
76514441 6093+ family_mask = profile->net.allow[family];
2380c486 6094+
76514441 6095+ error = (family_mask & (1 << type)) ? 0 : -EACCES;
2380c486 6096+
76514441 6097+ return audit_net(profile, op, family, type, protocol, sk, error);
9474138d 6098+}
2380c486 6099+
ceaf2cfb
AM
6100+/**
6101+ * aa_revalidate_sk - Revalidate access to a sock
76514441 6102+ * @op: operation being checked
ceaf2cfb 6103+ * @sk: sock being revalidated (NOT NULL)
ceaf2cfb
AM
6104+ *
6105+ * Returns: %0 else error if permission denied
6106+ */
76514441 6107+int aa_revalidate_sk(int op, struct sock *sk)
9474138d
AM
6108+{
6109+ struct aa_profile *profile;
9474138d 6110+ int error = 0;
2380c486 6111+
ceaf2cfb
AM
6112+ /* aa_revalidate_sk should not be called from interrupt context
6113+ * don't mediate these calls as they are not task related
6114+ */
6115+ if (in_interrupt())
9474138d 6116+ return 0;
2380c486 6117+
ceaf2cfb
AM
6118+ profile = __aa_current_profile();
6119+ if (!unconfined(profile))
76514441
AM
6120+ error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
6121+ sk->sk_protocol, sk);
9474138d
AM
6122+
6123+ return error;
6124+}
ceaf2cfb
AM
6125diff --git a/security/apparmor/path.c b/security/apparmor/path.c
6126new file mode 100644
76514441 6127index 0000000..96bab94
ceaf2cfb
AM
6128--- /dev/null
6129+++ b/security/apparmor/path.c
76514441 6130@@ -0,0 +1,235 @@
9474138d
AM
6131+/*
6132+ * AppArmor security module
6133+ *
6134+ * This file contains AppArmor function for pathnames
6135+ *
6136+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 6137+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
6138+ *
6139+ * This program is free software; you can redistribute it and/or
6140+ * modify it under the terms of the GNU General Public License as
6141+ * published by the Free Software Foundation, version 2 of the
6142+ * License.
6143+ */
2380c486 6144+
76514441 6145+#include <linux/magic.h>
9474138d
AM
6146+#include <linux/mnt_namespace.h>
6147+#include <linux/mount.h>
6148+#include <linux/namei.h>
ceaf2cfb 6149+#include <linux/nsproxy.h>
9474138d
AM
6150+#include <linux/path.h>
6151+#include <linux/sched.h>
6152+#include <linux/slab.h>
6153+#include <linux/fs_struct.h>
2380c486 6154+
9474138d
AM
6155+#include "include/apparmor.h"
6156+#include "include/path.h"
ceaf2cfb
AM
6157+#include "include/policy.h"
6158+
76514441
AM
6159+
6160+/* modified from dcache.c */
6161+static int prepend(char **buffer, int buflen, const char *str, int namelen)
6162+{
6163+ buflen -= namelen;
6164+ if (buflen < 0)
6165+ return -ENAMETOOLONG;
6166+ *buffer -= namelen;
6167+ memcpy(*buffer, str, namelen);
6168+ return 0;
6169+}
6170+
6171+#define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT)
6172+
ceaf2cfb
AM
6173+/**
6174+ * d_namespace_path - lookup a name associated with a given path
6175+ * @path: path to lookup (NOT NULL)
6176+ * @buf: buffer to store path to (NOT NULL)
6177+ * @buflen: length of @buf
76514441
AM
6178+ * @name: Returns - pointer for start of path name with in @buf (NOT NULL)
6179+ * @flags: flags controlling path lookup
ceaf2cfb
AM
6180+ *
6181+ * Handle path name lookup.
6182+ *
6183+ * Returns: %0 else error code if path lookup fails
6184+ * When no error the path name is returned in @name which points to
6185+ * to a position in @buf
6186+ */
6187+static int d_namespace_path(struct path *path, char *buf, int buflen,
6188+ char **name, int flags)
6189+{
6190+ struct path root, tmp;
6191+ char *res;
6192+ int deleted, connected;
6193+ int error = 0;
6194+
6195+ /* Get the root we want to resolve too */
6196+ if (flags & PATH_CHROOT_REL) {
6197+ /* resolve paths relative to chroot */
6198+ read_lock(&current->fs->lock);
6199+ root = current->fs->root;
6200+ /* released below */
6201+ path_get(&root);
6202+ read_unlock(&current->fs->lock);
6203+ } else {
6204+ /* resolve paths relative to namespace */
6205+ root.mnt = current->nsproxy->mnt_ns->root;
6206+ root.dentry = root.mnt->mnt_root;
6207+ /* released below */
6208+ path_get(&root);
6209+ }
6210+
6211+ spin_lock(&dcache_lock);
6212+ /* There is a race window between path lookup here and the
6213+ * need to strip the " (deleted) string that __d_path applies
6214+ * Detect the race and relookup the path
6215+ *
6216+ * The stripping of (deleted) is a hack that could be removed
6217+ * with an updated __d_path
6218+ */
6219+ do {
6220+ tmp = root;
6221+ deleted = d_unlinked(path->dentry);
6222+ res = __d_path(path, &tmp, buf, buflen);
6223+
6224+ } while (deleted != d_unlinked(path->dentry));
6225+ spin_unlock(&dcache_lock);
6226+
6227+ *name = res;
6228+ /* handle error conditions - and still allow a partial path to
6229+ * be returned.
6230+ */
6231+ if (IS_ERR(res)) {
6232+ error = PTR_ERR(res);
6233+ *name = buf;
6234+ goto out;
6235+ }
6236+ if (deleted) {
6237+ /* On some filesystems, newly allocated dentries appear to the
6238+ * security_path hooks as a deleted dentry except without an
6239+ * inode allocated.
6240+ *
6241+ * Remove the appended deleted text and return as string for
6242+ * normal mediation, or auditing. The (deleted) string is
76514441 6243+ * guaranteed to be added in this case, so just strip it.
ceaf2cfb
AM
6244+ */
6245+ buf[buflen - 11] = 0; /* - (len(" (deleted)") +\0) */
6246+
6247+ if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) {
6248+ error = -ENOENT;
6249+ goto out;
6250+ }
6251+ }
6252+
6253+ /* Determine if the path is connected to the expected root */
6254+ connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt;
6255+
76514441
AM
6256+ /* If the path is not connected,
6257+ * check if it is a sysctl and handle specially else remove any
6258+ * leading / that __d_path may have returned.
ceaf2cfb
AM
6259+ * Unless
6260+ * specifically directed to connect the path,
6261+ * OR
6262+ * if in a chroot and doing chroot relative paths and the path
6263+ * resolves to the namespace root (would be connected outside
6264+ * of chroot) and specifically directed to connect paths to
6265+ * namespace root.
6266+ */
76514441
AM
6267+ if (!connected) {
6268+ /* is the disconnect path a sysctl? */
6269+ if (tmp.dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
6270+ strncmp(*name, "/sys/", 5) == 0) {
6271+ /* TODO: convert over to using a per namespace
6272+ * control instead of hard coded /proc
6273+ */
6274+ error = prepend(name, *name - buf, "/proc", 5);
6275+ } else if (!(flags & PATH_CONNECT_PATH) &&
6276+ !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
6277+ (tmp.mnt == current->nsproxy->mnt_ns->root &&
6278+ tmp.dentry == tmp.mnt->mnt_root))) {
6279+ /* disconnected path, don't return pathname starting
6280+ * with '/'
6281+ */
6282+ error = -ESTALE;
6283+ if (*res == '/')
6284+ *name = res + 1;
6285+ }
ceaf2cfb
AM
6286+ }
6287+
6288+out:
6289+ path_put(&root);
6290+
6291+ return error;
6292+}
9474138d 6293+
ceaf2cfb
AM
6294+/**
6295+ * get_name_to_buffer - get the pathname to a buffer ensure dir / is appended
6296+ * @path: path to get name for (NOT NULL)
6297+ * @flags: flags controlling path lookup
6298+ * @buffer: buffer to put name in (NOT NULL)
6299+ * @size: size of buffer
76514441 6300+ * @name: Returns - contains position of path name in @buffer (NOT NULL)
ceaf2cfb
AM
6301+ *
6302+ * Returns: %0 else error on failure
6303+ */
6304+static int get_name_to_buffer(struct path *path, int flags, char *buffer,
6305+ int size, char **name)
9474138d 6306+{
ceaf2cfb
AM
6307+ int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
6308+ int error = d_namespace_path(path, buffer, size - adjust, name, flags);
9474138d 6309+
ceaf2cfb 6310+ if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0')
9474138d
AM
6311+ /*
6312+ * Append "/" to the pathname. The root directory is a special
6313+ * case; it already ends in slash.
6314+ */
6315+ strcpy(&buffer[size - 2], "/");
2380c486 6316+
2380c486
JR
6317+ return error;
6318+}
6319+
6320+/**
9474138d 6321+ * aa_get_name - compute the pathname of a file
ceaf2cfb 6322+ * @path: path the file (NOT NULL)
76514441 6323+ * @flags: flags controlling path name generation
ceaf2cfb 6324+ * @buffer: buffer that aa_get_name() allocated (NOT NULL)
76514441 6325+ * @name: Returns - the generated path name if !error (NOT NULL)
2380c486 6326+ *
ceaf2cfb 6327+ * @name is a pointer to the beginning of the pathname (which usually differs
9474138d 6328+ * from the beginning of the buffer), or NULL. If there is an error @name
ceaf2cfb
AM
6329+ * may contain a partial or invalid name that can be used for audit purposes,
6330+ * but it can not be used for mediation.
6331+ *
6332+ * We need PATH_IS_DIR to indicate whether the file is a directory or not
6333+ * because the file may not yet exist, and so we cannot check the inode's
6334+ * file type.
9474138d 6335+ *
ceaf2cfb 6336+ * Returns: %0 else error code if could retrieve name
2380c486 6337+ */
76514441 6338+int aa_get_name(struct path *path, int flags, char **buffer, const char **name)
2380c486 6339+{
9474138d
AM
6340+ char *buf, *str = NULL;
6341+ int size = 256;
6342+ int error;
2380c486 6343+
9474138d
AM
6344+ *name = NULL;
6345+ *buffer = NULL;
6346+ for (;;) {
ceaf2cfb 6347+ /* freed by caller */
9474138d
AM
6348+ buf = kmalloc(size, GFP_KERNEL);
6349+ if (!buf)
6350+ return -ENOMEM;
2380c486 6351+
ceaf2cfb 6352+ error = get_name_to_buffer(path, flags, buf, size, &str);
76514441 6353+ if (error != -ENAMETOOLONG)
9474138d 6354+ break;
2380c486 6355+
9474138d
AM
6356+ kfree(buf);
6357+ size <<= 1;
ceaf2cfb 6358+ if (size > aa_g_path_max)
9474138d
AM
6359+ return -ENAMETOOLONG;
6360+ }
6361+ *buffer = buf;
6362+ *name = str;
2380c486 6363+
9474138d
AM
6364+ return error;
6365+}
ceaf2cfb
AM
6366diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
6367new file mode 100644
76514441 6368index 0000000..e3020ed
ceaf2cfb
AM
6369--- /dev/null
6370+++ b/security/apparmor/policy.c
76514441 6371@@ -0,0 +1,1185 @@
9474138d
AM
6372+/*
6373+ * AppArmor security module
6374+ *
6375+ * This file contains AppArmor policy manipulation functions
6376+ *
6377+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 6378+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
6379+ *
6380+ * This program is free software; you can redistribute it and/or
6381+ * modify it under the terms of the GNU General Public License as
6382+ * published by the Free Software Foundation, version 2 of the
6383+ * License.
6384+ *
6385+ *
6386+ * AppArmor policy is based around profiles, which contain the rules a
76514441 6387+ * task is confined by. Every task in the system has a profile attached
9474138d
AM
6388+ * to it determined either by matching "unconfined" tasks against the
6389+ * visible set of profiles or by following a profiles attachment rules.
6390+ *
ceaf2cfb
AM
6391+ * Each profile exists in a profile namespace which is a container of
6392+ * visible profiles. Each namespace contains a special "unconfined" profile,
6393+ * which doesn't enforce any confinement on a task beyond DAC.
9474138d
AM
6394+ *
6395+ * Namespace and profile names can be written together in either
6396+ * of two syntaxes.
6397+ * :namespace:profile - used by kernel interfaces for easy detection
6398+ * namespace://profile - used by policy
6399+ *
ceaf2cfb 6400+ * Profile names can not start with : or @ or ^ and may not contain \0
76514441 6401+ *
9474138d
AM
6402+ * Reserved profile names
6403+ * unconfined - special automatically generated unconfined profile
6404+ * inherit - special name to indicate profile inheritance
76514441 6405+ * null-XXXX-YYYY - special automatically generated learning profiles
2380c486 6406+ *
ceaf2cfb 6407+ * Namespace names may not start with / or @ and may not contain \0 or :
76514441 6408+ * Reserved namespace names
9474138d 6409+ * user-XXXX - user defined profiles
ceaf2cfb 6410+ *
76514441 6411+ * a // in a profile or namespace name indicates a hierarchical name with the
ceaf2cfb
AM
6412+ * name before the // being the parent and the name after the child.
6413+ *
76514441 6414+ * Profile and namespace hierarchies serve two different but similar purposes.
ceaf2cfb
AM
6415+ * The namespace contains the set of visible profiles that are considered
6416+ * for attachment. The hierarchy of namespaces allows for virtualizing
6417+ * the namespace so that for example a chroot can have its own set of profiles
6418+ * which may define some local user namespaces.
76514441 6419+ * The profile hierarchy severs two distinct purposes,
ceaf2cfb
AM
6420+ * - it allows for sub profiles or hats, which allows an application to run
6421+ * subprograms under its own profile with different restriction than it
6422+ * self, and not have it use the system profile.
6423+ * eg. if a mail program starts an editor, the policy might make the
6424+ * restrictions tighter on the editor tighter than the mail program,
6425+ * and definitely different than general editor restrictions
6426+ * - it allows for binary hierarchy of profiles, so that execution history
6427+ * is preserved. This feature isn't exploited by AppArmor reference policy
6428+ * but is allowed. NOTE: this is currently suboptimal because profile
6429+ * aliasing is not currently implemented so that a profile for each
6430+ * level must be defined.
6431+ * eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started
6432+ * from /bin/bash
6433+ *
76514441
AM
6434+ * A profile or namespace name that can contain one or more // separators
6435+ * is referred to as an hname (hierarchical).
ceaf2cfb
AM
6436+ * eg. /bin/bash//bin/ls
6437+ *
6438+ * An fqname is a name that may contain both namespace and profile hnames.
6439+ * eg. :ns:/bin/bash//bin/ls
6440+ *
6441+ * NOTES:
6442+ * - locking of profile lists is currently fairly coarse. All profile
6443+ * lists within a namespace use the namespace lock.
6444+ * FIXME: move profile lists to using rcu_lists
2380c486 6445+ */
2380c486 6446+
9474138d
AM
6447+#include <linux/slab.h>
6448+#include <linux/spinlock.h>
6449+#include <linux/string.h>
6450+
6451+#include "include/apparmor.h"
6452+#include "include/capability.h"
ceaf2cfb 6453+#include "include/context.h"
9474138d
AM
6454+#include "include/file.h"
6455+#include "include/ipc.h"
6456+#include "include/match.h"
ceaf2cfb 6457+#include "include/path.h"
9474138d 6458+#include "include/policy.h"
ceaf2cfb 6459+#include "include/policy_unpack.h"
9474138d
AM
6460+#include "include/resource.h"
6461+#include "include/sid.h"
2380c486 6462+
2380c486 6463+
ceaf2cfb
AM
6464+/* root profile namespace */
6465+struct aa_namespace *root_ns;
2380c486 6466+
9474138d
AM
6467+const char *profile_mode_names[] = {
6468+ "enforce",
6469+ "complain",
6470+ "kill",
6471+};
2380c486 6472+
ceaf2cfb
AM
6473+/**
6474+ * hname_tail - find the last component of an hname
76514441 6475+ * @name: hname to find the base profile name component of (NOT NULL)
ceaf2cfb 6476+ *
76514441 6477+ * Returns: the tail (base profile name) name component of an hname
ceaf2cfb
AM
6478+ */
6479+static const char *hname_tail(const char *hname)
6480+{
6481+ char *split;
6482+ hname = strim((char *)hname);
6483+ for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
6484+ hname = split + 2;
2380c486 6485+
ceaf2cfb
AM
6486+ return hname;
6487+}
2380c486 6488+
ceaf2cfb
AM
6489+/**
6490+ * policy_init - initialize a policy structure
6491+ * @policy: policy to initialize (NOT NULL)
76514441 6492+ * @prefix: prefix name if any is required. (MAYBE NULL)
ceaf2cfb 6493+ * @name: name of the policy, init will make a copy of it (NOT NULL)
76514441
AM
6494+ *
6495+ * Note: this fn creates a copy of strings passed in
6496+ *
6497+ * Returns: true if policy init successful
ceaf2cfb 6498+ */
76514441
AM
6499+static bool policy_init(struct aa_policy *policy, const char *prefix,
6500+ const char *name)
2380c486 6501+{
ceaf2cfb 6502+ /* freed by policy_free */
76514441
AM
6503+ if (prefix) {
6504+ policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3,
6505+ GFP_KERNEL);
6506+ if (policy->hname)
6507+ sprintf(policy->hname, "%s//%s", prefix, name);
6508+ } else
6509+ policy->hname = kstrdup(name, GFP_KERNEL);
ceaf2cfb 6510+ if (!policy->hname)
9474138d 6511+ return 0;
ceaf2cfb
AM
6512+ /* base.name is a substring of fqname */
6513+ policy->name = (char *)hname_tail(policy->hname);
ceaf2cfb
AM
6514+ INIT_LIST_HEAD(&policy->list);
6515+ INIT_LIST_HEAD(&policy->profiles);
6516+ kref_init(&policy->count);
2380c486 6517+
9474138d
AM
6518+ return 1;
6519+}
2380c486 6520+
ceaf2cfb
AM
6521+/**
6522+ * policy_destroy - free the elements referenced by @policy
6523+ * @policy: policy that is to have its elements freed (NOT NULL)
6524+ */
6525+static void policy_destroy(struct aa_policy *policy)
9474138d
AM
6526+{
6527+ /* still contains profiles -- invalid */
ceaf2cfb 6528+ if (!list_empty(&policy->profiles)) {
9474138d
AM
6529+ AA_ERROR("%s: internal error, "
6530+ "policy '%s' still contains profiles\n",
ceaf2cfb 6531+ __func__, policy->name);
9474138d 6532+ BUG();
2380c486 6533+ }
ceaf2cfb 6534+ if (!list_empty(&policy->list)) {
9474138d 6535+ AA_ERROR("%s: internal error, policy '%s' still on list\n",
ceaf2cfb 6536+ __func__, policy->name);
9474138d 6537+ BUG();
2380c486
JR
6538+ }
6539+
ceaf2cfb
AM
6540+ /* don't free name as its a subset of hname */
6541+ kzfree(policy->hname);
9474138d
AM
6542+}
6543+
ceaf2cfb
AM
6544+/**
6545+ * __policy_find - find a policy by @name on a policy list
6546+ * @head: list to search (NOT NULL)
6547+ * @name: name to search for (NOT NULL)
6548+ *
6549+ * Requires: correct locks for the @head list be held
6550+ *
76514441 6551+ * Returns: unrefcounted policy that match @name or NULL if not found
ceaf2cfb
AM
6552+ */
6553+static struct aa_policy *__policy_find(struct list_head *head, const char *name)
9474138d 6554+{
ceaf2cfb 6555+ struct aa_policy *policy;
9474138d 6556+
ceaf2cfb
AM
6557+ list_for_each_entry(policy, head, list) {
6558+ if (!strcmp(policy->name, name))
6559+ return policy;
2380c486 6560+ }
9474138d
AM
6561+ return NULL;
6562+}
2380c486 6563+
ceaf2cfb 6564+/**
76514441 6565+ * __policy_strn_find - find a policy that's name matches @len chars of @str
ceaf2cfb
AM
6566+ * @head: list to search (NOT NULL)
6567+ * @str: string to search for (NOT NULL)
6568+ * @len: length of match required
6569+ *
6570+ * Requires: correct locks for the @head list be held
6571+ *
76514441 6572+ * Returns: unrefcounted policy that match @str or NULL if not found
ceaf2cfb
AM
6573+ *
6574+ * if @len == strlen(@strlen) then this is equiv to __policy_find
6575+ * other wise it allows searching for policy by a partial match of name
6576+ */
6577+static struct aa_policy *__policy_strn_find(struct list_head *head,
6578+ const char *str, int len)
9474138d 6579+{
ceaf2cfb 6580+ struct aa_policy *policy;
2380c486 6581+
ceaf2cfb
AM
6582+ list_for_each_entry(policy, head, list) {
6583+ if (aa_strneq(policy->name, str, len))
6584+ return policy;
9474138d 6585+ }
2380c486 6586+
9474138d 6587+ return NULL;
2380c486
JR
6588+}
6589+
9474138d
AM
6590+/*
6591+ * Routines for AppArmor namespaces
2380c486 6592+ */
2380c486 6593+
76514441
AM
6594+static const char *hidden_ns_name = "---";
6595+/**
6596+ * aa_ns_visible - test if @view is visible from @curr
6597+ * @curr: namespace to treat as the parent (NOT NULL)
6598+ * @view: namespace to test if visible from @curr (NOT NULL)
6599+ *
6600+ * Returns: true if @view is visible from @curr else false
6601+ */
6602+bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view)
6603+{
6604+ if (curr == view)
6605+ return true;
6606+
6607+ for ( ; view; view = view->parent) {
6608+ if (view->parent == curr)
6609+ return true;
6610+ }
6611+ return false;
6612+}
6613+
6614+/**
6615+ * aa_na_name - Find the ns name to display for @view from @curr
6616+ * @curr - current namespace (NOT NULL)
6617+ * @view - namespace attempting to view (NOT NULL)
6618+ *
6619+ * Returns: name of @view visible from @curr
6620+ */
6621+const char *aa_ns_name(struct aa_namespace *curr, struct aa_namespace *view)
6622+{
6623+ /* if view == curr then the namespace name isn't displayed */
6624+ if (curr == view)
6625+ return "";
6626+
6627+ if (aa_ns_visible(curr, view)) {
6628+ /* at this point if a ns is visible it is in a view ns
6629+ * thus the curr ns.hname is a prefix of its name.
6630+ * Only output the virtualized portion of the name
6631+ * Add + 2 to skip over // separating curr hname prefix
6632+ * from the visible tail of the views hname
6633+ */
6634+ return view->base.hname + strlen(curr->base.hname) + 2;
6635+ } else
6636+ return hidden_ns_name;
6637+}
6638+
2380c486 6639+/**
76514441
AM
6640+ * alloc_namespace - allocate, initialize and return a new namespace
6641+ * @prefix: parent namespace name (MAYBE NULL)
ceaf2cfb
AM
6642+ * @name: a preallocated name (NOT NULL)
6643+ *
76514441 6644+ * Returns: refcounted namespace or NULL on failure.
2380c486 6645+ */
76514441
AM
6646+static struct aa_namespace *alloc_namespace(const char *prefix,
6647+ const char *name)
2380c486 6648+{
9474138d 6649+ struct aa_namespace *ns;
2380c486 6650+
9474138d
AM
6651+ ns = kzalloc(sizeof(*ns), GFP_KERNEL);
6652+ AA_DEBUG("%s(%p)\n", __func__, ns);
6653+ if (!ns)
6654+ return NULL;
76514441 6655+ if (!policy_init(&ns->base, prefix, name))
9474138d 6656+ goto fail_ns;
76514441 6657+
ceaf2cfb
AM
6658+ INIT_LIST_HEAD(&ns->sub_ns);
6659+ rwlock_init(&ns->lock);
2380c486 6660+
76514441 6661+ /* released by free_namespace */
ceaf2cfb 6662+ ns->unconfined = aa_alloc_profile("unconfined");
9474138d
AM
6663+ if (!ns->unconfined)
6664+ goto fail_unconfined;
2380c486 6665+
ceaf2cfb 6666+ ns->unconfined->sid = aa_alloc_sid();
9474138d 6667+ ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR |
ceaf2cfb
AM
6668+ PFLAG_IMMUTABLE;
6669+
6670+ /*
76514441 6671+ * released by free_namespace, however __remove_namespace breaks
ceaf2cfb
AM
6672+ * the cyclic references (ns->unconfined, and unconfined->ns) and
6673+ * replaces with refs to parent namespace unconfined
6674+ */
9474138d 6675+ ns->unconfined->ns = aa_get_namespace(ns);
2380c486 6676+
9474138d 6677+ return ns;
2380c486 6678+
9474138d 6679+fail_unconfined:
ceaf2cfb 6680+ kzfree(ns->base.name);
9474138d 6681+fail_ns:
ceaf2cfb 6682+ kzfree(ns);
9474138d 6683+ return NULL;
2380c486
JR
6684+}
6685+
9474138d 6686+/**
76514441 6687+ * free_namespace - free a profile namespace
ceaf2cfb 6688+ * @ns: the namespace to free (MAYBE NULL)
9474138d 6689+ *
ceaf2cfb
AM
6690+ * Requires: All references to the namespace must have been put, if the
6691+ * namespace was referenced by a profile confining a task,
9474138d 6692+ */
76514441 6693+static void free_namespace(struct aa_namespace *ns)
9474138d
AM
6694+{
6695+ if (!ns)
6696+ return;
2380c486 6697+
ceaf2cfb
AM
6698+ policy_destroy(&ns->base);
6699+ aa_put_namespace(ns->parent);
2380c486 6700+
9474138d
AM
6701+ if (ns->unconfined && ns->unconfined->ns == ns)
6702+ ns->unconfined->ns = NULL;
2380c486 6703+
9474138d 6704+ aa_put_profile(ns->unconfined);
ceaf2cfb 6705+ kzfree(ns);
9474138d 6706+}
2380c486 6707+
ceaf2cfb
AM
6708+/**
6709+ * aa_free_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
6710+ * @kr: kref callback for freeing of a namespace (NOT NULL)
6711+ */
6712+void aa_free_namespace_kref(struct kref *kref)
9474138d 6713+{
76514441 6714+ free_namespace(container_of(kref, struct aa_namespace, base.count));
2380c486
JR
6715+}
6716+
6717+/**
ceaf2cfb
AM
6718+ * __aa_find_namespace - find a namespace on a list by @name
6719+ * @head: list to search for namespace on (NOT NULL)
6720+ * @name: name of namespace to look for (NOT NULL)
2380c486 6721+ *
ceaf2cfb
AM
6722+ * Returns: unrefcounted namespace
6723+ *
6724+ * Requires: ns lock be held
2380c486 6725+ */
ceaf2cfb
AM
6726+static struct aa_namespace *__aa_find_namespace(struct list_head *head,
6727+ const char *name)
2380c486 6728+{
ceaf2cfb 6729+ return (struct aa_namespace *)__policy_find(head, name);
9474138d 6730+}
2380c486 6731+
ceaf2cfb
AM
6732+/**
6733+ * aa_find_namespace - look up a profile namespace on the namespace list
6734+ * @root: namespace to search in (NOT NULL)
6735+ * @name: name of namespace to find (NOT NULL)
6736+ *
76514441
AM
6737+ * Returns: a refcounted namespace on the list, or NULL if no namespace
6738+ * called @name exists.
ceaf2cfb
AM
6739+ *
6740+ * refcount released by caller
6741+ */
6742+struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
6743+ const char *name)
9474138d
AM
6744+{
6745+ struct aa_namespace *ns = NULL;
2380c486 6746+
ceaf2cfb
AM
6747+ read_lock(&root->lock);
6748+ ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
6749+ read_unlock(&root->lock);
2380c486 6750+
9474138d
AM
6751+ return ns;
6752+}
2380c486 6753+
9474138d
AM
6754+/**
6755+ * aa_prepare_namespace - find an existing or create a new namespace of @name
76514441 6756+ * @name: the namespace to find or add (MAYBE NULL)
ceaf2cfb
AM
6757+ *
6758+ * Returns: refcounted namespace or NULL if failed to create one
9474138d 6759+ */
ceaf2cfb 6760+static struct aa_namespace *aa_prepare_namespace(const char *name)
9474138d 6761+{
ceaf2cfb
AM
6762+ struct aa_namespace *ns, *root;
6763+
6764+ root = aa_current_profile()->ns;
6765+
6766+ write_lock(&root->lock);
6767+
6768+ /* if name isn't specified the profile is loaded to the current ns */
6769+ if (!name) {
6770+ /* released by caller */
6771+ ns = aa_get_namespace(root);
6772+ goto out;
6773+ }
6774+
6775+ /* try and find the specified ns and if it doesn't exist create it */
6776+ /* released by caller */
6777+ ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
9474138d 6778+ if (!ns) {
76514441 6779+ /* namespace not found */
9474138d 6780+ struct aa_namespace *new_ns;
ceaf2cfb 6781+ write_unlock(&root->lock);
76514441 6782+ new_ns = alloc_namespace(root->base.hname, name);
9474138d
AM
6783+ if (!new_ns)
6784+ return NULL;
ceaf2cfb
AM
6785+ write_lock(&root->lock);
6786+ /* test for race when new_ns was allocated */
6787+ ns = __aa_find_namespace(&root->sub_ns, name);
9474138d 6788+ if (!ns) {
ceaf2cfb
AM
6789+ /* add parent ref */
6790+ new_ns->parent = aa_get_namespace(root);
6791+
6792+ list_add(&new_ns->base.list, &root->sub_ns);
6793+ /* add list ref */
6794+ ns = aa_get_namespace(new_ns);
9474138d
AM
6795+ } else {
6796+ /* raced so free the new one */
76514441 6797+ free_namespace(new_ns);
ceaf2cfb 6798+ /* get reference on namespace */
9474138d
AM
6799+ aa_get_namespace(ns);
6800+ }
2380c486 6801+ }
ceaf2cfb
AM
6802+out:
6803+ write_unlock(&root->lock);
2380c486 6804+
ceaf2cfb 6805+ /* return ref */
9474138d 6806+ return ns;
2380c486
JR
6807+}
6808+
ceaf2cfb 6809+/**
76514441 6810+ * __list_add_profile - add a profile to a list
ceaf2cfb
AM
6811+ * @list: list to add it to (NOT NULL)
6812+ * @profile: the profile to add (NOT NULL)
6813+ *
76514441 6814+ * refcount @profile, should be put by __list_remove_profile
ceaf2cfb
AM
6815+ *
6816+ * Requires: namespace lock be held, or list not be shared
9474138d 6817+ */
76514441
AM
6818+static void __list_add_profile(struct list_head *list,
6819+ struct aa_profile *profile)
2380c486 6820+{
ceaf2cfb
AM
6821+ list_add(&profile->base.list, list);
6822+ /* get list reference */
6823+ aa_get_profile(profile);
2380c486
JR
6824+}
6825+
ceaf2cfb 6826+/**
76514441 6827+ * __list_remove_profile - remove a profile from the list it is on
ceaf2cfb
AM
6828+ * @profile: the profile to remove (NOT NULL)
6829+ *
6830+ * remove a profile from the list, warning generally removal should
76514441 6831+ * be done with __replace_profile as most profile removals are
ceaf2cfb
AM
6832+ * replacements to the unconfined profile.
6833+ *
6834+ * put @profile list refcount
6835+ *
6836+ * Requires: namespace lock be held, or list not have been live
6837+ */
76514441 6838+static void __list_remove_profile(struct aa_profile *profile)
2380c486 6839+{
9474138d
AM
6840+ list_del_init(&profile->base.list);
6841+ if (!(profile->flags & PFLAG_NO_LIST_REF))
ceaf2cfb 6842+ /* release list reference */
9474138d
AM
6843+ aa_put_profile(profile);
6844+}
2380c486 6845+
ceaf2cfb 6846+/**
76514441 6847+ * __replace_profile - replace @old with @new on a list
ceaf2cfb 6848+ * @old: profile to be replaced (NOT NULL)
76514441 6849+ * @new: profile to replace @old with (NOT NULL)
ceaf2cfb 6850+ *
76514441
AM
6851+ * Will duplicate and refcount elements that @new inherits from @old
6852+ * and will inherit @old children.
ceaf2cfb
AM
6853+ *
6854+ * refcount @new for list, put @old list refcount
6855+ *
6856+ * Requires: namespace list lock be held, or list not be shared
6857+ */
76514441 6858+static void __replace_profile(struct aa_profile *old, struct aa_profile *new)
9474138d 6859+{
ceaf2cfb
AM
6860+ struct aa_policy *policy;
6861+ struct aa_profile *child, *tmp;
9474138d 6862+
ceaf2cfb
AM
6863+ if (old->parent)
6864+ policy = &old->parent->base;
6865+ else
6866+ policy = &old->ns->base;
6867+
76514441
AM
6868+ /* released when @new is freed */
6869+ new->parent = aa_get_profile(old->parent);
6870+ new->ns = aa_get_namespace(old->ns);
6871+ new->sid = old->sid;
6872+ __list_add_profile(&policy->profiles, new);
ceaf2cfb
AM
6873+ /* inherit children */
6874+ list_for_each_entry_safe(child, tmp, &old->base.profiles, base.list) {
6875+ aa_put_profile(child->parent);
6876+ child->parent = aa_get_profile(new);
76514441 6877+ /* list refcount transferred to @new*/
ceaf2cfb
AM
6878+ list_move(&child->base.list, &new->base.profiles);
6879+ }
6880+
76514441 6881+ /* released by free_profile */
ceaf2cfb 6882+ old->replacedby = aa_get_profile(new);
76514441 6883+ __list_remove_profile(old);
2380c486
JR
6884+}
6885+
76514441
AM
6886+static void __profile_list_release(struct list_head *head);
6887+
2380c486 6888+/**
76514441
AM
6889+ * __remove_profile - remove old profile, and children
6890+ * @profile: profile to be replaced (NOT NULL)
ceaf2cfb 6891+ *
76514441 6892+ * Requires: namespace list lock be held, or list not be shared
2380c486 6893+ */
76514441 6894+static void __remove_profile(struct aa_profile *profile)
2380c486 6895+{
76514441
AM
6896+ /* release any children lists first */
6897+ __profile_list_release(&profile->base.profiles);
6898+ /* released by free_profile */
6899+ profile->replacedby = aa_get_profile(profile->ns->unconfined);
6900+ __list_remove_profile(profile);
9474138d 6901+}
2380c486 6902+
ceaf2cfb 6903+/**
76514441
AM
6904+ * __profile_list_release - remove all profiles on the list and put refs
6905+ * @head: list of profiles (NOT NULL)
ceaf2cfb
AM
6906+ *
6907+ * Requires: namespace lock be held
6908+ */
76514441 6909+static void __profile_list_release(struct list_head *head)
ceaf2cfb 6910+{
76514441
AM
6911+ struct aa_profile *profile, *tmp;
6912+ list_for_each_entry_safe(profile, tmp, head, base.list)
6913+ __remove_profile(profile);
ceaf2cfb
AM
6914+}
6915+
76514441
AM
6916+static void __ns_list_release(struct list_head *head);
6917+
ceaf2cfb 6918+/**
76514441 6919+ * destroy_namespace - remove everything contained by @ns
ceaf2cfb
AM
6920+ * @ns: namespace to have it contents removed (NOT NULL)
6921+ */
76514441 6922+static void destroy_namespace(struct aa_namespace *ns)
ceaf2cfb
AM
6923+{
6924+ if (!ns)
6925+ return;
6926+
6927+ write_lock(&ns->lock);
6928+ /* release all profiles in this namespace */
76514441 6929+ __profile_list_release(&ns->base.profiles);
ceaf2cfb
AM
6930+
6931+ /* release all sub namespaces */
76514441 6932+ __ns_list_release(&ns->sub_ns);
ceaf2cfb
AM
6933+
6934+ write_unlock(&ns->lock);
6935+}
6936+
6937+/**
76514441 6938+ * __remove_namespace - remove a namespace and all its children
ceaf2cfb 6939+ * @ns: namespace to be removed (NOT NULL)
76514441 6940+ *
ceaf2cfb
AM
6941+ * Requires: ns->parent->lock be held and ns removed from parent.
6942+ */
76514441 6943+static void __remove_namespace(struct aa_namespace *ns)
9474138d
AM
6944+{
6945+ struct aa_profile *unconfined = ns->unconfined;
ceaf2cfb
AM
6946+
6947+ /* remove ns from namespace list */
9474138d 6948+ list_del_init(&ns->base.list);
2380c486 6949+
9474138d
AM
6950+ /*
6951+ * break the ns, unconfined profile cyclic reference and forward
ceaf2cfb
AM
6952+ * all new unconfined profiles requests to the parent namespace
6953+ * This will result in all confined tasks that have a profile
6954+ * being removed, inheriting the parent->unconfined profile.
9474138d 6955+ */
ceaf2cfb
AM
6956+ if (ns->parent)
6957+ ns->unconfined = aa_get_profile(ns->parent->unconfined);
6958+
76514441 6959+ destroy_namespace(ns);
ceaf2cfb
AM
6960+
6961+ /* release original ns->unconfined ref */
9474138d 6962+ aa_put_profile(unconfined);
ceaf2cfb 6963+ /* release ns->base.list ref, from removal above */
9474138d 6964+ aa_put_namespace(ns);
2380c486
JR
6965+}
6966+
6967+/**
76514441
AM
6968+ * __ns_list_release - remove all profile namespaces on the list put refs
6969+ * @head: list of profile namespaces (NOT NULL)
6970+ *
6971+ * Requires: namespace lock be held
6972+ */
6973+static void __ns_list_release(struct list_head *head)
6974+{
6975+ struct aa_namespace *ns, *tmp;
6976+ list_for_each_entry_safe(ns, tmp, head, base.list)
6977+ __remove_namespace(ns);
6978+
6979+}
6980+
6981+/**
ceaf2cfb
AM
6982+ * aa_alloc_root_ns - allocate the root profile namespace
6983+ *
6984+ * Returns: %0 on success else error
6985+ *
2380c486 6986+ */
ceaf2cfb 6987+int __init aa_alloc_root_ns(void)
2380c486 6988+{
ceaf2cfb 6989+ /* released by aa_free_root_ns - used as list ref*/
76514441 6990+ root_ns = alloc_namespace(NULL, "root");
ceaf2cfb
AM
6991+ if (!root_ns)
6992+ return -ENOMEM;
2380c486 6993+
ceaf2cfb
AM
6994+ return 0;
6995+}
2380c486 6996+
ceaf2cfb
AM
6997+ /**
6998+ * aa_free_root_ns - free the root profile namespace
6999+ */
76514441 7000+void __init aa_free_root_ns(void)
ceaf2cfb
AM
7001+ {
7002+ struct aa_namespace *ns = root_ns;
7003+ root_ns = NULL;
76514441
AM
7004+
7005+ destroy_namespace(ns);
ceaf2cfb 7006+ aa_put_namespace(ns);
2380c486
JR
7007+}
7008+
7009+/**
ceaf2cfb
AM
7010+ * aa_alloc_profile - allocate, initialize and return a new profile
7011+ * @hname: name of the profile (NOT NULL)
2380c486 7012+ *
76514441 7013+ * Returns: refcount profile or NULL on failure
2380c486 7014+ */
ceaf2cfb 7015+struct aa_profile *aa_alloc_profile(const char *hname)
2380c486 7016+{
9474138d
AM
7017+ struct aa_profile *profile;
7018+
76514441 7019+ /* freed by free_profile - usually through aa_put_profile */
9474138d
AM
7020+ profile = kzalloc(sizeof(*profile), GFP_KERNEL);
7021+ if (!profile)
7022+ return NULL;
ceaf2cfb 7023+
76514441 7024+ if (!policy_init(&profile->base, NULL, hname)) {
ceaf2cfb 7025+ kzfree(profile);
9474138d
AM
7026+ return NULL;
7027+ }
ceaf2cfb 7028+
76514441 7029+ /* refcount released by caller */
9474138d 7030+ return profile;
2380c486
JR
7031+}
7032+
7033+/**
9474138d 7034+ * aa_new_null_profile - create a new null-X learning profile
ceaf2cfb 7035+ * @parent: profile that caused this profile to be created (NOT NULL)
9474138d
AM
7036+ * @hat: true if the null- learning profile is a hat
7037+ *
7038+ * Create a null- complain mode profile used in learning mode. The name of
7039+ * the profile is unique and follows the format of parent//null-sid.
2380c486 7040+ *
9474138d
AM
7041+ * null profiles are added to the profile list but the list does not
7042+ * hold a count on them so that they are automatically released when
7043+ * not in use.
ceaf2cfb 7044+ *
76514441 7045+ * Returns: new refcounted profile else NULL on failure
2380c486 7046+ */
ceaf2cfb 7047+struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
2380c486 7048+{
9474138d
AM
7049+ struct aa_profile *profile = NULL;
7050+ char *name;
ceaf2cfb 7051+ u32 sid = aa_alloc_sid();
9474138d 7052+
ceaf2cfb
AM
7053+ /* freed below */
7054+ name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, GFP_KERNEL);
9474138d
AM
7055+ if (!name)
7056+ goto fail;
ceaf2cfb 7057+ sprintf(name, "%s//null-%x", parent->base.hname, sid);
9474138d 7058+
ceaf2cfb 7059+ profile = aa_alloc_profile(name);
9474138d
AM
7060+ kfree(name);
7061+ if (!profile)
7062+ goto fail;
7063+
ceaf2cfb 7064+ profile->sid = sid;
9474138d 7065+ profile->mode = APPARMOR_COMPLAIN;
76514441 7066+ profile->flags = PFLAG_NULL;
9474138d 7067+ if (hat)
ceaf2cfb 7068+ profile->flags |= PFLAG_HAT;
9474138d 7069+
76514441 7070+ /* released on free_profile */
9474138d 7071+ profile->parent = aa_get_profile(parent);
ceaf2cfb
AM
7072+ profile->ns = aa_get_namespace(parent->ns);
7073+
7074+ write_lock(&profile->ns->lock);
76514441 7075+ __list_add_profile(&parent->base.profiles, profile);
ceaf2cfb
AM
7076+ write_unlock(&profile->ns->lock);
7077+
76514441 7078+ /* refcount released by caller */
ceaf2cfb 7079+ return profile;
9474138d 7080+
ceaf2cfb
AM
7081+fail:
7082+ aa_free_sid(sid);
7083+ return NULL;
2380c486
JR
7084+}
7085+
9474138d 7086+/**
76514441 7087+ * free_profile - free a profile
ceaf2cfb 7088+ * @profile: the profile to free (MAYBE NULL)
2380c486 7089+ *
9474138d
AM
7090+ * Free a profile, its hats and null_profile. All references to the profile,
7091+ * its hats and null_profile must have been put.
2380c486 7092+ *
76514441 7093+ * If the profile was referenced from a task context, free_profile() will
9474138d 7094+ * be called from an rcu callback routine, so we must not sleep here.
2380c486 7095+ */
76514441 7096+static void free_profile(struct aa_profile *profile)
9474138d
AM
7097+{
7098+ AA_DEBUG("%s(%p)\n", __func__, profile);
2380c486 7099+
9474138d
AM
7100+ if (!profile)
7101+ return;
7102+
9474138d 7103+ if (!list_empty(&profile->base.list)) {
ceaf2cfb
AM
7104+ AA_ERROR("%s: internal error, "
7105+ "profile '%s' still on ns list\n",
7106+ __func__, profile->base.name);
7107+ BUG();
9474138d
AM
7108+ }
7109+
ceaf2cfb
AM
7110+ /* free children profiles */
7111+ policy_destroy(&profile->base);
7112+ aa_put_profile(profile->parent);
9474138d
AM
7113+
7114+ aa_put_namespace(profile->ns);
76514441 7115+ kzfree(profile->rename);
9474138d
AM
7116+
7117+ aa_free_file_rules(&profile->file);
7118+ aa_free_cap_rules(&profile->caps);
7119+ aa_free_net_rules(&profile->net);
7120+ aa_free_rlimit_rules(&profile->rlimits);
7121+
7122+ aa_free_sid(profile->sid);
ceaf2cfb 7123+ aa_put_dfa(profile->xmatch);
9474138d 7124+
76514441 7125+ aa_put_profile(profile->replacedby);
9474138d 7126+
ceaf2cfb 7127+ kzfree(profile);
9474138d
AM
7128+}
7129+
ceaf2cfb
AM
7130+/**
7131+ * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile)
7132+ * @kr: kref callback for freeing of a profile (NOT NULL)
7133+ */
7134+void aa_free_profile_kref(struct kref *kref)
7135+{
7136+ struct aa_profile *p = container_of(kref, struct aa_profile,
7137+ base.count);
9474138d 7138+
76514441 7139+ free_profile(p);
ceaf2cfb 7140+}
9474138d 7141+
76514441 7142+/* TODO: profile accounting - setup in remove */
9474138d 7143+
ceaf2cfb 7144+/**
76514441 7145+ * __find_child - find a profile on @head list with a name matching @name
ceaf2cfb
AM
7146+ * @head: list to search (NOT NULL)
7147+ * @name: name of profile (NOT NULL)
7148+ *
7149+ * Requires: ns lock protecting list be held
7150+ *
7151+ * Returns: unrefcounted profile ptr, or NULL if not found
7152+ */
76514441 7153+static struct aa_profile *__find_child(struct list_head *head, const char *name)
9474138d 7154+{
ceaf2cfb 7155+ return (struct aa_profile *)__policy_find(head, name);
9474138d
AM
7156+}
7157+
ceaf2cfb 7158+/**
76514441 7159+ * __strn_find_child - find a profile on @head list using substring of @name
ceaf2cfb
AM
7160+ * @head: list to search (NOT NULL)
7161+ * @name: name of profile (NOT NULL)
7162+ * @len: length of @name substring to match
7163+ *
7164+ * Requires: ns lock protecting list be held
7165+ *
7166+ * Returns: unrefcounted profile ptr, or NULL if not found
7167+ */
76514441
AM
7168+static struct aa_profile *__strn_find_child(struct list_head *head,
7169+ const char *name, int len)
9474138d 7170+{
ceaf2cfb 7171+ return (struct aa_profile *)__policy_strn_find(head, name, len);
9474138d 7172+}
2380c486 7173+
2380c486 7174+/**
9474138d 7175+ * aa_find_child - find a profile by @name in @parent
ceaf2cfb
AM
7176+ * @parent: profile to search (NOT NULL)
7177+ * @name: profile name to search for (NOT NULL)
9474138d 7178+ *
76514441 7179+ * Returns: a refcounted profile or NULL if not found
2380c486 7180+ */
9474138d
AM
7181+struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
7182+{
7183+ struct aa_profile *profile;
2380c486 7184+
ceaf2cfb 7185+ read_lock(&parent->ns->lock);
76514441 7186+ profile = aa_get_profile(__find_child(&parent->base.profiles, name));
ceaf2cfb 7187+ read_unlock(&parent->ns->lock);
2380c486 7188+
76514441 7189+ /* refcount released by caller */
9474138d
AM
7190+ return profile;
7191+}
2380c486 7192+
ceaf2cfb 7193+/**
76514441 7194+ * __lookup_parent - lookup the parent of a profile of name @hname
ceaf2cfb
AM
7195+ * @ns: namespace to lookup profile in (NOT NULL)
7196+ * @hname: hierarchical profile name to find parent of (NOT NULL)
7197+ *
7198+ * Lookups up the parent of a fully qualified profile name, the profile
7199+ * that matches hname does not need to exist, in general this
7200+ * is used to load a new profile.
7201+ *
7202+ * Requires: ns->lock be held
7203+ *
7204+ * Returns: unrefcounted policy or NULL if not found
7205+ */
76514441
AM
7206+static struct aa_policy *__lookup_parent(struct aa_namespace *ns,
7207+ const char *hname)
9474138d 7208+{
ceaf2cfb 7209+ struct aa_policy *policy;
9474138d
AM
7210+ struct aa_profile *profile = NULL;
7211+ char *split;
7212+
ceaf2cfb 7213+ policy = &ns->base;
9474138d 7214+
ceaf2cfb 7215+ for (split = strstr(hname, "//"); split;) {
76514441
AM
7216+ profile = __strn_find_child(&policy->profiles, hname,
7217+ split - hname);
9474138d
AM
7218+ if (!profile)
7219+ return NULL;
ceaf2cfb
AM
7220+ policy = &profile->base;
7221+ hname = split + 2;
7222+ split = strstr(hname, "//");
9474138d
AM
7223+ }
7224+ if (!profile)
7225+ return &ns->base;
7226+ return &profile->base;
7227+}
7228+
ceaf2cfb 7229+/**
76514441 7230+ * __lookup_profile - lookup the profile matching @hname
ceaf2cfb
AM
7231+ * @base: base list to start looking up profile name from (NOT NULL)
7232+ * @hname: hierarchical profile name (NOT NULL)
7233+ *
7234+ * Requires: ns->lock be held
7235+ *
7236+ * Returns: unrefcounted profile pointer or NULL if not found
7237+ *
7238+ * Do a relative name lookup, recursing through profile tree.
7239+ */
76514441
AM
7240+static struct aa_profile *__lookup_profile(struct aa_policy *base,
7241+ const char *hname)
9474138d 7242+{
9474138d
AM
7243+ struct aa_profile *profile = NULL;
7244+ char *split;
7245+
ceaf2cfb 7246+ for (split = strstr(hname, "//"); split;) {
76514441
AM
7247+ profile = __strn_find_child(&base->profiles, hname,
7248+ split - hname);
9474138d
AM
7249+ if (!profile)
7250+ return NULL;
7251+
ceaf2cfb
AM
7252+ base = &profile->base;
7253+ hname = split + 2;
7254+ split = strstr(hname, "//");
9474138d
AM
7255+ }
7256+
76514441 7257+ profile = __find_child(&base->profiles, hname);
2380c486 7258+
9474138d
AM
7259+ return profile;
7260+}
2380c486 7261+
9474138d 7262+/**
76514441
AM
7263+ * aa_lookup_profile - find a profile by its full or partial name
7264+ * @ns: the namespace to start from (NOT NULL)
7265+ * @hname: name to do lookup on. Does not contain namespace prefix (NOT NULL)
ceaf2cfb
AM
7266+ *
7267+ * Returns: refcounted profile or NULL if not found
9474138d 7268+ */
76514441 7269+struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname)
9474138d
AM
7270+{
7271+ struct aa_profile *profile;
2380c486 7272+
ceaf2cfb 7273+ read_lock(&ns->lock);
76514441 7274+ profile = aa_get_profile(__lookup_profile(&ns->base, hname));
ceaf2cfb 7275+ read_unlock(&ns->lock);
76514441
AM
7276+
7277+ /* refcount released by caller */
9474138d
AM
7278+ return profile;
7279+}
2380c486 7280+
ceaf2cfb
AM
7281+/**
7282+ * replacement_allowed - test to see if replacement is allowed
7283+ * @profile: profile to test if it can be replaced (MAYBE NULL)
76514441
AM
7284+ * @noreplace: true if replacement shouldn't be allowed but addition is okay
7285+ * @info: Returns - info about why replacement failed (NOT NULL)
9474138d 7286+ *
76514441 7287+ * Returns: %0 if replacement allowed else error code
9474138d 7288+ */
76514441
AM
7289+static int replacement_allowed(struct aa_profile *profile, int noreplace,
7290+ const char **info)
9474138d 7291+{
ceaf2cfb
AM
7292+ if (profile) {
7293+ if (profile->flags & PFLAG_IMMUTABLE) {
76514441
AM
7294+ *info = "cannot replace immutible profile";
7295+ return -EPERM;
7296+ } else if (noreplace) {
7297+ *info = "profile already exists";
7298+ return -EEXIST;
ceaf2cfb 7299+ }
9474138d 7300+ }
76514441 7301+ return 0;
ceaf2cfb 7302+}
2380c486 7303+
ceaf2cfb 7304+/**
76514441 7305+ * __add_new_profile - simple wrapper around __list_add_profile
ceaf2cfb
AM
7306+ * @ns: namespace that profile is being added to (NOT NULL)
7307+ * @policy: the policy container to add the profile to (NOT NULL)
7308+ * @profile: profile to add (NOT NULL)
7309+ *
7310+ * add a profile to a list and do other required basic allocations
7311+ */
76514441 7312+static void __add_new_profile(struct aa_namespace *ns, struct aa_policy *policy,
ceaf2cfb
AM
7313+ struct aa_profile *profile)
7314+{
7315+ if (policy != &ns->base)
76514441 7316+ /* released on profile replacement or free_profile */
ceaf2cfb 7317+ profile->parent = aa_get_profile((struct aa_profile *) policy);
76514441
AM
7318+ __list_add_profile(&policy->profiles, profile);
7319+ /* released on free_profile */
ceaf2cfb
AM
7320+ profile->sid = aa_alloc_sid();
7321+ profile->ns = aa_get_namespace(ns);
9474138d
AM
7322+}
7323+
7324+/**
76514441
AM
7325+ * aa_audit_policy - Do auditing of policy changes
7326+ * @op: policy operation being performed
7327+ * @gfp: memory allocation flags
7328+ * @name: name of profile being manipulated (NOT NULL)
7329+ * @info: any extra information to be audited (MAYBE NULL)
7330+ * @error: error code
7331+ *
7332+ * Returns: the error to be returned after audit is done
7333+ */
7334+static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
7335+ int error)
7336+{
7337+ struct common_audit_data sa;
7338+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
7339+ sa.aad.op = op;
7340+ sa.aad.name = name;
7341+ sa.aad.info = info;
7342+ sa.aad.error = error;
7343+
7344+ return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp,
7345+ &sa, NULL);
7346+}
7347+
7348+/**
7349+ * aa_may_manage_policy - can the current task manage policy
7350+ * @op: the policy manipulation operation being done
7351+ *
7352+ * Returns: true if the task is allowed to manipulate policy
7353+ */
7354+bool aa_may_manage_policy(int op)
7355+{
7356+ /* check if loading policy is locked out */
7357+ if (aa_g_lock_policy) {
7358+ audit_policy(op, GFP_KERNEL, NULL, "policy_locked", -EACCES);
7359+ return 0;
7360+ }
7361+
7362+ if (!capable(CAP_MAC_ADMIN)) {
7363+ audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES);
7364+ return 0;
7365+ }
7366+
7367+ return 1;
7368+}
7369+
7370+/**
7371+ * aa_replace_profiles - replace profile(s) on the profile list
ceaf2cfb
AM
7372+ * @udata: serialized data stream (NOT NULL)
7373+ * @size: size of the serialized data stream
76514441 7374+ * @noreplace: true if only doing addition, no replacement allowed
ceaf2cfb
AM
7375+ *
7376+ * unpack and replace a profile on the profile list and uses of that profile
7377+ * by any aa_task_cxt. If the profile does not exist on the profile list
7378+ * it is added.
7379+ *
7380+ * Returns: size of data consumed else error code on failure.
9474138d 7381+ */
76514441 7382+ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
2380c486 7383+{
ceaf2cfb
AM
7384+ struct aa_policy *policy;
7385+ struct aa_profile *old_profile = NULL, *new_profile = NULL;
7386+ struct aa_profile *rename_profile = NULL;
76514441
AM
7387+ struct aa_namespace *ns = NULL;
7388+ const char *ns_name, *name = NULL, *info = NULL;
7389+ int op = OP_PROF_REPL;
ceaf2cfb 7390+ ssize_t error;
9474138d 7391+
ceaf2cfb 7392+ /* released below */
76514441 7393+ new_profile = aa_unpack(udata, size, &ns_name);
ceaf2cfb 7394+ if (IS_ERR(new_profile)) {
76514441
AM
7395+ error = PTR_ERR(new_profile);
7396+ new_profile = NULL;
ceaf2cfb
AM
7397+ goto fail;
7398+ }
7399+
7400+ /* released below */
76514441 7401+ ns = aa_prepare_namespace(ns_name);
ceaf2cfb 7402+ if (!ns) {
76514441
AM
7403+ info = "failed to prepare namespace";
7404+ error = -ENOMEM;
7405+ name = ns_name;
ceaf2cfb
AM
7406+ goto fail;
7407+ }
7408+
76514441 7409+ name = new_profile->base.hname;
ceaf2cfb
AM
7410+
7411+ write_lock(&ns->lock);
7412+ /* no ref on policy only use inside lock */
76514441 7413+ policy = __lookup_parent(ns, new_profile->base.hname);
ceaf2cfb
AM
7414+
7415+ if (!policy) {
76514441
AM
7416+ info = "parent does not exist";
7417+ error = -ENOENT;
ceaf2cfb
AM
7418+ goto audit;
7419+ }
7420+
76514441 7421+ old_profile = __find_child(&policy->profiles, new_profile->base.name);
ceaf2cfb
AM
7422+ /* released below */
7423+ aa_get_profile(old_profile);
7424+
7425+ if (new_profile->rename) {
76514441
AM
7426+ rename_profile = __lookup_profile(&ns->base,
7427+ new_profile->rename);
ceaf2cfb
AM
7428+ /* released below */
7429+ aa_get_profile(rename_profile);
7430+
7431+ if (!rename_profile) {
76514441
AM
7432+ info = "profile to rename does not exist";
7433+ name = new_profile->rename;
7434+ error = -ENOENT;
ceaf2cfb
AM
7435+ goto audit;
7436+ }
7437+ }
7438+
76514441
AM
7439+ error = replacement_allowed(old_profile, noreplace, &info);
7440+ if (error)
ceaf2cfb
AM
7441+ goto audit;
7442+
76514441
AM
7443+ error = replacement_allowed(rename_profile, noreplace, &info);
7444+ if (error)
ceaf2cfb
AM
7445+ goto audit;
7446+
7447+audit:
7448+ if (!old_profile && !rename_profile)
76514441 7449+ op = OP_PROF_LOAD;
ceaf2cfb 7450+
76514441 7451+ error = audit_policy(op, GFP_ATOMIC, name, info, error);
ceaf2cfb
AM
7452+
7453+ if (!error) {
ceaf2cfb 7454+ if (rename_profile)
76514441
AM
7455+ __replace_profile(rename_profile, new_profile);
7456+ if (old_profile) {
7457+ /* when there are both rename and old profiles
7458+ * inherit old profiles sid
7459+ */
7460+ if (rename_profile)
7461+ aa_free_sid(new_profile->sid);
7462+ __replace_profile(old_profile, new_profile);
7463+ }
ceaf2cfb
AM
7464+ if (!(old_profile || rename_profile))
7465+ __add_new_profile(ns, policy, new_profile);
7466+ }
7467+ write_unlock(&ns->lock);
7468+
7469+out:
7470+ aa_put_namespace(ns);
7471+ aa_put_profile(rename_profile);
7472+ aa_put_profile(old_profile);
7473+ aa_put_profile(new_profile);
7474+ if (error)
7475+ return error;
7476+ return size;
7477+
7478+fail:
76514441 7479+ error = audit_policy(op, GFP_KERNEL, name, info, error);
ceaf2cfb 7480+ goto out;
9474138d
AM
7481+}
7482+
7483+/**
76514441 7484+ * aa_remove_profiles - remove profile(s) from the system
ceaf2cfb
AM
7485+ * @fqname: name of the profile or namespace to remove (NOT NULL)
7486+ * @size: size of the name
9474138d 7487+ *
ceaf2cfb
AM
7488+ * Remove a profile or sub namespace from the current namespace, so that
7489+ * they can not be found anymore and mark them as replaced by unconfined
9474138d 7490+ *
ceaf2cfb
AM
7491+ * NOTE: removing confinement does not restore rlimits to preconfinemnet values
7492+ *
7493+ * Returns: size of data consume else error code if fails
9474138d 7494+ */
76514441 7495+ssize_t aa_remove_profiles(char *fqname, size_t size)
9474138d 7496+{
ceaf2cfb
AM
7497+ struct aa_namespace *root, *ns = NULL;
7498+ struct aa_profile *profile = NULL;
76514441
AM
7499+ const char *name = fqname, *info = NULL;
7500+ ssize_t error = 0;
9474138d 7501+
ceaf2cfb 7502+ if (*fqname == 0) {
76514441
AM
7503+ info = "no profile specified";
7504+ error = -ENOENT;
ceaf2cfb
AM
7505+ goto fail;
7506+ }
7507+
ceaf2cfb
AM
7508+ root = aa_current_profile()->ns;
7509+
7510+ if (fqname[0] == ':') {
7511+ char *ns_name;
7512+ name = aa_split_fqname(fqname, &ns_name);
76514441 7513+ if (ns_name) {
ceaf2cfb
AM
7514+ /* released below */
7515+ ns = aa_find_namespace(root, ns_name);
76514441
AM
7516+ if (!ns) {
7517+ info = "namespace does not exist";
7518+ error = -ENOENT;
7519+ goto fail;
7520+ }
7521+ }
ceaf2cfb
AM
7522+ } else
7523+ /* released below */
7524+ ns = aa_get_namespace(root);
7525+
ceaf2cfb
AM
7526+ write_lock(&ns->lock);
7527+ if (!name) {
7528+ /* remove namespace - can only happen if fqname[0] == ':' */
76514441 7529+ __remove_namespace(ns);
ceaf2cfb
AM
7530+ } else {
7531+ /* remove profile */
76514441 7532+ profile = aa_get_profile(__lookup_profile(&ns->base, name));
ceaf2cfb 7533+ if (!profile) {
76514441
AM
7534+ error = -ENOENT;
7535+ info = "profile does not exist";
ceaf2cfb
AM
7536+ goto fail_ns_lock;
7537+ }
76514441
AM
7538+ name = profile->base.hname;
7539+ __remove_profile(profile);
ceaf2cfb
AM
7540+ }
7541+ write_unlock(&ns->lock);
2380c486 7542+
ceaf2cfb 7543+ /* don't fail removal if audit fails */
76514441 7544+ (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
ceaf2cfb
AM
7545+ aa_put_namespace(ns);
7546+ aa_put_profile(profile);
7547+ return size;
7548+
7549+fail_ns_lock:
7550+ write_unlock(&ns->lock);
7551+ aa_put_namespace(ns);
7552+
7553+fail:
76514441 7554+ (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
ceaf2cfb
AM
7555+ return error;
7556+}
7557diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
7558new file mode 100644
76514441 7559index 0000000..6b0637b
ceaf2cfb
AM
7560--- /dev/null
7561+++ b/security/apparmor/policy_unpack.c
76514441 7562@@ -0,0 +1,740 @@
2380c486 7563+/*
9474138d
AM
7564+ * AppArmor security module
7565+ *
7566+ * This file contains AppArmor functions for unpacking policy loaded from
7567+ * userspace.
2380c486 7568+ *
9474138d 7569+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 7570+ * Copyright 2009-2010 Canonical Ltd.
2380c486 7571+ *
9474138d
AM
7572+ * This program is free software; you can redistribute it and/or
7573+ * modify it under the terms of the GNU General Public License as
7574+ * published by the Free Software Foundation, version 2 of the
7575+ * License.
7576+ *
7577+ * AppArmor uses a serialized binary format for loading policy.
76514441
AM
7578+ * To find policy format documentation look in Documentation/apparmor.txt
7579+ * All policy is validated before it is used.
2380c486
JR
7580+ */
7581+
7582+#include <asm/unaligned.h>
ceaf2cfb 7583+#include <linux/ctype.h>
9474138d 7584+#include <linux/errno.h>
2380c486 7585+
9474138d
AM
7586+#include "include/apparmor.h"
7587+#include "include/audit.h"
7588+#include "include/context.h"
7589+#include "include/match.h"
7590+#include "include/policy.h"
ceaf2cfb 7591+#include "include/policy_unpack.h"
9474138d
AM
7592+#include "include/sid.h"
7593+
2380c486
JR
7594+/*
7595+ * The AppArmor interface treats data as a type byte followed by the
7596+ * actual data. The interface has the notion of a a named entry
7597+ * which has a name (AA_NAME typecode followed by name string) followed by
7598+ * the entries typecode and data. Named types allow for optional
7599+ * elements and extensions to be added and tested for without breaking
76514441 7600+ * backwards compatibility.
2380c486
JR
7601+ */
7602+
7603+enum aa_code {
7604+ AA_U8,
7605+ AA_U16,
7606+ AA_U32,
7607+ AA_U64,
ceaf2cfb 7608+ AA_NAME, /* same as string except it is items name */
2380c486
JR
7609+ AA_STRING,
7610+ AA_BLOB,
7611+ AA_STRUCT,
7612+ AA_STRUCTEND,
7613+ AA_LIST,
7614+ AA_LISTEND,
7615+ AA_ARRAY,
7616+ AA_ARRAYEND,
7617+};
7618+
7619+/*
7620+ * aa_ext is the read of the buffer containing the serialized profile. The
7621+ * data is copied into a kernel buffer in apparmorfs and then handed off to
7622+ * the unpack routines.
7623+ */
7624+struct aa_ext {
7625+ void *start;
7626+ void *end;
ceaf2cfb 7627+ void *pos; /* pointer to current position in the buffer */
2380c486 7628+ u32 version;
9474138d
AM
7629+};
7630+
ceaf2cfb 7631+/* audit callback for unpack fields */
76514441 7632+static void audit_cb(struct audit_buffer *ab, void *va)
9474138d 7633+{
76514441
AM
7634+ struct common_audit_data *sa = va;
7635+ if (sa->aad.iface.target) {
7636+ struct aa_profile *name = sa->aad.iface.target;
ceaf2cfb 7637+ audit_log_format(ab, " name=");
76514441 7638+ audit_log_untrustedstring(ab, name->base.hname);
5e665963 7639+ }
76514441
AM
7640+ if (sa->aad.iface.pos)
7641+ audit_log_format(ab, " offset=%ld", sa->aad.iface.pos);
9474138d
AM
7642+}
7643+
ceaf2cfb 7644+/**
76514441
AM
7645+ * audit_iface - do audit message for policy unpacking/load/replace/remove
7646+ * @new: profile if it has been allocated (MAYBE NULL)
7647+ * @name: name of the profile being manipulated (MAYBE NULL)
7648+ * @info: any extra info about the failure (MAYBE NULL)
7649+ * @e: buffer position info (NOT NULL)
7650+ * @error: error code
ceaf2cfb
AM
7651+ *
7652+ * Returns: %0 or error
7653+ */
76514441
AM
7654+static int audit_iface(struct aa_profile *new, const char *name,
7655+ const char *info, struct aa_ext *e, int error)
9474138d 7656+{
76514441
AM
7657+ struct aa_profile *profile = __aa_current_profile();
7658+ struct common_audit_data sa;
7659+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
7660+ sa.aad.iface.pos = e->pos - e->start;
7661+ sa.aad.iface.target = new;
7662+ sa.aad.name = name;
7663+ sa.aad.info = info;
7664+ sa.aad.error = error;
7665+
7666+ return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa,
7667+ audit_cb);
9474138d
AM
7668+}
7669+
ceaf2cfb 7670+/* test if read will be in packed data bounds */
76514441 7671+static bool inbounds(struct aa_ext *e, size_t size)
2380c486
JR
7672+{
7673+ return (size <= e->end - e->pos);
7674+}
7675+
7676+/**
7677+ * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
76514441
AM
7678+ * @e: serialized data read head (NOT NULL)
7679+ * @chunk: start address for chunk of data (NOT NULL)
2380c486 7680+ *
ceaf2cfb 7681+ * Returns: the size of chunk found with the read head at the end of the chunk.
2380c486 7682+ */
ceaf2cfb 7683+static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk)
2380c486 7684+{
2380c486
JR
7685+ size_t size = 0;
7686+
76514441 7687+ if (!inbounds(e, sizeof(u16)))
ceaf2cfb
AM
7688+ return 0;
7689+ size = le16_to_cpu(get_unaligned((u16 *) e->pos));
2380c486 7690+ e->pos += sizeof(u16);
76514441 7691+ if (!inbounds(e, size))
ceaf2cfb 7692+ return 0;
2380c486
JR
7693+ *chunk = e->pos;
7694+ e->pos += size;
7695+ return size;
2380c486
JR
7696+}
7697+
ceaf2cfb
AM
7698+/* unpack control byte */
7699+static bool unpack_X(struct aa_ext *e, enum aa_code code)
2380c486 7700+{
76514441 7701+ if (!inbounds(e, 1))
2380c486
JR
7702+ return 0;
7703+ if (*(u8 *) e->pos != code)
7704+ return 0;
7705+ e->pos++;
7706+ return 1;
7707+}
7708+
7709+/**
ceaf2cfb
AM
7710+ * unpack_nameX - check is the next element is of type X with a name of @name
7711+ * @e: serialized data extent information (NOT NULL)
2380c486 7712+ * @code: type code
ceaf2cfb 7713+ * @name: name to match to the serialized element. (MAYBE NULL)
2380c486
JR
7714+ *
7715+ * check that the next serialized data element is of type X and has a tag
7716+ * name @name. If @name is specified then there must be a matching
7717+ * name element in the stream. If @name is NULL any name element will be
7718+ * skipped and only the typecode will be tested.
76514441
AM
7719+ *
7720+ * Returns 1 on success (both type code and name tests match) and the read
2380c486 7721+ * head is advanced past the headers
ceaf2cfb 7722+ *
76514441 7723+ * Returns: 0 if either match fails, the read head does not move
2380c486 7724+ */
ceaf2cfb 7725+static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
2380c486 7726+{
ceaf2cfb
AM
7727+ /*
7728+ * May need to reset pos if name or type doesn't match
7729+ */
2380c486
JR
7730+ void *pos = e->pos;
7731+ /*
7732+ * Check for presence of a tagname, and if present name size
7733+ * AA_NAME tag value is a u16.
7734+ */
ceaf2cfb 7735+ if (unpack_X(e, AA_NAME)) {
9474138d 7736+ char *tag = NULL;
ceaf2cfb 7737+ size_t size = unpack_u16_chunk(e, &tag);
2380c486
JR
7738+ /* if a name is specified it must match. otherwise skip tag */
7739+ if (name && (!size || strcmp(name, tag)))
7740+ goto fail;
7741+ } else if (name) {
7742+ /* if a name is specified and there is no name tag fail */
7743+ goto fail;
7744+ }
7745+
7746+ /* now check if type code matches */
ceaf2cfb 7747+ if (unpack_X(e, code))
2380c486
JR
7748+ return 1;
7749+
7750+fail:
7751+ e->pos = pos;
7752+ return 0;
7753+}
7754+
ceaf2cfb 7755+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
2380c486 7756+{
ceaf2cfb 7757+ if (unpack_nameX(e, AA_U16, name)) {
76514441 7758+ if (!inbounds(e, sizeof(u16)))
ceaf2cfb 7759+ return 0;
2380c486 7760+ if (data)
ceaf2cfb 7761+ *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
2380c486
JR
7762+ e->pos += sizeof(u16);
7763+ return 1;
7764+ }
2380c486
JR
7765+ return 0;
7766+}
7767+
ceaf2cfb 7768+static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
2380c486 7769+{
ceaf2cfb 7770+ if (unpack_nameX(e, AA_U32, name)) {
76514441 7771+ if (!inbounds(e, sizeof(u32)))
ceaf2cfb 7772+ return 0;
2380c486 7773+ if (data)
ceaf2cfb 7774+ *data = le32_to_cpu(get_unaligned((u32 *) e->pos));
2380c486
JR
7775+ e->pos += sizeof(u32);
7776+ return 1;
7777+ }
2380c486
JR
7778+ return 0;
7779+}
7780+
ceaf2cfb 7781+static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name)
2380c486 7782+{
ceaf2cfb 7783+ if (unpack_nameX(e, AA_U64, name)) {
76514441 7784+ if (!inbounds(e, sizeof(u64)))
ceaf2cfb 7785+ return 0;
2380c486 7786+ if (data)
ceaf2cfb 7787+ *data = le64_to_cpu(get_unaligned((u64 *) e->pos));
2380c486
JR
7788+ e->pos += sizeof(u64);
7789+ return 1;
7790+ }
2380c486
JR
7791+ return 0;
7792+}
7793+
ceaf2cfb 7794+static size_t unpack_array(struct aa_ext *e, const char *name)
2380c486 7795+{
ceaf2cfb 7796+ if (unpack_nameX(e, AA_ARRAY, name)) {
2380c486 7797+ int size;
76514441 7798+ if (!inbounds(e, sizeof(u16)))
ceaf2cfb
AM
7799+ return 0;
7800+ size = (int)le16_to_cpu(get_unaligned((u16 *) e->pos));
2380c486
JR
7801+ e->pos += sizeof(u16);
7802+ return size;
7803+ }
2380c486
JR
7804+ return 0;
7805+}
7806+
ceaf2cfb 7807+static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
2380c486 7808+{
ceaf2cfb 7809+ if (unpack_nameX(e, AA_BLOB, name)) {
2380c486 7810+ u32 size;
76514441 7811+ if (!inbounds(e, sizeof(u32)))
ceaf2cfb
AM
7812+ return 0;
7813+ size = le32_to_cpu(get_unaligned((u32 *) e->pos));
2380c486 7814+ e->pos += sizeof(u32);
76514441 7815+ if (inbounds(e, (size_t) size)) {
9474138d 7816+ *blob = e->pos;
2380c486
JR
7817+ e->pos += size;
7818+ return size;
7819+ }
7820+ }
2380c486
JR
7821+ return 0;
7822+}
7823+
ceaf2cfb 7824+static int unpack_str(struct aa_ext *e, const char **string, const char *name)
2380c486
JR
7825+{
7826+ char *src_str;
7827+ size_t size = 0;
7828+ void *pos = e->pos;
7829+ *string = NULL;
ceaf2cfb
AM
7830+ if (unpack_nameX(e, AA_STRING, name)) {
7831+ size = unpack_u16_chunk(e, &src_str);
7832+ if (size) {
7833+ /* strings are null terminated, length is size - 1 */
7834+ if (src_str[size - 1] != 0)
7835+ goto fail;
7836+ *string = src_str;
7837+ }
2380c486 7838+ }
2380c486
JR
7839+ return size;
7840+
7841+fail:
7842+ e->pos = pos;
7843+ return 0;
7844+}
7845+
ceaf2cfb 7846+static int unpack_strdup(struct aa_ext *e, char **string, const char *name)
9474138d 7847+{
ceaf2cfb 7848+ const char *tmp;
9474138d 7849+ void *pos = e->pos;
ceaf2cfb 7850+ int res = unpack_str(e, &tmp, name);
9474138d
AM
7851+ *string = NULL;
7852+
7853+ if (!res)
ceaf2cfb 7854+ return 0;
9474138d 7855+
ceaf2cfb 7856+ *string = kmemdup(tmp, res, GFP_KERNEL);
9474138d
AM
7857+ if (!*string) {
7858+ e->pos = pos;
7859+ return 0;
7860+ }
7861+
7862+ return res;
7863+}
7864+
76514441
AM
7865+/**
7866+ * verify_accept - verify the accept tables of a dfa
7867+ * @dfa: dfa to verify accept tables of (NOT NULL)
7868+ * @flags: flags governing dfa
7869+ *
7870+ * Returns: 1 if valid accept tables else 0 if error
7871+ */
ceaf2cfb
AM
7872+static bool verify_accept(struct aa_dfa *dfa, int flags)
7873+{
7874+ int i;
7875+
7876+ /* verify accept permissions */
7877+ for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
7878+ int mode = ACCEPT_TABLE(dfa)[i];
7879+
7880+ if (mode & ~DFA_VALID_PERM_MASK)
7881+ return 0;
7882+
7883+ if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK)
7884+ return 0;
7885+ }
7886+ return 1;
7887+}
7888+
2380c486 7889+/**
ceaf2cfb 7890+ * unpack_dfa - unpack a file rule dfa
76514441 7891+ * @e: serialized data extent information (NOT NULL)
2380c486 7892+ *
ceaf2cfb 7893+ * returns dfa or ERR_PTR or NULL if no dfa
2380c486 7894+ */
ceaf2cfb 7895+static struct aa_dfa *unpack_dfa(struct aa_ext *e)
2380c486
JR
7896+{
7897+ char *blob = NULL;
ceaf2cfb 7898+ size_t size;
2380c486
JR
7899+ struct aa_dfa *dfa = NULL;
7900+
ceaf2cfb 7901+ size = unpack_blob(e, &blob, "aadfa");
2380c486 7902+ if (size) {
ceaf2cfb
AM
7903+ /*
7904+ * The dfa is aligned with in the blob to 8 bytes
7905+ * from the beginning of the stream.
7906+ */
7907+ size_t sz = blob - (char *)e->start;
7908+ size_t pad = ALIGN(sz, 8) - sz;
7909+ int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
7910+ TO_ACCEPT2_FLAG(YYTD_DATA32);
2380c486 7911+
ceaf2cfb
AM
7912+
7913+ if (aa_g_paranoid_load)
7914+ flags |= DFA_FLAG_VERIFY_STATES;
7915+
7916+ dfa = aa_dfa_unpack(blob + pad, size - pad, flags);
76514441
AM
7917+
7918+ if (IS_ERR(dfa))
7919+ return dfa;
7920+
7921+ if (!verify_accept(dfa, flags))
ceaf2cfb 7922+ goto fail;
2380c486
JR
7923+ }
7924+
7925+ return dfa;
ceaf2cfb
AM
7926+
7927+fail:
7928+ aa_put_dfa(dfa);
7929+ return ERR_PTR(-EPROTO);
2380c486
JR
7930+}
7931+
76514441
AM
7932+/**
7933+ * unpack_trans_table - unpack a profile transition table
7934+ * @e: serialized data extent information (NOT NULL)
7935+ * @profile: profile to add the accept table to (NOT NULL)
7936+ *
7937+ * Returns: 1 if table succesfully unpacked
7938+ */
ceaf2cfb 7939+static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
2380c486
JR
7940+{
7941+ void *pos = e->pos;
7942+
7943+ /* exec table is optional */
ceaf2cfb 7944+ if (unpack_nameX(e, AA_STRUCT, "xtable")) {
2380c486
JR
7945+ int i, size;
7946+
ceaf2cfb 7947+ size = unpack_array(e, NULL);
2380c486
JR
7948+ /* currently 4 exec bits and entries 0-3 are reserved iupcx */
7949+ if (size > 16 - 4)
7950+ goto fail;
9474138d 7951+ profile->file.trans.table = kzalloc(sizeof(char *) * size,
ceaf2cfb 7952+ GFP_KERNEL);
9474138d 7953+ if (!profile->file.trans.table)
2380c486
JR
7954+ goto fail;
7955+
ceaf2cfb 7956+ profile->file.trans.size = size;
2380c486 7957+ for (i = 0; i < size; i++) {
ceaf2cfb
AM
7958+ char *str;
7959+ int c, j, size = unpack_strdup(e, &str, NULL);
76514441
AM
7960+ /* unpack_strdup verifies that the last character is
7961+ * null termination byte.
7962+ */
ceaf2cfb
AM
7963+ if (!size)
7964+ goto fail;
7965+ profile->file.trans.table[i] = str;
7966+ /* verify that name doesn't start with space */
7967+ if (isspace(*str))
7968+ goto fail;
7969+
7970+ /* count internal # of internal \0 */
7971+ for (c = j = 0; j < size - 2; j++) {
7972+ if (!str[j])
7973+ c++;
7974+ }
7975+ if (*str == ':') {
76514441
AM
7976+ /* beginning with : requires an embedded \0,
7977+ * verify that exactly 1 internal \0 exists
7978+ * trailing \0 already verified by unpack_strdup
7979+ */
ceaf2cfb
AM
7980+ if (c != 1)
7981+ goto fail;
7982+ /* first character after : must be valid */
7983+ if (!str[1])
7984+ goto fail;
7985+ } else if (c)
7986+ /* fail - all other cases with embedded \0 */
2380c486 7987+ goto fail;
2380c486 7988+ }
ceaf2cfb 7989+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
2380c486 7990+ goto fail;
ceaf2cfb 7991+ if (!unpack_nameX(e, AA_STRUCTEND, NULL))
2380c486
JR
7992+ goto fail;
7993+ }
7994+ return 1;
7995+
7996+fail:
ceaf2cfb 7997+ aa_free_domain_entries(&profile->file.trans);
2380c486
JR
7998+ e->pos = pos;
7999+ return 0;
8000+}
8001+
ceaf2cfb 8002+static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
2380c486
JR
8003+{
8004+ void *pos = e->pos;
8005+
8006+ /* rlimits are optional */
ceaf2cfb 8007+ if (unpack_nameX(e, AA_STRUCT, "rlimits")) {
2380c486
JR
8008+ int i, size;
8009+ u32 tmp = 0;
ceaf2cfb 8010+ if (!unpack_u32(e, &tmp, NULL))
2380c486
JR
8011+ goto fail;
8012+ profile->rlimits.mask = tmp;
8013+
ceaf2cfb 8014+ size = unpack_array(e, NULL);
2380c486
JR
8015+ if (size > RLIM_NLIMITS)
8016+ goto fail;
8017+ for (i = 0; i < size; i++) {
8018+ u64 tmp = 0;
76514441 8019+ int a = aa_map_resource(i);
ceaf2cfb 8020+ if (!unpack_u64(e, &tmp, NULL))
2380c486 8021+ goto fail;
76514441 8022+ profile->rlimits.limits[a].rlim_max = tmp;
2380c486 8023+ }
ceaf2cfb 8024+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
2380c486 8025+ goto fail;
ceaf2cfb 8026+ if (!unpack_nameX(e, AA_STRUCTEND, NULL))
2380c486
JR
8027+ goto fail;
8028+ }
8029+ return 1;
8030+
8031+fail:
8032+ e->pos = pos;
8033+ return 0;
8034+}
8035+
8036+/**
ceaf2cfb 8037+ * unpack_profile - unpack a serialized profile
76514441 8038+ * @e: serialized data extent information (NOT NULL)
ceaf2cfb
AM
8039+ *
8040+ * NOTE: unpack profile sets audit struct if there is a failure
2380c486 8041+ */
76514441 8042+static struct aa_profile *unpack_profile(struct aa_ext *e)
2380c486
JR
8043+{
8044+ struct aa_profile *profile = NULL;
ceaf2cfb 8045+ const char *name = NULL;
2380c486
JR
8046+ size_t size = 0;
8047+ int i, error = -EPROTO;
ceaf2cfb 8048+ kernel_cap_t tmpcap;
9474138d
AM
8049+ u32 tmp;
8050+
8051+ /* check that we have the right struct being passed */
ceaf2cfb 8052+ if (!unpack_nameX(e, AA_STRUCT, "profile"))
9474138d 8053+ goto fail;
ceaf2cfb 8054+ if (!unpack_str(e, &name, NULL))
9474138d 8055+ goto fail;
2380c486 8056+
ceaf2cfb 8057+ profile = aa_alloc_profile(name);
2380c486
JR
8058+ if (!profile)
8059+ return ERR_PTR(-ENOMEM);
8060+
ceaf2cfb
AM
8061+ /* profile renaming is optional */
8062+ (void) unpack_str(e, &profile->rename, "rename");
8063+
9474138d 8064+ /* xmatch is optional and may be NULL */
ceaf2cfb 8065+ profile->xmatch = unpack_dfa(e);
9474138d
AM
8066+ if (IS_ERR(profile->xmatch)) {
8067+ error = PTR_ERR(profile->xmatch);
8068+ profile->xmatch = NULL;
2380c486 8069+ goto fail;
9474138d 8070+ }
ceaf2cfb
AM
8071+ /* xmatch_len is not optional if xmatch is set */
8072+ if (profile->xmatch) {
8073+ if (!unpack_u32(e, &tmp, NULL))
8074+ goto fail;
8075+ profile->xmatch_len = tmp;
8076+ }
2380c486
JR
8077+
8078+ /* per profile debug flags (complain, audit) */
ceaf2cfb 8079+ if (!unpack_nameX(e, AA_STRUCT, "flags"))
2380c486 8080+ goto fail;
ceaf2cfb 8081+ if (!unpack_u32(e, &tmp, NULL))
2380c486 8082+ goto fail;
9474138d
AM
8083+ if (tmp)
8084+ profile->flags |= PFLAG_HAT;
ceaf2cfb 8085+ if (!unpack_u32(e, &tmp, NULL))
2380c486 8086+ goto fail;
9474138d
AM
8087+ if (tmp)
8088+ profile->mode = APPARMOR_COMPLAIN;
ceaf2cfb 8089+ if (!unpack_u32(e, &tmp, NULL))
2380c486 8090+ goto fail;
9474138d
AM
8091+ if (tmp)
8092+ profile->audit = AUDIT_ALL;
8093+
ceaf2cfb 8094+ if (!unpack_nameX(e, AA_STRUCTEND, NULL))
2380c486
JR
8095+ goto fail;
8096+
ceaf2cfb 8097+ /* path_flags is optional */
76514441
AM
8098+ if (unpack_u32(e, &profile->path_flags, "path_flags"))
8099+ profile->path_flags |= profile->flags & PFLAG_MEDIATE_DELETED;
8100+ else
8101+ /* set a default value if path_flags field is not present */
8102+ profile->path_flags = PFLAG_MEDIATE_DELETED;
ceaf2cfb 8103+
76514441 8104+ if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL))
2380c486 8105+ goto fail;
ceaf2cfb 8106+ if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL))
2380c486 8107+ goto fail;
ceaf2cfb 8108+ if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL))
2380c486 8109+ goto fail;
ceaf2cfb 8110+ if (!unpack_u32(e, &tmpcap.cap[0], NULL))
2380c486
JR
8111+ goto fail;
8112+
ceaf2cfb 8113+ if (unpack_nameX(e, AA_STRUCT, "caps64")) {
2380c486 8114+ /* optional upper half of 64 bit caps */
76514441 8115+ if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL))
ceaf2cfb
AM
8116+ goto fail;
8117+ if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL))
2380c486 8118+ goto fail;
ceaf2cfb 8119+ if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL))
2380c486 8120+ goto fail;
ceaf2cfb 8121+ if (!unpack_u32(e, &(tmpcap.cap[1]), NULL))
2380c486 8122+ goto fail;
ceaf2cfb
AM
8123+ if (!unpack_nameX(e, AA_STRUCTEND, NULL))
8124+ goto fail;
8125+ }
8126+
8127+ if (unpack_nameX(e, AA_STRUCT, "capsx")) {
8128+ /* optional extended caps mediation mask */
8129+ if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL))
2380c486 8130+ goto fail;
ceaf2cfb 8131+ if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
2380c486
JR
8132+ goto fail;
8133+ }
8134+
ceaf2cfb 8135+ if (!unpack_rlimits(e, profile))
2380c486
JR
8136+ goto fail;
8137+
ceaf2cfb 8138+ size = unpack_array(e, "net_allowed_af");
2380c486
JR
8139+ if (size) {
8140+ if (size > AF_MAX)
8141+ goto fail;
8142+
8143+ for (i = 0; i < size; i++) {
76514441 8144+ if (!unpack_u16(e, &profile->net.allow[i], NULL))
2380c486 8145+ goto fail;
ceaf2cfb 8146+ if (!unpack_u16(e, &profile->net.audit[i], NULL))
2380c486 8147+ goto fail;
ceaf2cfb 8148+ if (!unpack_u16(e, &profile->net.quiet[i], NULL))
2380c486
JR
8149+ goto fail;
8150+ }
ceaf2cfb 8151+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
2380c486 8152+ goto fail;
ceaf2cfb
AM
8153+ /*
8154+ * allow unix domain and netlink sockets they are handled
2380c486
JR
8155+ * by IPC
8156+ */
8157+ }
76514441
AM
8158+ profile->net.allow[AF_UNIX] = 0xffff;
8159+ profile->net.allow[AF_NETLINK] = 0xffff;
2380c486
JR
8160+
8161+ /* get file rules */
ceaf2cfb 8162+ profile->file.dfa = unpack_dfa(e);
9474138d
AM
8163+ if (IS_ERR(profile->file.dfa)) {
8164+ error = PTR_ERR(profile->file.dfa);
8165+ profile->file.dfa = NULL;
2380c486
JR
8166+ goto fail;
8167+ }
8168+
ceaf2cfb
AM
8169+ if (!unpack_u32(e, &profile->file.start, "dfa_start"))
8170+ /* default start state */
8171+ profile->file.start = DFA_START;
8172+
8173+ if (!unpack_trans_table(e, profile))
2380c486
JR
8174+ goto fail;
8175+
ceaf2cfb 8176+ if (!unpack_nameX(e, AA_STRUCTEND, NULL))
2380c486
JR
8177+ goto fail;
8178+
8179+ return profile;
8180+
8181+fail:
76514441
AM
8182+ if (profile)
8183+ name = NULL;
8184+ else if (!name)
8185+ name = "unknown";
8186+ audit_iface(profile, name, "failed to unpack profile", e, error);
ceaf2cfb 8187+ aa_put_profile(profile);
2380c486
JR
8188+
8189+ return ERR_PTR(error);
8190+}
8191+
8192+/**
76514441
AM
8193+ * verify_head - unpack serialized stream header
8194+ * @e: serialized data read head (NOT NULL)
8195+ * @ns: Returns - namespace if one is specified else NULL (NOT NULL)
2380c486 8196+ *
ceaf2cfb 8197+ * Returns: error or 0 if header is good
2380c486 8198+ */
76514441 8199+static int verify_header(struct aa_ext *e, const char **ns)
2380c486 8200+{
76514441 8201+ int error = -EPROTONOSUPPORT;
2380c486 8202+ /* get the interface version */
ceaf2cfb 8203+ if (!unpack_u32(e, &e->version, "version")) {
76514441
AM
8204+ audit_iface(NULL, NULL, "invalid profile format", e, error);
8205+ return error;
2380c486
JR
8206+ }
8207+
8208+ /* check that the interface version is currently supported */
8209+ if (e->version != 5) {
76514441
AM
8210+ audit_iface(NULL, NULL, "unsupported interface version", e,
8211+ error);
8212+ return error;
2380c486
JR
8213+ }
8214+
8215+ /* read the namespace if present */
76514441
AM
8216+ if (!unpack_str(e, ns, "namespace"))
8217+ *ns = NULL;
2380c486
JR
8218+
8219+ return 0;
8220+}
8221+
ceaf2cfb 8222+static bool verify_xindex(int xindex, int table_size)
2380c486 8223+{
ceaf2cfb
AM
8224+ int index, xtype;
8225+ xtype = xindex & AA_X_TYPE_MASK;
8226+ index = xindex & AA_X_INDEX_MASK;
8227+ if (xtype == AA_X_TABLE && index > table_size)
8228+ return 0;
8229+ return 1;
8230+}
9474138d 8231+
ceaf2cfb
AM
8232+/* verify dfa xindexes are in range of transition tables */
8233+static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
8234+{
8235+ int i;
8236+ for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
8237+ if (!verify_xindex(dfa_user_xindex(dfa, i), table_size))
8238+ return 0;
8239+ if (!verify_xindex(dfa_other_xindex(dfa, i), table_size))
8240+ return 0;
2380c486 8241+ }
ceaf2cfb
AM
8242+ return 1;
8243+}
2380c486 8244+
76514441
AM
8245+/**
8246+ * verify_profile - Do post unpack analysis to verify profile consistency
8247+ * @profile: profile to verify (NOT NULL)
8248+ *
8249+ * Returns: 0 if passes verification else error
8250+ */
8251+static int verify_profile(struct aa_profile *profile)
ceaf2cfb
AM
8252+{
8253+ if (aa_g_paranoid_load) {
8254+ if (profile->file.dfa &&
8255+ !verify_dfa_xindex(profile->file.dfa,
8256+ profile->file.trans.size)) {
76514441
AM
8257+ audit_iface(profile, NULL, "Invalid named transition",
8258+ NULL, -EPROTO);
ceaf2cfb
AM
8259+ return -EPROTO;
8260+ }
2380c486 8261+ }
2380c486 8262+
ceaf2cfb 8263+ return 0;
2380c486
JR
8264+}
8265+
8266+/**
ceaf2cfb
AM
8267+ * aa_unpack - unpack packed binary profile data loaded from user space
8268+ * @udata: user data copied to kmem (NOT NULL)
8269+ * @size: the size of the user data
76514441 8270+ * @ns: Returns namespace profile is in if specified else NULL (NOT NULL)
2380c486 8271+ *
ceaf2cfb
AM
8272+ * Unpack user data and return refcounted allocated profile or ERR_PTR
8273+ *
8274+ * Returns: profile else error pointer if fails to unpack
2380c486 8275+ */
76514441 8276+struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns)
2380c486 8277+{
76514441 8278+ struct aa_profile *profile = NULL;
ceaf2cfb 8279+ int error;
2380c486
JR
8280+ struct aa_ext e = {
8281+ .start = udata,
8282+ .end = udata + size,
8283+ .pos = udata,
2380c486 8284+ };
2380c486 8285+
76514441 8286+ error = verify_header(&e, ns);
2380c486 8287+ if (error)
ceaf2cfb 8288+ return ERR_PTR(error);
2380c486 8289+
76514441 8290+ profile = unpack_profile(&e);
ceaf2cfb 8291+ if (IS_ERR(profile))
76514441 8292+ return profile;
2380c486 8293+
76514441 8294+ error = verify_profile(profile);
ceaf2cfb
AM
8295+ if (error) {
8296+ aa_put_profile(profile);
8297+ profile = ERR_PTR(error);
2380c486 8298+ }
9474138d 8299+
ceaf2cfb
AM
8300+ /* return refcount */
8301+ return profile;
2380c486 8302+}
76514441
AM
8303diff --git a/security/apparmor/policy_unpack.c.rej b/security/apparmor/policy_unpack.c.rej
8304new file mode 100644
8305index 0000000..5bddfd6
8306--- /dev/null
8307+++ b/security/apparmor/policy_unpack.c.rej
8308@@ -0,0 +1,11 @@
8309+diff a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c (rejected hunks)
8310+@@ -473,7 +473,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
8311+ {
8312+ struct aa_profile *profile = NULL;
8313+ const char *name = NULL, *info = NULL;
8314+- int error = -EPROTO;
8315++ size_t size = 0;
8316++ int i, error = -EPROTO;
8317+ kernel_cap_t tmpcap;
8318+ u32 tmp;
8319+ u64 tmp64;
ceaf2cfb
AM
8320diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
8321new file mode 100644
76514441 8322index 0000000..04a2cf8
ceaf2cfb
AM
8323--- /dev/null
8324+++ b/security/apparmor/procattr.c
76514441 8325@@ -0,0 +1,170 @@
2380c486 8326+/*
9474138d
AM
8327+ * AppArmor security module
8328+ *
8329+ * This file contains AppArmor /proc/<pid>/attr/ interface functions
2380c486 8330+ *
9474138d 8331+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 8332+ * Copyright 2009-2010 Canonical Ltd.
2380c486 8333+ *
9474138d
AM
8334+ * This program is free software; you can redistribute it and/or
8335+ * modify it under the terms of the GNU General Public License as
8336+ * published by the Free Software Foundation, version 2 of the
8337+ * License.
2380c486
JR
8338+ */
8339+
9474138d 8340+#include "include/apparmor.h"
76514441 8341+#include "include/context.h"
9474138d
AM
8342+#include "include/policy.h"
8343+#include "include/domain.h"
2380c486 8344+
76514441 8345+
ceaf2cfb
AM
8346+/**
8347+ * aa_getprocattr - Return the profile information for @profile
8348+ * @profile: the profile to print profile info about (NOT NULL)
76514441 8349+ * @string: Returns - string containing the profile info (NOT NULL)
ceaf2cfb
AM
8350+ *
8351+ * Returns: length of @string on success else error on failure
8352+ *
8353+ * Requires: profile != NULL
8354+ *
8355+ * Creates a string containing the namespace_name://profile_name for
8356+ * @profile.
8357+ *
8358+ * Returns: size of string placed in @string else error code on failure
8359+ */
8360+int aa_getprocattr(struct aa_profile *profile, char **string)
2380c486
JR
8361+{
8362+ char *str;
76514441 8363+ int len = 0, mode_len = 0, ns_len = 0, name_len;
ceaf2cfb 8364+ const char *mode_str = profile_mode_names[profile->mode];
76514441 8365+ const char *ns_name = NULL;
ceaf2cfb 8366+ struct aa_namespace *ns = profile->ns;
76514441 8367+ struct aa_namespace *current_ns = __aa_current_profile()->ns;
ceaf2cfb
AM
8368+ char *s;
8369+
76514441
AM
8370+ if (!aa_ns_visible(current_ns, ns))
8371+ return -EACCES;
8372+
8373+ ns_name = aa_ns_name(current_ns, ns);
8374+ ns_len = strlen(ns_name);
8375+
8376+ /* if the visible ns_name is > 0 increase size for : :// seperator */
8377+ if (ns_len)
8378+ ns_len += 4;
8379+
8380+ /* unconfined profiles don't have a mode string appended */
8381+ if (!unconfined(profile))
8382+ mode_len = strlen(mode_str) + 3; /* + 3 for _() */
8383+
ceaf2cfb 8384+ name_len = strlen(profile->base.hname);
76514441
AM
8385+ len = mode_len + ns_len + name_len + 1; /* + 1 for \n */
8386+ s = str = kmalloc(len + 1, GFP_KERNEL); /* + 1 \0 */
ceaf2cfb
AM
8387+ if (!str)
8388+ return -ENOMEM;
2380c486 8389+
ceaf2cfb 8390+ if (ns_len) {
76514441
AM
8391+ /* skip over prefix current_ns->base.hname and separating // */
8392+ sprintf(s, ":%s://", ns_name);
ceaf2cfb 8393+ s += ns_len;
2380c486 8394+ }
76514441
AM
8395+ if (unconfined(profile))
8396+ /* mode string not being appended */
ceaf2cfb
AM
8397+ sprintf(s, "%s\n", profile->base.hname);
8398+ else
8399+ sprintf(s, "%s (%s)\n", profile->base.hname, mode_str);
2380c486
JR
8400+ *string = str;
8401+
ceaf2cfb 8402+ /* NOTE: len does not include \0 of string, not saved as part of file */
9474138d 8403+ return len;
2380c486
JR
8404+}
8405+
ceaf2cfb
AM
8406+/**
8407+ * split_token_from_name - separate a string of form <token>^<name>
76514441 8408+ * @op: operation being checked
ceaf2cfb
AM
8409+ * @args: string to parse (NOT NULL)
8410+ * @token: stores returned parsed token value (NOT NULL)
8411+ *
8412+ * Returns: start position of name after token else NULL on failure
8413+ */
76514441 8414+static char *split_token_from_name(int op, char *args, u64 * token)
2380c486
JR
8415+{
8416+ char *name;
8417+
9474138d 8418+ *token = simple_strtoull(args, &name, 16);
2380c486 8419+ if ((name == args) || *name != '^') {
76514441 8420+ AA_ERROR("%s: Invalid input '%s'", op_table[op], args);
2380c486
JR
8421+ return ERR_PTR(-EINVAL);
8422+ }
8423+
ceaf2cfb 8424+ name++; /* skip ^ */
2380c486
JR
8425+ if (!*name)
8426+ name = NULL;
8427+ return name;
8428+}
8429+
ceaf2cfb
AM
8430+/**
8431+ * aa_setprocattr_chagnehat - handle procattr interface to change_hat
8432+ * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL)
8433+ * @size: size of the args
8434+ * @test: true if this is a test of change_hat permissions
8435+ *
8436+ * Returns: %0 or error code if change_hat fails
8437+ */
8438+int aa_setprocattr_changehat(char *args, size_t size, int test)
2380c486
JR
8439+{
8440+ char *hat;
9474138d 8441+ u64 token;
ceaf2cfb
AM
8442+ const char *hats[16]; /* current hard limit on # of names */
8443+ int count = 0;
2380c486 8444+
76514441 8445+ hat = split_token_from_name(OP_CHANGE_HAT, args, &token);
2380c486
JR
8446+ if (IS_ERR(hat))
8447+ return PTR_ERR(hat);
8448+
9474138d 8449+ if (!hat && !token) {
2380c486
JR
8450+ AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
8451+ return -EINVAL;
8452+ }
8453+
ceaf2cfb 8454+ if (hat) {
76514441
AM
8455+ /* set up hat name vector, args guaranteed null terminated
8456+ * at args[size] by setprocattr.
8457+ *
8458+ * If there are multiple hat names in the buffer each is
8459+ * separated by a \0. Ie. userspace writes them pre tokenized
ceaf2cfb
AM
8460+ */
8461+ char *end = args + size;
8462+ for (count = 0; (hat < end) && count < 16; ++count) {
8463+ char *next = hat + strlen(hat) + 1;
8464+ hats[count] = hat;
8465+ hat = next;
8466+ }
8467+ }
8468+
2380c486 8469+ AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
9474138d 8470+ __func__, token, hat ? hat : NULL);
2380c486 8471+
ceaf2cfb 8472+ return aa_change_hat(hats, count, token, test);
2380c486
JR
8473+}
8474+
ceaf2cfb
AM
8475+/**
8476+ * aa_setprocattr_changeprofile - handle procattr interface to changeprofile
8477+ * @fqname: args received from writting to /proc/<pid>/attr/current (NOT NULL)
8478+ * @onexec: true if change_profile should be delayed until exec
8479+ * @test: true if this is a test of change_profile permissions
8480+ *
8481+ * Returns: %0 or error code if change_profile fails
8482+ */
76514441 8483+int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test)
2380c486 8484+{
9474138d
AM
8485+ char *name, *ns_name;
8486+
ceaf2cfb 8487+ name = aa_split_fqname(fqname, &ns_name);
9474138d
AM
8488+ return aa_change_profile(ns_name, name, onexec, test);
8489+}
2380c486 8490+
ceaf2cfb 8491+int aa_setprocattr_permipc(char *fqname)
9474138d
AM
8492+{
8493+ /* TODO: add ipc permission querying */
8494+ return -ENOTSUPP;
2380c486 8495+}
ceaf2cfb
AM
8496diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
8497new file mode 100644
76514441 8498index 0000000..4a368f1
ceaf2cfb
AM
8499--- /dev/null
8500+++ b/security/apparmor/resource.c
76514441 8501@@ -0,0 +1,134 @@
9474138d
AM
8502+/*
8503+ * AppArmor security module
8504+ *
8505+ * This file contains AppArmor resource mediation and attachment
8506+ *
8507+ * Copyright (C) 1998-2008 Novell/SUSE
ceaf2cfb 8508+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
8509+ *
8510+ * This program is free software; you can redistribute it and/or
8511+ * modify it under the terms of the GNU General Public License as
8512+ * published by the Free Software Foundation, version 2 of the
8513+ * License.
8514+ */
8515+
8516+#include <linux/audit.h>
8517+
8518+#include "include/audit.h"
8519+#include "include/resource.h"
8520+#include "include/policy.h"
8521+
76514441
AM
8522+/*
8523+ * Table of rlimit names: we generate it from resource.h.
8524+ */
8525+#include "rlim_names.h"
2380c486 8526+
ceaf2cfb 8527+/* audit callback for resource specific fields */
76514441 8528+static void audit_cb(struct audit_buffer *ab, void *va)
2380c486 8529+{
76514441 8530+ struct common_audit_data *sa = va;
9474138d 8531+
76514441
AM
8532+ audit_log_format(ab, " rlimit=%s value=%lu",
8533+ rlim_names[sa->aad.rlim.rlim], sa->aad.rlim.max);
9474138d
AM
8534+}
8535+
ceaf2cfb 8536+/**
76514441 8537+ * audit_resource - audit setting resource limit
ceaf2cfb 8538+ * @profile: profile being enforced (NOT NULL)
76514441
AM
8539+ * @resoure: rlimit being auditing
8540+ * @value: value being set
8541+ * @error: error value
ceaf2cfb
AM
8542+ *
8543+ * Returns: 0 or sa->error else other error code on failure
8544+ */
76514441
AM
8545+static int audit_resource(struct aa_profile *profile, unsigned int resource,
8546+ unsigned long value, int error)
8547+{
8548+ struct common_audit_data sa;
8549+
8550+ COMMON_AUDIT_DATA_INIT(&sa, NONE);
8551+ sa.aad.op = OP_SETRLIMIT,
8552+ sa.aad.rlim.rlim = resource;
8553+ sa.aad.rlim.max = value;
8554+ sa.aad.error = error;
8555+ return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa,
8556+ audit_cb);
8557+}
8558+
8559+/**
8560+ * aa_map_resouce - map compiled policy resource to internal #
8561+ * @resource: flattened policy resource number
8562+ *
8563+ * Returns: resource # for the current architecture.
8564+ *
8565+ * rlimit resource can vary based on architecture, map the compiled policy
8566+ * resource # to the internal representation for the architecture.
8567+ */
8568+int aa_map_resource(int resource)
9474138d 8569+{
76514441 8570+ return rlim_map[resource];
9474138d
AM
8571+}
8572+
8573+/**
8574+ * aa_task_setrlimit - test permission to set an rlimit
ceaf2cfb 8575+ * @profile - profile confining the task (NOT NULL)
9474138d 8576+ * @resource - the resource being set
ceaf2cfb 8577+ * @new_rlim - the new resource limit (NOT NULL)
9474138d
AM
8578+ *
8579+ * Control raising the processes hard limit.
ceaf2cfb
AM
8580+ *
8581+ * Returns: 0 or error code if setting resource failed
9474138d
AM
8582+ */
8583+int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
8584+ struct rlimit *new_rlim)
8585+{
9474138d 8586+ int error = 0;
2380c486 8587+
9474138d 8588+ if (profile->rlimits.mask & (1 << resource) &&
76514441 8589+ new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)
9474138d 8590+
76514441
AM
8591+ error = audit_resource(profile, resource, new_rlim->rlim_max,
8592+ -EACCES);
2380c486 8593+
9474138d
AM
8594+ return error;
8595+}
8596+
ceaf2cfb
AM
8597+/**
8598+ * __aa_transition_rlimits - apply new profile rlimits
76514441 8599+ * @old: old profile on task (NOT NULL)
ceaf2cfb
AM
8600+ * @new: new profile with rlimits to apply (NOT NULL)
8601+ */
9474138d
AM
8602+void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new)
8603+{
8604+ unsigned int mask = 0;
8605+ struct rlimit *rlim, *initrlim;
8606+ int i;
8607+
8608+ /* for any rlimits the profile controlled reset the soft limit
8609+ * to the less of the tasks hard limit and the init tasks soft limit
8610+ */
76514441 8611+ if (old->rlimits.mask) {
ceaf2cfb 8612+ for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
9474138d
AM
8613+ if (old->rlimits.mask & mask) {
8614+ rlim = current->signal->rlim + i;
8615+ initrlim = init_task.signal->rlim + i;
8616+ rlim->rlim_cur = min(rlim->rlim_max,
8617+ initrlim->rlim_cur);
8618+ }
2380c486
JR
8619+ }
8620+ }
8621+
9474138d 8622+ /* set any new hard limits as dictated by the new profile */
76514441 8623+ if (!new->rlimits.mask)
9474138d 8624+ return;
ceaf2cfb 8625+ for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
9474138d
AM
8626+ if (!(new->rlimits.mask & mask))
8627+ continue;
2380c486 8628+
9474138d
AM
8629+ rlim = current->signal->rlim + i;
8630+ rlim->rlim_max = min(rlim->rlim_max,
8631+ new->rlimits.limits[i].rlim_max);
8632+ /* soft limit should not exceed hard limit */
8633+ rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
2380c486 8634+ }
9474138d 8635+}
ceaf2cfb
AM
8636diff --git a/security/apparmor/sid.c b/security/apparmor/sid.c
8637new file mode 100644
76514441 8638index 0000000..f0b34f7
ceaf2cfb
AM
8639--- /dev/null
8640+++ b/security/apparmor/sid.c
8641@@ -0,0 +1,55 @@
9474138d
AM
8642+/*
8643+ * AppArmor security module
8644+ *
8645+ * This file contains AppArmor security identifier (sid) manipulation fns
8646+ *
ceaf2cfb 8647+ * Copyright 2009-2010 Canonical Ltd.
9474138d
AM
8648+ *
8649+ * This program is free software; you can redistribute it and/or
8650+ * modify it under the terms of the GNU General Public License as
8651+ * published by the Free Software Foundation, version 2 of the
8652+ * License.
8653+ *
8654+ *
8655+ * AppArmor allocates a unique sid for every profile loaded. If a profile
76514441 8656+ * is replaced it receives the sid of the profile it is replacing.
9474138d 8657+ *
ceaf2cfb 8658+ * The sid value of 0 is invalid.
9474138d
AM
8659+ */
8660+
8661+#include <linux/spinlock.h>
8662+#include <linux/errno.h>
8663+#include <linux/err.h>
8664+
8665+#include "include/sid.h"
8666+
8667+/* global counter from which sids are allocated */
76514441 8668+static u32 global_sid;
9474138d 8669+static DEFINE_SPINLOCK(sid_lock);
2380c486 8670+
9474138d
AM
8671+/* TODO FIXME: add sid to profile mapping, and sid recycling */
8672+
9474138d
AM
8673+/**
8674+ * aa_alloc_sid - allocate a new sid for a profile
9474138d 8675+ */
ceaf2cfb 8676+u32 aa_alloc_sid(void)
9474138d
AM
8677+{
8678+ u32 sid;
8679+
ceaf2cfb 8680+ /*
9474138d
AM
8681+ * TODO FIXME: sid recycling - part of profile mapping table
8682+ */
8683+ spin_lock(&sid_lock);
ceaf2cfb 8684+ sid = (++global_sid);
9474138d
AM
8685+ spin_unlock(&sid_lock);
8686+ return sid;
8687+}
8688+
8689+/**
8690+ * aa_free_sid - free a sid
8691+ * @sid: sid to free
8692+ */
8693+void aa_free_sid(u32 sid)
8694+{
ceaf2cfb 8695+ ; /* NOP ATM */
9474138d 8696+}
76514441
AM
8697--
86981.7.1
8699
This page took 1.39491 seconds and 4 git commands to generate.