aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig6
-rw-r--r--security/Makefile2
-rw-r--r--security/apparmor/.gitignore5
-rw-r--r--security/apparmor/Kconfig31
-rw-r--r--security/apparmor/Makefile24
-rw-r--r--security/apparmor/apparmorfs.c239
-rw-r--r--security/apparmor/audit.c215
-rw-r--r--security/apparmor/capability.c141
-rw-r--r--security/apparmor/context.c216
-rw-r--r--security/apparmor/domain.c823
-rw-r--r--security/apparmor/file.c457
-rw-r--r--security/apparmor/include/apparmor.h92
-rw-r--r--security/apparmor/include/apparmorfs.h20
-rw-r--r--security/apparmor/include/audit.h123
-rw-r--r--security/apparmor/include/capability.h45
-rw-r--r--security/apparmor/include/context.h154
-rw-r--r--security/apparmor/include/domain.h36
-rw-r--r--security/apparmor/include/file.h217
-rw-r--r--security/apparmor/include/ipc.h28
-rw-r--r--security/apparmor/include/match.h132
-rw-r--r--security/apparmor/include/path.h31
-rw-r--r--security/apparmor/include/policy.h305
-rw-r--r--security/apparmor/include/policy_unpack.h20
-rw-r--r--security/apparmor/include/procattr.h26
-rw-r--r--security/apparmor/include/resource.h46
-rw-r--r--security/apparmor/include/sid.h24
-rw-r--r--security/apparmor/ipc.c114
-rw-r--r--security/apparmor/lib.c133
-rw-r--r--security/apparmor/lsm.c938
-rw-r--r--security/apparmor/match.c353
-rw-r--r--security/apparmor/path.c235
-rw-r--r--security/apparmor/policy.c1184
-rw-r--r--security/apparmor/policy_unpack.c703
-rw-r--r--security/apparmor/procattr.c170
-rw-r--r--security/apparmor/resource.c134
-rw-r--r--security/apparmor/sid.c55
-rw-r--r--security/capability.c5
-rw-r--r--security/inode.c4
-rw-r--r--security/integrity/ima/ima_fs.c9
-rw-r--r--security/keys/internal.h5
-rw-r--r--security/keys/keyctl.c29
-rw-r--r--security/keys/proc.c20
-rw-r--r--security/keys/process_keys.c64
-rw-r--r--security/keys/request_key.c3
-rw-r--r--security/security.c21
-rw-r--r--security/selinux/Makefile2
-rw-r--r--security/selinux/avc.c25
-rw-r--r--security/selinux/hooks.c292
-rw-r--r--security/selinux/include/classmap.h16
-rw-r--r--security/selinux/netnode.c2
-rw-r--r--security/selinux/selinuxfs.c16
-rw-r--r--security/selinux/ss/avtab.c39
-rw-r--r--security/selinux/ss/conditional.c65
-rw-r--r--security/selinux/ss/policydb.c658
-rw-r--r--security/selinux/ss/policydb.h4
-rw-r--r--security/selinux/ss/services.c7
-rw-r--r--security/selinux/ss/symtab.c2
-rw-r--r--security/smack/smack.h10
-rw-r--r--security/smack/smack_lsm.c18
-rw-r--r--security/tomoyo/Makefile2
-rw-r--r--security/tomoyo/common.c2836
-rw-r--r--security/tomoyo/common.h850
-rw-r--r--security/tomoyo/domain.c855
-rw-r--r--security/tomoyo/file.c1533
-rw-r--r--security/tomoyo/gc.c360
-rw-r--r--security/tomoyo/group.c130
-rw-r--r--security/tomoyo/load_policy.c81
-rw-r--r--security/tomoyo/memory.c282
-rw-r--r--security/tomoyo/mount.c284
-rw-r--r--security/tomoyo/path_group.c172
-rw-r--r--security/tomoyo/realpath.c426
-rw-r--r--security/tomoyo/securityfs_if.c155
-rw-r--r--security/tomoyo/tomoyo.c35
-rw-r--r--security/tomoyo/util.c963
74 files changed, 13186 insertions, 4571 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 226b9556b25..bd72ae62349 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -140,6 +140,7 @@ config LSM_MMAP_MIN_ADDR
140source security/selinux/Kconfig 140source security/selinux/Kconfig
141source security/smack/Kconfig 141source security/smack/Kconfig
142source security/tomoyo/Kconfig 142source security/tomoyo/Kconfig
143source security/apparmor/Kconfig
143 144
144source security/integrity/ima/Kconfig 145source security/integrity/ima/Kconfig
145 146
@@ -148,6 +149,7 @@ choice
148 default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX 149 default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX
149 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK 150 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
150 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO 151 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
152 default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
151 default DEFAULT_SECURITY_DAC 153 default DEFAULT_SECURITY_DAC
152 154
153 help 155 help
@@ -163,6 +165,9 @@ choice
163 config DEFAULT_SECURITY_TOMOYO 165 config DEFAULT_SECURITY_TOMOYO
164 bool "TOMOYO" if SECURITY_TOMOYO=y 166 bool "TOMOYO" if SECURITY_TOMOYO=y
165 167
168 config DEFAULT_SECURITY_APPARMOR
169 bool "AppArmor" if SECURITY_APPARMOR=y
170
166 config DEFAULT_SECURITY_DAC 171 config DEFAULT_SECURITY_DAC
167 bool "Unix Discretionary Access Controls" 172 bool "Unix Discretionary Access Controls"
168 173
@@ -173,6 +178,7 @@ config DEFAULT_SECURITY
173 default "selinux" if DEFAULT_SECURITY_SELINUX 178 default "selinux" if DEFAULT_SECURITY_SELINUX
174 default "smack" if DEFAULT_SECURITY_SMACK 179 default "smack" if DEFAULT_SECURITY_SMACK
175 default "tomoyo" if DEFAULT_SECURITY_TOMOYO 180 default "tomoyo" if DEFAULT_SECURITY_TOMOYO
181 default "apparmor" if DEFAULT_SECURITY_APPARMOR
176 default "" if DEFAULT_SECURITY_DAC 182 default "" if DEFAULT_SECURITY_DAC
177 183
178endmenu 184endmenu
diff --git a/security/Makefile b/security/Makefile
index da20a193c8d..8bb0fe9e1ca 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_KEYS) += keys/
6subdir-$(CONFIG_SECURITY_SELINUX) += selinux 6subdir-$(CONFIG_SECURITY_SELINUX) += selinux
7subdir-$(CONFIG_SECURITY_SMACK) += smack 7subdir-$(CONFIG_SECURITY_SMACK) += smack
8subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo 8subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
9subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
9 10
10# always enable default capabilities 11# always enable default capabilities
11obj-y += commoncap.o 12obj-y += commoncap.o
@@ -19,6 +20,7 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
19obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o 20obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
20obj-$(CONFIG_AUDIT) += lsm_audit.o 21obj-$(CONFIG_AUDIT) += lsm_audit.o
21obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o 22obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
23obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o
22obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o 24obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
23 25
24# Object integrity file lists 26# Object integrity file lists
diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
new file mode 100644
index 00000000000..0a0a99f3b08
--- /dev/null
+++ b/security/apparmor/.gitignore
@@ -0,0 +1,5 @@
1#
2# Generated include files
3#
4af_names.h
5capability_names.h
diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
new file mode 100644
index 00000000000..9b9013b2e32
--- /dev/null
+++ b/security/apparmor/Kconfig
@@ -0,0 +1,31 @@
1config SECURITY_APPARMOR
2 bool "AppArmor support"
3 depends on SECURITY && NET
4 select AUDIT
5 select SECURITY_PATH
6 select SECURITYFS
7 select SECURITY_NETWORK
8 default n
9 help
10 This enables the AppArmor security module.
11 Required userspace tools (if they are not included in your
12 distribution) and further information may be found at
13 http://apparmor.wiki.kernel.org
14
15 If you are unsure how to answer this question, answer N.
16
17config SECURITY_APPARMOR_BOOTPARAM_VALUE
18 int "AppArmor boot parameter default value"
19 depends on SECURITY_APPARMOR
20 range 0 1
21 default 1
22 help
23 This option sets the default value for the kernel parameter
24 'apparmor', which allows AppArmor to be enabled or disabled
25 at boot. If this option is set to 0 (zero), the AppArmor
26 kernel parameter will default to 0, disabling AppArmor at
27 boot. If this option is set to 1 (one), the AppArmor
28 kernel parameter will default to 1, enabling AppArmor at
29 boot.
30
31 If you are unsure how to answer this question, answer 1.
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
new file mode 100644
index 00000000000..f204869399e
--- /dev/null
+++ b/security/apparmor/Makefile
@@ -0,0 +1,24 @@
1# Makefile for AppArmor Linux Security Module
2#
3obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
4
5apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
6 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
7 resource.o sid.o file.o
8
9clean-files: capability_names.h af_names.h
10
11quiet_cmd_make-caps = GEN $@
12cmd_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 "};" >> $@
13
14quiet_cmd_make-rlim = GEN $@
15cmd_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 "};" >> $@
16
17$(obj)/capability.o : $(obj)/capability_names.h
18$(obj)/resource.o : $(obj)/rlim_names.h
19$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
20 $(call cmd,make-caps)
21$(obj)/af_names.h : $(srctree)/include/linux/socket.h
22 $(call cmd,make-af)
23$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
24 $(call cmd,make-rlim)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
new file mode 100644
index 00000000000..7320331b44a
--- /dev/null
+++ b/security/apparmor/apparmorfs.c
@@ -0,0 +1,239 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor /sys/kernel/security/apparmor interface functions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/security.h>
16#include <linux/vmalloc.h>
17#include <linux/module.h>
18#include <linux/seq_file.h>
19#include <linux/uaccess.h>
20#include <linux/namei.h>
21
22#include "include/apparmor.h"
23#include "include/apparmorfs.h"
24#include "include/audit.h"
25#include "include/context.h"
26#include "include/policy.h"
27
28/**
29 * aa_simple_write_to_buffer - common routine for getting policy from user
30 * @op: operation doing the user buffer copy
31 * @userbuf: user buffer to copy data from (NOT NULL)
32 * @alloc_size: size of user buffer
33 * @copy_size: size of data to copy from user buffer
34 * @pos: position write is at in the file (NOT NULL)
35 *
36 * Returns: kernel buffer containing copy of user buffer data or an
37 * ERR_PTR on failure.
38 */
39static char *aa_simple_write_to_buffer(int op, const char __user *userbuf,
40 size_t alloc_size, size_t copy_size,
41 loff_t *pos)
42{
43 char *data;
44
45 if (*pos != 0)
46 /* only writes from pos 0, that is complete writes */
47 return ERR_PTR(-ESPIPE);
48
49 /*
50 * Don't allow profile load/replace/remove from profiles that don't
51 * have CAP_MAC_ADMIN
52 */
53 if (!aa_may_manage_policy(op))
54 return ERR_PTR(-EACCES);
55
56 /* freed by caller to simple_write_to_buffer */
57 data = kvmalloc(alloc_size);
58 if (data == NULL)
59 return ERR_PTR(-ENOMEM);
60
61 if (copy_from_user(data, userbuf, copy_size)) {
62 kvfree(data);
63 return ERR_PTR(-EFAULT);
64 }
65
66 return data;
67}
68
69
70/* .load file hook fn to load policy */
71static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
72 loff_t *pos)
73{
74 char *data;
75 ssize_t error;
76
77 data = aa_simple_write_to_buffer(OP_PROF_LOAD, buf, size, size, pos);
78
79 error = PTR_ERR(data);
80 if (!IS_ERR(data)) {
81 error = aa_replace_profiles(data, size, PROF_ADD);
82 kvfree(data);
83 }
84
85 return error;
86}
87
88static const struct file_operations aa_fs_profile_load = {
89 .write = profile_load
90};
91
92/* .replace file hook fn to load and/or replace policy */
93static ssize_t profile_replace(struct file *f, const char __user *buf,
94 size_t size, loff_t *pos)
95{
96 char *data;
97 ssize_t error;
98
99 data = aa_simple_write_to_buffer(OP_PROF_REPL, buf, size, size, pos);
100 error = PTR_ERR(data);
101 if (!IS_ERR(data)) {
102 error = aa_replace_profiles(data, size, PROF_REPLACE);
103 kvfree(data);
104 }
105
106 return error;
107}
108
109static const struct file_operations aa_fs_profile_replace = {
110 .write = profile_replace
111};
112
113/* .remove file hook fn to remove loaded policy */
114static ssize_t profile_remove(struct file *f, const char __user *buf,
115 size_t size, loff_t *pos)
116{
117 char *data;
118 ssize_t error;
119
120 /*
121 * aa_remove_profile needs a null terminated string so 1 extra
122 * byte is allocated and the copied data is null terminated.
123 */
124 data = aa_simple_write_to_buffer(OP_PROF_RM, buf, size + 1, size, pos);
125
126 error = PTR_ERR(data);
127 if (!IS_ERR(data)) {
128 data[size] = 0;
129 error = aa_remove_profiles(data, size);
130 kvfree(data);
131 }
132
133 return error;
134}
135
136static const struct file_operations aa_fs_profile_remove = {
137 .write = profile_remove
138};
139
140/** Base file system setup **/
141
142static struct dentry *aa_fs_dentry __initdata;
143
144static void __init aafs_remove(const char *name)
145{
146 struct dentry *dentry;
147
148 dentry = lookup_one_len(name, aa_fs_dentry, strlen(name));
149 if (!IS_ERR(dentry)) {
150 securityfs_remove(dentry);
151 dput(dentry);
152 }
153}
154
155/**
156 * aafs_create - create an entry in the apparmor filesystem
157 * @name: name of the entry (NOT NULL)
158 * @mask: file permission mask of the file
159 * @fops: file operations for the file (NOT NULL)
160 *
161 * Used aafs_remove to remove entries created with this fn.
162 */
163static int __init aafs_create(const char *name, int mask,
164 const struct file_operations *fops)
165{
166 struct dentry *dentry;
167
168 dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry,
169 NULL, fops);
170
171 return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
172}
173
174/**
175 * aa_destroy_aafs - cleanup and free aafs
176 *
177 * releases dentries allocated by aa_create_aafs
178 */
179void __init aa_destroy_aafs(void)
180{
181 if (aa_fs_dentry) {
182 aafs_remove(".remove");
183 aafs_remove(".replace");
184 aafs_remove(".load");
185
186 securityfs_remove(aa_fs_dentry);
187 aa_fs_dentry = NULL;
188 }
189}
190
191/**
192 * aa_create_aafs - create the apparmor security filesystem
193 *
194 * dentries created here are released by aa_destroy_aafs
195 *
196 * Returns: error on failure
197 */
198int __init aa_create_aafs(void)
199{
200 int error;
201
202 if (!apparmor_initialized)
203 return 0;
204
205 if (aa_fs_dentry) {
206 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
207 return -EEXIST;
208 }
209
210 aa_fs_dentry = securityfs_create_dir("apparmor", NULL);
211 if (IS_ERR(aa_fs_dentry)) {
212 error = PTR_ERR(aa_fs_dentry);
213 aa_fs_dentry = NULL;
214 goto error;
215 }
216
217 error = aafs_create(".load", 0640, &aa_fs_profile_load);
218 if (error)
219 goto error;
220 error = aafs_create(".replace", 0640, &aa_fs_profile_replace);
221 if (error)
222 goto error;
223 error = aafs_create(".remove", 0640, &aa_fs_profile_remove);
224 if (error)
225 goto error;
226
227 /* TODO: add support for apparmorfs_null and apparmorfs_mnt */
228
229 /* Report that AppArmor fs is enabled */
230 aa_info_message("AppArmor Filesystem Enabled");
231 return 0;
232
233error:
234 aa_destroy_aafs();
235 AA_ERROR("Error creating AppArmor securityfs\n");
236 return error;
237}
238
239fs_initcall(aa_create_aafs);
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
new file mode 100644
index 00000000000..96502b22b26
--- /dev/null
+++ b/security/apparmor/audit.c
@@ -0,0 +1,215 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor auditing functions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/audit.h>
16#include <linux/socket.h>
17
18#include "include/apparmor.h"
19#include "include/audit.h"
20#include "include/policy.h"
21
22const char *op_table[] = {
23 "null",
24
25 "sysctl",
26 "capable",
27
28 "unlink",
29 "mkdir",
30 "rmdir",
31 "mknod",
32 "truncate",
33 "link",
34 "symlink",
35 "rename_src",
36 "rename_dest",
37 "chmod",
38 "chown",
39 "getattr",
40 "open",
41
42 "file_perm",
43 "file_lock",
44 "file_mmap",
45 "file_mprotect",
46
47 "create",
48 "post_create",
49 "bind",
50 "connect",
51 "listen",
52 "accept",
53 "sendmsg",
54 "recvmsg",
55 "getsockname",
56 "getpeername",
57 "getsockopt",
58 "setsockopt",
59 "socket_shutdown",
60
61 "ptrace",
62
63 "exec",
64 "change_hat",
65 "change_profile",
66 "change_onexec",
67
68 "setprocattr",
69 "setrlimit",
70
71 "profile_replace",
72 "profile_load",
73 "profile_remove"
74};
75
76const char *audit_mode_names[] = {
77 "normal",
78 "quiet_denied",
79 "quiet",
80 "noquiet",
81 "all"
82};
83
84static char *aa_audit_type[] = {
85 "AUDIT",
86 "ALLOWED",
87 "DENIED",
88 "HINT",
89 "STATUS",
90 "ERROR",
91 "KILLED"
92};
93
94/*
95 * Currently AppArmor auditing is fed straight into the audit framework.
96 *
97 * TODO:
98 * netlink interface for complain mode
99 * user auditing, - send user auditing to netlink interface
100 * system control of whether user audit messages go to system log
101 */
102
103/**
104 * audit_base - core AppArmor function.
105 * @ab: audit buffer to fill (NOT NULL)
106 * @ca: audit structure containing data to audit (NOT NULL)
107 *
108 * Record common AppArmor audit data from @sa
109 */
110static void audit_pre(struct audit_buffer *ab, void *ca)
111{
112 struct common_audit_data *sa = ca;
113 struct task_struct *tsk = sa->tsk ? sa->tsk : current;
114
115 if (aa_g_audit_header) {
116 audit_log_format(ab, "apparmor=");
117 audit_log_string(ab, aa_audit_type[sa->aad.type]);
118 }
119
120 if (sa->aad.op) {
121 audit_log_format(ab, " operation=");
122 audit_log_string(ab, op_table[sa->aad.op]);
123 }
124
125 if (sa->aad.info) {
126 audit_log_format(ab, " info=");
127 audit_log_string(ab, sa->aad.info);
128 if (sa->aad.error)
129 audit_log_format(ab, " error=%d", sa->aad.error);
130 }
131
132 if (sa->aad.profile) {
133 struct aa_profile *profile = sa->aad.profile;
134 pid_t pid;
135 rcu_read_lock();
136 pid = tsk->real_parent->pid;
137 rcu_read_unlock();
138 audit_log_format(ab, " parent=%d", pid);
139 if (profile->ns != root_ns) {
140 audit_log_format(ab, " namespace=");
141 audit_log_untrustedstring(ab, profile->ns->base.hname);
142 }
143 audit_log_format(ab, " profile=");
144 audit_log_untrustedstring(ab, profile->base.hname);
145 }
146
147 if (sa->aad.name) {
148 audit_log_format(ab, " name=");
149 audit_log_untrustedstring(ab, sa->aad.name);
150 }
151}
152
153/**
154 * aa_audit_msg - Log a message to the audit subsystem
155 * @sa: audit event structure (NOT NULL)
156 * @cb: optional callback fn for type specific fields (MAYBE NULL)
157 */
158void aa_audit_msg(int type, struct common_audit_data *sa,
159 void (*cb) (struct audit_buffer *, void *))
160{
161 sa->aad.type = type;
162 sa->lsm_pre_audit = audit_pre;
163 sa->lsm_post_audit = cb;
164 common_lsm_audit(sa);
165}
166
167/**
168 * aa_audit - Log a profile based audit event to the audit subsystem
169 * @type: audit type for the message
170 * @profile: profile to check against (NOT NULL)
171 * @gfp: allocation flags to use
172 * @sa: audit event (NOT NULL)
173 * @cb: optional callback fn for type specific fields (MAYBE NULL)
174 *
175 * Handle default message switching based off of audit mode flags
176 *
177 * Returns: error on failure
178 */
179int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
180 struct common_audit_data *sa,
181 void (*cb) (struct audit_buffer *, void *))
182{
183 BUG_ON(!profile);
184
185 if (type == AUDIT_APPARMOR_AUTO) {
186 if (likely(!sa->aad.error)) {
187 if (AUDIT_MODE(profile) != AUDIT_ALL)
188 return 0;
189 type = AUDIT_APPARMOR_AUDIT;
190 } else if (COMPLAIN_MODE(profile))
191 type = AUDIT_APPARMOR_ALLOWED;
192 else
193 type = AUDIT_APPARMOR_DENIED;
194 }
195 if (AUDIT_MODE(profile) == AUDIT_QUIET ||
196 (type == AUDIT_APPARMOR_DENIED &&
197 AUDIT_MODE(profile) == AUDIT_QUIET))
198 return sa->aad.error;
199
200 if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
201 type = AUDIT_APPARMOR_KILL;
202
203 if (!unconfined(profile))
204 sa->aad.profile = profile;
205
206 aa_audit_msg(type, sa, cb);
207
208 if (sa->aad.type == AUDIT_APPARMOR_KILL)
209 (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current);
210
211 if (sa->aad.type == AUDIT_APPARMOR_ALLOWED)
212 return complain_error(sa->aad.error);
213
214 return sa->aad.error;
215}
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
new file mode 100644
index 00000000000..9982c48def4
--- /dev/null
+++ b/security/apparmor/capability.c
@@ -0,0 +1,141 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor capability mediation functions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/capability.h>
16#include <linux/errno.h>
17#include <linux/gfp.h>
18
19#include "include/apparmor.h"
20#include "include/capability.h"
21#include "include/context.h"
22#include "include/policy.h"
23#include "include/audit.h"
24
25/*
26 * Table of capability names: we generate it from capabilities.h.
27 */
28#include "capability_names.h"
29
30struct audit_cache {
31 struct aa_profile *profile;
32 kernel_cap_t caps;
33};
34
35static DEFINE_PER_CPU(struct audit_cache, audit_cache);
36
37/**
38 * audit_cb - call back for capability components of audit struct
39 * @ab - audit buffer (NOT NULL)
40 * @va - audit struct to audit data from (NOT NULL)
41 */
42static void audit_cb(struct audit_buffer *ab, void *va)
43{
44 struct common_audit_data *sa = va;
45 audit_log_format(ab, " capname=");
46 audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
47}
48
49/**
50 * audit_caps - audit a capability
51 * @profile: profile confining task (NOT NULL)
52 * @task: task capability test was performed against (NOT NULL)
53 * @cap: capability tested
54 * @error: error code returned by test
55 *
56 * Do auditing of capability and handle, audit/complain/kill modes switching
57 * and duplicate message elimination.
58 *
59 * Returns: 0 or sa->error on success, error code on failure
60 */
61static int audit_caps(struct aa_profile *profile, struct task_struct *task,
62 int cap, int error)
63{
64 struct audit_cache *ent;
65 int type = AUDIT_APPARMOR_AUTO;
66 struct common_audit_data sa;
67 COMMON_AUDIT_DATA_INIT(&sa, CAP);
68 sa.tsk = task;
69 sa.u.cap = cap;
70 sa.aad.op = OP_CAPABLE;
71 sa.aad.error = error;
72
73 if (likely(!error)) {
74 /* test if auditing is being forced */
75 if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
76 !cap_raised(profile->caps.audit, cap)))
77 return 0;
78 type = AUDIT_APPARMOR_AUDIT;
79 } else if (KILL_MODE(profile) ||
80 cap_raised(profile->caps.kill, cap)) {
81 type = AUDIT_APPARMOR_KILL;
82 } else if (cap_raised(profile->caps.quiet, cap) &&
83 AUDIT_MODE(profile) != AUDIT_NOQUIET &&
84 AUDIT_MODE(profile) != AUDIT_ALL) {
85 /* quiet auditing */
86 return error;
87 }
88
89 /* Do simple duplicate message elimination */
90 ent = &get_cpu_var(audit_cache);
91 if (profile == ent->profile && cap_raised(ent->caps, cap)) {
92 put_cpu_var(audit_cache);
93 if (COMPLAIN_MODE(profile))
94 return complain_error(error);
95 return error;
96 } else {
97 aa_put_profile(ent->profile);
98 ent->profile = aa_get_profile(profile);
99 cap_raise(ent->caps, cap);
100 }
101 put_cpu_var(audit_cache);
102
103 return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb);
104}
105
106/**
107 * profile_capable - test if profile allows use of capability @cap
108 * @profile: profile being enforced (NOT NULL, NOT unconfined)
109 * @cap: capability to test if allowed
110 *
111 * Returns: 0 if allowed else -EPERM
112 */
113static int profile_capable(struct aa_profile *profile, int cap)
114{
115 return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM;
116}
117
118/**
119 * aa_capable - test permission to use capability
120 * @task: task doing capability test against (NOT NULL)
121 * @profile: profile confining @task (NOT NULL)
122 * @cap: capability to be tested
123 * @audit: whether an audit record should be generated
124 *
125 * Look up capability in profile capability set.
126 *
127 * Returns: 0 on success, or else an error code.
128 */
129int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
130 int audit)
131{
132 int error = profile_capable(profile, cap);
133
134 if (!audit) {
135 if (COMPLAIN_MODE(profile))
136 return complain_error(error);
137 return error;
138 }
139
140 return audit_caps(profile, task, cap, error);
141}
diff --git a/security/apparmor/context.c b/security/apparmor/context.c
new file mode 100644
index 00000000000..8a9b5027c81
--- /dev/null
+++ b/security/apparmor/context.c
@@ -0,0 +1,216 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor functions used to manipulate object security
5 * contexts.
6 *
7 * Copyright (C) 1998-2008 Novell/SUSE
8 * Copyright 2009-2010 Canonical Ltd.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation, version 2 of the
13 * License.
14 *
15 *
16 * AppArmor sets confinement on every task, via the the aa_task_cxt and
17 * the aa_task_cxt.profile, both of which are required and are not allowed
18 * to be NULL. The aa_task_cxt is not reference counted and is unique
19 * to each cred (which is reference count). The profile pointed to by
20 * the task_cxt is reference counted.
21 *
22 * TODO
23 * If a task uses change_hat it currently does not return to the old
24 * cred or task context but instead creates a new one. Ideally the task
25 * should return to the previous cred if it has not been modified.
26 *
27 */
28
29#include "include/context.h"
30#include "include/policy.h"
31
32/**
33 * aa_alloc_task_context - allocate a new task_cxt
34 * @flags: gfp flags for allocation
35 *
36 * Returns: allocated buffer or NULL on failure
37 */
38struct aa_task_cxt *aa_alloc_task_context(gfp_t flags)
39{
40 return kzalloc(sizeof(struct aa_task_cxt), flags);
41}
42
43/**
44 * aa_free_task_context - free a task_cxt
45 * @cxt: task_cxt to free (MAYBE NULL)
46 */
47void aa_free_task_context(struct aa_task_cxt *cxt)
48{
49 if (cxt) {
50 aa_put_profile(cxt->profile);
51 aa_put_profile(cxt->previous);
52 aa_put_profile(cxt->onexec);
53
54 kzfree(cxt);
55 }
56}
57
58/**
59 * aa_dup_task_context - duplicate a task context, incrementing reference counts
60 * @new: a blank task context (NOT NULL)
61 * @old: the task context to copy (NOT NULL)
62 */
63void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
64{
65 *new = *old;
66 aa_get_profile(new->profile);
67 aa_get_profile(new->previous);
68 aa_get_profile(new->onexec);
69}
70
71/**
72 * aa_replace_current_profile - replace the current tasks profiles
73 * @profile: new profile (NOT NULL)
74 *
75 * Returns: 0 or error on failure
76 */
77int aa_replace_current_profile(struct aa_profile *profile)
78{
79 struct aa_task_cxt *cxt = current_cred()->security;
80 struct cred *new;
81 BUG_ON(!profile);
82
83 if (cxt->profile == profile)
84 return 0;
85
86 new = prepare_creds();
87 if (!new)
88 return -ENOMEM;
89
90 cxt = new->security;
91 if (unconfined(profile) || (cxt->profile->ns != profile->ns)) {
92 /* if switching to unconfined or a different profile namespace
93 * clear out context state
94 */
95 aa_put_profile(cxt->previous);
96 aa_put_profile(cxt->onexec);
97 cxt->previous = NULL;
98 cxt->onexec = NULL;
99 cxt->token = 0;
100 }
101 /* be careful switching cxt->profile, when racing replacement it
102 * is possible that cxt->profile->replacedby is the reference keeping
103 * @profile valid, so make sure to get its reference before dropping
104 * the reference on cxt->profile */
105 aa_get_profile(profile);
106 aa_put_profile(cxt->profile);
107 cxt->profile = profile;
108
109 commit_creds(new);
110 return 0;
111}
112
113/**
114 * aa_set_current_onexec - set the tasks change_profile to happen onexec
115 * @profile: system profile to set at exec (MAYBE NULL to clear value)
116 *
117 * Returns: 0 or error on failure
118 */
119int aa_set_current_onexec(struct aa_profile *profile)
120{
121 struct aa_task_cxt *cxt;
122 struct cred *new = prepare_creds();
123 if (!new)
124 return -ENOMEM;
125
126 cxt = new->security;
127 aa_get_profile(profile);
128 aa_put_profile(cxt->onexec);
129 cxt->onexec = profile;
130
131 commit_creds(new);
132 return 0;
133}
134
135/**
136 * aa_set_current_hat - set the current tasks hat
137 * @profile: profile to set as the current hat (NOT NULL)
138 * @token: token value that must be specified to change from the hat
139 *
140 * Do switch of tasks hat. If the task is currently in a hat
141 * validate the token to match.
142 *
143 * Returns: 0 or error on failure
144 */
145int aa_set_current_hat(struct aa_profile *profile, u64 token)
146{
147 struct aa_task_cxt *cxt;
148 struct cred *new = prepare_creds();
149 if (!new)
150 return -ENOMEM;
151 BUG_ON(!profile);
152
153 cxt = new->security;
154 if (!cxt->previous) {
155 /* transfer refcount */
156 cxt->previous = cxt->profile;
157 cxt->token = token;
158 } else if (cxt->token == token) {
159 aa_put_profile(cxt->profile);
160 } else {
161 /* previous_profile && cxt->token != token */
162 abort_creds(new);
163 return -EACCES;
164 }
165 cxt->profile = aa_get_profile(aa_newest_version(profile));
166 /* clear exec on switching context */
167 aa_put_profile(cxt->onexec);
168 cxt->onexec = NULL;
169
170 commit_creds(new);
171 return 0;
172}
173
174/**
175 * aa_restore_previous_profile - exit from hat context restoring the profile
176 * @token: the token that must be matched to exit hat context
177 *
178 * Attempt to return out of a hat to the previous profile. The token
179 * must match the stored token value.
180 *
181 * Returns: 0 or error of failure
182 */
183int aa_restore_previous_profile(u64 token)
184{
185 struct aa_task_cxt *cxt;
186 struct cred *new = prepare_creds();
187 if (!new)
188 return -ENOMEM;
189
190 cxt = new->security;
191 if (cxt->token != token) {
192 abort_creds(new);
193 return -EACCES;
194 }
195 /* ignore restores when there is no saved profile */
196 if (!cxt->previous) {
197 abort_creds(new);
198 return 0;
199 }
200
201 aa_put_profile(cxt->profile);
202 cxt->profile = aa_newest_version(cxt->previous);
203 BUG_ON(!cxt->profile);
204 if (unlikely(cxt->profile != cxt->previous)) {
205 aa_get_profile(cxt->profile);
206 aa_put_profile(cxt->previous);
207 }
208 /* clear exec && prev information when restoring to previous context */
209 cxt->previous = NULL;
210 cxt->token = 0;
211 aa_put_profile(cxt->onexec);
212 cxt->onexec = NULL;
213
214 commit_creds(new);
215 return 0;
216}
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
new file mode 100644
index 00000000000..c825c6e0b63
--- /dev/null
+++ b/security/apparmor/domain.c
@@ -0,0 +1,823 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor policy attachment and domain transitions
5 *
6 * Copyright (C) 2002-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/errno.h>
16#include <linux/fdtable.h>
17#include <linux/file.h>
18#include <linux/mount.h>
19#include <linux/syscalls.h>
20#include <linux/tracehook.h>
21#include <linux/personality.h>
22
23#include "include/audit.h"
24#include "include/apparmorfs.h"
25#include "include/context.h"
26#include "include/domain.h"
27#include "include/file.h"
28#include "include/ipc.h"
29#include "include/match.h"
30#include "include/path.h"
31#include "include/policy.h"
32
33/**
34 * aa_free_domain_entries - free entries in a domain table
35 * @domain: the domain table to free (MAYBE NULL)
36 */
37void aa_free_domain_entries(struct aa_domain *domain)
38{
39 int i;
40 if (domain) {
41 if (!domain->table)
42 return;
43
44 for (i = 0; i < domain->size; i++)
45 kzfree(domain->table[i]);
46 kzfree(domain->table);
47 domain->table = NULL;
48 }
49}
50
51/**
52 * may_change_ptraced_domain - check if can change profile on ptraced task
53 * @task: task we want to change profile of (NOT NULL)
54 * @to_profile: profile to change to (NOT NULL)
55 *
56 * Check if the task is ptraced and if so if the tracing task is allowed
57 * to trace the new domain
58 *
59 * Returns: %0 or error if change not allowed
60 */
61static int may_change_ptraced_domain(struct task_struct *task,
62 struct aa_profile *to_profile)
63{
64 struct task_struct *tracer;
65 const struct cred *cred = NULL;
66 struct aa_profile *tracerp = NULL;
67 int error = 0;
68
69 rcu_read_lock();
70 tracer = tracehook_tracer_task(task);
71 if (tracer) {
72 /* released below */
73 cred = get_task_cred(tracer);
74 tracerp = aa_cred_profile(cred);
75 }
76 rcu_read_unlock();
77
78 /* not ptraced */
79 if (!tracer || unconfined(tracerp))
80 goto out;
81
82 error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
83
84out:
85 if (cred)
86 put_cred(cred);
87
88 return error;
89}
90
91/**
92 * change_profile_perms - find permissions for change_profile
93 * @profile: the current profile (NOT NULL)
94 * @ns: the namespace being switched to (NOT NULL)
95 * @name: the name of the profile to change to (NOT NULL)
96 * @request: requested perms
97 * @start: state to start matching in
98 *
99 * Returns: permission set
100 */
101static struct file_perms change_profile_perms(struct aa_profile *profile,
102 struct aa_namespace *ns,
103 const char *name, u32 request,
104 unsigned int start)
105{
106 struct file_perms perms;
107 struct path_cond cond = { };
108 unsigned int state;
109
110 if (unconfined(profile)) {
111 perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC;
112 perms.audit = perms.quiet = perms.kill = 0;
113 return perms;
114 } else if (!profile->file.dfa) {
115 return nullperms;
116 } else if ((ns == profile->ns)) {
117 /* try matching against rules with out namespace prepended */
118 aa_str_perms(profile->file.dfa, start, name, &cond, &perms);
119 if (COMBINED_PERM_MASK(perms) & request)
120 return perms;
121 }
122
123 /* try matching with namespace name and then profile */
124 state = aa_dfa_match(profile->file.dfa, start, ns->base.name);
125 state = aa_dfa_match_len(profile->file.dfa, state, ":", 1);
126 aa_str_perms(profile->file.dfa, state, name, &cond, &perms);
127
128 return perms;
129}
130
131/**
132 * __attach_match_ - find an attachment match
133 * @name - to match against (NOT NULL)
134 * @head - profile list to walk (NOT NULL)
135 *
136 * Do a linear search on the profiles in the list. There is a matching
137 * preference where an exact match is preferred over a name which uses
138 * expressions to match, and matching expressions with the greatest
139 * xmatch_len are preferred.
140 *
141 * Requires: @head not be shared or have appropriate locks held
142 *
143 * Returns: profile or NULL if no match found
144 */
145static struct aa_profile *__attach_match(const char *name,
146 struct list_head *head)
147{
148 int len = 0;
149 struct aa_profile *profile, *candidate = NULL;
150
151 list_for_each_entry(profile, head, base.list) {
152 if (profile->flags & PFLAG_NULL)
153 continue;
154 if (profile->xmatch && profile->xmatch_len > len) {
155 unsigned int state = aa_dfa_match(profile->xmatch,
156 DFA_START, name);
157 u32 perm = dfa_user_allow(profile->xmatch, state);
158 /* any accepting state means a valid match. */
159 if (perm & MAY_EXEC) {
160 candidate = profile;
161 len = profile->xmatch_len;
162 }
163 } else if (!strcmp(profile->base.name, name))
164 /* exact non-re match, no more searching required */
165 return profile;
166 }
167
168 return candidate;
169}
170
171/**
172 * find_attach - do attachment search for unconfined processes
173 * @ns: the current namespace (NOT NULL)
174 * @list: list to search (NOT NULL)
175 * @name: the executable name to match against (NOT NULL)
176 *
177 * Returns: profile or NULL if no match found
178 */
179static struct aa_profile *find_attach(struct aa_namespace *ns,
180 struct list_head *list, const char *name)
181{
182 struct aa_profile *profile;
183
184 read_lock(&ns->lock);
185 profile = aa_get_profile(__attach_match(name, list));
186 read_unlock(&ns->lock);
187
188 return profile;
189}
190
191/**
192 * separate_fqname - separate the namespace and profile names
193 * @fqname: the fqname name to split (NOT NULL)
194 * @ns_name: the namespace name if it exists (NOT NULL)
195 *
196 * This is the xtable equivalent routine of aa_split_fqname. It finds the
197 * split in an xtable fqname which contains an embedded \0 instead of a :
198 * if a namespace is specified. This is done so the xtable is constant and
199 * isn't re-split on every lookup.
200 *
201 * Either the profile or namespace name may be optional but if the namespace
202 * is specified the profile name termination must be present. This results
203 * in the following possible encodings:
204 * profile_name\0
205 * :ns_name\0profile_name\0
206 * :ns_name\0\0
207 *
208 * NOTE: the xtable fqname is pre-validated at load time in unpack_trans_table
209 *
210 * Returns: profile name if it is specified else NULL
211 */
212static const char *separate_fqname(const char *fqname, const char **ns_name)
213{
214 const char *name;
215
216 if (fqname[0] == ':') {
217 /* In this case there is guaranteed to be two \0 terminators
218 * in the string. They are verified at load time by
219 * by unpack_trans_table
220 */
221 *ns_name = fqname + 1; /* skip : */
222 name = *ns_name + strlen(*ns_name) + 1;
223 if (!*name)
224 name = NULL;
225 } else {
226 *ns_name = NULL;
227 name = fqname;
228 }
229
230 return name;
231}
232
233static const char *next_name(int xtype, const char *name)
234{
235 return NULL;
236}
237
238/**
239 * x_table_lookup - lookup an x transition name via transition table
240 * @profile: current profile (NOT NULL)
241 * @xindex: index into x transition table
242 *
243 * Returns: refcounted profile, or NULL on failure (MAYBE NULL)
244 */
245static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
246{
247 struct aa_profile *new_profile = NULL;
248 struct aa_namespace *ns = profile->ns;
249 u32 xtype = xindex & AA_X_TYPE_MASK;
250 int index = xindex & AA_X_INDEX_MASK;
251 const char *name;
252
253 /* index is guaranteed to be in range, validated at load time */
254 for (name = profile->file.trans.table[index]; !new_profile && name;
255 name = next_name(xtype, name)) {
256 struct aa_namespace *new_ns;
257 const char *xname = NULL;
258
259 new_ns = NULL;
260 if (xindex & AA_X_CHILD) {
261 /* release by caller */
262 new_profile = aa_find_child(profile, name);
263 continue;
264 } else if (*name == ':') {
265 /* switching namespace */
266 const char *ns_name;
267 xname = name = separate_fqname(name, &ns_name);
268 if (!xname)
269 /* no name so use profile name */
270 xname = profile->base.hname;
271 if (*ns_name == '@') {
272 /* TODO: variable support */
273 ;
274 }
275 /* released below */
276 new_ns = aa_find_namespace(ns, ns_name);
277 if (!new_ns)
278 continue;
279 } else if (*name == '@') {
280 /* TODO: variable support */
281 continue;
282 } else {
283 /* basic namespace lookup */
284 xname = name;
285 }
286
287 /* released by caller */
288 new_profile = aa_lookup_profile(new_ns ? new_ns : ns, xname);
289 aa_put_namespace(new_ns);
290 }
291
292 /* released by caller */
293 return new_profile;
294}
295
296/**
297 * x_to_profile - get target profile for a given xindex
298 * @profile: current profile (NOT NULL)
299 * @name: name to lookup (NOT NULL)
300 * @xindex: index into x transition table
301 *
302 * find profile for a transition index
303 *
304 * Returns: refcounted profile or NULL if not found available
305 */
306static struct aa_profile *x_to_profile(struct aa_profile *profile,
307 const char *name, u32 xindex)
308{
309 struct aa_profile *new_profile = NULL;
310 struct aa_namespace *ns = profile->ns;
311 u32 xtype = xindex & AA_X_TYPE_MASK;
312
313 switch (xtype) {
314 case AA_X_NONE:
315 /* fail exec unless ix || ux fallback - handled by caller */
316 return NULL;
317 case AA_X_NAME:
318 if (xindex & AA_X_CHILD)
319 /* released by caller */
320 new_profile = find_attach(ns, &profile->base.profiles,
321 name);
322 else
323 /* released by caller */
324 new_profile = find_attach(ns, &ns->base.profiles,
325 name);
326 break;
327 case AA_X_TABLE:
328 /* released by caller */
329 new_profile = x_table_lookup(profile, xindex);
330 break;
331 }
332
333 /* released by caller */
334 return new_profile;
335}
336
337/**
338 * apparmor_bprm_set_creds - set the new creds on the bprm struct
339 * @bprm: binprm for the exec (NOT NULL)
340 *
341 * Returns: %0 or error on failure
342 */
343int apparmor_bprm_set_creds(struct linux_binprm *bprm)
344{
345 struct aa_task_cxt *cxt;
346 struct aa_profile *profile, *new_profile = NULL;
347 struct aa_namespace *ns;
348 char *buffer = NULL;
349 unsigned int state;
350 struct file_perms perms = {};
351 struct path_cond cond = {
352 bprm->file->f_path.dentry->d_inode->i_uid,
353 bprm->file->f_path.dentry->d_inode->i_mode
354 };
355 const char *name = NULL, *target = NULL, *info = NULL;
356 int error = cap_bprm_set_creds(bprm);
357 if (error)
358 return error;
359
360 if (bprm->cred_prepared)
361 return 0;
362
363 cxt = bprm->cred->security;
364 BUG_ON(!cxt);
365
366 profile = aa_get_profile(aa_newest_version(cxt->profile));
367 /*
368 * get the namespace from the replacement profile as replacement
369 * can change the namespace
370 */
371 ns = profile->ns;
372 state = profile->file.start;
373
374 /* buffer freed below, name is pointer into buffer */
375 error = aa_get_name(&bprm->file->f_path, profile->path_flags, &buffer,
376 &name);
377 if (error) {
378 if (profile->flags &
379 (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED))
380 error = 0;
381 info = "Exec failed name resolution";
382 name = bprm->filename;
383 goto audit;
384 }
385
386 /* Test for onexec first as onexec directives override other
387 * x transitions.
388 */
389 if (unconfined(profile)) {
390 /* unconfined task */
391 if (cxt->onexec)
392 /* change_profile on exec already been granted */
393 new_profile = aa_get_profile(cxt->onexec);
394 else
395 new_profile = find_attach(ns, &ns->base.profiles, name);
396 if (!new_profile)
397 goto cleanup;
398 goto apply;
399 }
400
401 /* find exec permissions for name */
402 state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms);
403 if (cxt->onexec) {
404 struct file_perms cp;
405 info = "change_profile onexec";
406 if (!(perms.allow & AA_MAY_ONEXEC))
407 goto audit;
408
409 /* test if this exec can be paired with change_profile onexec.
410 * onexec permission is linked to exec with a standard pairing
411 * exec\0change_profile
412 */
413 state = aa_dfa_null_transition(profile->file.dfa, state);
414 cp = change_profile_perms(profile, cxt->onexec->ns, name,
415 AA_MAY_ONEXEC, state);
416
417 if (!(cp.allow & AA_MAY_ONEXEC))
418 goto audit;
419 new_profile = aa_get_profile(aa_newest_version(cxt->onexec));
420 goto apply;
421 }
422
423 if (perms.allow & MAY_EXEC) {
424 /* exec permission determine how to transition */
425 new_profile = x_to_profile(profile, name, perms.xindex);
426 if (!new_profile) {
427 if (perms.xindex & AA_X_INHERIT) {
428 /* (p|c|n)ix - don't change profile but do
429 * use the newest version, which was picked
430 * up above when getting profile
431 */
432 info = "ix fallback";
433 new_profile = aa_get_profile(profile);
434 goto x_clear;
435 } else if (perms.xindex & AA_X_UNCONFINED) {
436 new_profile = aa_get_profile(ns->unconfined);
437 info = "ux fallback";
438 } else {
439 error = -ENOENT;
440 info = "profile not found";
441 }
442 }
443 } else if (COMPLAIN_MODE(profile)) {
444 /* no exec permission - are we in learning mode */
445 new_profile = aa_new_null_profile(profile, 0);
446 if (!new_profile) {
447 error = -ENOMEM;
448 info = "could not create null profile";
449 } else {
450 error = -EACCES;
451 target = new_profile->base.hname;
452 }
453 perms.xindex |= AA_X_UNSAFE;
454 } else
455 /* fail exec */
456 error = -EACCES;
457
458 if (!new_profile)
459 goto audit;
460
461 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
462 /* FIXME: currently don't mediate shared state */
463 ;
464 }
465
466 if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
467 error = may_change_ptraced_domain(current, new_profile);
468 if (error) {
469 aa_put_profile(new_profile);
470 goto audit;
471 }
472 }
473
474 /* Determine if secure exec is needed.
475 * Can be at this point for the following reasons:
476 * 1. unconfined switching to confined
477 * 2. confined switching to different confinement
478 * 3. confined switching to unconfined
479 *
480 * Cases 2 and 3 are marked as requiring secure exec
481 * (unless policy specified "unsafe exec")
482 *
483 * bprm->unsafe is used to cache the AA_X_UNSAFE permission
484 * to avoid having to recompute in secureexec
485 */
486 if (!(perms.xindex & AA_X_UNSAFE)) {
487 AA_DEBUG("scrubbing environment variables for %s profile=%s\n",
488 name, new_profile->base.hname);
489 bprm->unsafe |= AA_SECURE_X_NEEDED;
490 }
491apply:
492 target = new_profile->base.hname;
493 /* when transitioning profiles clear unsafe personality bits */
494 bprm->per_clear |= PER_CLEAR_ON_SETID;
495
496x_clear:
497 aa_put_profile(cxt->profile);
498 /* transfer new profile reference will be released when cxt is freed */
499 cxt->profile = new_profile;
500
501 /* clear out all temporary/transitional state from the context */
502 aa_put_profile(cxt->previous);
503 aa_put_profile(cxt->onexec);
504 cxt->previous = NULL;
505 cxt->onexec = NULL;
506 cxt->token = 0;
507
508audit:
509 error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
510 name, target, cond.uid, info, error);
511
512cleanup:
513 aa_put_profile(profile);
514 kfree(buffer);
515
516 return error;
517}
518
519/**
520 * apparmor_bprm_secureexec - determine if secureexec is needed
521 * @bprm: binprm for exec (NOT NULL)
522 *
523 * Returns: %1 if secureexec is needed else %0
524 */
525int apparmor_bprm_secureexec(struct linux_binprm *bprm)
526{
527 int ret = cap_bprm_secureexec(bprm);
528
529 /* the decision to use secure exec is computed in set_creds
530 * and stored in bprm->unsafe.
531 */
532 if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
533 ret = 1;
534
535 return ret;
536}
537
538/**
539 * apparmor_bprm_committing_creds - do task cleanup on committing new creds
540 * @bprm: binprm for the exec (NOT NULL)
541 */
542void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
543{
544 struct aa_profile *profile = __aa_current_profile();
545 struct aa_task_cxt *new_cxt = bprm->cred->security;
546
547 /* bail out if unconfined or not changing profile */
548 if ((new_cxt->profile == profile) ||
549 (unconfined(new_cxt->profile)))
550 return;
551
552 current->pdeath_signal = 0;
553
554 /* reset soft limits and set hard limits for the new profile */
555 __aa_transition_rlimits(profile, new_cxt->profile);
556}
557
558/**
559 * apparmor_bprm_commited_cred - do cleanup after new creds committed
560 * @bprm: binprm for the exec (NOT NULL)
561 */
562void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
563{
564 /* TODO: cleanup signals - ipc mediation */
565 return;
566}
567
568/*
569 * Functions for self directed profile change
570 */
571
572/**
573 * new_compound_name - create an hname with @n2 appended to @n1
574 * @n1: base of hname (NOT NULL)
575 * @n2: name to append (NOT NULL)
576 *
577 * Returns: new name or NULL on error
578 */
579static char *new_compound_name(const char *n1, const char *n2)
580{
581 char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
582 if (name)
583 sprintf(name, "%s//%s", n1, n2);
584 return name;
585}
586
587/**
588 * aa_change_hat - change hat to/from subprofile
589 * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0)
590 * @count: number of hat names in @hats
591 * @token: magic value to validate the hat change
592 * @permtest: true if this is just a permission test
593 *
594 * Change to the first profile specified in @hats that exists, and store
595 * the @hat_magic in the current task context. If the count == 0 and the
596 * @token matches that stored in the current task context, return to the
597 * top level profile.
598 *
599 * Returns %0 on success, error otherwise.
600 */
601int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
602{
603 const struct cred *cred;
604 struct aa_task_cxt *cxt;
605 struct aa_profile *profile, *previous_profile, *hat = NULL;
606 char *name = NULL;
607 int i;
608 struct file_perms perms = {};
609 const char *target = NULL, *info = NULL;
610 int error = 0;
611
612 /* released below */
613 cred = get_current_cred();
614 cxt = cred->security;
615 profile = aa_cred_profile(cred);
616 previous_profile = cxt->previous;
617
618 if (unconfined(profile)) {
619 info = "unconfined";
620 error = -EPERM;
621 goto audit;
622 }
623
624 if (count) {
625 /* attempting to change into a new hat or switch to a sibling */
626 struct aa_profile *root;
627 root = PROFILE_IS_HAT(profile) ? profile->parent : profile;
628
629 /* find first matching hat */
630 for (i = 0; i < count && !hat; i++)
631 /* released below */
632 hat = aa_find_child(root, hats[i]);
633 if (!hat) {
634 if (!COMPLAIN_MODE(root) || permtest) {
635 if (list_empty(&root->base.profiles))
636 error = -ECHILD;
637 else
638 error = -ENOENT;
639 goto out;
640 }
641
642 /*
643 * In complain mode and failed to match any hats.
644 * Audit the failure is based off of the first hat
645 * supplied. This is done due how userspace
646 * interacts with change_hat.
647 *
648 * TODO: Add logging of all failed hats
649 */
650
651 /* freed below */
652 name = new_compound_name(root->base.hname, hats[0]);
653 target = name;
654 /* released below */
655 hat = aa_new_null_profile(profile, 1);
656 if (!hat) {
657 info = "failed null profile create";
658 error = -ENOMEM;
659 goto audit;
660 }
661 } else {
662 target = hat->base.hname;
663 if (!PROFILE_IS_HAT(hat)) {
664 info = "target not hat";
665 error = -EPERM;
666 goto audit;
667 }
668 }
669
670 error = may_change_ptraced_domain(current, hat);
671 if (error) {
672 info = "ptraced";
673 error = -EPERM;
674 goto audit;
675 }
676
677 if (!permtest) {
678 error = aa_set_current_hat(hat, token);
679 if (error == -EACCES)
680 /* kill task in case of brute force attacks */
681 perms.kill = AA_MAY_CHANGEHAT;
682 else if (name && !error)
683 /* reset error for learning of new hats */
684 error = -ENOENT;
685 }
686 } else if (previous_profile) {
687 /* Return to saved profile. Kill task if restore fails
688 * to avoid brute force attacks
689 */
690 target = previous_profile->base.hname;
691 error = aa_restore_previous_profile(token);
692 perms.kill = AA_MAY_CHANGEHAT;
693 } else
694 /* ignore restores when there is no saved profile */
695 goto out;
696
697audit:
698 if (!permtest)
699 error = aa_audit_file(profile, &perms, GFP_KERNEL,
700 OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL,
701 target, 0, info, error);
702
703out:
704 aa_put_profile(hat);
705 kfree(name);
706 put_cred(cred);
707
708 return error;
709}
710
711/**
712 * aa_change_profile - perform a one-way profile transition
713 * @ns_name: name of the profile namespace to change to (MAYBE NULL)
714 * @hname: name of profile to change to (MAYBE NULL)
715 * @onexec: whether this transition is to take place immediately or at exec
716 * @permtest: true if this is just a permission test
717 *
718 * Change to new profile @name. Unlike with hats, there is no way
719 * to change back. If @name isn't specified the current profile name is
720 * used.
721 * If @onexec then the transition is delayed until
722 * the next exec.
723 *
724 * Returns %0 on success, error otherwise.
725 */
726int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
727 bool permtest)
728{
729 const struct cred *cred;
730 struct aa_task_cxt *cxt;
731 struct aa_profile *profile, *target = NULL;
732 struct aa_namespace *ns = NULL;
733 struct file_perms perms = {};
734 const char *name = NULL, *info = NULL;
735 int op, error = 0;
736 u32 request;
737
738 if (!hname && !ns_name)
739 return -EINVAL;
740
741 if (onexec) {
742 request = AA_MAY_ONEXEC;
743 op = OP_CHANGE_ONEXEC;
744 } else {
745 request = AA_MAY_CHANGE_PROFILE;
746 op = OP_CHANGE_PROFILE;
747 }
748
749 cred = get_current_cred();
750 cxt = cred->security;
751 profile = aa_cred_profile(cred);
752
753 if (ns_name) {
754 /* released below */
755 ns = aa_find_namespace(profile->ns, ns_name);
756 if (!ns) {
757 /* we don't create new namespace in complain mode */
758 name = ns_name;
759 info = "namespace not found";
760 error = -ENOENT;
761 goto audit;
762 }
763 } else
764 /* released below */
765 ns = aa_get_namespace(profile->ns);
766
767 /* if the name was not specified, use the name of the current profile */
768 if (!hname) {
769 if (unconfined(profile))
770 hname = ns->unconfined->base.hname;
771 else
772 hname = profile->base.hname;
773 }
774
775 perms = change_profile_perms(profile, ns, hname, request,
776 profile->file.start);
777 if (!(perms.allow & request)) {
778 error = -EACCES;
779 goto audit;
780 }
781
782 /* released below */
783 target = aa_lookup_profile(ns, hname);
784 if (!target) {
785 info = "profile not found";
786 error = -ENOENT;
787 if (permtest || !COMPLAIN_MODE(profile))
788 goto audit;
789 /* released below */
790 target = aa_new_null_profile(profile, 0);
791 if (!target) {
792 info = "failed null profile create";
793 error = -ENOMEM;
794 goto audit;
795 }
796 }
797
798 /* check if tracing task is allowed to trace target domain */
799 error = may_change_ptraced_domain(current, target);
800 if (error) {
801 info = "ptrace prevents transition";
802 goto audit;
803 }
804
805 if (permtest)
806 goto audit;
807
808 if (onexec)
809 error = aa_set_current_onexec(target);
810 else
811 error = aa_replace_current_profile(target);
812
813audit:
814 if (!permtest)
815 error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request,
816 name, hname, 0, info, error);
817
818 aa_put_namespace(ns);
819 aa_put_profile(target);
820 put_cred(cred);
821
822 return error;
823}
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
new file mode 100644
index 00000000000..7312db74121
--- /dev/null
+++ b/security/apparmor/file.c
@@ -0,0 +1,457 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor mediation of files
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include "include/apparmor.h"
16#include "include/audit.h"
17#include "include/file.h"
18#include "include/match.h"
19#include "include/path.h"
20#include "include/policy.h"
21
22struct file_perms nullperms;
23
24
25/**
26 * audit_file_mask - convert mask to permission string
27 * @buffer: buffer to write string to (NOT NULL)
28 * @mask: permission mask to convert
29 */
30static void audit_file_mask(struct audit_buffer *ab, u32 mask)
31{
32 char str[10];
33
34 char *m = str;
35
36 if (mask & AA_EXEC_MMAP)
37 *m++ = 'm';
38 if (mask & (MAY_READ | AA_MAY_META_READ))
39 *m++ = 'r';
40 if (mask & (MAY_WRITE | AA_MAY_META_WRITE | AA_MAY_CHMOD |
41 AA_MAY_CHOWN))
42 *m++ = 'w';
43 else if (mask & MAY_APPEND)
44 *m++ = 'a';
45 if (mask & AA_MAY_CREATE)
46 *m++ = 'c';
47 if (mask & AA_MAY_DELETE)
48 *m++ = 'd';
49 if (mask & AA_MAY_LINK)
50 *m++ = 'l';
51 if (mask & AA_MAY_LOCK)
52 *m++ = 'k';
53 if (mask & MAY_EXEC)
54 *m++ = 'x';
55 *m = '\0';
56
57 audit_log_string(ab, str);
58}
59
60/**
61 * file_audit_cb - call back for file specific audit fields
62 * @ab: audit_buffer (NOT NULL)
63 * @va: audit struct to audit values of (NOT NULL)
64 */
65static void file_audit_cb(struct audit_buffer *ab, void *va)
66{
67 struct common_audit_data *sa = va;
68 uid_t fsuid = current_fsuid();
69
70 if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
71 audit_log_format(ab, " requested_mask=");
72 audit_file_mask(ab, sa->aad.fs.request);
73 }
74 if (sa->aad.fs.denied & AA_AUDIT_FILE_MASK) {
75 audit_log_format(ab, " denied_mask=");
76 audit_file_mask(ab, sa->aad.fs.denied);
77 }
78 if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
79 audit_log_format(ab, " fsuid=%d", fsuid);
80 audit_log_format(ab, " ouid=%d", sa->aad.fs.ouid);
81 }
82
83 if (sa->aad.fs.target) {
84 audit_log_format(ab, " target=");
85 audit_log_untrustedstring(ab, sa->aad.fs.target);
86 }
87}
88
89/**
90 * aa_audit_file - handle the auditing of file operations
91 * @profile: the profile being enforced (NOT NULL)
92 * @perms: the permissions computed for the request (NOT NULL)
93 * @gfp: allocation flags
94 * @op: operation being mediated
95 * @request: permissions requested
96 * @name: name of object being mediated (MAYBE NULL)
97 * @target: name of target (MAYBE NULL)
98 * @ouid: object uid
99 * @info: extra information message (MAYBE NULL)
100 * @error: 0 if operation allowed else failure error code
101 *
102 * Returns: %0 or error on failure
103 */
104int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
105 gfp_t gfp, int op, u32 request, const char *name,
106 const char *target, uid_t ouid, const char *info, int error)
107{
108 int type = AUDIT_APPARMOR_AUTO;
109 struct common_audit_data sa;
110 COMMON_AUDIT_DATA_INIT(&sa, NONE);
111 sa.aad.op = op,
112 sa.aad.fs.request = request;
113 sa.aad.name = name;
114 sa.aad.fs.target = target;
115 sa.aad.fs.ouid = ouid;
116 sa.aad.info = info;
117 sa.aad.error = error;
118
119 if (likely(!sa.aad.error)) {
120 u32 mask = perms->audit;
121
122 if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
123 mask = 0xffff;
124
125 /* mask off perms that are not being force audited */
126 sa.aad.fs.request &= mask;
127
128 if (likely(!sa.aad.fs.request))
129 return 0;
130 type = AUDIT_APPARMOR_AUDIT;
131 } else {
132 /* only report permissions that were denied */
133 sa.aad.fs.request = sa.aad.fs.request & ~perms->allow;
134
135 if (sa.aad.fs.request & perms->kill)
136 type = AUDIT_APPARMOR_KILL;
137
138 /* quiet known rejects, assumes quiet and kill do not overlap */
139 if ((sa.aad.fs.request & perms->quiet) &&
140 AUDIT_MODE(profile) != AUDIT_NOQUIET &&
141 AUDIT_MODE(profile) != AUDIT_ALL)
142 sa.aad.fs.request &= ~perms->quiet;
143
144 if (!sa.aad.fs.request)
145 return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
146 }
147
148 sa.aad.fs.denied = sa.aad.fs.request & ~perms->allow;
149 return aa_audit(type, profile, gfp, &sa, file_audit_cb);
150}
151
152/**
153 * map_old_perms - map old file perms layout to the new layout
154 * @old: permission set in old mapping
155 *
156 * Returns: new permission mapping
157 */
158static u32 map_old_perms(u32 old)
159{
160 u32 new = old & 0xf;
161 if (old & MAY_READ)
162 new |= AA_MAY_META_READ;
163 if (old & MAY_WRITE)
164 new |= AA_MAY_META_WRITE | AA_MAY_CREATE | AA_MAY_DELETE |
165 AA_MAY_CHMOD | AA_MAY_CHOWN;
166 if (old & 0x10)
167 new |= AA_MAY_LINK;
168 /* the old mapping lock and link_subset flags where overlaid
169 * and use was determined by part of a pair that they were in
170 */
171 if (old & 0x20)
172 new |= AA_MAY_LOCK | AA_LINK_SUBSET;
173 if (old & 0x40) /* AA_EXEC_MMAP */
174 new |= AA_EXEC_MMAP;
175
176 new |= AA_MAY_META_READ;
177
178 return new;
179}
180
181/**
182 * compute_perms - convert dfa compressed perms to internal perms
183 * @dfa: dfa to compute perms for (NOT NULL)
184 * @state: state in dfa
185 * @cond: conditions to consider (NOT NULL)
186 *
187 * TODO: convert from dfa + state to permission entry, do computation conversion
188 * at load time.
189 *
190 * Returns: computed permission set
191 */
192static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state,
193 struct path_cond *cond)
194{
195 struct file_perms perms;
196
197 /* FIXME: change over to new dfa format
198 * currently file perms are encoded in the dfa, new format
199 * splits the permissions from the dfa. This mapping can be
200 * done at profile load
201 */
202 perms.kill = 0;
203
204 if (current_fsuid() == cond->uid) {
205 perms.allow = map_old_perms(dfa_user_allow(dfa, state));
206 perms.audit = map_old_perms(dfa_user_audit(dfa, state));
207 perms.quiet = map_old_perms(dfa_user_quiet(dfa, state));
208 perms.xindex = dfa_user_xindex(dfa, state);
209 } else {
210 perms.allow = map_old_perms(dfa_other_allow(dfa, state));
211 perms.audit = map_old_perms(dfa_other_audit(dfa, state));
212 perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
213 perms.xindex = dfa_other_xindex(dfa, state);
214 }
215
216 /* change_profile wasn't determined by ownership in old mapping */
217 if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
218 perms.allow |= AA_MAY_CHANGE_PROFILE;
219
220 return perms;
221}
222
223/**
224 * aa_str_perms - find permission that match @name
225 * @dfa: to match against (MAYBE NULL)
226 * @state: state to start matching in
227 * @name: string to match against dfa (NOT NULL)
228 * @cond: conditions to consider for permission set computation (NOT NULL)
229 * @perms: Returns - the permissions found when matching @name
230 *
231 * Returns: the final state in @dfa when beginning @start and walking @name
232 */
233unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
234 const char *name, struct path_cond *cond,
235 struct file_perms *perms)
236{
237 unsigned int state;
238 if (!dfa) {
239 *perms = nullperms;
240 return DFA_NOMATCH;
241 }
242
243 state = aa_dfa_match(dfa, start, name);
244 *perms = compute_perms(dfa, state, cond);
245
246 return state;
247}
248
249/**
250 * is_deleted - test if a file has been completely unlinked
251 * @dentry: dentry of file to test for deletion (NOT NULL)
252 *
253 * Returns: %1 if deleted else %0
254 */
255static inline bool is_deleted(struct dentry *dentry)
256{
257 if (d_unlinked(dentry) && dentry->d_inode->i_nlink == 0)
258 return 1;
259 return 0;
260}
261
262/**
263 * aa_path_perm - do permissions check & audit for @path
264 * @op: operation being checked
265 * @profile: profile being enforced (NOT NULL)
266 * @path: path to check permissions of (NOT NULL)
267 * @flags: any additional path flags beyond what the profile specifies
268 * @request: requested permissions
269 * @cond: conditional info for this request (NOT NULL)
270 *
271 * Returns: %0 else error if access denied or other error
272 */
273int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
274 int flags, u32 request, struct path_cond *cond)
275{
276 char *buffer = NULL;
277 struct file_perms perms = {};
278 const char *name, *info = NULL;
279 int error;
280
281 flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
282 error = aa_get_name(path, flags, &buffer, &name);
283 if (error) {
284 if (error == -ENOENT && is_deleted(path->dentry)) {
285 /* Access to open files that are deleted are
286 * give a pass (implicit delegation)
287 */
288 error = 0;
289 perms.allow = request;
290 } else if (error == -ENOENT)
291 info = "Failed name lookup - deleted entry";
292 else if (error == -ESTALE)
293 info = "Failed name lookup - disconnected path";
294 else if (error == -ENAMETOOLONG)
295 info = "Failed name lookup - name too long";
296 else
297 info = "Failed name lookup";
298 } else {
299 aa_str_perms(profile->file.dfa, profile->file.start, name, cond,
300 &perms);
301 if (request & ~perms.allow)
302 error = -EACCES;
303 }
304 error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request, name,
305 NULL, cond->uid, info, error);
306 kfree(buffer);
307
308 return error;
309}
310
311/**
312 * xindex_is_subset - helper for aa_path_link
313 * @link: link permission set
314 * @target: target permission set
315 *
316 * test target x permissions are equal OR a subset of link x permissions
317 * this is done as part of the subset test, where a hardlink must have
318 * a subset of permissions that the target has.
319 *
320 * Returns: %1 if subset else %0
321 */
322static inline bool xindex_is_subset(u32 link, u32 target)
323{
324 if (((link & ~AA_X_UNSAFE) != (target & ~AA_X_UNSAFE)) ||
325 ((link & AA_X_UNSAFE) && !(target & AA_X_UNSAFE)))
326 return 0;
327
328 return 1;
329}
330
331/**
332 * aa_path_link - Handle hard link permission check
333 * @profile: the profile being enforced (NOT NULL)
334 * @old_dentry: the target dentry (NOT NULL)
335 * @new_dir: directory the new link will be created in (NOT NULL)
336 * @new_dentry: the link being created (NOT NULL)
337 *
338 * Handle the permission test for a link & target pair. Permission
339 * is encoded as a pair where the link permission is determined
340 * first, and if allowed, the target is tested. The target test
341 * is done from the point of the link match (not start of DFA)
342 * making the target permission dependent on the link permission match.
343 *
344 * The subset test if required forces that permissions granted
345 * on link are a subset of the permission granted to target.
346 *
347 * Returns: %0 if allowed else error
348 */
349int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
350 struct path *new_dir, struct dentry *new_dentry)
351{
352 struct path link = { new_dir->mnt, new_dentry };
353 struct path target = { new_dir->mnt, old_dentry };
354 struct path_cond cond = {
355 old_dentry->d_inode->i_uid,
356 old_dentry->d_inode->i_mode
357 };
358 char *buffer = NULL, *buffer2 = NULL;
359 const char *lname, *tname = NULL, *info = NULL;
360 struct file_perms lperms, perms;
361 u32 request = AA_MAY_LINK;
362 unsigned int state;
363 int error;
364
365 lperms = nullperms;
366
367 /* buffer freed below, lname is pointer in buffer */
368 error = aa_get_name(&link, profile->path_flags, &buffer, &lname);
369 if (error)
370 goto audit;
371
372 /* buffer2 freed below, tname is pointer in buffer2 */
373 error = aa_get_name(&target, profile->path_flags, &buffer2, &tname);
374 if (error)
375 goto audit;
376
377 error = -EACCES;
378 /* aa_str_perms - handles the case of the dfa being NULL */
379 state = aa_str_perms(profile->file.dfa, profile->file.start, lname,
380 &cond, &lperms);
381
382 if (!(lperms.allow & AA_MAY_LINK))
383 goto audit;
384
385 /* test to see if target can be paired with link */
386 state = aa_dfa_null_transition(profile->file.dfa, state);
387 aa_str_perms(profile->file.dfa, state, tname, &cond, &perms);
388
389 /* force audit/quiet masks for link are stored in the second entry
390 * in the link pair.
391 */
392 lperms.audit = perms.audit;
393 lperms.quiet = perms.quiet;
394 lperms.kill = perms.kill;
395
396 if (!(perms.allow & AA_MAY_LINK)) {
397 info = "target restricted";
398 goto audit;
399 }
400
401 /* done if link subset test is not required */
402 if (!(perms.allow & AA_LINK_SUBSET))
403 goto done_tests;
404
405 /* Do link perm subset test requiring allowed permission on link are a
406 * subset of the allowed permissions on target.
407 */
408 aa_str_perms(profile->file.dfa, profile->file.start, tname, &cond,
409 &perms);
410
411 /* AA_MAY_LINK is not considered in the subset test */
412 request = lperms.allow & ~AA_MAY_LINK;
413 lperms.allow &= perms.allow | AA_MAY_LINK;
414
415 request |= AA_AUDIT_FILE_MASK & (lperms.allow & ~perms.allow);
416 if (request & ~lperms.allow) {
417 goto audit;
418 } else if ((lperms.allow & MAY_EXEC) &&
419 !xindex_is_subset(lperms.xindex, perms.xindex)) {
420 lperms.allow &= ~MAY_EXEC;
421 request |= MAY_EXEC;
422 info = "link not subset of target";
423 goto audit;
424 }
425
426done_tests:
427 error = 0;
428
429audit:
430 error = aa_audit_file(profile, &lperms, GFP_KERNEL, OP_LINK, request,
431 lname, tname, cond.uid, info, error);
432 kfree(buffer);
433 kfree(buffer2);
434
435 return error;
436}
437
438/**
439 * aa_file_perm - do permission revalidation check & audit for @file
440 * @op: operation being checked
441 * @profile: profile being enforced (NOT NULL)
442 * @file: file to revalidate access permissions on (NOT NULL)
443 * @request: requested permissions
444 *
445 * Returns: %0 if access allowed else error
446 */
447int aa_file_perm(int op, struct aa_profile *profile, struct file *file,
448 u32 request)
449{
450 struct path_cond cond = {
451 .uid = file->f_path.dentry->d_inode->i_uid,
452 .mode = file->f_path.dentry->d_inode->i_mode
453 };
454
455 return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED,
456 request, &cond);
457}
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
new file mode 100644
index 00000000000..38ccaea0820
--- /dev/null
+++ b/security/apparmor/include/apparmor.h
@@ -0,0 +1,92 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor basic global and lib definitions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __APPARMOR_H
16#define __APPARMOR_H
17
18#include <linux/fs.h>
19
20#include "match.h"
21
22/* Control parameters settable through module/boot flags */
23extern enum audit_mode aa_g_audit;
24extern int aa_g_audit_header;
25extern int aa_g_debug;
26extern int aa_g_lock_policy;
27extern int aa_g_logsyscall;
28extern int aa_g_paranoid_load;
29extern unsigned int aa_g_path_max;
30
31/*
32 * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
33 * which is not related to profile accesses.
34 */
35
36#define AA_DEBUG(fmt, args...) \
37 do { \
38 if (aa_g_debug && printk_ratelimit()) \
39 printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
40 } while (0)
41
42#define AA_ERROR(fmt, args...) \
43 do { \
44 if (printk_ratelimit()) \
45 printk(KERN_ERR "AppArmor: " fmt, ##args); \
46 } while (0)
47
48/* Flag indicating whether initialization completed */
49extern int apparmor_initialized __initdata;
50
51/* fn's in lib */
52char *aa_split_fqname(char *args, char **ns_name);
53void aa_info_message(const char *str);
54void *kvmalloc(size_t size);
55void kvfree(void *buffer);
56
57
58/**
59 * aa_strneq - compare null terminated @str to a non null terminated substring
60 * @str: a null terminated string
61 * @sub: a substring, not necessarily null terminated
62 * @len: length of @sub to compare
63 *
64 * The @str string must be full consumed for this to be considered a match
65 */
66static inline bool aa_strneq(const char *str, const char *sub, int len)
67{
68 return !strncmp(str, sub, len) && !str[len];
69}
70
71/**
72 * aa_dfa_null_transition - step to next state after null character
73 * @dfa: the dfa to match against
74 * @start: the state of the dfa to start matching in
75 *
76 * aa_dfa_null_transition transitions to the next state after a null
77 * character which is not used in standard matching and is only
78 * used to separate pairs.
79 */
80static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
81 unsigned int start)
82{
83 /* the null transition only needs the string's null terminator byte */
84 return aa_dfa_match_len(dfa, start, "", 1);
85}
86
87static inline bool mediated_filesystem(struct inode *inode)
88{
89 return !(inode->i_sb->s_flags & MS_NOUSER);
90}
91
92#endif /* __APPARMOR_H */
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
new file mode 100644
index 00000000000..cb1e93a114d
--- /dev/null
+++ b/security/apparmor/include/apparmorfs.h
@@ -0,0 +1,20 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor filesystem definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_APPARMORFS_H
16#define __AA_APPARMORFS_H
17
18extern void __init aa_destroy_aafs(void);
19
20#endif /* __AA_APPARMORFS_H */
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
new file mode 100644
index 00000000000..1951786d32e
--- /dev/null
+++ b/security/apparmor/include/audit.h
@@ -0,0 +1,123 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor auditing function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_AUDIT_H
16#define __AA_AUDIT_H
17
18#include <linux/audit.h>
19#include <linux/fs.h>
20#include <linux/lsm_audit.h>
21#include <linux/sched.h>
22#include <linux/slab.h>
23
24#include "file.h"
25
26struct aa_profile;
27
28extern const char *audit_mode_names[];
29#define AUDIT_MAX_INDEX 5
30
31#define AUDIT_APPARMOR_AUTO 0 /* auto choose audit message type */
32
33enum audit_mode {
34 AUDIT_NORMAL, /* follow normal auditing of accesses */
35 AUDIT_QUIET_DENIED, /* quiet all denied access messages */
36 AUDIT_QUIET, /* quiet all messages */
37 AUDIT_NOQUIET, /* do not quiet audit messages */
38 AUDIT_ALL /* audit all accesses */
39};
40
41enum audit_type {
42 AUDIT_APPARMOR_AUDIT,
43 AUDIT_APPARMOR_ALLOWED,
44 AUDIT_APPARMOR_DENIED,
45 AUDIT_APPARMOR_HINT,
46 AUDIT_APPARMOR_STATUS,
47 AUDIT_APPARMOR_ERROR,
48 AUDIT_APPARMOR_KILL
49};
50
51extern const char *op_table[];
52enum aa_ops {
53 OP_NULL,
54
55 OP_SYSCTL,
56 OP_CAPABLE,
57
58 OP_UNLINK,
59 OP_MKDIR,
60 OP_RMDIR,
61 OP_MKNOD,
62 OP_TRUNC,
63 OP_LINK,
64 OP_SYMLINK,
65 OP_RENAME_SRC,
66 OP_RENAME_DEST,
67 OP_CHMOD,
68 OP_CHOWN,
69 OP_GETATTR,
70 OP_OPEN,
71
72 OP_FPERM,
73 OP_FLOCK,
74 OP_FMMAP,
75 OP_FMPROT,
76
77 OP_CREATE,
78 OP_POST_CREATE,
79 OP_BIND,
80 OP_CONNECT,
81 OP_LISTEN,
82 OP_ACCEPT,
83 OP_SENDMSG,
84 OP_RECVMSG,
85 OP_GETSOCKNAME,
86 OP_GETPEERNAME,
87 OP_GETSOCKOPT,
88 OP_SETSOCKOPT,
89 OP_SOCK_SHUTDOWN,
90
91 OP_PTRACE,
92
93 OP_EXEC,
94 OP_CHANGE_HAT,
95 OP_CHANGE_PROFILE,
96 OP_CHANGE_ONEXEC,
97
98 OP_SETPROCATTR,
99 OP_SETRLIMIT,
100
101 OP_PROF_REPL,
102 OP_PROF_LOAD,
103 OP_PROF_RM,
104};
105
106
107/* define a short hand for apparmor_audit_data portion of common_audit_data */
108#define aad apparmor_audit_data
109
110void aa_audit_msg(int type, struct common_audit_data *sa,
111 void (*cb) (struct audit_buffer *, void *));
112int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
113 struct common_audit_data *sa,
114 void (*cb) (struct audit_buffer *, void *));
115
116static inline int complain_error(int error)
117{
118 if (error == -EPERM || error == -EACCES)
119 return 0;
120 return error;
121}
122
123#endif /* __AA_AUDIT_H */
diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
new file mode 100644
index 00000000000..c24d2959ea0
--- /dev/null
+++ b/security/apparmor/include/capability.h
@@ -0,0 +1,45 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor capability mediation definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_CAPABILITY_H
16#define __AA_CAPABILITY_H
17
18#include <linux/sched.h>
19
20struct aa_profile;
21
22/* aa_caps - confinement data for capabilities
23 * @allowed: capabilities mask
24 * @audit: caps that are to be audited
25 * @quiet: caps that should not be audited
26 * @kill: caps that when requested will result in the task being killed
27 * @extended: caps that are subject finer grained mediation
28 */
29struct aa_caps {
30 kernel_cap_t allow;
31 kernel_cap_t audit;
32 kernel_cap_t quiet;
33 kernel_cap_t kill;
34 kernel_cap_t extended;
35};
36
37int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
38 int audit);
39
40static inline void aa_free_cap_rules(struct aa_caps *caps)
41{
42 /* NOP */
43}
44
45#endif /* __AA_CAPBILITY_H */
diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h
new file mode 100644
index 00000000000..a9cbee4d9e4
--- /dev/null
+++ b/security/apparmor/include/context.h
@@ -0,0 +1,154 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor contexts used to associate "labels" to objects.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_CONTEXT_H
16#define __AA_CONTEXT_H
17
18#include <linux/cred.h>
19#include <linux/slab.h>
20#include <linux/sched.h>
21
22#include "policy.h"
23
24/* struct aa_file_cxt - the AppArmor context the file was opened in
25 * @perms: the permission the file was opened with
26 *
27 * The file_cxt could currently be directly stored in file->f_security
28 * as the profile reference is now stored in the f_cred. However the
29 * cxt struct will expand in the future so we keep the struct.
30 */
31struct aa_file_cxt {
32 u16 allow;
33};
34
35/**
36 * aa_alloc_file_context - allocate file_cxt
37 * @gfp: gfp flags for allocation
38 *
39 * Returns: file_cxt or NULL on failure
40 */
41static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp)
42{
43 return kzalloc(sizeof(struct aa_file_cxt), gfp);
44}
45
46/**
47 * aa_free_file_context - free a file_cxt
48 * @cxt: file_cxt to free (MAYBE_NULL)
49 */
50static inline void aa_free_file_context(struct aa_file_cxt *cxt)
51{
52 if (cxt)
53 kzfree(cxt);
54}
55
56/**
57 * struct aa_task_cxt - primary label for confined tasks
58 * @profile: the current profile (NOT NULL)
59 * @exec: profile to transition to on next exec (MAYBE NULL)
60 * @previous: profile the task may return to (MAYBE NULL)
61 * @token: magic value the task must know for returning to @previous_profile
62 *
63 * Contains the task's current profile (which could change due to
64 * change_hat). Plus the hat_magic needed during change_hat.
65 *
66 * TODO: make so a task can be confined by a stack of contexts
67 */
68struct aa_task_cxt {
69 struct aa_profile *profile;
70 struct aa_profile *onexec;
71 struct aa_profile *previous;
72 u64 token;
73};
74
75struct aa_task_cxt *aa_alloc_task_context(gfp_t flags);
76void aa_free_task_context(struct aa_task_cxt *cxt);
77void aa_dup_task_context(struct aa_task_cxt *new,
78 const struct aa_task_cxt *old);
79int aa_replace_current_profile(struct aa_profile *profile);
80int aa_set_current_onexec(struct aa_profile *profile);
81int aa_set_current_hat(struct aa_profile *profile, u64 token);
82int aa_restore_previous_profile(u64 cookie);
83
84/**
85 * __aa_task_is_confined - determine if @task has any confinement
86 * @task: task to check confinement of (NOT NULL)
87 *
88 * If @task != current needs to be called in RCU safe critical section
89 */
90static inline bool __aa_task_is_confined(struct task_struct *task)
91{
92 struct aa_task_cxt *cxt = __task_cred(task)->security;
93
94 BUG_ON(!cxt || !cxt->profile);
95 if (unconfined(aa_newest_version(cxt->profile)))
96 return 0;
97
98 return 1;
99}
100
101/**
102 * aa_cred_profile - obtain cred's profiles
103 * @cred: cred to obtain profiles from (NOT NULL)
104 *
105 * Returns: confining profile
106 *
107 * does NOT increment reference count
108 */
109static inline struct aa_profile *aa_cred_profile(const struct cred *cred)
110{
111 struct aa_task_cxt *cxt = cred->security;
112 BUG_ON(!cxt || !cxt->profile);
113 return aa_newest_version(cxt->profile);
114}
115
116/**
117 * __aa_current_profile - find the current tasks confining profile
118 *
119 * Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
120 *
121 * This fn will not update the tasks cred to the most up to date version
122 * of the profile so it is safe to call when inside of locks.
123 */
124static inline struct aa_profile *__aa_current_profile(void)
125{
126 return aa_cred_profile(current_cred());
127}
128
129/**
130 * aa_current_profile - find the current tasks confining profile and do updates
131 *
132 * Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
133 *
134 * This fn will update the tasks cred structure if the profile has been
135 * replaced. Not safe to call inside locks
136 */
137static inline struct aa_profile *aa_current_profile(void)
138{
139 const struct aa_task_cxt *cxt = current_cred()->security;
140 struct aa_profile *profile;
141 BUG_ON(!cxt || !cxt->profile);
142
143 profile = aa_newest_version(cxt->profile);
144 /*
145 * Whether or not replacement succeeds, use newest profile so
146 * there is no need to update it after replacement.
147 */
148 if (unlikely((cxt->profile != profile)))
149 aa_replace_current_profile(profile);
150
151 return profile;
152}
153
154#endif /* __AA_CONTEXT_H */
diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
new file mode 100644
index 00000000000..de04464f0a3
--- /dev/null
+++ b/security/apparmor/include/domain.h
@@ -0,0 +1,36 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor security domain transition function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/binfmts.h>
16#include <linux/types.h>
17
18#ifndef __AA_DOMAIN_H
19#define __AA_DOMAIN_H
20
21struct aa_domain {
22 int size;
23 char **table;
24};
25
26int apparmor_bprm_set_creds(struct linux_binprm *bprm);
27int apparmor_bprm_secureexec(struct linux_binprm *bprm);
28void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
29void apparmor_bprm_committed_creds(struct linux_binprm *bprm);
30
31void aa_free_domain_entries(struct aa_domain *domain);
32int aa_change_hat(const char *hats[], int count, u64 token, bool permtest);
33int aa_change_profile(const char *ns_name, const char *name, bool onexec,
34 bool permtest);
35
36#endif /* __AA_DOMAIN_H */
diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
new file mode 100644
index 00000000000..be36feabb16
--- /dev/null
+++ b/security/apparmor/include/file.h
@@ -0,0 +1,217 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor file mediation function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_FILE_H
16#define __AA_FILE_H
17
18#include <linux/path.h>
19
20#include "domain.h"
21#include "match.h"
22
23struct aa_profile;
24
25/*
26 * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags
27 * for profile permissions
28 */
29#define AA_MAY_CREATE 0x0010
30#define AA_MAY_DELETE 0x0020
31#define AA_MAY_META_WRITE 0x0040
32#define AA_MAY_META_READ 0x0080
33
34#define AA_MAY_CHMOD 0x0100
35#define AA_MAY_CHOWN 0x0200
36#define AA_MAY_LOCK 0x0400
37#define AA_EXEC_MMAP 0x0800
38
39#define AA_MAY_LINK 0x1000
40#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */
41#define AA_MAY_ONEXEC 0x40000000 /* exec allows onexec */
42#define AA_MAY_CHANGE_PROFILE 0x80000000
43#define AA_MAY_CHANGEHAT 0x80000000 /* ctrl auditing only */
44
45#define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\
46 AA_MAY_CREATE | AA_MAY_DELETE | \
47 AA_MAY_META_READ | AA_MAY_META_WRITE | \
48 AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \
49 AA_EXEC_MMAP | AA_MAY_LINK)
50
51/*
52 * The xindex is broken into 3 parts
53 * - index - an index into either the exec name table or the variable table
54 * - exec type - which determines how the executable name and index are used
55 * - flags - which modify how the destination name is applied
56 */
57#define AA_X_INDEX_MASK 0x03ff
58
59#define AA_X_TYPE_MASK 0x0c00
60#define AA_X_TYPE_SHIFT 10
61#define AA_X_NONE 0x0000
62#define AA_X_NAME 0x0400 /* use executable name px */
63#define AA_X_TABLE 0x0800 /* use a specified name ->n# */
64
65#define AA_X_UNSAFE 0x1000
66#define AA_X_CHILD 0x2000 /* make >AA_X_NONE apply to children */
67#define AA_X_INHERIT 0x4000
68#define AA_X_UNCONFINED 0x8000
69
70/* AA_SECURE_X_NEEDED - is passed in the bprm->unsafe field */
71#define AA_SECURE_X_NEEDED 0x8000
72
73/* need to make conditional which ones are being set */
74struct path_cond {
75 uid_t uid;
76 umode_t mode;
77};
78
79/* struct file_perms - file permission
80 * @allow: mask of permissions that are allowed
81 * @audit: mask of permissions to force an audit message for
82 * @quiet: mask of permissions to quiet audit messages for
83 * @kill: mask of permissions that when matched will kill the task
84 * @xindex: exec transition index if @allow contains MAY_EXEC
85 *
86 * The @audit and @queit mask should be mutually exclusive.
87 */
88struct file_perms {
89 u32 allow;
90 u32 audit;
91 u32 quiet;
92 u32 kill;
93 u16 xindex;
94};
95
96extern struct file_perms nullperms;
97
98#define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill)
99
100/* FIXME: split perms from dfa and match this to description
101 * also add delegation info.
102 */
103static inline u16 dfa_map_xindex(u16 mask)
104{
105 u16 old_index = (mask >> 10) & 0xf;
106 u16 index = 0;
107
108 if (mask & 0x100)
109 index |= AA_X_UNSAFE;
110 if (mask & 0x200)
111 index |= AA_X_INHERIT;
112 if (mask & 0x80)
113 index |= AA_X_UNCONFINED;
114
115 if (old_index == 1) {
116 index |= AA_X_UNCONFINED;
117 } else if (old_index == 2) {
118 index |= AA_X_NAME;
119 } else if (old_index == 3) {
120 index |= AA_X_NAME | AA_X_CHILD;
121 } else {
122 index |= AA_X_TABLE;
123 index |= old_index - 4;
124 }
125
126 return index;
127}
128
129/*
130 * map old dfa inline permissions to new format
131 */
132#define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \
133 ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
134#define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f)
135#define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f)
136#define dfa_user_xindex(dfa, state) \
137 (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff))
138
139#define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \
140 0x7f) | \
141 ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
142#define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f)
143#define dfa_other_quiet(dfa, state) \
144 ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f)
145#define dfa_other_xindex(dfa, state) \
146 dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
147
148int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
149 gfp_t gfp, int op, u32 request, const char *name,
150 const char *target, uid_t ouid, const char *info, int error);
151
152/**
153 * struct aa_file_rules - components used for file rule permissions
154 * @dfa: dfa to match path names and conditionals against
155 * @perms: permission table indexed by the matched state accept entry of @dfa
156 * @trans: transition table for indexed by named x transitions
157 *
158 * File permission are determined by matching a path against @dfa and then
159 * then using the value of the accept entry for the matching state as
160 * an index into @perms. If a named exec transition is required it is
161 * looked up in the transition table.
162 */
163struct aa_file_rules {
164 unsigned int start;
165 struct aa_dfa *dfa;
166 /* struct perms perms; */
167 struct aa_domain trans;
168 /* TODO: add delegate table */
169};
170
171unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
172 const char *name, struct path_cond *cond,
173 struct file_perms *perms);
174
175int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
176 int flags, u32 request, struct path_cond *cond);
177
178int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
179 struct path *new_dir, struct dentry *new_dentry);
180
181int aa_file_perm(int op, struct aa_profile *profile, struct file *file,
182 u32 request);
183
184static inline void aa_free_file_rules(struct aa_file_rules *rules)
185{
186 aa_put_dfa(rules->dfa);
187 aa_free_domain_entries(&rules->trans);
188}
189
190#define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40))
191
192/* from namei.c */
193#define MAP_OPEN_FLAGS(x) ((((x) + 1) & O_ACCMODE) ? (x) + 1 : (x))
194
195/**
196 * aa_map_file_perms - map file flags to AppArmor permissions
197 * @file: open file to map flags to AppArmor permissions
198 *
199 * Returns: apparmor permission set for the file
200 */
201static inline u32 aa_map_file_to_perms(struct file *file)
202{
203 int flags = MAP_OPEN_FLAGS(file->f_flags);
204 u32 perms = ACC_FMODE(file->f_mode);
205
206 if ((flags & O_APPEND) && (perms & MAY_WRITE))
207 perms = (perms & ~MAY_WRITE) | MAY_APPEND;
208 /* trunc implies write permission */
209 if (flags & O_TRUNC)
210 perms |= MAY_WRITE;
211 if (flags & O_CREAT)
212 perms |= AA_MAY_CREATE;
213
214 return perms;
215}
216
217#endif /* __AA_FILE_H */
diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h
new file mode 100644
index 00000000000..aeda0fbc8b2
--- /dev/null
+++ b/security/apparmor/include/ipc.h
@@ -0,0 +1,28 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor ipc mediation function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_IPC_H
16#define __AA_IPC_H
17
18#include <linux/sched.h>
19
20struct aa_profile;
21
22int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
23 struct aa_profile *tracee, unsigned int mode);
24
25int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
26 unsigned int mode);
27
28#endif /* __AA_IPC_H */
diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
new file mode 100644
index 00000000000..734a6d35112
--- /dev/null
+++ b/security/apparmor/include/match.h
@@ -0,0 +1,132 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor policy dfa matching engine definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_MATCH_H
16#define __AA_MATCH_H
17
18#include <linux/workqueue.h>
19
20#define DFA_NOMATCH 0
21#define DFA_START 1
22
23#define DFA_VALID_PERM_MASK 0xffffffff
24#define DFA_VALID_PERM2_MASK 0xffffffff
25
26/**
27 * The format used for transition tables is based on the GNU flex table
28 * file format (--tables-file option; see Table File Format in the flex
29 * info pages and the flex sources for documentation). The magic number
30 * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
31 * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
32 * slightly differently (see the apparmor-parser package).
33 */
34
35#define YYTH_MAGIC 0x1B5E783D
36#define YYTH_DEF_RECURSE 0x1 /* DEF Table is recursive */
37
38struct table_set_header {
39 u32 th_magic; /* YYTH_MAGIC */
40 u32 th_hsize;
41 u32 th_ssize;
42 u16 th_flags;
43 char th_version[];
44};
45
46/* The YYTD_ID are one less than flex table mappings. The flex id
47 * has 1 subtracted at table load time, this allows us to directly use the
48 * ID's as indexes.
49 */
50#define YYTD_ID_ACCEPT 0
51#define YYTD_ID_BASE 1
52#define YYTD_ID_CHK 2
53#define YYTD_ID_DEF 3
54#define YYTD_ID_EC 4
55#define YYTD_ID_META 5
56#define YYTD_ID_ACCEPT2 6
57#define YYTD_ID_NXT 7
58#define YYTD_ID_TSIZE 8
59
60#define YYTD_DATA8 1
61#define YYTD_DATA16 2
62#define YYTD_DATA32 4
63#define YYTD_DATA64 8
64
65/* Each ACCEPT2 table gets 6 dedicated flags, YYTD_DATAX define the
66 * first flags
67 */
68#define ACCEPT1_FLAGS(X) ((X) & 0x3f)
69#define ACCEPT2_FLAGS(X) ACCEPT1_FLAGS((X) >> YYTD_ID_ACCEPT2)
70#define TO_ACCEPT1_FLAG(X) ACCEPT1_FLAGS(X)
71#define TO_ACCEPT2_FLAG(X) (ACCEPT1_FLAGS(X) << YYTD_ID_ACCEPT2)
72#define DFA_FLAG_VERIFY_STATES 0x1000
73
74struct table_header {
75 u16 td_id;
76 u16 td_flags;
77 u32 td_hilen;
78 u32 td_lolen;
79 char td_data[];
80};
81
82#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF]->td_data))
83#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE]->td_data))
84#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT]->td_data))
85#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK]->td_data))
86#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC]->td_data))
87#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT]->td_data))
88#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2]->td_data))
89
90struct aa_dfa {
91 struct kref count;
92 u16 flags;
93 struct table_header *tables[YYTD_ID_TSIZE];
94};
95
96#define byte_to_byte(X) (X)
97
98#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
99 do { \
100 typeof(LEN) __i; \
101 TYPE *__t = (TYPE *) TABLE; \
102 TYPE *__b = (TYPE *) BLOB; \
103 for (__i = 0; __i < LEN; __i++) { \
104 __t[__i] = NTOHX(__b[__i]); \
105 } \
106 } while (0)
107
108static inline size_t table_size(size_t len, size_t el_size)
109{
110 return ALIGN(sizeof(struct table_header) + len * el_size, 8);
111}
112
113struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
114unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
115 const char *str, int len);
116unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
117 const char *str);
118void aa_dfa_free_kref(struct kref *kref);
119
120/**
121 * aa_put_dfa - put a dfa refcount
122 * @dfa: dfa to put refcount (MAYBE NULL)
123 *
124 * Requires: if @dfa != NULL that a valid refcount be held
125 */
126static inline void aa_put_dfa(struct aa_dfa *dfa)
127{
128 if (dfa)
129 kref_put(&dfa->count, aa_dfa_free_kref);
130}
131
132#endif /* __AA_MATCH_H */
diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
new file mode 100644
index 00000000000..27b327a7fae
--- /dev/null
+++ b/security/apparmor/include/path.h
@@ -0,0 +1,31 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor basic path manipulation function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_PATH_H
16#define __AA_PATH_H
17
18
19enum path_flags {
20 PATH_IS_DIR = 0x1, /* path is a directory */
21 PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */
22 PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */
23 PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */
24
25 PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */
26 PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */
27};
28
29int aa_get_name(struct path *path, int flags, char **buffer, const char **name);
30
31#endif /* __AA_PATH_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
new file mode 100644
index 00000000000..aeda5cf5690
--- /dev/null
+++ b/security/apparmor/include/policy.h
@@ -0,0 +1,305 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor policy definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_POLICY_H
16#define __AA_POLICY_H
17
18#include <linux/capability.h>
19#include <linux/cred.h>
20#include <linux/kref.h>
21#include <linux/sched.h>
22#include <linux/slab.h>
23#include <linux/socket.h>
24
25#include "apparmor.h"
26#include "audit.h"
27#include "capability.h"
28#include "domain.h"
29#include "file.h"
30#include "resource.h"
31
32extern const char *profile_mode_names[];
33#define APPARMOR_NAMES_MAX_INDEX 3
34
35#define COMPLAIN_MODE(_profile) \
36 ((aa_g_profile_mode == APPARMOR_COMPLAIN) || \
37 ((_profile)->mode == APPARMOR_COMPLAIN))
38
39#define KILL_MODE(_profile) \
40 ((aa_g_profile_mode == APPARMOR_KILL) || \
41 ((_profile)->mode == APPARMOR_KILL))
42
43#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT)
44
45/*
46 * FIXME: currently need a clean way to replace and remove profiles as a
47 * set. It should be done at the namespace level.
48 * Either, with a set of profiles loaded at the namespace level or via
49 * a mark and remove marked interface.
50 */
51enum profile_mode {
52 APPARMOR_ENFORCE, /* enforce access rules */
53 APPARMOR_COMPLAIN, /* allow and log access violations */
54 APPARMOR_KILL, /* kill task on access violation */
55};
56
57enum profile_flags {
58 PFLAG_HAT = 1, /* profile is a hat */
59 PFLAG_UNCONFINED = 2, /* profile is an unconfined profile */
60 PFLAG_NULL = 4, /* profile is null learning profile */
61 PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */
62 PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */
63 PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */
64 PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */
65 PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */
66
67 /* These flags must correspond with PATH_flags */
68 PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */
69};
70
71struct aa_profile;
72
73/* struct aa_policy - common part of both namespaces and profiles
74 * @name: name of the object
75 * @hname - The hierarchical name
76 * @count: reference count of the obj
77 * @list: list policy object is on
78 * @profiles: head of the profiles list contained in the object
79 */
80struct aa_policy {
81 char *name;
82 char *hname;
83 struct kref count;
84 struct list_head list;
85 struct list_head profiles;
86};
87
88/* struct aa_ns_acct - accounting of profiles in namespace
89 * @max_size: maximum space allowed for all profiles in namespace
90 * @max_count: maximum number of profiles that can be in this namespace
91 * @size: current size of profiles
92 * @count: current count of profiles (includes null profiles)
93 */
94struct aa_ns_acct {
95 int max_size;
96 int max_count;
97 int size;
98 int count;
99};
100
101/* struct aa_namespace - namespace for a set of profiles
102 * @base: common policy
103 * @parent: parent of namespace
104 * @lock: lock for modifying the object
105 * @acct: accounting for the namespace
106 * @unconfined: special unconfined profile for the namespace
107 * @sub_ns: list of namespaces under the current namespace.
108 *
109 * An aa_namespace defines the set profiles that are searched to determine
110 * which profile to attach to a task. Profiles can not be shared between
111 * aa_namespaces and profile names within a namespace are guaranteed to be
112 * unique. When profiles in separate namespaces have the same name they
113 * are NOT considered to be equivalent.
114 *
115 * Namespaces are hierarchical and only namespaces and profiles below the
116 * current namespace are visible.
117 *
118 * Namespace names must be unique and can not contain the characters :/\0
119 *
120 * FIXME TODO: add vserver support of namespaces (can it all be done in
121 * userspace?)
122 */
123struct aa_namespace {
124 struct aa_policy base;
125 struct aa_namespace *parent;
126 rwlock_t lock;
127 struct aa_ns_acct acct;
128 struct aa_profile *unconfined;
129 struct list_head sub_ns;
130};
131
132/* struct aa_profile - basic confinement data
133 * @base - base components of the profile (name, refcount, lists, lock ...)
134 * @parent: parent of profile
135 * @ns: namespace the profile is in
136 * @replacedby: is set to the profile that replaced this profile
137 * @rename: optional profile name that this profile renamed
138 * @xmatch: optional extended matching for unconfined executables names
139 * @xmatch_len: xmatch prefix len, used to determine xmatch priority
140 * @sid: the unique security id number of this profile
141 * @audit: the auditing mode of the profile
142 * @mode: the enforcement mode of the profile
143 * @flags: flags controlling profile behavior
144 * @path_flags: flags controlling path generation behavior
145 * @size: the memory consumed by this profiles rules
146 * @file: The set of rules governing basic file access and domain transitions
147 * @caps: capabilities for the profile
148 * @rlimits: rlimits for the profile
149 *
150 * The AppArmor profile contains the basic confinement data. Each profile
151 * has a name, and exists in a namespace. The @name and @exec_match are
152 * used to determine profile attachment against unconfined tasks. All other
153 * attachments are determined by profile X transition rules.
154 *
155 * The @replacedby field is write protected by the profile lock. Reads
156 * are assumed to be atomic, and are done without locking.
157 *
158 * Profiles have a hierarchy where hats and children profiles keep
159 * a reference to their parent.
160 *
161 * Profile names can not begin with a : and can not contain the \0
162 * character. If a profile name begins with / it will be considered when
163 * determining profile attachment on "unconfined" tasks.
164 */
165struct aa_profile {
166 struct aa_policy base;
167 struct aa_profile *parent;
168
169 struct aa_namespace *ns;
170 struct aa_profile *replacedby;
171 const char *rename;
172
173 struct aa_dfa *xmatch;
174 int xmatch_len;
175 u32 sid;
176 enum audit_mode audit;
177 enum profile_mode mode;
178 u32 flags;
179 u32 path_flags;
180 int size;
181
182 struct aa_file_rules file;
183 struct aa_caps caps;
184 struct aa_rlimit rlimits;
185};
186
187extern struct aa_namespace *root_ns;
188extern enum profile_mode aa_g_profile_mode;
189
190void aa_add_profile(struct aa_policy *common, struct aa_profile *profile);
191
192bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view);
193const char *aa_ns_name(struct aa_namespace *parent, struct aa_namespace *child);
194int aa_alloc_root_ns(void);
195void aa_free_root_ns(void);
196void aa_free_namespace_kref(struct kref *kref);
197
198struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
199 const char *name);
200
201static inline struct aa_policy *aa_get_common(struct aa_policy *c)
202{
203 if (c)
204 kref_get(&c->count);
205
206 return c;
207}
208
209/**
210 * aa_get_namespace - increment references count on @ns
211 * @ns: namespace to increment reference count of (MAYBE NULL)
212 *
213 * Returns: pointer to @ns, if @ns is NULL returns NULL
214 * Requires: @ns must be held with valid refcount when called
215 */
216static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
217{
218 if (ns)
219 kref_get(&(ns->base.count));
220
221 return ns;
222}
223
224/**
225 * aa_put_namespace - decrement refcount on @ns
226 * @ns: namespace to put reference of
227 *
228 * Decrement reference count of @ns and if no longer in use free it
229 */
230static inline void aa_put_namespace(struct aa_namespace *ns)
231{
232 if (ns)
233 kref_put(&ns->base.count, aa_free_namespace_kref);
234}
235
236struct aa_profile *aa_alloc_profile(const char *name);
237struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat);
238void aa_free_profile_kref(struct kref *kref);
239struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
240struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *name);
241struct aa_profile *aa_match_profile(struct aa_namespace *ns, const char *name);
242
243ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace);
244ssize_t aa_remove_profiles(char *name, size_t size);
245
246#define PROF_ADD 1
247#define PROF_REPLACE 0
248
249#define unconfined(X) ((X)->flags & PFLAG_UNCONFINED)
250
251/**
252 * aa_newest_version - find the newest version of @profile
253 * @profile: the profile to check for newer versions of (NOT NULL)
254 *
255 * Returns: newest version of @profile, if @profile is the newest version
256 * return @profile.
257 *
258 * NOTE: the profile returned is not refcounted, The refcount on @profile
259 * must be held until the caller decides what to do with the returned newest
260 * version.
261 */
262static inline struct aa_profile *aa_newest_version(struct aa_profile *profile)
263{
264 while (profile->replacedby)
265 profile = profile->replacedby;
266
267 return profile;
268}
269
270/**
271 * aa_get_profile - increment refcount on profile @p
272 * @p: profile (MAYBE NULL)
273 *
274 * Returns: pointer to @p if @p is NULL will return NULL
275 * Requires: @p must be held with valid refcount when called
276 */
277static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
278{
279 if (p)
280 kref_get(&(p->base.count));
281
282 return p;
283}
284
285/**
286 * aa_put_profile - decrement refcount on profile @p
287 * @p: profile (MAYBE NULL)
288 */
289static inline void aa_put_profile(struct aa_profile *p)
290{
291 if (p)
292 kref_put(&p->base.count, aa_free_profile_kref);
293}
294
295static inline int AUDIT_MODE(struct aa_profile *profile)
296{
297 if (aa_g_audit != AUDIT_NORMAL)
298 return aa_g_audit;
299
300 return profile->audit;
301}
302
303bool aa_may_manage_policy(int op);
304
305#endif /* __AA_POLICY_H */
diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
new file mode 100644
index 00000000000..a2dcccac45a
--- /dev/null
+++ b/security/apparmor/include/policy_unpack.h
@@ -0,0 +1,20 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor policy loading interface function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __POLICY_INTERFACE_H
16#define __POLICY_INTERFACE_H
17
18struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns);
19
20#endif /* __POLICY_INTERFACE_H */
diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h
new file mode 100644
index 00000000000..544aa6b766a
--- /dev/null
+++ b/security/apparmor/include/procattr.h
@@ -0,0 +1,26 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor /proc/<pid>/attr/ interface function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_PROCATTR_H
16#define __AA_PROCATTR_H
17
18#define AA_DO_TEST 1
19#define AA_ONEXEC 1
20
21int aa_getprocattr(struct aa_profile *profile, char **string);
22int aa_setprocattr_changehat(char *args, size_t size, int test);
23int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test);
24int aa_setprocattr_permipc(char *fqname);
25
26#endif /* __AA_PROCATTR_H */
diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
new file mode 100644
index 00000000000..3c88be94649
--- /dev/null
+++ b/security/apparmor/include/resource.h
@@ -0,0 +1,46 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor resource limits function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_RESOURCE_H
16#define __AA_RESOURCE_H
17
18#include <linux/resource.h>
19#include <linux/sched.h>
20
21struct aa_profile;
22
23/* struct aa_rlimit - rlimit settings for the profile
24 * @mask: which hard limits to set
25 * @limits: rlimit values that override task limits
26 *
27 * AppArmor rlimits are used to set confined task rlimits. Only the
28 * limits specified in @mask will be controlled by apparmor.
29 */
30struct aa_rlimit {
31 unsigned int mask;
32 struct rlimit limits[RLIM_NLIMITS];
33};
34
35int aa_map_resource(int resource);
36int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
37 struct rlimit *new_rlim);
38
39void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
40
41static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
42{
43 /* NOP */
44}
45
46#endif /* __AA_RESOURCE_H */
diff --git a/security/apparmor/include/sid.h b/security/apparmor/include/sid.h
new file mode 100644
index 00000000000..020db35c301
--- /dev/null
+++ b/security/apparmor/include/sid.h
@@ -0,0 +1,24 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor security identifier (sid) definitions
5 *
6 * Copyright 2009-2010 Canonical Ltd.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2 of the
11 * License.
12 */
13
14#ifndef __AA_SID_H
15#define __AA_SID_H
16
17#include <linux/types.h>
18
19struct aa_profile;
20
21u32 aa_alloc_sid(void);
22void aa_free_sid(u32 sid);
23
24#endif /* __AA_SID_H */
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
new file mode 100644
index 00000000000..649fad88869
--- /dev/null
+++ b/security/apparmor/ipc.c
@@ -0,0 +1,114 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor ipc mediation
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/gfp.h>
16#include <linux/ptrace.h>
17
18#include "include/audit.h"
19#include "include/capability.h"
20#include "include/context.h"
21#include "include/policy.h"
22
23/* call back to audit ptrace fields */
24static void audit_cb(struct audit_buffer *ab, void *va)
25{
26 struct common_audit_data *sa = va;
27 audit_log_format(ab, " target=");
28 audit_log_untrustedstring(ab, sa->aad.target);
29}
30
31/**
32 * aa_audit_ptrace - do auditing for ptrace
33 * @profile: profile being enforced (NOT NULL)
34 * @target: profile being traced (NOT NULL)
35 * @error: error condition
36 *
37 * Returns: %0 or error code
38 */
39static int aa_audit_ptrace(struct aa_profile *profile,
40 struct aa_profile *target, int error)
41{
42 struct common_audit_data sa;
43 COMMON_AUDIT_DATA_INIT(&sa, NONE);
44 sa.aad.op = OP_PTRACE;
45 sa.aad.target = target;
46 sa.aad.error = error;
47
48 return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
49 audit_cb);
50}
51
52/**
53 * aa_may_ptrace - test if tracer task can trace the tracee
54 * @tracer_task: task who will do the tracing (NOT NULL)
55 * @tracer: profile of the task doing the tracing (NOT NULL)
56 * @tracee: task to be traced
57 * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH
58 *
59 * Returns: %0 else error code if permission denied or error
60 */
61int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
62 struct aa_profile *tracee, unsigned int mode)
63{
64 /* TODO: currently only based on capability, not extended ptrace
65 * rules,
66 * Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
67 */
68
69 if (unconfined(tracer) || tracer == tracee)
70 return 0;
71 /* log this capability request */
72 return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1);
73}
74
75/**
76 * aa_ptrace - do ptrace permission check and auditing
77 * @tracer: task doing the tracing (NOT NULL)
78 * @tracee: task being traced (NOT NULL)
79 * @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH
80 *
81 * Returns: %0 else error code if permission denied or error
82 */
83int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
84 unsigned int mode)
85{
86 /*
87 * tracer can ptrace tracee when
88 * - tracer is unconfined ||
89 * - tracer is in complain mode
90 * - tracer has rules allowing it to trace tracee currently this is:
91 * - confined by the same profile ||
92 * - tracer profile has CAP_SYS_PTRACE
93 */
94
95 struct aa_profile *tracer_p;
96 /* cred released below */
97 const struct cred *cred = get_task_cred(tracer);
98 int error = 0;
99 tracer_p = aa_cred_profile(cred);
100
101 if (!unconfined(tracer_p)) {
102 /* lcred released below */
103 const struct cred *lcred = get_task_cred(tracee);
104 struct aa_profile *tracee_p = aa_cred_profile(lcred);
105
106 error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode);
107 error = aa_audit_ptrace(tracer_p, tracee_p, error);
108
109 put_cred(lcred);
110 }
111 put_cred(cred);
112
113 return error;
114}
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
new file mode 100644
index 00000000000..6e85cdb4303
--- /dev/null
+++ b/security/apparmor/lib.c
@@ -0,0 +1,133 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains basic common functions used in AppArmor
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/slab.h>
16#include <linux/string.h>
17#include <linux/vmalloc.h>
18
19#include "include/audit.h"
20
21
22/**
23 * aa_split_fqname - split a fqname into a profile and namespace name
24 * @fqname: a full qualified name in namespace profile format (NOT NULL)
25 * @ns_name: pointer to portion of the string containing the ns name (NOT NULL)
26 *
27 * Returns: profile name or NULL if one is not specified
28 *
29 * Split a namespace name from a profile name (see policy.c for naming
30 * description). If a portion of the name is missing it returns NULL for
31 * that portion.
32 *
33 * NOTE: may modify the @fqname string. The pointers returned point
34 * into the @fqname string.
35 */
36char *aa_split_fqname(char *fqname, char **ns_name)
37{
38 char *name = strim(fqname);
39
40 *ns_name = NULL;
41 if (name[0] == ':') {
42 char *split = strchr(&name[1], ':');
43 if (split) {
44 /* overwrite ':' with \0 */
45 *split = 0;
46 name = skip_spaces(split + 1);
47 } else
48 /* a ns name without a following profile is allowed */
49 name = NULL;
50 *ns_name = &name[1];
51 }
52 if (name && *name == 0)
53 name = NULL;
54
55 return name;
56}
57
58/**
59 * aa_info_message - log a none profile related status message
60 * @str: message to log
61 */
62void aa_info_message(const char *str)
63{
64 if (audit_enabled) {
65 struct common_audit_data sa;
66 COMMON_AUDIT_DATA_INIT(&sa, NONE);
67 sa.aad.info = str;
68 aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
69 }
70 printk(KERN_INFO "AppArmor: %s\n", str);
71}
72
73/**
74 * kvmalloc - do allocation preferring kmalloc but falling back to vmalloc
75 * @size: size of allocation
76 *
77 * Return: allocated buffer or NULL if failed
78 *
79 * It is possible that policy being loaded from the user is larger than
80 * what can be allocated by kmalloc, in those cases fall back to vmalloc.
81 */
82void *kvmalloc(size_t size)
83{
84 void *buffer = NULL;
85
86 if (size == 0)
87 return NULL;
88
89 /* do not attempt kmalloc if we need more than 16 pages at once */
90 if (size <= (16*PAGE_SIZE))
91 buffer = kmalloc(size, GFP_NOIO | __GFP_NOWARN);
92 if (!buffer) {
93 /* see kvfree for why size must be at least work_struct size
94 * when allocated via vmalloc
95 */
96 if (size < sizeof(struct work_struct))
97 size = sizeof(struct work_struct);
98 buffer = vmalloc(size);
99 }
100 return buffer;
101}
102
103/**
104 * do_vfree - workqueue routine for freeing vmalloced memory
105 * @work: data to be freed
106 *
107 * The work_struct is overlaid to the data being freed, as at the point
108 * the work is scheduled the data is no longer valid, be its freeing
109 * needs to be delayed until safe.
110 */
111static void do_vfree(struct work_struct *work)
112{
113 vfree(work);
114}
115
116/**
117 * kvfree - free an allocation do by kvmalloc
118 * @buffer: buffer to free (MAYBE_NULL)
119 *
120 * Free a buffer allocated by kvmalloc
121 */
122void kvfree(void *buffer)
123{
124 if (is_vmalloc_addr(buffer)) {
125 /* Data is no longer valid so just use the allocated space
126 * as the work_struct
127 */
128 struct work_struct *work = (struct work_struct *) buffer;
129 INIT_WORK(work, do_vfree);
130 schedule_work(work);
131 } else
132 kfree(buffer);
133}
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
new file mode 100644
index 00000000000..8db33a8b50c
--- /dev/null
+++ b/security/apparmor/lsm.c
@@ -0,0 +1,938 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor LSM hooks.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/security.h>
16#include <linux/moduleparam.h>
17#include <linux/mm.h>
18#include <linux/mman.h>
19#include <linux/mount.h>
20#include <linux/namei.h>
21#include <linux/ptrace.h>
22#include <linux/ctype.h>
23#include <linux/sysctl.h>
24#include <linux/audit.h>
25#include <net/sock.h>
26
27#include "include/apparmor.h"
28#include "include/apparmorfs.h"
29#include "include/audit.h"
30#include "include/capability.h"
31#include "include/context.h"
32#include "include/file.h"
33#include "include/ipc.h"
34#include "include/path.h"
35#include "include/policy.h"
36#include "include/procattr.h"
37
38/* Flag indicating whether initialization completed */
39int apparmor_initialized __initdata;
40
41/*
42 * LSM hook functions
43 */
44
45/*
46 * free the associated aa_task_cxt and put its profiles
47 */
48static void apparmor_cred_free(struct cred *cred)
49{
50 aa_free_task_context(cred->security);
51 cred->security = NULL;
52}
53
54/*
55 * allocate the apparmor part of blank credentials
56 */
57static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp)
58{
59 /* freed by apparmor_cred_free */
60 struct aa_task_cxt *cxt = aa_alloc_task_context(gfp);
61 if (!cxt)
62 return -ENOMEM;
63
64 cred->security = cxt;
65 return 0;
66}
67
68/*
69 * prepare new aa_task_cxt for modification by prepare_cred block
70 */
71static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
72 gfp_t gfp)
73{
74 /* freed by apparmor_cred_free */
75 struct aa_task_cxt *cxt = aa_alloc_task_context(gfp);
76 if (!cxt)
77 return -ENOMEM;
78
79 aa_dup_task_context(cxt, old->security);
80 new->security = cxt;
81 return 0;
82}
83
84/*
85 * transfer the apparmor data to a blank set of creds
86 */
87static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
88{
89 const struct aa_task_cxt *old_cxt = old->security;
90 struct aa_task_cxt *new_cxt = new->security;
91
92 aa_dup_task_context(new_cxt, old_cxt);
93}
94
95static int apparmor_ptrace_access_check(struct task_struct *child,
96 unsigned int mode)
97{
98 int error = cap_ptrace_access_check(child, mode);
99 if (error)
100 return error;
101
102 return aa_ptrace(current, child, mode);
103}
104
105static int apparmor_ptrace_traceme(struct task_struct *parent)
106{
107 int error = cap_ptrace_traceme(parent);
108 if (error)
109 return error;
110
111 return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
112}
113
114/* Derived from security/commoncap.c:cap_capget */
115static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
116 kernel_cap_t *inheritable, kernel_cap_t *permitted)
117{
118 struct aa_profile *profile;
119 const struct cred *cred;
120
121 rcu_read_lock();
122 cred = __task_cred(target);
123 profile = aa_cred_profile(cred);
124
125 *effective = cred->cap_effective;
126 *inheritable = cred->cap_inheritable;
127 *permitted = cred->cap_permitted;
128
129 if (!unconfined(profile)) {
130 *effective = cap_intersect(*effective, profile->caps.allow);
131 *permitted = cap_intersect(*permitted, profile->caps.allow);
132 }
133 rcu_read_unlock();
134
135 return 0;
136}
137
138static int apparmor_capable(struct task_struct *task, const struct cred *cred,
139 int cap, int audit)
140{
141 struct aa_profile *profile;
142 /* cap_capable returns 0 on success, else -EPERM */
143 int error = cap_capable(task, cred, cap, audit);
144 if (!error) {
145 profile = aa_cred_profile(cred);
146 if (!unconfined(profile))
147 error = aa_capable(task, profile, cap, audit);
148 }
149 return error;
150}
151
152/**
153 * common_perm - basic common permission check wrapper fn for paths
154 * @op: operation being checked
155 * @path: path to check permission of (NOT NULL)
156 * @mask: requested permissions mask
157 * @cond: conditional info for the permission request (NOT NULL)
158 *
159 * Returns: %0 else error code if error or permission denied
160 */
161static int common_perm(int op, struct path *path, u32 mask,
162 struct path_cond *cond)
163{
164 struct aa_profile *profile;
165 int error = 0;
166
167 profile = __aa_current_profile();
168 if (!unconfined(profile))
169 error = aa_path_perm(op, profile, path, 0, mask, cond);
170
171 return error;
172}
173
174/**
175 * common_perm_dir_dentry - common permission wrapper when path is dir, dentry
176 * @op: operation being checked
177 * @dir: directory of the dentry (NOT NULL)
178 * @dentry: dentry to check (NOT NULL)
179 * @mask: requested permissions mask
180 * @cond: conditional info for the permission request (NOT NULL)
181 *
182 * Returns: %0 else error code if error or permission denied
183 */
184static int common_perm_dir_dentry(int op, struct path *dir,
185 struct dentry *dentry, u32 mask,
186 struct path_cond *cond)
187{
188 struct path path = { dir->mnt, dentry };
189
190 return common_perm(op, &path, mask, cond);
191}
192
193/**
194 * common_perm_mnt_dentry - common permission wrapper when mnt, dentry
195 * @op: operation being checked
196 * @mnt: mount point of dentry (NOT NULL)
197 * @dentry: dentry to check (NOT NULL)
198 * @mask: requested permissions mask
199 *
200 * Returns: %0 else error code if error or permission denied
201 */
202static int common_perm_mnt_dentry(int op, struct vfsmount *mnt,
203 struct dentry *dentry, u32 mask)
204{
205 struct path path = { mnt, dentry };
206 struct path_cond cond = { dentry->d_inode->i_uid,
207 dentry->d_inode->i_mode
208 };
209
210 return common_perm(op, &path, mask, &cond);
211}
212
213/**
214 * common_perm_rm - common permission wrapper for operations doing rm
215 * @op: operation being checked
216 * @dir: directory that the dentry is in (NOT NULL)
217 * @dentry: dentry being rm'd (NOT NULL)
218 * @mask: requested permission mask
219 *
220 * Returns: %0 else error code if error or permission denied
221 */
222static int common_perm_rm(int op, struct path *dir,
223 struct dentry *dentry, u32 mask)
224{
225 struct inode *inode = dentry->d_inode;
226 struct path_cond cond = { };
227
228 if (!inode || !dir->mnt || !mediated_filesystem(inode))
229 return 0;
230
231 cond.uid = inode->i_uid;
232 cond.mode = inode->i_mode;
233
234 return common_perm_dir_dentry(op, dir, dentry, mask, &cond);
235}
236
237/**
238 * common_perm_create - common permission wrapper for operations doing create
239 * @op: operation being checked
240 * @dir: directory that dentry will be created in (NOT NULL)
241 * @dentry: dentry to create (NOT NULL)
242 * @mask: request permission mask
243 * @mode: created file mode
244 *
245 * Returns: %0 else error code if error or permission denied
246 */
247static int common_perm_create(int op, struct path *dir, struct dentry *dentry,
248 u32 mask, umode_t mode)
249{
250 struct path_cond cond = { current_fsuid(), mode };
251
252 if (!dir->mnt || !mediated_filesystem(dir->dentry->d_inode))
253 return 0;
254
255 return common_perm_dir_dentry(op, dir, dentry, mask, &cond);
256}
257
258static int apparmor_path_unlink(struct path *dir, struct dentry *dentry)
259{
260 return common_perm_rm(OP_UNLINK, dir, dentry, AA_MAY_DELETE);
261}
262
263static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry,
264 int mode)
265{
266 return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE,
267 S_IFDIR);
268}
269
270static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry)
271{
272 return common_perm_rm(OP_RMDIR, dir, dentry, AA_MAY_DELETE);
273}
274
275static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
276 int mode, unsigned int dev)
277{
278 return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode);
279}
280
281static int apparmor_path_truncate(struct path *path)
282{
283 struct path_cond cond = { path->dentry->d_inode->i_uid,
284 path->dentry->d_inode->i_mode
285 };
286
287 if (!path->mnt || !mediated_filesystem(path->dentry->d_inode))
288 return 0;
289
290 return common_perm(OP_TRUNC, path, MAY_WRITE | AA_MAY_META_WRITE,
291 &cond);
292}
293
294static int apparmor_path_symlink(struct path *dir, struct dentry *dentry,
295 const char *old_name)
296{
297 return common_perm_create(OP_SYMLINK, dir, dentry, AA_MAY_CREATE,
298 S_IFLNK);
299}
300
301static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir,
302 struct dentry *new_dentry)
303{
304 struct aa_profile *profile;
305 int error = 0;
306
307 if (!mediated_filesystem(old_dentry->d_inode))
308 return 0;
309
310 profile = aa_current_profile();
311 if (!unconfined(profile))
312 error = aa_path_link(profile, old_dentry, new_dir, new_dentry);
313 return error;
314}
315
316static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
317 struct path *new_dir, struct dentry *new_dentry)
318{
319 struct aa_profile *profile;
320 int error = 0;
321
322 if (!mediated_filesystem(old_dentry->d_inode))
323 return 0;
324
325 profile = aa_current_profile();
326 if (!unconfined(profile)) {
327 struct path old_path = { old_dir->mnt, old_dentry };
328 struct path new_path = { new_dir->mnt, new_dentry };
329 struct path_cond cond = { old_dentry->d_inode->i_uid,
330 old_dentry->d_inode->i_mode
331 };
332
333 error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0,
334 MAY_READ | AA_MAY_META_READ | MAY_WRITE |
335 AA_MAY_META_WRITE | AA_MAY_DELETE,
336 &cond);
337 if (!error)
338 error = aa_path_perm(OP_RENAME_DEST, profile, &new_path,
339 0, MAY_WRITE | AA_MAY_META_WRITE |
340 AA_MAY_CREATE, &cond);
341
342 }
343 return error;
344}
345
346static int apparmor_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
347 mode_t mode)
348{
349 if (!mediated_filesystem(dentry->d_inode))
350 return 0;
351
352 return common_perm_mnt_dentry(OP_CHMOD, mnt, dentry, AA_MAY_CHMOD);
353}
354
355static int apparmor_path_chown(struct path *path, uid_t uid, gid_t gid)
356{
357 struct path_cond cond = { path->dentry->d_inode->i_uid,
358 path->dentry->d_inode->i_mode
359 };
360
361 if (!mediated_filesystem(path->dentry->d_inode))
362 return 0;
363
364 return common_perm(OP_CHOWN, path, AA_MAY_CHOWN, &cond);
365}
366
367static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
368{
369 if (!mediated_filesystem(dentry->d_inode))
370 return 0;
371
372 return common_perm_mnt_dentry(OP_GETATTR, mnt, dentry,
373 AA_MAY_META_READ);
374}
375
376static int apparmor_dentry_open(struct file *file, const struct cred *cred)
377{
378 struct aa_file_cxt *fcxt = file->f_security;
379 struct aa_profile *profile;
380 int error = 0;
381
382 if (!mediated_filesystem(file->f_path.dentry->d_inode))
383 return 0;
384
385 /* If in exec, permission is handled by bprm hooks.
386 * Cache permissions granted by the previous exec check, with
387 * implicit read and executable mmap which are required to
388 * actually execute the image.
389 */
390 if (current->in_execve) {
391 fcxt->allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP;
392 return 0;
393 }
394
395 profile = aa_cred_profile(cred);
396 if (!unconfined(profile)) {
397 struct inode *inode = file->f_path.dentry->d_inode;
398 struct path_cond cond = { inode->i_uid, inode->i_mode };
399
400 error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0,
401 aa_map_file_to_perms(file), &cond);
402 /* todo cache full allowed permissions set and state */
403 fcxt->allow = aa_map_file_to_perms(file);
404 }
405
406 return error;
407}
408
409static int apparmor_file_alloc_security(struct file *file)
410{
411 /* freed by apparmor_file_free_security */
412 file->f_security = aa_alloc_file_context(GFP_KERNEL);
413 if (!file->f_security)
414 return -ENOMEM;
415 return 0;
416
417}
418
419static void apparmor_file_free_security(struct file *file)
420{
421 struct aa_file_cxt *cxt = file->f_security;
422
423 aa_free_file_context(cxt);
424}
425
426static int common_file_perm(int op, struct file *file, u32 mask)
427{
428 struct aa_file_cxt *fcxt = file->f_security;
429 struct aa_profile *profile, *fprofile = aa_cred_profile(file->f_cred);
430 int error = 0;
431
432 BUG_ON(!fprofile);
433
434 if (!file->f_path.mnt ||
435 !mediated_filesystem(file->f_path.dentry->d_inode))
436 return 0;
437
438 profile = __aa_current_profile();
439
440 /* revalidate access, if task is unconfined, or the cached cred
441 * doesn't match or if the request is for more permissions than
442 * was granted.
443 *
444 * Note: the test for !unconfined(fprofile) is to handle file
445 * delegation from unconfined tasks
446 */
447 if (!unconfined(profile) && !unconfined(fprofile) &&
448 ((fprofile != profile) || (mask & ~fcxt->allow)))
449 error = aa_file_perm(op, profile, file, mask);
450
451 return error;
452}
453
454static int apparmor_file_permission(struct file *file, int mask)
455{
456 return common_file_perm(OP_FPERM, file, mask);
457}
458
459static int apparmor_file_lock(struct file *file, unsigned int cmd)
460{
461 u32 mask = AA_MAY_LOCK;
462
463 if (cmd == F_WRLCK)
464 mask |= MAY_WRITE;
465
466 return common_file_perm(OP_FLOCK, file, mask);
467}
468
469static int common_mmap(int op, struct file *file, unsigned long prot,
470 unsigned long flags)
471{
472 struct dentry *dentry;
473 int mask = 0;
474
475 if (!file || !file->f_security)
476 return 0;
477
478 if (prot & PROT_READ)
479 mask |= MAY_READ;
480 /*
481 * Private mappings don't require write perms since they don't
482 * write back to the files
483 */
484 if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
485 mask |= MAY_WRITE;
486 if (prot & PROT_EXEC)
487 mask |= AA_EXEC_MMAP;
488
489 dentry = file->f_path.dentry;
490 return common_file_perm(op, file, mask);
491}
492
493static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
494 unsigned long prot, unsigned long flags,
495 unsigned long addr, unsigned long addr_only)
496{
497 int rc = 0;
498
499 /* do DAC check */
500 rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
501 if (rc || addr_only)
502 return rc;
503
504 return common_mmap(OP_FMMAP, file, prot, flags);
505}
506
507static int apparmor_file_mprotect(struct vm_area_struct *vma,
508 unsigned long reqprot, unsigned long prot)
509{
510 return common_mmap(OP_FMPROT, vma->vm_file, prot,
511 !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
512}
513
514static int apparmor_getprocattr(struct task_struct *task, char *name,
515 char **value)
516{
517 int error = -ENOENT;
518 struct aa_profile *profile;
519 /* released below */
520 const struct cred *cred = get_task_cred(task);
521 struct aa_task_cxt *cxt = cred->security;
522 profile = aa_cred_profile(cred);
523
524 if (strcmp(name, "current") == 0)
525 error = aa_getprocattr(aa_newest_version(cxt->profile),
526 value);
527 else if (strcmp(name, "prev") == 0 && cxt->previous)
528 error = aa_getprocattr(aa_newest_version(cxt->previous),
529 value);
530 else if (strcmp(name, "exec") == 0 && cxt->onexec)
531 error = aa_getprocattr(aa_newest_version(cxt->onexec),
532 value);
533 else
534 error = -EINVAL;
535
536 put_cred(cred);
537
538 return error;
539}
540
541static int apparmor_setprocattr(struct task_struct *task, char *name,
542 void *value, size_t size)
543{
544 char *command, *args = value;
545 size_t arg_size;
546 int error;
547
548 if (size == 0)
549 return -EINVAL;
550 /* args points to a PAGE_SIZE buffer, AppArmor requires that
551 * the buffer must be null terminated or have size <= PAGE_SIZE -1
552 * so that AppArmor can null terminate them
553 */
554 if (args[size - 1] != '\0') {
555 if (size == PAGE_SIZE)
556 return -EINVAL;
557 args[size] = '\0';
558 }
559
560 /* task can only write its own attributes */
561 if (current != task)
562 return -EACCES;
563
564 args = value;
565 args = strim(args);
566 command = strsep(&args, " ");
567 if (!args)
568 return -EINVAL;
569 args = skip_spaces(args);
570 if (!*args)
571 return -EINVAL;
572
573 arg_size = size - (args - (char *) value);
574 if (strcmp(name, "current") == 0) {
575 if (strcmp(command, "changehat") == 0) {
576 error = aa_setprocattr_changehat(args, arg_size,
577 !AA_DO_TEST);
578 } else if (strcmp(command, "permhat") == 0) {
579 error = aa_setprocattr_changehat(args, arg_size,
580 AA_DO_TEST);
581 } else if (strcmp(command, "changeprofile") == 0) {
582 error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
583 !AA_DO_TEST);
584 } else if (strcmp(command, "permprofile") == 0) {
585 error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
586 AA_DO_TEST);
587 } else if (strcmp(command, "permipc") == 0) {
588 error = aa_setprocattr_permipc(args);
589 } else {
590 struct common_audit_data sa;
591 COMMON_AUDIT_DATA_INIT(&sa, NONE);
592 sa.aad.op = OP_SETPROCATTR;
593 sa.aad.info = name;
594 sa.aad.error = -EINVAL;
595 return aa_audit(AUDIT_APPARMOR_DENIED, NULL, GFP_KERNEL,
596 &sa, NULL);
597 }
598 } else if (strcmp(name, "exec") == 0) {
599 error = aa_setprocattr_changeprofile(args, AA_ONEXEC,
600 !AA_DO_TEST);
601 } else {
602 /* only support the "current" and "exec" process attributes */
603 return -EINVAL;
604 }
605 if (!error)
606 error = size;
607 return error;
608}
609
610static int apparmor_task_setrlimit(unsigned int resource,
611 struct rlimit *new_rlim)
612{
613 struct aa_profile *profile = aa_current_profile();
614 int error = 0;
615
616 if (!unconfined(profile))
617 error = aa_task_setrlimit(profile, resource, new_rlim);
618
619 return error;
620}
621
622static struct security_operations apparmor_ops = {
623 .name = "apparmor",
624
625 .ptrace_access_check = apparmor_ptrace_access_check,
626 .ptrace_traceme = apparmor_ptrace_traceme,
627 .capget = apparmor_capget,
628 .capable = apparmor_capable,
629
630 .path_link = apparmor_path_link,
631 .path_unlink = apparmor_path_unlink,
632 .path_symlink = apparmor_path_symlink,
633 .path_mkdir = apparmor_path_mkdir,
634 .path_rmdir = apparmor_path_rmdir,
635 .path_mknod = apparmor_path_mknod,
636 .path_rename = apparmor_path_rename,
637 .path_chmod = apparmor_path_chmod,
638 .path_chown = apparmor_path_chown,
639 .path_truncate = apparmor_path_truncate,
640 .dentry_open = apparmor_dentry_open,
641 .inode_getattr = apparmor_inode_getattr,
642
643 .file_permission = apparmor_file_permission,
644 .file_alloc_security = apparmor_file_alloc_security,
645 .file_free_security = apparmor_file_free_security,
646 .file_mmap = apparmor_file_mmap,
647 .file_mprotect = apparmor_file_mprotect,
648 .file_lock = apparmor_file_lock,
649
650 .getprocattr = apparmor_getprocattr,
651 .setprocattr = apparmor_setprocattr,
652
653 .cred_alloc_blank = apparmor_cred_alloc_blank,
654 .cred_free = apparmor_cred_free,
655 .cred_prepare = apparmor_cred_prepare,
656 .cred_transfer = apparmor_cred_transfer,
657
658 .bprm_set_creds = apparmor_bprm_set_creds,
659 .bprm_committing_creds = apparmor_bprm_committing_creds,
660 .bprm_committed_creds = apparmor_bprm_committed_creds,
661 .bprm_secureexec = apparmor_bprm_secureexec,
662
663 .task_setrlimit = apparmor_task_setrlimit,
664};
665
666/*
667 * AppArmor sysfs module parameters
668 */
669
670static int param_set_aabool(const char *val, struct kernel_param *kp);
671static int param_get_aabool(char *buffer, struct kernel_param *kp);
672#define param_check_aabool(name, p) __param_check(name, p, int)
673
674static int param_set_aauint(const char *val, struct kernel_param *kp);
675static int param_get_aauint(char *buffer, struct kernel_param *kp);
676#define param_check_aauint(name, p) __param_check(name, p, int)
677
678static int param_set_aalockpolicy(const char *val, struct kernel_param *kp);
679static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp);
680#define param_check_aalockpolicy(name, p) __param_check(name, p, int)
681
682static int param_set_audit(const char *val, struct kernel_param *kp);
683static int param_get_audit(char *buffer, struct kernel_param *kp);
684#define param_check_audit(name, p) __param_check(name, p, int)
685
686static int param_set_mode(const char *val, struct kernel_param *kp);
687static int param_get_mode(char *buffer, struct kernel_param *kp);
688#define param_check_mode(name, p) __param_check(name, p, int)
689
690/* Flag values, also controllable via /sys/module/apparmor/parameters
691 * We define special types as we want to do additional mediation.
692 */
693
694/* AppArmor global enforcement switch - complain, enforce, kill */
695enum profile_mode aa_g_profile_mode = APPARMOR_ENFORCE;
696module_param_call(mode, param_set_mode, param_get_mode,
697 &aa_g_profile_mode, S_IRUSR | S_IWUSR);
698
699/* Debug mode */
700int aa_g_debug;
701module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR);
702
703/* Audit mode */
704enum audit_mode aa_g_audit;
705module_param_call(audit, param_set_audit, param_get_audit,
706 &aa_g_audit, S_IRUSR | S_IWUSR);
707
708/* Determines if audit header is included in audited messages. This
709 * provides more context if the audit daemon is not running
710 */
711int aa_g_audit_header = 1;
712module_param_named(audit_header, aa_g_audit_header, aabool,
713 S_IRUSR | S_IWUSR);
714
715/* lock out loading/removal of policy
716 * TODO: add in at boot loading of policy, which is the only way to
717 * load policy, if lock_policy is set
718 */
719int aa_g_lock_policy;
720module_param_named(lock_policy, aa_g_lock_policy, aalockpolicy,
721 S_IRUSR | S_IWUSR);
722
723/* Syscall logging mode */
724int aa_g_logsyscall;
725module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR);
726
727/* Maximum pathname length before accesses will start getting rejected */
728unsigned int aa_g_path_max = 2 * PATH_MAX;
729module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR | S_IWUSR);
730
731/* Determines how paranoid loading of policy is and how much verification
732 * on the loaded policy is done.
733 */
734int aa_g_paranoid_load = 1;
735module_param_named(paranoid_load, aa_g_paranoid_load, aabool,
736 S_IRUSR | S_IWUSR);
737
738/* Boot time disable flag */
739static unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
740module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR);
741
742static int __init apparmor_enabled_setup(char *str)
743{
744 unsigned long enabled;
745 int error = strict_strtoul(str, 0, &enabled);
746 if (!error)
747 apparmor_enabled = enabled ? 1 : 0;
748 return 1;
749}
750
751__setup("apparmor=", apparmor_enabled_setup);
752
753/* set global flag turning off the ability to load policy */
754static int param_set_aalockpolicy(const char *val, struct kernel_param *kp)
755{
756 if (!capable(CAP_MAC_ADMIN))
757 return -EPERM;
758 if (aa_g_lock_policy)
759 return -EACCES;
760 return param_set_bool(val, kp);
761}
762
763static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp)
764{
765 if (!capable(CAP_MAC_ADMIN))
766 return -EPERM;
767 return param_get_bool(buffer, kp);
768}
769
770static int param_set_aabool(const char *val, struct kernel_param *kp)
771{
772 if (!capable(CAP_MAC_ADMIN))
773 return -EPERM;
774 return param_set_bool(val, kp);
775}
776
777static int param_get_aabool(char *buffer, struct kernel_param *kp)
778{
779 if (!capable(CAP_MAC_ADMIN))
780 return -EPERM;
781 return param_get_bool(buffer, kp);
782}
783
784static int param_set_aauint(const char *val, struct kernel_param *kp)
785{
786 if (!capable(CAP_MAC_ADMIN))
787 return -EPERM;
788 return param_set_uint(val, kp);
789}
790
791static int param_get_aauint(char *buffer, struct kernel_param *kp)
792{
793 if (!capable(CAP_MAC_ADMIN))
794 return -EPERM;
795 return param_get_uint(buffer, kp);
796}
797
798static int param_get_audit(char *buffer, struct kernel_param *kp)
799{
800 if (!capable(CAP_MAC_ADMIN))
801 return -EPERM;
802
803 if (!apparmor_enabled)
804 return -EINVAL;
805
806 return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]);
807}
808
809static int param_set_audit(const char *val, struct kernel_param *kp)
810{
811 int i;
812 if (!capable(CAP_MAC_ADMIN))
813 return -EPERM;
814
815 if (!apparmor_enabled)
816 return -EINVAL;
817
818 if (!val)
819 return -EINVAL;
820
821 for (i = 0; i < AUDIT_MAX_INDEX; i++) {
822 if (strcmp(val, audit_mode_names[i]) == 0) {
823 aa_g_audit = i;
824 return 0;
825 }
826 }
827
828 return -EINVAL;
829}
830
831static int param_get_mode(char *buffer, struct kernel_param *kp)
832{
833 if (!capable(CAP_MAC_ADMIN))
834 return -EPERM;
835
836 if (!apparmor_enabled)
837 return -EINVAL;
838
839 return sprintf(buffer, "%s", profile_mode_names[aa_g_profile_mode]);
840}
841
842static int param_set_mode(const char *val, struct kernel_param *kp)
843{
844 int i;
845 if (!capable(CAP_MAC_ADMIN))
846 return -EPERM;
847
848 if (!apparmor_enabled)
849 return -EINVAL;
850
851 if (!val)
852 return -EINVAL;
853
854 for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) {
855 if (strcmp(val, profile_mode_names[i]) == 0) {
856 aa_g_profile_mode = i;
857 return 0;
858 }
859 }
860
861 return -EINVAL;
862}
863
864/*
865 * AppArmor init functions
866 */
867
868/**
869 * set_init_cxt - set a task context and profile on the first task.
870 *
871 * TODO: allow setting an alternate profile than unconfined
872 */
873static int __init set_init_cxt(void)
874{
875 struct cred *cred = (struct cred *)current->real_cred;
876 struct aa_task_cxt *cxt;
877
878 cxt = aa_alloc_task_context(GFP_KERNEL);
879 if (!cxt)
880 return -ENOMEM;
881
882 cxt->profile = aa_get_profile(root_ns->unconfined);
883 cred->security = cxt;
884
885 return 0;
886}
887
888static int __init apparmor_init(void)
889{
890 int error;
891
892 if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
893 aa_info_message("AppArmor disabled by boot time parameter");
894 apparmor_enabled = 0;
895 return 0;
896 }
897
898 error = aa_alloc_root_ns();
899 if (error) {
900 AA_ERROR("Unable to allocate default profile namespace\n");
901 goto alloc_out;
902 }
903
904 error = set_init_cxt();
905 if (error) {
906 AA_ERROR("Failed to set context on init task\n");
907 goto register_security_out;
908 }
909
910 error = register_security(&apparmor_ops);
911 if (error) {
912 AA_ERROR("Unable to register AppArmor\n");
913 goto register_security_out;
914 }
915
916 /* Report that AppArmor successfully initialized */
917 apparmor_initialized = 1;
918 if (aa_g_profile_mode == APPARMOR_COMPLAIN)
919 aa_info_message("AppArmor initialized: complain mode enabled");
920 else if (aa_g_profile_mode == APPARMOR_KILL)
921 aa_info_message("AppArmor initialized: kill mode enabled");
922 else
923 aa_info_message("AppArmor initialized");
924
925 return error;
926
927register_security_out:
928 aa_free_root_ns();
929
930alloc_out:
931 aa_destroy_aafs();
932
933 apparmor_enabled = 0;
934 return error;
935
936}
937
938security_initcall(apparmor_init);
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
new file mode 100644
index 00000000000..5cb4dc1f699
--- /dev/null
+++ b/security/apparmor/match.c
@@ -0,0 +1,353 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor dfa based regular expression matching engine
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/errno.h>
16#include <linux/kernel.h>
17#include <linux/mm.h>
18#include <linux/slab.h>
19#include <linux/vmalloc.h>
20#include <linux/err.h>
21#include <linux/kref.h>
22
23#include "include/apparmor.h"
24#include "include/match.h"
25
26/**
27 * unpack_table - unpack a dfa table (one of accept, default, base, next check)
28 * @blob: data to unpack (NOT NULL)
29 * @bsize: size of blob
30 *
31 * Returns: pointer to table else NULL on failure
32 *
33 * NOTE: must be freed by kvfree (not kmalloc)
34 */
35static struct table_header *unpack_table(char *blob, size_t bsize)
36{
37 struct table_header *table = NULL;
38 struct table_header th;
39 size_t tsize;
40
41 if (bsize < sizeof(struct table_header))
42 goto out;
43
44 /* loaded td_id's start at 1, subtract 1 now to avoid doing
45 * it every time we use td_id as an index
46 */
47 th.td_id = be16_to_cpu(*(u16 *) (blob)) - 1;
48 th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
49 th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
50 blob += sizeof(struct table_header);
51
52 if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
53 th.td_flags == YYTD_DATA8))
54 goto out;
55
56 tsize = table_size(th.td_lolen, th.td_flags);
57 if (bsize < tsize)
58 goto out;
59
60 table = kvmalloc(tsize);
61 if (table) {
62 *table = th;
63 if (th.td_flags == YYTD_DATA8)
64 UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
65 u8, byte_to_byte);
66 else if (th.td_flags == YYTD_DATA16)
67 UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
68 u16, be16_to_cpu);
69 else if (th.td_flags == YYTD_DATA32)
70 UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
71 u32, be32_to_cpu);
72 else
73 goto fail;
74 }
75
76out:
77 /* if table was vmalloced make sure the page tables are synced
78 * before it is used, as it goes live to all cpus.
79 */
80 if (is_vmalloc_addr(table))
81 vm_unmap_aliases();
82 return table;
83fail:
84 kvfree(table);
85 return NULL;
86}
87
88/**
89 * verify_dfa - verify that transitions and states in the tables are in bounds.
90 * @dfa: dfa to test (NOT NULL)
91 * @flags: flags controlling what type of accept table are acceptable
92 *
93 * Assumes dfa has gone through the first pass verification done by unpacking
94 * NOTE: this does not valid accept table values
95 *
96 * Returns: %0 else error code on failure to verify
97 */
98static int verify_dfa(struct aa_dfa *dfa, int flags)
99{
100 size_t i, state_count, trans_count;
101 int error = -EPROTO;
102
103 /* check that required tables exist */
104 if (!(dfa->tables[YYTD_ID_DEF] &&
105 dfa->tables[YYTD_ID_BASE] &&
106 dfa->tables[YYTD_ID_NXT] && dfa->tables[YYTD_ID_CHK]))
107 goto out;
108
109 /* accept.size == default.size == base.size */
110 state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
111 if (ACCEPT1_FLAGS(flags)) {
112 if (!dfa->tables[YYTD_ID_ACCEPT])
113 goto out;
114 if (state_count != dfa->tables[YYTD_ID_ACCEPT]->td_lolen)
115 goto out;
116 }
117 if (ACCEPT2_FLAGS(flags)) {
118 if (!dfa->tables[YYTD_ID_ACCEPT2])
119 goto out;
120 if (state_count != dfa->tables[YYTD_ID_ACCEPT2]->td_lolen)
121 goto out;
122 }
123 if (state_count != dfa->tables[YYTD_ID_DEF]->td_lolen)
124 goto out;
125
126 /* next.size == chk.size */
127 trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen;
128 if (trans_count != dfa->tables[YYTD_ID_CHK]->td_lolen)
129 goto out;
130
131 /* if equivalence classes then its table size must be 256 */
132 if (dfa->tables[YYTD_ID_EC] &&
133 dfa->tables[YYTD_ID_EC]->td_lolen != 256)
134 goto out;
135
136 if (flags & DFA_FLAG_VERIFY_STATES) {
137 for (i = 0; i < state_count; i++) {
138 if (DEFAULT_TABLE(dfa)[i] >= state_count)
139 goto out;
140 /* TODO: do check that DEF state recursion terminates */
141 if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
142 printk(KERN_ERR "AppArmor DFA next/check upper "
143 "bounds error\n");
144 goto out;
145 }
146 }
147
148 for (i = 0; i < trans_count; i++) {
149 if (NEXT_TABLE(dfa)[i] >= state_count)
150 goto out;
151 if (CHECK_TABLE(dfa)[i] >= state_count)
152 goto out;
153 }
154 }
155
156 error = 0;
157out:
158 return error;
159}
160
161/**
162 * dfa_free - free a dfa allocated by aa_dfa_unpack
163 * @dfa: the dfa to free (MAYBE NULL)
164 *
165 * Requires: reference count to dfa == 0
166 */
167static void dfa_free(struct aa_dfa *dfa)
168{
169 if (dfa) {
170 int i;
171
172 for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
173 kvfree(dfa->tables[i]);
174 dfa->tables[i] = NULL;
175 }
176 kfree(dfa);
177 }
178}
179
180/**
181 * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa)
182 * @kr: kref callback for freeing of a dfa (NOT NULL)
183 */
184void aa_dfa_free_kref(struct kref *kref)
185{
186 struct aa_dfa *dfa = container_of(kref, struct aa_dfa, count);
187 dfa_free(dfa);
188}
189
190/**
191 * aa_dfa_unpack - unpack the binary tables of a serialized dfa
192 * @blob: aligned serialized stream of data to unpack (NOT NULL)
193 * @size: size of data to unpack
194 * @flags: flags controlling what type of accept tables are acceptable
195 *
196 * Unpack a dfa that has been serialized. To find information on the dfa
197 * format look in Documentation/apparmor.txt
198 * Assumes the dfa @blob stream has been aligned on a 8 byte boundry
199 *
200 * Returns: an unpacked dfa ready for matching or ERR_PTR on failure
201 */
202struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)
203{
204 int hsize;
205 int error = -ENOMEM;
206 char *data = blob;
207 struct table_header *table = NULL;
208 struct aa_dfa *dfa = kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
209 if (!dfa)
210 goto fail;
211
212 kref_init(&dfa->count);
213
214 error = -EPROTO;
215
216 /* get dfa table set header */
217 if (size < sizeof(struct table_set_header))
218 goto fail;
219
220 if (ntohl(*(u32 *) data) != YYTH_MAGIC)
221 goto fail;
222
223 hsize = ntohl(*(u32 *) (data + 4));
224 if (size < hsize)
225 goto fail;
226
227 dfa->flags = ntohs(*(u16 *) (data + 12));
228 data += hsize;
229 size -= hsize;
230
231 while (size > 0) {
232 table = unpack_table(data, size);
233 if (!table)
234 goto fail;
235
236 switch (table->td_id) {
237 case YYTD_ID_ACCEPT:
238 if (!(table->td_flags & ACCEPT1_FLAGS(flags)))
239 goto fail;
240 break;
241 case YYTD_ID_ACCEPT2:
242 if (!(table->td_flags & ACCEPT2_FLAGS(flags)))
243 goto fail;
244 break;
245 case YYTD_ID_BASE:
246 if (table->td_flags != YYTD_DATA32)
247 goto fail;
248 break;
249 case YYTD_ID_DEF:
250 case YYTD_ID_NXT:
251 case YYTD_ID_CHK:
252 if (table->td_flags != YYTD_DATA16)
253 goto fail;
254 break;
255 case YYTD_ID_EC:
256 if (table->td_flags != YYTD_DATA8)
257 goto fail;
258 break;
259 default:
260 goto fail;
261 }
262 /* check for duplicate table entry */
263 if (dfa->tables[table->td_id])
264 goto fail;
265 dfa->tables[table->td_id] = table;
266 data += table_size(table->td_lolen, table->td_flags);
267 size -= table_size(table->td_lolen, table->td_flags);
268 table = NULL;
269 }
270
271 error = verify_dfa(dfa, flags);
272 if (error)
273 goto fail;
274
275 return dfa;
276
277fail:
278 kvfree(table);
279 dfa_free(dfa);
280 return ERR_PTR(error);
281}
282
283/**
284 * aa_dfa_match_len - traverse @dfa to find state @str stops at
285 * @dfa: the dfa to match @str against (NOT NULL)
286 * @start: the state of the dfa to start matching in
287 * @str: the string of bytes to match against the dfa (NOT NULL)
288 * @len: length of the string of bytes to match
289 *
290 * aa_dfa_match_len will match @str against the dfa and return the state it
291 * finished matching in. The final state can be used to look up the accepting
292 * label, or as the start state of a continuing match.
293 *
294 * This function will happily match again the 0 byte and only finishes
295 * when @len input is consumed.
296 *
297 * Returns: final state reached after input is consumed
298 */
299unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
300 const char *str, int len)
301{
302 u16 *def = DEFAULT_TABLE(dfa);
303 u32 *base = BASE_TABLE(dfa);
304 u16 *next = NEXT_TABLE(dfa);
305 u16 *check = CHECK_TABLE(dfa);
306 unsigned int state = start, pos;
307
308 if (state == 0)
309 return 0;
310
311 /* current state is <state>, matching character *str */
312 if (dfa->tables[YYTD_ID_EC]) {
313 /* Equivalence class table defined */
314 u8 *equiv = EQUIV_TABLE(dfa);
315 /* default is direct to next state */
316 for (; len; len--) {
317 pos = base[state] + equiv[(u8) *str++];
318 if (check[pos] == state)
319 state = next[pos];
320 else
321 state = def[state];
322 }
323 } else {
324 /* default is direct to next state */
325 for (; len; len--) {
326 pos = base[state] + (u8) *str++;
327 if (check[pos] == state)
328 state = next[pos];
329 else
330 state = def[state];
331 }
332 }
333
334 return state;
335}
336
337/**
338 * aa_dfa_next_state - traverse @dfa to find state @str stops at
339 * @dfa: the dfa to match @str against (NOT NULL)
340 * @start: the state of the dfa to start matching in
341 * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
342 *
343 * aa_dfa_next_state will match @str against the dfa and return the state it
344 * finished matching in. The final state can be used to look up the accepting
345 * label, or as the start state of a continuing match.
346 *
347 * Returns: final state reached after input is consumed
348 */
349unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
350 const char *str)
351{
352 return aa_dfa_match_len(dfa, start, str, strlen(str));
353}
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
new file mode 100644
index 00000000000..96bab9469d4
--- /dev/null
+++ b/security/apparmor/path.c
@@ -0,0 +1,235 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor function for pathnames
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/magic.h>
16#include <linux/mnt_namespace.h>
17#include <linux/mount.h>
18#include <linux/namei.h>
19#include <linux/nsproxy.h>
20#include <linux/path.h>
21#include <linux/sched.h>
22#include <linux/slab.h>
23#include <linux/fs_struct.h>
24
25#include "include/apparmor.h"
26#include "include/path.h"
27#include "include/policy.h"
28
29
30/* modified from dcache.c */
31static int prepend(char **buffer, int buflen, const char *str, int namelen)
32{
33 buflen -= namelen;
34 if (buflen < 0)
35 return -ENAMETOOLONG;
36 *buffer -= namelen;
37 memcpy(*buffer, str, namelen);
38 return 0;
39}
40
41#define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT)
42
43/**
44 * d_namespace_path - lookup a name associated with a given path
45 * @path: path to lookup (NOT NULL)
46 * @buf: buffer to store path to (NOT NULL)
47 * @buflen: length of @buf
48 * @name: Returns - pointer for start of path name with in @buf (NOT NULL)
49 * @flags: flags controlling path lookup
50 *
51 * Handle path name lookup.
52 *
53 * Returns: %0 else error code if path lookup fails
54 * When no error the path name is returned in @name which points to
55 * to a position in @buf
56 */
57static int d_namespace_path(struct path *path, char *buf, int buflen,
58 char **name, int flags)
59{
60 struct path root, tmp;
61 char *res;
62 int deleted, connected;
63 int error = 0;
64
65 /* Get the root we want to resolve too */
66 if (flags & PATH_CHROOT_REL) {
67 /* resolve paths relative to chroot */
68 read_lock(&current->fs->lock);
69 root = current->fs->root;
70 /* released below */
71 path_get(&root);
72 read_unlock(&current->fs->lock);
73 } else {
74 /* resolve paths relative to namespace */
75 root.mnt = current->nsproxy->mnt_ns->root;
76 root.dentry = root.mnt->mnt_root;
77 /* released below */
78 path_get(&root);
79 }
80
81 spin_lock(&dcache_lock);
82 /* There is a race window between path lookup here and the
83 * need to strip the " (deleted) string that __d_path applies
84 * Detect the race and relookup the path
85 *
86 * The stripping of (deleted) is a hack that could be removed
87 * with an updated __d_path
88 */
89 do {
90 tmp = root;
91 deleted = d_unlinked(path->dentry);
92 res = __d_path(path, &tmp, buf, buflen);
93
94 } while (deleted != d_unlinked(path->dentry));
95 spin_unlock(&dcache_lock);
96
97 *name = res;
98 /* handle error conditions - and still allow a partial path to
99 * be returned.
100 */
101 if (IS_ERR(res)) {
102 error = PTR_ERR(res);
103 *name = buf;
104 goto out;
105 }
106 if (deleted) {
107 /* On some filesystems, newly allocated dentries appear to the
108 * security_path hooks as a deleted dentry except without an
109 * inode allocated.
110 *
111 * Remove the appended deleted text and return as string for
112 * normal mediation, or auditing. The (deleted) string is
113 * guaranteed to be added in this case, so just strip it.
114 */
115 buf[buflen - 11] = 0; /* - (len(" (deleted)") +\0) */
116
117 if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) {
118 error = -ENOENT;
119 goto out;
120 }
121 }
122
123 /* Determine if the path is connected to the expected root */
124 connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt;
125
126 /* If the path is not connected,
127 * check if it is a sysctl and handle specially else remove any
128 * leading / that __d_path may have returned.
129 * Unless
130 * specifically directed to connect the path,
131 * OR
132 * if in a chroot and doing chroot relative paths and the path
133 * resolves to the namespace root (would be connected outside
134 * of chroot) and specifically directed to connect paths to
135 * namespace root.
136 */
137 if (!connected) {
138 /* is the disconnect path a sysctl? */
139 if (tmp.dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
140 strncmp(*name, "/sys/", 5) == 0) {
141 /* TODO: convert over to using a per namespace
142 * control instead of hard coded /proc
143 */
144 error = prepend(name, *name - buf, "/proc", 5);
145 } else if (!(flags & PATH_CONNECT_PATH) &&
146 !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
147 (tmp.mnt == current->nsproxy->mnt_ns->root &&
148 tmp.dentry == tmp.mnt->mnt_root))) {
149 /* disconnected path, don't return pathname starting
150 * with '/'
151 */
152 error = -ESTALE;
153 if (*res == '/')
154 *name = res + 1;
155 }
156 }
157
158out:
159 path_put(&root);
160
161 return error;
162}
163
164/**
165 * get_name_to_buffer - get the pathname to a buffer ensure dir / is appended
166 * @path: path to get name for (NOT NULL)
167 * @flags: flags controlling path lookup
168 * @buffer: buffer to put name in (NOT NULL)
169 * @size: size of buffer
170 * @name: Returns - contains position of path name in @buffer (NOT NULL)
171 *
172 * Returns: %0 else error on failure
173 */
174static int get_name_to_buffer(struct path *path, int flags, char *buffer,
175 int size, char **name)
176{
177 int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
178 int error = d_namespace_path(path, buffer, size - adjust, name, flags);
179
180 if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0')
181 /*
182 * Append "/" to the pathname. The root directory is a special
183 * case; it already ends in slash.
184 */
185 strcpy(&buffer[size - 2], "/");
186
187 return error;
188}
189
190/**
191 * aa_get_name - compute the pathname of a file
192 * @path: path the file (NOT NULL)
193 * @flags: flags controlling path name generation
194 * @buffer: buffer that aa_get_name() allocated (NOT NULL)
195 * @name: Returns - the generated path name if !error (NOT NULL)
196 *
197 * @name is a pointer to the beginning of the pathname (which usually differs
198 * from the beginning of the buffer), or NULL. If there is an error @name
199 * may contain a partial or invalid name that can be used for audit purposes,
200 * but it can not be used for mediation.
201 *
202 * We need PATH_IS_DIR to indicate whether the file is a directory or not
203 * because the file may not yet exist, and so we cannot check the inode's
204 * file type.
205 *
206 * Returns: %0 else error code if could retrieve name
207 */
208int aa_get_name(struct path *path, int flags, char **buffer, const char **name)
209{
210 char *buf, *str = NULL;
211 int size = 256;
212 int error;
213
214 *name = NULL;
215 *buffer = NULL;
216 for (;;) {
217 /* freed by caller */
218 buf = kmalloc(size, GFP_KERNEL);
219 if (!buf)
220 return -ENOMEM;
221
222 error = get_name_to_buffer(path, flags, buf, size, &str);
223 if (error != -ENAMETOOLONG)
224 break;
225
226 kfree(buf);
227 size <<= 1;
228 if (size > aa_g_path_max)
229 return -ENAMETOOLONG;
230 }
231 *buffer = buf;
232 *name = str;
233
234 return error;
235}
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
new file mode 100644
index 00000000000..3cdc1ad0787
--- /dev/null
+++ b/security/apparmor/policy.c
@@ -0,0 +1,1184 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor policy manipulation functions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 *
14 *
15 * AppArmor policy is based around profiles, which contain the rules a
16 * task is confined by. Every task in the system has a profile attached
17 * to it determined either by matching "unconfined" tasks against the
18 * visible set of profiles or by following a profiles attachment rules.
19 *
20 * Each profile exists in a profile namespace which is a container of
21 * visible profiles. Each namespace contains a special "unconfined" profile,
22 * which doesn't enforce any confinement on a task beyond DAC.
23 *
24 * Namespace and profile names can be written together in either
25 * of two syntaxes.
26 * :namespace:profile - used by kernel interfaces for easy detection
27 * namespace://profile - used by policy
28 *
29 * Profile names can not start with : or @ or ^ and may not contain \0
30 *
31 * Reserved profile names
32 * unconfined - special automatically generated unconfined profile
33 * inherit - special name to indicate profile inheritance
34 * null-XXXX-YYYY - special automatically generated learning profiles
35 *
36 * Namespace names may not start with / or @ and may not contain \0 or :
37 * Reserved namespace names
38 * user-XXXX - user defined profiles
39 *
40 * a // in a profile or namespace name indicates a hierarchical name with the
41 * name before the // being the parent and the name after the child.
42 *
43 * Profile and namespace hierarchies serve two different but similar purposes.
44 * The namespace contains the set of visible profiles that are considered
45 * for attachment. The hierarchy of namespaces allows for virtualizing
46 * the namespace so that for example a chroot can have its own set of profiles
47 * which may define some local user namespaces.
48 * The profile hierarchy severs two distinct purposes,
49 * - it allows for sub profiles or hats, which allows an application to run
50 * subprograms under its own profile with different restriction than it
51 * self, and not have it use the system profile.
52 * eg. if a mail program starts an editor, the policy might make the
53 * restrictions tighter on the editor tighter than the mail program,
54 * and definitely different than general editor restrictions
55 * - it allows for binary hierarchy of profiles, so that execution history
56 * is preserved. This feature isn't exploited by AppArmor reference policy
57 * but is allowed. NOTE: this is currently suboptimal because profile
58 * aliasing is not currently implemented so that a profile for each
59 * level must be defined.
60 * eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started
61 * from /bin/bash
62 *
63 * A profile or namespace name that can contain one or more // separators
64 * is referred to as an hname (hierarchical).
65 * eg. /bin/bash//bin/ls
66 *
67 * An fqname is a name that may contain both namespace and profile hnames.
68 * eg. :ns:/bin/bash//bin/ls
69 *
70 * NOTES:
71 * - locking of profile lists is currently fairly coarse. All profile
72 * lists within a namespace use the namespace lock.
73 * FIXME: move profile lists to using rcu_lists
74 */
75
76#include <linux/slab.h>
77#include <linux/spinlock.h>
78#include <linux/string.h>
79
80#include "include/apparmor.h"
81#include "include/capability.h"
82#include "include/context.h"
83#include "include/file.h"
84#include "include/ipc.h"
85#include "include/match.h"
86#include "include/path.h"
87#include "include/policy.h"
88#include "include/policy_unpack.h"
89#include "include/resource.h"
90#include "include/sid.h"
91
92
93/* root profile namespace */
94struct aa_namespace *root_ns;
95
96const char *profile_mode_names[] = {
97 "enforce",
98 "complain",
99 "kill",
100};
101
102/**
103 * hname_tail - find the last component of an hname
104 * @name: hname to find the base profile name component of (NOT NULL)
105 *
106 * Returns: the tail (base profile name) name component of an hname
107 */
108static const char *hname_tail(const char *hname)
109{
110 char *split;
111 hname = strim((char *)hname);
112 for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
113 hname = split + 2;
114
115 return hname;
116}
117
118/**
119 * policy_init - initialize a policy structure
120 * @policy: policy to initialize (NOT NULL)
121 * @prefix: prefix name if any is required. (MAYBE NULL)
122 * @name: name of the policy, init will make a copy of it (NOT NULL)
123 *
124 * Note: this fn creates a copy of strings passed in
125 *
126 * Returns: true if policy init successful
127 */
128static bool policy_init(struct aa_policy *policy, const char *prefix,
129 const char *name)
130{
131 /* freed by policy_free */
132 if (prefix) {
133 policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3,
134 GFP_KERNEL);
135 if (policy->hname)
136 sprintf(policy->hname, "%s//%s", prefix, name);
137 } else
138 policy->hname = kstrdup(name, GFP_KERNEL);
139 if (!policy->hname)
140 return 0;
141 /* base.name is a substring of fqname */
142 policy->name = (char *)hname_tail(policy->hname);
143 INIT_LIST_HEAD(&policy->list);
144 INIT_LIST_HEAD(&policy->profiles);
145 kref_init(&policy->count);
146
147 return 1;
148}
149
150/**
151 * policy_destroy - free the elements referenced by @policy
152 * @policy: policy that is to have its elements freed (NOT NULL)
153 */
154static void policy_destroy(struct aa_policy *policy)
155{
156 /* still contains profiles -- invalid */
157 if (!list_empty(&policy->profiles)) {
158 AA_ERROR("%s: internal error, "
159 "policy '%s' still contains profiles\n",
160 __func__, policy->name);
161 BUG();
162 }
163 if (!list_empty(&policy->list)) {
164 AA_ERROR("%s: internal error, policy '%s' still on list\n",
165 __func__, policy->name);
166 BUG();
167 }
168
169 /* don't free name as its a subset of hname */
170 kzfree(policy->hname);
171}
172
173/**
174 * __policy_find - find a policy by @name on a policy list
175 * @head: list to search (NOT NULL)
176 * @name: name to search for (NOT NULL)
177 *
178 * Requires: correct locks for the @head list be held
179 *
180 * Returns: unrefcounted policy that match @name or NULL if not found
181 */
182static struct aa_policy *__policy_find(struct list_head *head, const char *name)
183{
184 struct aa_policy *policy;
185
186 list_for_each_entry(policy, head, list) {
187 if (!strcmp(policy->name, name))
188 return policy;
189 }
190 return NULL;
191}
192
193/**
194 * __policy_strn_find - find a policy that's name matches @len chars of @str
195 * @head: list to search (NOT NULL)
196 * @str: string to search for (NOT NULL)
197 * @len: length of match required
198 *
199 * Requires: correct locks for the @head list be held
200 *
201 * Returns: unrefcounted policy that match @str or NULL if not found
202 *
203 * if @len == strlen(@strlen) then this is equiv to __policy_find
204 * other wise it allows searching for policy by a partial match of name
205 */
206static struct aa_policy *__policy_strn_find(struct list_head *head,
207 const char *str, int len)
208{
209 struct aa_policy *policy;
210
211 list_for_each_entry(policy, head, list) {
212 if (aa_strneq(policy->name, str, len))
213 return policy;
214 }
215
216 return NULL;
217}
218
219/*
220 * Routines for AppArmor namespaces
221 */
222
223static const char *hidden_ns_name = "---";
224/**
225 * aa_ns_visible - test if @view is visible from @curr
226 * @curr: namespace to treat as the parent (NOT NULL)
227 * @view: namespace to test if visible from @curr (NOT NULL)
228 *
229 * Returns: true if @view is visible from @curr else false
230 */
231bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view)
232{
233 if (curr == view)
234 return true;
235
236 for ( ; view; view = view->parent) {
237 if (view->parent == curr)
238 return true;
239 }
240 return false;
241}
242
243/**
244 * aa_na_name - Find the ns name to display for @view from @curr
245 * @curr - current namespace (NOT NULL)
246 * @view - namespace attempting to view (NOT NULL)
247 *
248 * Returns: name of @view visible from @curr
249 */
250const char *aa_ns_name(struct aa_namespace *curr, struct aa_namespace *view)
251{
252 /* if view == curr then the namespace name isn't displayed */
253 if (curr == view)
254 return "";
255
256 if (aa_ns_visible(curr, view)) {
257 /* at this point if a ns is visible it is in a view ns
258 * thus the curr ns.hname is a prefix of its name.
259 * Only output the virtualized portion of the name
260 * Add + 2 to skip over // separating curr hname prefix
261 * from the visible tail of the views hname
262 */
263 return view->base.hname + strlen(curr->base.hname) + 2;
264 } else
265 return hidden_ns_name;
266}
267
268/**
269 * alloc_namespace - allocate, initialize and return a new namespace
270 * @prefix: parent namespace name (MAYBE NULL)
271 * @name: a preallocated name (NOT NULL)
272 *
273 * Returns: refcounted namespace or NULL on failure.
274 */
275static struct aa_namespace *alloc_namespace(const char *prefix,
276 const char *name)
277{
278 struct aa_namespace *ns;
279
280 ns = kzalloc(sizeof(*ns), GFP_KERNEL);
281 AA_DEBUG("%s(%p)\n", __func__, ns);
282 if (!ns)
283 return NULL;
284 if (!policy_init(&ns->base, prefix, name))
285 goto fail_ns;
286
287 INIT_LIST_HEAD(&ns->sub_ns);
288 rwlock_init(&ns->lock);
289
290 /* released by free_namespace */
291 ns->unconfined = aa_alloc_profile("unconfined");
292 if (!ns->unconfined)
293 goto fail_unconfined;
294
295 ns->unconfined->sid = aa_alloc_sid();
296 ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR |
297 PFLAG_IMMUTABLE;
298
299 /*
300 * released by free_namespace, however __remove_namespace breaks
301 * the cyclic references (ns->unconfined, and unconfined->ns) and
302 * replaces with refs to parent namespace unconfined
303 */
304 ns->unconfined->ns = aa_get_namespace(ns);
305
306 return ns;
307
308fail_unconfined:
309 kzfree(ns->base.name);
310fail_ns:
311 kzfree(ns);
312 return NULL;
313}
314
315/**
316 * free_namespace - free a profile namespace
317 * @ns: the namespace to free (MAYBE NULL)
318 *
319 * Requires: All references to the namespace must have been put, if the
320 * namespace was referenced by a profile confining a task,
321 */
322static void free_namespace(struct aa_namespace *ns)
323{
324 if (!ns)
325 return;
326
327 policy_destroy(&ns->base);
328 aa_put_namespace(ns->parent);
329
330 if (ns->unconfined && ns->unconfined->ns == ns)
331 ns->unconfined->ns = NULL;
332
333 aa_put_profile(ns->unconfined);
334 kzfree(ns);
335}
336
337/**
338 * aa_free_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
339 * @kr: kref callback for freeing of a namespace (NOT NULL)
340 */
341void aa_free_namespace_kref(struct kref *kref)
342{
343 free_namespace(container_of(kref, struct aa_namespace, base.count));
344}
345
346/**
347 * __aa_find_namespace - find a namespace on a list by @name
348 * @head: list to search for namespace on (NOT NULL)
349 * @name: name of namespace to look for (NOT NULL)
350 *
351 * Returns: unrefcounted namespace
352 *
353 * Requires: ns lock be held
354 */
355static struct aa_namespace *__aa_find_namespace(struct list_head *head,
356 const char *name)
357{
358 return (struct aa_namespace *)__policy_find(head, name);
359}
360
361/**
362 * aa_find_namespace - look up a profile namespace on the namespace list
363 * @root: namespace to search in (NOT NULL)
364 * @name: name of namespace to find (NOT NULL)
365 *
366 * Returns: a refcounted namespace on the list, or NULL if no namespace
367 * called @name exists.
368 *
369 * refcount released by caller
370 */
371struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
372 const char *name)
373{
374 struct aa_namespace *ns = NULL;
375
376 read_lock(&root->lock);
377 ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
378 read_unlock(&root->lock);
379
380 return ns;
381}
382
383/**
384 * aa_prepare_namespace - find an existing or create a new namespace of @name
385 * @name: the namespace to find or add (MAYBE NULL)
386 *
387 * Returns: refcounted namespace or NULL if failed to create one
388 */
389static struct aa_namespace *aa_prepare_namespace(const char *name)
390{
391 struct aa_namespace *ns, *root;
392
393 root = aa_current_profile()->ns;
394
395 write_lock(&root->lock);
396
397 /* if name isn't specified the profile is loaded to the current ns */
398 if (!name) {
399 /* released by caller */
400 ns = aa_get_namespace(root);
401 goto out;
402 }
403
404 /* try and find the specified ns and if it doesn't exist create it */
405 /* released by caller */
406 ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
407 if (!ns) {
408 /* namespace not found */
409 struct aa_namespace *new_ns;
410 write_unlock(&root->lock);
411 new_ns = alloc_namespace(root->base.hname, name);
412 if (!new_ns)
413 return NULL;
414 write_lock(&root->lock);
415 /* test for race when new_ns was allocated */
416 ns = __aa_find_namespace(&root->sub_ns, name);
417 if (!ns) {
418 /* add parent ref */
419 new_ns->parent = aa_get_namespace(root);
420
421 list_add(&new_ns->base.list, &root->sub_ns);
422 /* add list ref */
423 ns = aa_get_namespace(new_ns);
424 } else {
425 /* raced so free the new one */
426 free_namespace(new_ns);
427 /* get reference on namespace */
428 aa_get_namespace(ns);
429 }
430 }
431out:
432 write_unlock(&root->lock);
433
434 /* return ref */
435 return ns;
436}
437
438/**
439 * __list_add_profile - add a profile to a list
440 * @list: list to add it to (NOT NULL)
441 * @profile: the profile to add (NOT NULL)
442 *
443 * refcount @profile, should be put by __list_remove_profile
444 *
445 * Requires: namespace lock be held, or list not be shared
446 */
447static void __list_add_profile(struct list_head *list,
448 struct aa_profile *profile)
449{
450 list_add(&profile->base.list, list);
451 /* get list reference */
452 aa_get_profile(profile);
453}
454
455/**
456 * __list_remove_profile - remove a profile from the list it is on
457 * @profile: the profile to remove (NOT NULL)
458 *
459 * remove a profile from the list, warning generally removal should
460 * be done with __replace_profile as most profile removals are
461 * replacements to the unconfined profile.
462 *
463 * put @profile list refcount
464 *
465 * Requires: namespace lock be held, or list not have been live
466 */
467static void __list_remove_profile(struct aa_profile *profile)
468{
469 list_del_init(&profile->base.list);
470 if (!(profile->flags & PFLAG_NO_LIST_REF))
471 /* release list reference */
472 aa_put_profile(profile);
473}
474
475/**
476 * __replace_profile - replace @old with @new on a list
477 * @old: profile to be replaced (NOT NULL)
478 * @new: profile to replace @old with (NOT NULL)
479 *
480 * Will duplicate and refcount elements that @new inherits from @old
481 * and will inherit @old children.
482 *
483 * refcount @new for list, put @old list refcount
484 *
485 * Requires: namespace list lock be held, or list not be shared
486 */
487static void __replace_profile(struct aa_profile *old, struct aa_profile *new)
488{
489 struct aa_policy *policy;
490 struct aa_profile *child, *tmp;
491
492 if (old->parent)
493 policy = &old->parent->base;
494 else
495 policy = &old->ns->base;
496
497 /* released when @new is freed */
498 new->parent = aa_get_profile(old->parent);
499 new->ns = aa_get_namespace(old->ns);
500 new->sid = old->sid;
501 __list_add_profile(&policy->profiles, new);
502 /* inherit children */
503 list_for_each_entry_safe(child, tmp, &old->base.profiles, base.list) {
504 aa_put_profile(child->parent);
505 child->parent = aa_get_profile(new);
506 /* list refcount transferred to @new*/
507 list_move(&child->base.list, &new->base.profiles);
508 }
509
510 /* released by free_profile */
511 old->replacedby = aa_get_profile(new);
512 __list_remove_profile(old);
513}
514
515static void __profile_list_release(struct list_head *head);
516
517/**
518 * __remove_profile - remove old profile, and children
519 * @profile: profile to be replaced (NOT NULL)
520 *
521 * Requires: namespace list lock be held, or list not be shared
522 */
523static void __remove_profile(struct aa_profile *profile)
524{
525 /* release any children lists first */
526 __profile_list_release(&profile->base.profiles);
527 /* released by free_profile */
528 profile->replacedby = aa_get_profile(profile->ns->unconfined);
529 __list_remove_profile(profile);
530}
531
532/**
533 * __profile_list_release - remove all profiles on the list and put refs
534 * @head: list of profiles (NOT NULL)
535 *
536 * Requires: namespace lock be held
537 */
538static void __profile_list_release(struct list_head *head)
539{
540 struct aa_profile *profile, *tmp;
541 list_for_each_entry_safe(profile, tmp, head, base.list)
542 __remove_profile(profile);
543}
544
545static void __ns_list_release(struct list_head *head);
546
547/**
548 * destroy_namespace - remove everything contained by @ns
549 * @ns: namespace to have it contents removed (NOT NULL)
550 */
551static void destroy_namespace(struct aa_namespace *ns)
552{
553 if (!ns)
554 return;
555
556 write_lock(&ns->lock);
557 /* release all profiles in this namespace */
558 __profile_list_release(&ns->base.profiles);
559
560 /* release all sub namespaces */
561 __ns_list_release(&ns->sub_ns);
562
563 write_unlock(&ns->lock);
564}
565
566/**
567 * __remove_namespace - remove a namespace and all its children
568 * @ns: namespace to be removed (NOT NULL)
569 *
570 * Requires: ns->parent->lock be held and ns removed from parent.
571 */
572static void __remove_namespace(struct aa_namespace *ns)
573{
574 struct aa_profile *unconfined = ns->unconfined;
575
576 /* remove ns from namespace list */
577 list_del_init(&ns->base.list);
578
579 /*
580 * break the ns, unconfined profile cyclic reference and forward
581 * all new unconfined profiles requests to the parent namespace
582 * This will result in all confined tasks that have a profile
583 * being removed, inheriting the parent->unconfined profile.
584 */
585 if (ns->parent)
586 ns->unconfined = aa_get_profile(ns->parent->unconfined);
587
588 destroy_namespace(ns);
589
590 /* release original ns->unconfined ref */
591 aa_put_profile(unconfined);
592 /* release ns->base.list ref, from removal above */
593 aa_put_namespace(ns);
594}
595
596/**
597 * __ns_list_release - remove all profile namespaces on the list put refs
598 * @head: list of profile namespaces (NOT NULL)
599 *
600 * Requires: namespace lock be held
601 */
602static void __ns_list_release(struct list_head *head)
603{
604 struct aa_namespace *ns, *tmp;
605 list_for_each_entry_safe(ns, tmp, head, base.list)
606 __remove_namespace(ns);
607
608}
609
610/**
611 * aa_alloc_root_ns - allocate the root profile namespace
612 *
613 * Returns: %0 on success else error
614 *
615 */
616int __init aa_alloc_root_ns(void)
617{
618 /* released by aa_free_root_ns - used as list ref*/
619 root_ns = alloc_namespace(NULL, "root");
620 if (!root_ns)
621 return -ENOMEM;
622
623 return 0;
624}
625
626 /**
627 * aa_free_root_ns - free the root profile namespace
628 */
629void __init aa_free_root_ns(void)
630 {
631 struct aa_namespace *ns = root_ns;
632 root_ns = NULL;
633
634 destroy_namespace(ns);
635 aa_put_namespace(ns);
636}
637
638/**
639 * aa_alloc_profile - allocate, initialize and return a new profile
640 * @hname: name of the profile (NOT NULL)
641 *
642 * Returns: refcount profile or NULL on failure
643 */
644struct aa_profile *aa_alloc_profile(const char *hname)
645{
646 struct aa_profile *profile;
647
648 /* freed by free_profile - usually through aa_put_profile */
649 profile = kzalloc(sizeof(*profile), GFP_KERNEL);
650 if (!profile)
651 return NULL;
652
653 if (!policy_init(&profile->base, NULL, hname)) {
654 kzfree(profile);
655 return NULL;
656 }
657
658 /* refcount released by caller */
659 return profile;
660}
661
662/**
663 * aa_new_null_profile - create a new null-X learning profile
664 * @parent: profile that caused this profile to be created (NOT NULL)
665 * @hat: true if the null- learning profile is a hat
666 *
667 * Create a null- complain mode profile used in learning mode. The name of
668 * the profile is unique and follows the format of parent//null-sid.
669 *
670 * null profiles are added to the profile list but the list does not
671 * hold a count on them so that they are automatically released when
672 * not in use.
673 *
674 * Returns: new refcounted profile else NULL on failure
675 */
676struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
677{
678 struct aa_profile *profile = NULL;
679 char *name;
680 u32 sid = aa_alloc_sid();
681
682 /* freed below */
683 name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, GFP_KERNEL);
684 if (!name)
685 goto fail;
686 sprintf(name, "%s//null-%x", parent->base.hname, sid);
687
688 profile = aa_alloc_profile(name);
689 kfree(name);
690 if (!profile)
691 goto fail;
692
693 profile->sid = sid;
694 profile->mode = APPARMOR_COMPLAIN;
695 profile->flags = PFLAG_NULL;
696 if (hat)
697 profile->flags |= PFLAG_HAT;
698
699 /* released on free_profile */
700 profile->parent = aa_get_profile(parent);
701 profile->ns = aa_get_namespace(parent->ns);
702
703 write_lock(&profile->ns->lock);
704 __list_add_profile(&parent->base.profiles, profile);
705 write_unlock(&profile->ns->lock);
706
707 /* refcount released by caller */
708 return profile;
709
710fail:
711 aa_free_sid(sid);
712 return NULL;
713}
714
715/**
716 * free_profile - free a profile
717 * @profile: the profile to free (MAYBE NULL)
718 *
719 * Free a profile, its hats and null_profile. All references to the profile,
720 * its hats and null_profile must have been put.
721 *
722 * If the profile was referenced from a task context, free_profile() will
723 * be called from an rcu callback routine, so we must not sleep here.
724 */
725static void free_profile(struct aa_profile *profile)
726{
727 AA_DEBUG("%s(%p)\n", __func__, profile);
728
729 if (!profile)
730 return;
731
732 if (!list_empty(&profile->base.list)) {
733 AA_ERROR("%s: internal error, "
734 "profile '%s' still on ns list\n",
735 __func__, profile->base.name);
736 BUG();
737 }
738
739 /* free children profiles */
740 policy_destroy(&profile->base);
741 aa_put_profile(profile->parent);
742
743 aa_put_namespace(profile->ns);
744 kzfree(profile->rename);
745
746 aa_free_file_rules(&profile->file);
747 aa_free_cap_rules(&profile->caps);
748 aa_free_rlimit_rules(&profile->rlimits);
749
750 aa_free_sid(profile->sid);
751 aa_put_dfa(profile->xmatch);
752
753 aa_put_profile(profile->replacedby);
754
755 kzfree(profile);
756}
757
758/**
759 * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile)
760 * @kr: kref callback for freeing of a profile (NOT NULL)
761 */
762void aa_free_profile_kref(struct kref *kref)
763{
764 struct aa_profile *p = container_of(kref, struct aa_profile,
765 base.count);
766
767 free_profile(p);
768}
769
770/* TODO: profile accounting - setup in remove */
771
772/**
773 * __find_child - find a profile on @head list with a name matching @name
774 * @head: list to search (NOT NULL)
775 * @name: name of profile (NOT NULL)
776 *
777 * Requires: ns lock protecting list be held
778 *
779 * Returns: unrefcounted profile ptr, or NULL if not found
780 */
781static struct aa_profile *__find_child(struct list_head *head, const char *name)
782{
783 return (struct aa_profile *)__policy_find(head, name);
784}
785
786/**
787 * __strn_find_child - find a profile on @head list using substring of @name
788 * @head: list to search (NOT NULL)
789 * @name: name of profile (NOT NULL)
790 * @len: length of @name substring to match
791 *
792 * Requires: ns lock protecting list be held
793 *
794 * Returns: unrefcounted profile ptr, or NULL if not found
795 */
796static struct aa_profile *__strn_find_child(struct list_head *head,
797 const char *name, int len)
798{
799 return (struct aa_profile *)__policy_strn_find(head, name, len);
800}
801
802/**
803 * aa_find_child - find a profile by @name in @parent
804 * @parent: profile to search (NOT NULL)
805 * @name: profile name to search for (NOT NULL)
806 *
807 * Returns: a refcounted profile or NULL if not found
808 */
809struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
810{
811 struct aa_profile *profile;
812
813 read_lock(&parent->ns->lock);
814 profile = aa_get_profile(__find_child(&parent->base.profiles, name));
815 read_unlock(&parent->ns->lock);
816
817 /* refcount released by caller */
818 return profile;
819}
820
821/**
822 * __lookup_parent - lookup the parent of a profile of name @hname
823 * @ns: namespace to lookup profile in (NOT NULL)
824 * @hname: hierarchical profile name to find parent of (NOT NULL)
825 *
826 * Lookups up the parent of a fully qualified profile name, the profile
827 * that matches hname does not need to exist, in general this
828 * is used to load a new profile.
829 *
830 * Requires: ns->lock be held
831 *
832 * Returns: unrefcounted policy or NULL if not found
833 */
834static struct aa_policy *__lookup_parent(struct aa_namespace *ns,
835 const char *hname)
836{
837 struct aa_policy *policy;
838 struct aa_profile *profile = NULL;
839 char *split;
840
841 policy = &ns->base;
842
843 for (split = strstr(hname, "//"); split;) {
844 profile = __strn_find_child(&policy->profiles, hname,
845 split - hname);
846 if (!profile)
847 return NULL;
848 policy = &profile->base;
849 hname = split + 2;
850 split = strstr(hname, "//");
851 }
852 if (!profile)
853 return &ns->base;
854 return &profile->base;
855}
856
857/**
858 * __lookup_profile - lookup the profile matching @hname
859 * @base: base list to start looking up profile name from (NOT NULL)
860 * @hname: hierarchical profile name (NOT NULL)
861 *
862 * Requires: ns->lock be held
863 *
864 * Returns: unrefcounted profile pointer or NULL if not found
865 *
866 * Do a relative name lookup, recursing through profile tree.
867 */
868static struct aa_profile *__lookup_profile(struct aa_policy *base,
869 const char *hname)
870{
871 struct aa_profile *profile = NULL;
872 char *split;
873
874 for (split = strstr(hname, "//"); split;) {
875 profile = __strn_find_child(&base->profiles, hname,
876 split - hname);
877 if (!profile)
878 return NULL;
879
880 base = &profile->base;
881 hname = split + 2;
882 split = strstr(hname, "//");
883 }
884
885 profile = __find_child(&base->profiles, hname);
886
887 return profile;
888}
889
890/**
891 * aa_lookup_profile - find a profile by its full or partial name
892 * @ns: the namespace to start from (NOT NULL)
893 * @hname: name to do lookup on. Does not contain namespace prefix (NOT NULL)
894 *
895 * Returns: refcounted profile or NULL if not found
896 */
897struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname)
898{
899 struct aa_profile *profile;
900
901 read_lock(&ns->lock);
902 profile = aa_get_profile(__lookup_profile(&ns->base, hname));
903 read_unlock(&ns->lock);
904
905 /* refcount released by caller */
906 return profile;
907}
908
909/**
910 * replacement_allowed - test to see if replacement is allowed
911 * @profile: profile to test if it can be replaced (MAYBE NULL)
912 * @noreplace: true if replacement shouldn't be allowed but addition is okay
913 * @info: Returns - info about why replacement failed (NOT NULL)
914 *
915 * Returns: %0 if replacement allowed else error code
916 */
917static int replacement_allowed(struct aa_profile *profile, int noreplace,
918 const char **info)
919{
920 if (profile) {
921 if (profile->flags & PFLAG_IMMUTABLE) {
922 *info = "cannot replace immutible profile";
923 return -EPERM;
924 } else if (noreplace) {
925 *info = "profile already exists";
926 return -EEXIST;
927 }
928 }
929 return 0;
930}
931
932/**
933 * __add_new_profile - simple wrapper around __list_add_profile
934 * @ns: namespace that profile is being added to (NOT NULL)
935 * @policy: the policy container to add the profile to (NOT NULL)
936 * @profile: profile to add (NOT NULL)
937 *
938 * add a profile to a list and do other required basic allocations
939 */
940static void __add_new_profile(struct aa_namespace *ns, struct aa_policy *policy,
941 struct aa_profile *profile)
942{
943 if (policy != &ns->base)
944 /* released on profile replacement or free_profile */
945 profile->parent = aa_get_profile((struct aa_profile *) policy);
946 __list_add_profile(&policy->profiles, profile);
947 /* released on free_profile */
948 profile->sid = aa_alloc_sid();
949 profile->ns = aa_get_namespace(ns);
950}
951
952/**
953 * aa_audit_policy - Do auditing of policy changes
954 * @op: policy operation being performed
955 * @gfp: memory allocation flags
956 * @name: name of profile being manipulated (NOT NULL)
957 * @info: any extra information to be audited (MAYBE NULL)
958 * @error: error code
959 *
960 * Returns: the error to be returned after audit is done
961 */
962static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
963 int error)
964{
965 struct common_audit_data sa;
966 COMMON_AUDIT_DATA_INIT(&sa, NONE);
967 sa.aad.op = op;
968 sa.aad.name = name;
969 sa.aad.info = info;
970 sa.aad.error = error;
971
972 return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp,
973 &sa, NULL);
974}
975
976/**
977 * aa_may_manage_policy - can the current task manage policy
978 * @op: the policy manipulation operation being done
979 *
980 * Returns: true if the task is allowed to manipulate policy
981 */
982bool aa_may_manage_policy(int op)
983{
984 /* check if loading policy is locked out */
985 if (aa_g_lock_policy) {
986 audit_policy(op, GFP_KERNEL, NULL, "policy_locked", -EACCES);
987 return 0;
988 }
989
990 if (!capable(CAP_MAC_ADMIN)) {
991 audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES);
992 return 0;
993 }
994
995 return 1;
996}
997
998/**
999 * aa_replace_profiles - replace profile(s) on the profile list
1000 * @udata: serialized data stream (NOT NULL)
1001 * @size: size of the serialized data stream
1002 * @noreplace: true if only doing addition, no replacement allowed
1003 *
1004 * unpack and replace a profile on the profile list and uses of that profile
1005 * by any aa_task_cxt. If the profile does not exist on the profile list
1006 * it is added.
1007 *
1008 * Returns: size of data consumed else error code on failure.
1009 */
1010ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
1011{
1012 struct aa_policy *policy;
1013 struct aa_profile *old_profile = NULL, *new_profile = NULL;
1014 struct aa_profile *rename_profile = NULL;
1015 struct aa_namespace *ns = NULL;
1016 const char *ns_name, *name = NULL, *info = NULL;
1017 int op = OP_PROF_REPL;
1018 ssize_t error;
1019
1020 /* released below */
1021 new_profile = aa_unpack(udata, size, &ns_name);
1022 if (IS_ERR(new_profile)) {
1023 error = PTR_ERR(new_profile);
1024 new_profile = NULL;
1025 goto fail;
1026 }
1027
1028 /* released below */
1029 ns = aa_prepare_namespace(ns_name);
1030 if (!ns) {
1031 info = "failed to prepare namespace";
1032 error = -ENOMEM;
1033 name = ns_name;
1034 goto fail;
1035 }
1036
1037 name = new_profile->base.hname;
1038
1039 write_lock(&ns->lock);
1040 /* no ref on policy only use inside lock */
1041 policy = __lookup_parent(ns, new_profile->base.hname);
1042
1043 if (!policy) {
1044 info = "parent does not exist";
1045 error = -ENOENT;
1046 goto audit;
1047 }
1048
1049 old_profile = __find_child(&policy->profiles, new_profile->base.name);
1050 /* released below */
1051 aa_get_profile(old_profile);
1052
1053 if (new_profile->rename) {
1054 rename_profile = __lookup_profile(&ns->base,
1055 new_profile->rename);
1056 /* released below */
1057 aa_get_profile(rename_profile);
1058
1059 if (!rename_profile) {
1060 info = "profile to rename does not exist";
1061 name = new_profile->rename;
1062 error = -ENOENT;
1063 goto audit;
1064 }
1065 }
1066
1067 error = replacement_allowed(old_profile, noreplace, &info);
1068 if (error)
1069 goto audit;
1070
1071 error = replacement_allowed(rename_profile, noreplace, &info);
1072 if (error)
1073 goto audit;
1074
1075audit:
1076 if (!old_profile && !rename_profile)
1077 op = OP_PROF_LOAD;
1078
1079 error = audit_policy(op, GFP_ATOMIC, name, info, error);
1080
1081 if (!error) {
1082 if (rename_profile)
1083 __replace_profile(rename_profile, new_profile);
1084 if (old_profile) {
1085 /* when there are both rename and old profiles
1086 * inherit old profiles sid
1087 */
1088 if (rename_profile)
1089 aa_free_sid(new_profile->sid);
1090 __replace_profile(old_profile, new_profile);
1091 }
1092 if (!(old_profile || rename_profile))
1093 __add_new_profile(ns, policy, new_profile);
1094 }
1095 write_unlock(&ns->lock);
1096
1097out:
1098 aa_put_namespace(ns);
1099 aa_put_profile(rename_profile);
1100 aa_put_profile(old_profile);
1101 aa_put_profile(new_profile);
1102 if (error)
1103 return error;
1104 return size;
1105
1106fail:
1107 error = audit_policy(op, GFP_KERNEL, name, info, error);
1108 goto out;
1109}
1110
1111/**
1112 * aa_remove_profiles - remove profile(s) from the system
1113 * @fqname: name of the profile or namespace to remove (NOT NULL)
1114 * @size: size of the name
1115 *
1116 * Remove a profile or sub namespace from the current namespace, so that
1117 * they can not be found anymore and mark them as replaced by unconfined
1118 *
1119 * NOTE: removing confinement does not restore rlimits to preconfinemnet values
1120 *
1121 * Returns: size of data consume else error code if fails
1122 */
1123ssize_t aa_remove_profiles(char *fqname, size_t size)
1124{
1125 struct aa_namespace *root, *ns = NULL;
1126 struct aa_profile *profile = NULL;
1127 const char *name = fqname, *info = NULL;
1128 ssize_t error = 0;
1129
1130 if (*fqname == 0) {
1131 info = "no profile specified";
1132 error = -ENOENT;
1133 goto fail;
1134 }
1135
1136 root = aa_current_profile()->ns;
1137
1138 if (fqname[0] == ':') {
1139 char *ns_name;
1140 name = aa_split_fqname(fqname, &ns_name);
1141 if (ns_name) {
1142 /* released below */
1143 ns = aa_find_namespace(root, ns_name);
1144 if (!ns) {
1145 info = "namespace does not exist";
1146 error = -ENOENT;
1147 goto fail;
1148 }
1149 }
1150 } else
1151 /* released below */
1152 ns = aa_get_namespace(root);
1153
1154 write_lock(&ns->lock);
1155 if (!name) {
1156 /* remove namespace - can only happen if fqname[0] == ':' */
1157 __remove_namespace(ns);
1158 } else {
1159 /* remove profile */
1160 profile = aa_get_profile(__lookup_profile(&ns->base, name));
1161 if (!profile) {
1162 error = -ENOENT;
1163 info = "profile does not exist";
1164 goto fail_ns_lock;
1165 }
1166 name = profile->base.hname;
1167 __remove_profile(profile);
1168 }
1169 write_unlock(&ns->lock);
1170
1171 /* don't fail removal if audit fails */
1172 (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
1173 aa_put_namespace(ns);
1174 aa_put_profile(profile);
1175 return size;
1176
1177fail_ns_lock:
1178 write_unlock(&ns->lock);
1179 aa_put_namespace(ns);
1180
1181fail:
1182 (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
1183 return error;
1184}
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
new file mode 100644
index 00000000000..eb3700e9fd3
--- /dev/null
+++ b/security/apparmor/policy_unpack.c
@@ -0,0 +1,703 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor functions for unpacking policy loaded from
5 * userspace.
6 *
7 * Copyright (C) 1998-2008 Novell/SUSE
8 * Copyright 2009-2010 Canonical Ltd.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation, version 2 of the
13 * License.
14 *
15 * AppArmor uses a serialized binary format for loading policy.
16 * To find policy format documentation look in Documentation/apparmor.txt
17 * All policy is validated before it is used.
18 */
19
20#include <asm/unaligned.h>
21#include <linux/ctype.h>
22#include <linux/errno.h>
23
24#include "include/apparmor.h"
25#include "include/audit.h"
26#include "include/context.h"
27#include "include/match.h"
28#include "include/policy.h"
29#include "include/policy_unpack.h"
30#include "include/sid.h"
31
32/*
33 * The AppArmor interface treats data as a type byte followed by the
34 * actual data. The interface has the notion of a a named entry
35 * which has a name (AA_NAME typecode followed by name string) followed by
36 * the entries typecode and data. Named types allow for optional
37 * elements and extensions to be added and tested for without breaking
38 * backwards compatibility.
39 */
40
41enum aa_code {
42 AA_U8,
43 AA_U16,
44 AA_U32,
45 AA_U64,
46 AA_NAME, /* same as string except it is items name */
47 AA_STRING,
48 AA_BLOB,
49 AA_STRUCT,
50 AA_STRUCTEND,
51 AA_LIST,
52 AA_LISTEND,
53 AA_ARRAY,
54 AA_ARRAYEND,
55};
56
57/*
58 * aa_ext is the read of the buffer containing the serialized profile. The
59 * data is copied into a kernel buffer in apparmorfs and then handed off to
60 * the unpack routines.
61 */
62struct aa_ext {
63 void *start;
64 void *end;
65 void *pos; /* pointer to current position in the buffer */
66 u32 version;
67};
68
69/* audit callback for unpack fields */
70static void audit_cb(struct audit_buffer *ab, void *va)
71{
72 struct common_audit_data *sa = va;
73 if (sa->aad.iface.target) {
74 struct aa_profile *name = sa->aad.iface.target;
75 audit_log_format(ab, " name=");
76 audit_log_untrustedstring(ab, name->base.hname);
77 }
78 if (sa->aad.iface.pos)
79 audit_log_format(ab, " offset=%ld", sa->aad.iface.pos);
80}
81
82/**
83 * audit_iface - do audit message for policy unpacking/load/replace/remove
84 * @new: profile if it has been allocated (MAYBE NULL)
85 * @name: name of the profile being manipulated (MAYBE NULL)
86 * @info: any extra info about the failure (MAYBE NULL)
87 * @e: buffer position info (NOT NULL)
88 * @error: error code
89 *
90 * Returns: %0 or error
91 */
92static int audit_iface(struct aa_profile *new, const char *name,
93 const char *info, struct aa_ext *e, int error)
94{
95 struct aa_profile *profile = __aa_current_profile();
96 struct common_audit_data sa;
97 COMMON_AUDIT_DATA_INIT(&sa, NONE);
98 sa.aad.iface.pos = e->pos - e->start;
99 sa.aad.iface.target = new;
100 sa.aad.name = name;
101 sa.aad.info = info;
102 sa.aad.error = error;
103
104 return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa,
105 audit_cb);
106}
107
108/* test if read will be in packed data bounds */
109static bool inbounds(struct aa_ext *e, size_t size)
110{
111 return (size <= e->end - e->pos);
112}
113
114/**
115 * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
116 * @e: serialized data read head (NOT NULL)
117 * @chunk: start address for chunk of data (NOT NULL)
118 *
119 * Returns: the size of chunk found with the read head at the end of the chunk.
120 */
121static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk)
122{
123 size_t size = 0;
124
125 if (!inbounds(e, sizeof(u16)))
126 return 0;
127 size = le16_to_cpu(get_unaligned((u16 *) e->pos));
128 e->pos += sizeof(u16);
129 if (!inbounds(e, size))
130 return 0;
131 *chunk = e->pos;
132 e->pos += size;
133 return size;
134}
135
136/* unpack control byte */
137static bool unpack_X(struct aa_ext *e, enum aa_code code)
138{
139 if (!inbounds(e, 1))
140 return 0;
141 if (*(u8 *) e->pos != code)
142 return 0;
143 e->pos++;
144 return 1;
145}
146
147/**
148 * unpack_nameX - check is the next element is of type X with a name of @name
149 * @e: serialized data extent information (NOT NULL)
150 * @code: type code
151 * @name: name to match to the serialized element. (MAYBE NULL)
152 *
153 * check that the next serialized data element is of type X and has a tag
154 * name @name. If @name is specified then there must be a matching
155 * name element in the stream. If @name is NULL any name element will be
156 * skipped and only the typecode will be tested.
157 *
158 * Returns 1 on success (both type code and name tests match) and the read
159 * head is advanced past the headers
160 *
161 * Returns: 0 if either match fails, the read head does not move
162 */
163static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
164{
165 /*
166 * May need to reset pos if name or type doesn't match
167 */
168 void *pos = e->pos;
169 /*
170 * Check for presence of a tagname, and if present name size
171 * AA_NAME tag value is a u16.
172 */
173 if (unpack_X(e, AA_NAME)) {
174 char *tag = NULL;
175 size_t size = unpack_u16_chunk(e, &tag);
176 /* if a name is specified it must match. otherwise skip tag */
177 if (name && (!size || strcmp(name, tag)))
178 goto fail;
179 } else if (name) {
180 /* if a name is specified and there is no name tag fail */
181 goto fail;
182 }
183
184 /* now check if type code matches */
185 if (unpack_X(e, code))
186 return 1;
187
188fail:
189 e->pos = pos;
190 return 0;
191}
192
193static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
194{
195 if (unpack_nameX(e, AA_U32, name)) {
196 if (!inbounds(e, sizeof(u32)))
197 return 0;
198 if (data)
199 *data = le32_to_cpu(get_unaligned((u32 *) e->pos));
200 e->pos += sizeof(u32);
201 return 1;
202 }
203 return 0;
204}
205
206static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name)
207{
208 if (unpack_nameX(e, AA_U64, name)) {
209 if (!inbounds(e, sizeof(u64)))
210 return 0;
211 if (data)
212 *data = le64_to_cpu(get_unaligned((u64 *) e->pos));
213 e->pos += sizeof(u64);
214 return 1;
215 }
216 return 0;
217}
218
219static size_t unpack_array(struct aa_ext *e, const char *name)
220{
221 if (unpack_nameX(e, AA_ARRAY, name)) {
222 int size;
223 if (!inbounds(e, sizeof(u16)))
224 return 0;
225 size = (int)le16_to_cpu(get_unaligned((u16 *) e->pos));
226 e->pos += sizeof(u16);
227 return size;
228 }
229 return 0;
230}
231
232static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
233{
234 if (unpack_nameX(e, AA_BLOB, name)) {
235 u32 size;
236 if (!inbounds(e, sizeof(u32)))
237 return 0;
238 size = le32_to_cpu(get_unaligned((u32 *) e->pos));
239 e->pos += sizeof(u32);
240 if (inbounds(e, (size_t) size)) {
241 *blob = e->pos;
242 e->pos += size;
243 return size;
244 }
245 }
246 return 0;
247}
248
249static int unpack_str(struct aa_ext *e, const char **string, const char *name)
250{
251 char *src_str;
252 size_t size = 0;
253 void *pos = e->pos;
254 *string = NULL;
255 if (unpack_nameX(e, AA_STRING, name)) {
256 size = unpack_u16_chunk(e, &src_str);
257 if (size) {
258 /* strings are null terminated, length is size - 1 */
259 if (src_str[size - 1] != 0)
260 goto fail;
261 *string = src_str;
262 }
263 }
264 return size;
265
266fail:
267 e->pos = pos;
268 return 0;
269}
270
271static int unpack_strdup(struct aa_ext *e, char **string, const char *name)
272{
273 const char *tmp;
274 void *pos = e->pos;
275 int res = unpack_str(e, &tmp, name);
276 *string = NULL;
277
278 if (!res)
279 return 0;
280
281 *string = kmemdup(tmp, res, GFP_KERNEL);
282 if (!*string) {
283 e->pos = pos;
284 return 0;
285 }
286
287 return res;
288}
289
290/**
291 * verify_accept - verify the accept tables of a dfa
292 * @dfa: dfa to verify accept tables of (NOT NULL)
293 * @flags: flags governing dfa
294 *
295 * Returns: 1 if valid accept tables else 0 if error
296 */
297static bool verify_accept(struct aa_dfa *dfa, int flags)
298{
299 int i;
300
301 /* verify accept permissions */
302 for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
303 int mode = ACCEPT_TABLE(dfa)[i];
304
305 if (mode & ~DFA_VALID_PERM_MASK)
306 return 0;
307
308 if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK)
309 return 0;
310 }
311 return 1;
312}
313
314/**
315 * unpack_dfa - unpack a file rule dfa
316 * @e: serialized data extent information (NOT NULL)
317 *
318 * returns dfa or ERR_PTR or NULL if no dfa
319 */
320static struct aa_dfa *unpack_dfa(struct aa_ext *e)
321{
322 char *blob = NULL;
323 size_t size;
324 struct aa_dfa *dfa = NULL;
325
326 size = unpack_blob(e, &blob, "aadfa");
327 if (size) {
328 /*
329 * The dfa is aligned with in the blob to 8 bytes
330 * from the beginning of the stream.
331 */
332 size_t sz = blob - (char *)e->start;
333 size_t pad = ALIGN(sz, 8) - sz;
334 int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
335 TO_ACCEPT2_FLAG(YYTD_DATA32);
336
337
338 if (aa_g_paranoid_load)
339 flags |= DFA_FLAG_VERIFY_STATES;
340
341 dfa = aa_dfa_unpack(blob + pad, size - pad, flags);
342
343 if (IS_ERR(dfa))
344 return dfa;
345
346 if (!verify_accept(dfa, flags))
347 goto fail;
348 }
349
350 return dfa;
351
352fail:
353 aa_put_dfa(dfa);
354 return ERR_PTR(-EPROTO);
355}
356
357/**
358 * unpack_trans_table - unpack a profile transition table
359 * @e: serialized data extent information (NOT NULL)
360 * @profile: profile to add the accept table to (NOT NULL)
361 *
362 * Returns: 1 if table succesfully unpacked
363 */
364static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
365{
366 void *pos = e->pos;
367
368 /* exec table is optional */
369 if (unpack_nameX(e, AA_STRUCT, "xtable")) {
370 int i, size;
371
372 size = unpack_array(e, NULL);
373 /* currently 4 exec bits and entries 0-3 are reserved iupcx */
374 if (size > 16 - 4)
375 goto fail;
376 profile->file.trans.table = kzalloc(sizeof(char *) * size,
377 GFP_KERNEL);
378 if (!profile->file.trans.table)
379 goto fail;
380
381 profile->file.trans.size = size;
382 for (i = 0; i < size; i++) {
383 char *str;
384 int c, j, size = unpack_strdup(e, &str, NULL);
385 /* unpack_strdup verifies that the last character is
386 * null termination byte.
387 */
388 if (!size)
389 goto fail;
390 profile->file.trans.table[i] = str;
391 /* verify that name doesn't start with space */
392 if (isspace(*str))
393 goto fail;
394
395 /* count internal # of internal \0 */
396 for (c = j = 0; j < size - 2; j++) {
397 if (!str[j])
398 c++;
399 }
400 if (*str == ':') {
401 /* beginning with : requires an embedded \0,
402 * verify that exactly 1 internal \0 exists
403 * trailing \0 already verified by unpack_strdup
404 */
405 if (c != 1)
406 goto fail;
407 /* first character after : must be valid */
408 if (!str[1])
409 goto fail;
410 } else if (c)
411 /* fail - all other cases with embedded \0 */
412 goto fail;
413 }
414 if (!unpack_nameX(e, AA_ARRAYEND, NULL))
415 goto fail;
416 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
417 goto fail;
418 }
419 return 1;
420
421fail:
422 aa_free_domain_entries(&profile->file.trans);
423 e->pos = pos;
424 return 0;
425}
426
427static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
428{
429 void *pos = e->pos;
430
431 /* rlimits are optional */
432 if (unpack_nameX(e, AA_STRUCT, "rlimits")) {
433 int i, size;
434 u32 tmp = 0;
435 if (!unpack_u32(e, &tmp, NULL))
436 goto fail;
437 profile->rlimits.mask = tmp;
438
439 size = unpack_array(e, NULL);
440 if (size > RLIM_NLIMITS)
441 goto fail;
442 for (i = 0; i < size; i++) {
443 u64 tmp = 0;
444 int a = aa_map_resource(i);
445 if (!unpack_u64(e, &tmp, NULL))
446 goto fail;
447 profile->rlimits.limits[a].rlim_max = tmp;
448 }
449 if (!unpack_nameX(e, AA_ARRAYEND, NULL))
450 goto fail;
451 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
452 goto fail;
453 }
454 return 1;
455
456fail:
457 e->pos = pos;
458 return 0;
459}
460
461/**
462 * unpack_profile - unpack a serialized profile
463 * @e: serialized data extent information (NOT NULL)
464 *
465 * NOTE: unpack profile sets audit struct if there is a failure
466 */
467static struct aa_profile *unpack_profile(struct aa_ext *e)
468{
469 struct aa_profile *profile = NULL;
470 const char *name = NULL;
471 int error = -EPROTO;
472 kernel_cap_t tmpcap;
473 u32 tmp;
474
475 /* check that we have the right struct being passed */
476 if (!unpack_nameX(e, AA_STRUCT, "profile"))
477 goto fail;
478 if (!unpack_str(e, &name, NULL))
479 goto fail;
480
481 profile = aa_alloc_profile(name);
482 if (!profile)
483 return ERR_PTR(-ENOMEM);
484
485 /* profile renaming is optional */
486 (void) unpack_str(e, &profile->rename, "rename");
487
488 /* xmatch is optional and may be NULL */
489 profile->xmatch = unpack_dfa(e);
490 if (IS_ERR(profile->xmatch)) {
491 error = PTR_ERR(profile->xmatch);
492 profile->xmatch = NULL;
493 goto fail;
494 }
495 /* xmatch_len is not optional if xmatch is set */
496 if (profile->xmatch) {
497 if (!unpack_u32(e, &tmp, NULL))
498 goto fail;
499 profile->xmatch_len = tmp;
500 }
501
502 /* per profile debug flags (complain, audit) */
503 if (!unpack_nameX(e, AA_STRUCT, "flags"))
504 goto fail;
505 if (!unpack_u32(e, &tmp, NULL))
506 goto fail;
507 if (tmp)
508 profile->flags |= PFLAG_HAT;
509 if (!unpack_u32(e, &tmp, NULL))
510 goto fail;
511 if (tmp)
512 profile->mode = APPARMOR_COMPLAIN;
513 if (!unpack_u32(e, &tmp, NULL))
514 goto fail;
515 if (tmp)
516 profile->audit = AUDIT_ALL;
517
518 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
519 goto fail;
520
521 /* path_flags is optional */
522 if (unpack_u32(e, &profile->path_flags, "path_flags"))
523 profile->path_flags |= profile->flags & PFLAG_MEDIATE_DELETED;
524 else
525 /* set a default value if path_flags field is not present */
526 profile->path_flags = PFLAG_MEDIATE_DELETED;
527
528 if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL))
529 goto fail;
530 if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL))
531 goto fail;
532 if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL))
533 goto fail;
534 if (!unpack_u32(e, &tmpcap.cap[0], NULL))
535 goto fail;
536
537 if (unpack_nameX(e, AA_STRUCT, "caps64")) {
538 /* optional upper half of 64 bit caps */
539 if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL))
540 goto fail;
541 if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL))
542 goto fail;
543 if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL))
544 goto fail;
545 if (!unpack_u32(e, &(tmpcap.cap[1]), NULL))
546 goto fail;
547 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
548 goto fail;
549 }
550
551 if (unpack_nameX(e, AA_STRUCT, "capsx")) {
552 /* optional extended caps mediation mask */
553 if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL))
554 goto fail;
555 if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
556 goto fail;
557 }
558
559 if (!unpack_rlimits(e, profile))
560 goto fail;
561
562 /* get file rules */
563 profile->file.dfa = unpack_dfa(e);
564 if (IS_ERR(profile->file.dfa)) {
565 error = PTR_ERR(profile->file.dfa);
566 profile->file.dfa = NULL;
567 goto fail;
568 }
569
570 if (!unpack_u32(e, &profile->file.start, "dfa_start"))
571 /* default start state */
572 profile->file.start = DFA_START;
573
574 if (!unpack_trans_table(e, profile))
575 goto fail;
576
577 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
578 goto fail;
579
580 return profile;
581
582fail:
583 if (profile)
584 name = NULL;
585 else if (!name)
586 name = "unknown";
587 audit_iface(profile, name, "failed to unpack profile", e, error);
588 aa_put_profile(profile);
589
590 return ERR_PTR(error);
591}
592
593/**
594 * verify_head - unpack serialized stream header
595 * @e: serialized data read head (NOT NULL)
596 * @ns: Returns - namespace if one is specified else NULL (NOT NULL)
597 *
598 * Returns: error or 0 if header is good
599 */
600static int verify_header(struct aa_ext *e, const char **ns)
601{
602 int error = -EPROTONOSUPPORT;
603 /* get the interface version */
604 if (!unpack_u32(e, &e->version, "version")) {
605 audit_iface(NULL, NULL, "invalid profile format", e, error);
606 return error;
607 }
608
609 /* check that the interface version is currently supported */
610 if (e->version != 5) {
611 audit_iface(NULL, NULL, "unsupported interface version", e,
612 error);
613 return error;
614 }
615
616 /* read the namespace if present */
617 if (!unpack_str(e, ns, "namespace"))
618 *ns = NULL;
619
620 return 0;
621}
622
623static bool verify_xindex(int xindex, int table_size)
624{
625 int index, xtype;
626 xtype = xindex & AA_X_TYPE_MASK;
627 index = xindex & AA_X_INDEX_MASK;
628 if (xtype == AA_X_TABLE && index > table_size)
629 return 0;
630 return 1;
631}
632
633/* verify dfa xindexes are in range of transition tables */
634static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
635{
636 int i;
637 for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
638 if (!verify_xindex(dfa_user_xindex(dfa, i), table_size))
639 return 0;
640 if (!verify_xindex(dfa_other_xindex(dfa, i), table_size))
641 return 0;
642 }
643 return 1;
644}
645
646/**
647 * verify_profile - Do post unpack analysis to verify profile consistency
648 * @profile: profile to verify (NOT NULL)
649 *
650 * Returns: 0 if passes verification else error
651 */
652static int verify_profile(struct aa_profile *profile)
653{
654 if (aa_g_paranoid_load) {
655 if (profile->file.dfa &&
656 !verify_dfa_xindex(profile->file.dfa,
657 profile->file.trans.size)) {
658 audit_iface(profile, NULL, "Invalid named transition",
659 NULL, -EPROTO);
660 return -EPROTO;
661 }
662 }
663
664 return 0;
665}
666
667/**
668 * aa_unpack - unpack packed binary profile data loaded from user space
669 * @udata: user data copied to kmem (NOT NULL)
670 * @size: the size of the user data
671 * @ns: Returns namespace profile is in if specified else NULL (NOT NULL)
672 *
673 * Unpack user data and return refcounted allocated profile or ERR_PTR
674 *
675 * Returns: profile else error pointer if fails to unpack
676 */
677struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns)
678{
679 struct aa_profile *profile = NULL;
680 int error;
681 struct aa_ext e = {
682 .start = udata,
683 .end = udata + size,
684 .pos = udata,
685 };
686
687 error = verify_header(&e, ns);
688 if (error)
689 return ERR_PTR(error);
690
691 profile = unpack_profile(&e);
692 if (IS_ERR(profile))
693 return profile;
694
695 error = verify_profile(profile);
696 if (error) {
697 aa_put_profile(profile);
698 profile = ERR_PTR(error);
699 }
700
701 /* return refcount */
702 return profile;
703}
diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
new file mode 100644
index 00000000000..04a2cf8d1b6
--- /dev/null
+++ b/security/apparmor/procattr.c
@@ -0,0 +1,170 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor /proc/<pid>/attr/ interface functions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include "include/apparmor.h"
16#include "include/context.h"
17#include "include/policy.h"
18#include "include/domain.h"
19
20
21/**
22 * aa_getprocattr - Return the profile information for @profile
23 * @profile: the profile to print profile info about (NOT NULL)
24 * @string: Returns - string containing the profile info (NOT NULL)
25 *
26 * Returns: length of @string on success else error on failure
27 *
28 * Requires: profile != NULL
29 *
30 * Creates a string containing the namespace_name://profile_name for
31 * @profile.
32 *
33 * Returns: size of string placed in @string else error code on failure
34 */
35int aa_getprocattr(struct aa_profile *profile, char **string)
36{
37 char *str;
38 int len = 0, mode_len = 0, ns_len = 0, name_len;
39 const char *mode_str = profile_mode_names[profile->mode];
40 const char *ns_name = NULL;
41 struct aa_namespace *ns = profile->ns;
42 struct aa_namespace *current_ns = __aa_current_profile()->ns;
43 char *s;
44
45 if (!aa_ns_visible(current_ns, ns))
46 return -EACCES;
47
48 ns_name = aa_ns_name(current_ns, ns);
49 ns_len = strlen(ns_name);
50
51 /* if the visible ns_name is > 0 increase size for : :// seperator */
52 if (ns_len)
53 ns_len += 4;
54
55 /* unconfined profiles don't have a mode string appended */
56 if (!unconfined(profile))
57 mode_len = strlen(mode_str) + 3; /* + 3 for _() */
58
59 name_len = strlen(profile->base.hname);
60 len = mode_len + ns_len + name_len + 1; /* + 1 for \n */
61 s = str = kmalloc(len + 1, GFP_KERNEL); /* + 1 \0 */
62 if (!str)
63 return -ENOMEM;
64
65 if (ns_len) {
66 /* skip over prefix current_ns->base.hname and separating // */
67 sprintf(s, ":%s://", ns_name);
68 s += ns_len;
69 }
70 if (unconfined(profile))
71 /* mode string not being appended */
72 sprintf(s, "%s\n", profile->base.hname);
73 else
74 sprintf(s, "%s (%s)\n", profile->base.hname, mode_str);
75 *string = str;
76
77 /* NOTE: len does not include \0 of string, not saved as part of file */
78 return len;
79}
80
81/**
82 * split_token_from_name - separate a string of form <token>^<name>
83 * @op: operation being checked
84 * @args: string to parse (NOT NULL)
85 * @token: stores returned parsed token value (NOT NULL)
86 *
87 * Returns: start position of name after token else NULL on failure
88 */
89static char *split_token_from_name(int op, char *args, u64 * token)
90{
91 char *name;
92
93 *token = simple_strtoull(args, &name, 16);
94 if ((name == args) || *name != '^') {
95 AA_ERROR("%s: Invalid input '%s'", op_table[op], args);
96 return ERR_PTR(-EINVAL);
97 }
98
99 name++; /* skip ^ */
100 if (!*name)
101 name = NULL;
102 return name;
103}
104
105/**
106 * aa_setprocattr_chagnehat - handle procattr interface to change_hat
107 * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL)
108 * @size: size of the args
109 * @test: true if this is a test of change_hat permissions
110 *
111 * Returns: %0 or error code if change_hat fails
112 */
113int aa_setprocattr_changehat(char *args, size_t size, int test)
114{
115 char *hat;
116 u64 token;
117 const char *hats[16]; /* current hard limit on # of names */
118 int count = 0;
119
120 hat = split_token_from_name(OP_CHANGE_HAT, args, &token);
121 if (IS_ERR(hat))
122 return PTR_ERR(hat);
123
124 if (!hat && !token) {
125 AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
126 return -EINVAL;
127 }
128
129 if (hat) {
130 /* set up hat name vector, args guaranteed null terminated
131 * at args[size] by setprocattr.
132 *
133 * If there are multiple hat names in the buffer each is
134 * separated by a \0. Ie. userspace writes them pre tokenized
135 */
136 char *end = args + size;
137 for (count = 0; (hat < end) && count < 16; ++count) {
138 char *next = hat + strlen(hat) + 1;
139 hats[count] = hat;
140 hat = next;
141 }
142 }
143
144 AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
145 __func__, token, hat ? hat : NULL);
146
147 return aa_change_hat(hats, count, token, test);
148}
149
150/**
151 * aa_setprocattr_changeprofile - handle procattr interface to changeprofile
152 * @fqname: args received from writting to /proc/<pid>/attr/current (NOT NULL)
153 * @onexec: true if change_profile should be delayed until exec
154 * @test: true if this is a test of change_profile permissions
155 *
156 * Returns: %0 or error code if change_profile fails
157 */
158int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test)
159{
160 char *name, *ns_name;
161
162 name = aa_split_fqname(fqname, &ns_name);
163 return aa_change_profile(ns_name, name, onexec, test);
164}
165
166int aa_setprocattr_permipc(char *fqname)
167{
168 /* TODO: add ipc permission querying */
169 return -ENOTSUPP;
170}
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
new file mode 100644
index 00000000000..4a368f1fd36
--- /dev/null
+++ b/security/apparmor/resource.c
@@ -0,0 +1,134 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor resource mediation and attachment
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/audit.h>
16
17#include "include/audit.h"
18#include "include/resource.h"
19#include "include/policy.h"
20
21/*
22 * Table of rlimit names: we generate it from resource.h.
23 */
24#include "rlim_names.h"
25
26/* audit callback for resource specific fields */
27static void audit_cb(struct audit_buffer *ab, void *va)
28{
29 struct common_audit_data *sa = va;
30
31 audit_log_format(ab, " rlimit=%s value=%lu",
32 rlim_names[sa->aad.rlim.rlim], sa->aad.rlim.max);
33}
34
35/**
36 * audit_resource - audit setting resource limit
37 * @profile: profile being enforced (NOT NULL)
38 * @resoure: rlimit being auditing
39 * @value: value being set
40 * @error: error value
41 *
42 * Returns: 0 or sa->error else other error code on failure
43 */
44static int audit_resource(struct aa_profile *profile, unsigned int resource,
45 unsigned long value, int error)
46{
47 struct common_audit_data sa;
48
49 COMMON_AUDIT_DATA_INIT(&sa, NONE);
50 sa.aad.op = OP_SETRLIMIT,
51 sa.aad.rlim.rlim = resource;
52 sa.aad.rlim.max = value;
53 sa.aad.error = error;
54 return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa,
55 audit_cb);
56}
57
58/**
59 * aa_map_resouce - map compiled policy resource to internal #
60 * @resource: flattened policy resource number
61 *
62 * Returns: resource # for the current architecture.
63 *
64 * rlimit resource can vary based on architecture, map the compiled policy
65 * resource # to the internal representation for the architecture.
66 */
67int aa_map_resource(int resource)
68{
69 return rlim_map[resource];
70}
71
72/**
73 * aa_task_setrlimit - test permission to set an rlimit
74 * @profile - profile confining the task (NOT NULL)
75 * @resource - the resource being set
76 * @new_rlim - the new resource limit (NOT NULL)
77 *
78 * Control raising the processes hard limit.
79 *
80 * Returns: 0 or error code if setting resource failed
81 */
82int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
83 struct rlimit *new_rlim)
84{
85 int error = 0;
86
87 if (profile->rlimits.mask & (1 << resource) &&
88 new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)
89
90 error = audit_resource(profile, resource, new_rlim->rlim_max,
91 -EACCES);
92
93 return error;
94}
95
96/**
97 * __aa_transition_rlimits - apply new profile rlimits
98 * @old: old profile on task (NOT NULL)
99 * @new: new profile with rlimits to apply (NOT NULL)
100 */
101void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new)
102{
103 unsigned int mask = 0;
104 struct rlimit *rlim, *initrlim;
105 int i;
106
107 /* for any rlimits the profile controlled reset the soft limit
108 * to the less of the tasks hard limit and the init tasks soft limit
109 */
110 if (old->rlimits.mask) {
111 for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
112 if (old->rlimits.mask & mask) {
113 rlim = current->signal->rlim + i;
114 initrlim = init_task.signal->rlim + i;
115 rlim->rlim_cur = min(rlim->rlim_max,
116 initrlim->rlim_cur);
117 }
118 }
119 }
120
121 /* set any new hard limits as dictated by the new profile */
122 if (!new->rlimits.mask)
123 return;
124 for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
125 if (!(new->rlimits.mask & mask))
126 continue;
127
128 rlim = current->signal->rlim + i;
129 rlim->rlim_max = min(rlim->rlim_max,
130 new->rlimits.limits[i].rlim_max);
131 /* soft limit should not exceed hard limit */
132 rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
133 }
134}
diff --git a/security/apparmor/sid.c b/security/apparmor/sid.c
new file mode 100644
index 00000000000..f0b34f76ebe
--- /dev/null
+++ b/security/apparmor/sid.c
@@ -0,0 +1,55 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor security identifier (sid) manipulation fns
5 *
6 * Copyright 2009-2010 Canonical Ltd.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2 of the
11 * License.
12 *
13 *
14 * AppArmor allocates a unique sid for every profile loaded. If a profile
15 * is replaced it receives the sid of the profile it is replacing.
16 *
17 * The sid value of 0 is invalid.
18 */
19
20#include <linux/spinlock.h>
21#include <linux/errno.h>
22#include <linux/err.h>
23
24#include "include/sid.h"
25
26/* global counter from which sids are allocated */
27static u32 global_sid;
28static DEFINE_SPINLOCK(sid_lock);
29
30/* TODO FIXME: add sid to profile mapping, and sid recycling */
31
32/**
33 * aa_alloc_sid - allocate a new sid for a profile
34 */
35u32 aa_alloc_sid(void)
36{
37 u32 sid;
38
39 /*
40 * TODO FIXME: sid recycling - part of profile mapping table
41 */
42 spin_lock(&sid_lock);
43 sid = (++global_sid);
44 spin_unlock(&sid_lock);
45 return sid;
46}
47
48/**
49 * aa_free_sid - free a sid
50 * @sid: sid to free
51 */
52void aa_free_sid(u32 sid)
53{
54 ; /* NOP ATM */
55}
diff --git a/security/capability.c b/security/capability.c
index 7e468263f2d..95a6599a37b 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -27,7 +27,7 @@ static int cap_quota_on(struct dentry *dentry)
27 return 0; 27 return 0;
28} 28}
29 29
30static int cap_bprm_check_security (struct linux_binprm *bprm) 30static int cap_bprm_check_security(struct linux_binprm *bprm)
31{ 31{
32 return 0; 32 return 0;
33} 33}
@@ -268,8 +268,7 @@ static int cap_path_rename(struct path *old_path, struct dentry *old_dentry,
268 return 0; 268 return 0;
269} 269}
270 270
271static int cap_path_truncate(struct path *path, loff_t length, 271static int cap_path_truncate(struct path *path)
272 unsigned int time_attrs)
273{ 272{
274 return 0; 273 return 0;
275} 274}
diff --git a/security/inode.c b/security/inode.c
index 1c812e87450..8c777f022ad 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -86,7 +86,7 @@ static int mknod(struct inode *dir, struct dentry *dentry,
86 int mode, dev_t dev) 86 int mode, dev_t dev)
87{ 87{
88 struct inode *inode; 88 struct inode *inode;
89 int error = -EPERM; 89 int error = -ENOMEM;
90 90
91 if (dentry->d_inode) 91 if (dentry->d_inode)
92 return -EEXIST; 92 return -EEXIST;
@@ -166,6 +166,8 @@ static int create_by_name(const char *name, mode_t mode,
166 error = mkdir(parent->d_inode, *dentry, mode); 166 error = mkdir(parent->d_inode, *dentry, mode);
167 else 167 else
168 error = create(parent->d_inode, *dentry, mode); 168 error = create(parent->d_inode, *dentry, mode);
169 if (error)
170 dput(*dentry);
169 } else 171 } else
170 error = PTR_ERR(*dentry); 172 error = PTR_ERR(*dentry);
171 mutex_unlock(&parent->d_inode->i_mutex); 173 mutex_unlock(&parent->d_inode->i_mutex);
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 8fe736aabe7..ef21b96a0b4 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -45,7 +45,8 @@ static ssize_t ima_show_htable_violations(struct file *filp,
45} 45}
46 46
47static const struct file_operations ima_htable_violations_ops = { 47static const struct file_operations ima_htable_violations_ops = {
48 .read = ima_show_htable_violations 48 .read = ima_show_htable_violations,
49 .llseek = generic_file_llseek,
49}; 50};
50 51
51static ssize_t ima_show_measurements_count(struct file *filp, 52static ssize_t ima_show_measurements_count(struct file *filp,
@@ -57,7 +58,8 @@ static ssize_t ima_show_measurements_count(struct file *filp,
57} 58}
58 59
59static const struct file_operations ima_measurements_count_ops = { 60static const struct file_operations ima_measurements_count_ops = {
60 .read = ima_show_measurements_count 61 .read = ima_show_measurements_count,
62 .llseek = generic_file_llseek,
61}; 63};
62 64
63/* returns pointer to hlist_node */ 65/* returns pointer to hlist_node */
@@ -319,7 +321,8 @@ static int ima_release_policy(struct inode *inode, struct file *file)
319static const struct file_operations ima_measure_policy_ops = { 321static const struct file_operations ima_measure_policy_ops = {
320 .open = ima_open_policy, 322 .open = ima_open_policy,
321 .write = ima_write_policy, 323 .write = ima_write_policy,
322 .release = ima_release_policy 324 .release = ima_release_policy,
325 .llseek = generic_file_llseek,
323}; 326};
324 327
325int __init ima_fs_init(void) 328int __init ima_fs_init(void)
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 38783dcf6c6..addb67b169f 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -114,6 +114,10 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
114 const void *description, 114 const void *description,
115 key_match_func_t match); 115 key_match_func_t match);
116 116
117extern key_ref_t search_my_process_keyrings(struct key_type *type,
118 const void *description,
119 key_match_func_t match,
120 const struct cred *cred);
117extern key_ref_t search_process_keyrings(struct key_type *type, 121extern key_ref_t search_process_keyrings(struct key_type *type,
118 const void *description, 122 const void *description,
119 key_match_func_t match, 123 key_match_func_t match,
@@ -134,6 +138,7 @@ extern struct key *request_key_and_link(struct key_type *type,
134 struct key *dest_keyring, 138 struct key *dest_keyring,
135 unsigned long flags); 139 unsigned long flags);
136 140
141extern int lookup_user_key_possessed(const struct key *key, const void *target);
137extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, 142extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
138 key_perm_t perm); 143 key_perm_t perm);
139#define KEY_LOOKUP_CREATE 0x01 144#define KEY_LOOKUP_CREATE 0x01
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 6261745e445..b2b0998d6ab 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -505,13 +505,11 @@ okay:
505 505
506 ret = snprintf(tmpbuf, PAGE_SIZE - 1, 506 ret = snprintf(tmpbuf, PAGE_SIZE - 1,
507 "%s;%d;%d;%08x;%s", 507 "%s;%d;%d;%08x;%s",
508 key_ref_to_ptr(key_ref)->type->name, 508 key->type->name,
509 key_ref_to_ptr(key_ref)->uid, 509 key->uid,
510 key_ref_to_ptr(key_ref)->gid, 510 key->gid,
511 key_ref_to_ptr(key_ref)->perm, 511 key->perm,
512 key_ref_to_ptr(key_ref)->description ? 512 key->description ?: "");
513 key_ref_to_ptr(key_ref)->description : ""
514 );
515 513
516 /* include a NUL char at the end of the data */ 514 /* include a NUL char at the end of the data */
517 if (ret > PAGE_SIZE - 1) 515 if (ret > PAGE_SIZE - 1)
@@ -1091,7 +1089,7 @@ error:
1091long keyctl_set_timeout(key_serial_t id, unsigned timeout) 1089long keyctl_set_timeout(key_serial_t id, unsigned timeout)
1092{ 1090{
1093 struct timespec now; 1091 struct timespec now;
1094 struct key *key; 1092 struct key *key, *instkey;
1095 key_ref_t key_ref; 1093 key_ref_t key_ref;
1096 time_t expiry; 1094 time_t expiry;
1097 long ret; 1095 long ret;
@@ -1099,10 +1097,25 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout)
1099 key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, 1097 key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
1100 KEY_SETATTR); 1098 KEY_SETATTR);
1101 if (IS_ERR(key_ref)) { 1099 if (IS_ERR(key_ref)) {
1100 /* setting the timeout on a key under construction is permitted
1101 * if we have the authorisation token handy */
1102 if (PTR_ERR(key_ref) == -EACCES) {
1103 instkey = key_get_instantiation_authkey(id);
1104 if (!IS_ERR(instkey)) {
1105 key_put(instkey);
1106 key_ref = lookup_user_key(id,
1107 KEY_LOOKUP_PARTIAL,
1108 0);
1109 if (!IS_ERR(key_ref))
1110 goto okay;
1111 }
1112 }
1113
1102 ret = PTR_ERR(key_ref); 1114 ret = PTR_ERR(key_ref);
1103 goto error; 1115 goto error;
1104 } 1116 }
1105 1117
1118okay:
1106 key = key_ref_to_ptr(key_ref); 1119 key = key_ref_to_ptr(key_ref);
1107 1120
1108 /* make the changes with the locks held to prevent races */ 1121 /* make the changes with the locks held to prevent races */
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 068b66ea2f1..70373966816 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -184,20 +184,36 @@ static void proc_keys_stop(struct seq_file *p, void *v)
184 184
185static int proc_keys_show(struct seq_file *m, void *v) 185static int proc_keys_show(struct seq_file *m, void *v)
186{ 186{
187 const struct cred *cred = current_cred();
187 struct rb_node *_p = v; 188 struct rb_node *_p = v;
188 struct key *key = rb_entry(_p, struct key, serial_node); 189 struct key *key = rb_entry(_p, struct key, serial_node);
189 struct timespec now; 190 struct timespec now;
190 unsigned long timo; 191 unsigned long timo;
192 key_ref_t key_ref, skey_ref;
191 char xbuf[12]; 193 char xbuf[12];
192 int rc; 194 int rc;
193 195
196 key_ref = make_key_ref(key, 0);
197
198 /* determine if the key is possessed by this process (a test we can
199 * skip if the key does not indicate the possessor can view it
200 */
201 if (key->perm & KEY_POS_VIEW) {
202 skey_ref = search_my_process_keyrings(key->type, key,
203 lookup_user_key_possessed,
204 cred);
205 if (!IS_ERR(skey_ref)) {
206 key_ref_put(skey_ref);
207 key_ref = make_key_ref(key, 1);
208 }
209 }
210
194 /* check whether the current task is allowed to view the key (assuming 211 /* check whether the current task is allowed to view the key (assuming
195 * non-possession) 212 * non-possession)
196 * - the caller holds a spinlock, and thus the RCU read lock, making our 213 * - the caller holds a spinlock, and thus the RCU read lock, making our
197 * access to __current_cred() safe 214 * access to __current_cred() safe
198 */ 215 */
199 rc = key_task_permission(make_key_ref(key, 0), current_cred(), 216 rc = key_task_permission(key_ref, cred, KEY_VIEW);
200 KEY_VIEW);
201 if (rc < 0) 217 if (rc < 0)
202 return 0; 218 return 0;
203 219
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 6b8e4ff4cc6..f8e7251ae2c 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -309,22 +309,19 @@ void key_fsgid_changed(struct task_struct *tsk)
309 309
310/*****************************************************************************/ 310/*****************************************************************************/
311/* 311/*
312 * search the process keyrings for the first matching key 312 * search only my process keyrings for the first matching key
313 * - we use the supplied match function to see if the description (or other 313 * - we use the supplied match function to see if the description (or other
314 * feature of interest) matches 314 * feature of interest) matches
315 * - we return -EAGAIN if we didn't find any matching key 315 * - we return -EAGAIN if we didn't find any matching key
316 * - we return -ENOKEY if we found only negative matching keys 316 * - we return -ENOKEY if we found only negative matching keys
317 */ 317 */
318key_ref_t search_process_keyrings(struct key_type *type, 318key_ref_t search_my_process_keyrings(struct key_type *type,
319 const void *description, 319 const void *description,
320 key_match_func_t match, 320 key_match_func_t match,
321 const struct cred *cred) 321 const struct cred *cred)
322{ 322{
323 struct request_key_auth *rka;
324 key_ref_t key_ref, ret, err; 323 key_ref_t key_ref, ret, err;
325 324
326 might_sleep();
327
328 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 325 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
329 * searchable, but we failed to find a key or we found a negative key; 326 * searchable, but we failed to find a key or we found a negative key;
330 * otherwise we want to return a sample error (probably -EACCES) if 327 * otherwise we want to return a sample error (probably -EACCES) if
@@ -424,6 +421,36 @@ key_ref_t search_process_keyrings(struct key_type *type,
424 } 421 }
425 } 422 }
426 423
424 /* no key - decide on the error we're going to go for */
425 key_ref = ret ? ret : err;
426
427found:
428 return key_ref;
429}
430
431/*****************************************************************************/
432/*
433 * search the process keyrings for the first matching key
434 * - we use the supplied match function to see if the description (or other
435 * feature of interest) matches
436 * - we return -EAGAIN if we didn't find any matching key
437 * - we return -ENOKEY if we found only negative matching keys
438 */
439key_ref_t search_process_keyrings(struct key_type *type,
440 const void *description,
441 key_match_func_t match,
442 const struct cred *cred)
443{
444 struct request_key_auth *rka;
445 key_ref_t key_ref, ret = ERR_PTR(-EACCES), err;
446
447 might_sleep();
448
449 key_ref = search_my_process_keyrings(type, description, match, cred);
450 if (!IS_ERR(key_ref))
451 goto found;
452 err = key_ref;
453
427 /* if this process has an instantiation authorisation key, then we also 454 /* if this process has an instantiation authorisation key, then we also
428 * search the keyrings of the process mentioned there 455 * search the keyrings of the process mentioned there
429 * - we don't permit access to request_key auth keys via this method 456 * - we don't permit access to request_key auth keys via this method
@@ -446,24 +473,19 @@ key_ref_t search_process_keyrings(struct key_type *type,
446 if (!IS_ERR(key_ref)) 473 if (!IS_ERR(key_ref))
447 goto found; 474 goto found;
448 475
449 switch (PTR_ERR(key_ref)) { 476 ret = key_ref;
450 case -EAGAIN: /* no key */
451 if (ret)
452 break;
453 case -ENOKEY: /* negative key */
454 ret = key_ref;
455 break;
456 default:
457 err = key_ref;
458 break;
459 }
460 } else { 477 } else {
461 up_read(&cred->request_key_auth->sem); 478 up_read(&cred->request_key_auth->sem);
462 } 479 }
463 } 480 }
464 481
465 /* no key - decide on the error we're going to go for */ 482 /* no key - decide on the error we're going to go for */
466 key_ref = ret ? ret : err; 483 if (err == ERR_PTR(-ENOKEY) || ret == ERR_PTR(-ENOKEY))
484 key_ref = ERR_PTR(-ENOKEY);
485 else if (err == ERR_PTR(-EACCES))
486 key_ref = ret;
487 else
488 key_ref = err;
467 489
468found: 490found:
469 return key_ref; 491 return key_ref;
@@ -474,7 +496,7 @@ found:
474/* 496/*
475 * see if the key we're looking at is the target key 497 * see if the key we're looking at is the target key
476 */ 498 */
477static int lookup_user_key_possessed(const struct key *key, const void *target) 499int lookup_user_key_possessed(const struct key *key, const void *target)
478{ 500{
479 return key == target; 501 return key == target;
480 502
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index f5ec9ac5d57..0088dd8bf68 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -144,6 +144,7 @@ static int call_sbin_request_key(struct key_construction *cons,
144 prkey = 0; 144 prkey = 0;
145 if (cred->tgcred->process_keyring) 145 if (cred->tgcred->process_keyring)
146 prkey = cred->tgcred->process_keyring->serial; 146 prkey = cred->tgcred->process_keyring->serial;
147 sprintf(keyring_str[1], "%d", prkey);
147 148
148 rcu_read_lock(); 149 rcu_read_lock();
149 session = rcu_dereference(cred->tgcred->session_keyring); 150 session = rcu_dereference(cred->tgcred->session_keyring);
@@ -536,6 +537,8 @@ int wait_for_key_construction(struct key *key, bool intr)
536 intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); 537 intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
537 if (ret < 0) 538 if (ret < 0)
538 return ret; 539 return ret;
540 if (test_bit(KEY_FLAG_NEGATIVE, &key->flags))
541 return -ENOKEY;
539 return key_validate(key); 542 return key_validate(key);
540} 543}
541EXPORT_SYMBOL(wait_for_key_construction); 544EXPORT_SYMBOL(wait_for_key_construction);
diff --git a/security/security.c b/security/security.c
index aa510609a95..c53949f17d9 100644
--- a/security/security.c
+++ b/security/security.c
@@ -417,12 +417,11 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
417 new_dentry); 417 new_dentry);
418} 418}
419 419
420int security_path_truncate(struct path *path, loff_t length, 420int security_path_truncate(struct path *path)
421 unsigned int time_attrs)
422{ 421{
423 if (unlikely(IS_PRIVATE(path->dentry->d_inode))) 422 if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
424 return 0; 423 return 0;
425 return security_ops->path_truncate(path, length, time_attrs); 424 return security_ops->path_truncate(path);
426} 425}
427 426
428int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt, 427int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
@@ -620,7 +619,13 @@ void security_inode_getsecid(const struct inode *inode, u32 *secid)
620 619
621int security_file_permission(struct file *file, int mask) 620int security_file_permission(struct file *file, int mask)
622{ 621{
623 return security_ops->file_permission(file, mask); 622 int ret;
623
624 ret = security_ops->file_permission(file, mask);
625 if (ret)
626 return ret;
627
628 return fsnotify_perm(file, mask);
624} 629}
625 630
626int security_file_alloc(struct file *file) 631int security_file_alloc(struct file *file)
@@ -684,7 +689,13 @@ int security_file_receive(struct file *file)
684 689
685int security_dentry_open(struct file *file, const struct cred *cred) 690int security_dentry_open(struct file *file, const struct cred *cred)
686{ 691{
687 return security_ops->dentry_open(file, cred); 692 int ret;
693
694 ret = security_ops->dentry_open(file, cred);
695 if (ret)
696 return ret;
697
698 return fsnotify_perm(file, MAY_OPEN);
688} 699}
689 700
690int security_task_create(unsigned long clone_flags) 701int security_task_create(unsigned long clone_flags)
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index f013982df41..58d80f3bd6f 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -25,6 +25,6 @@ $(obj)/avc.o: $(obj)/flask.h
25quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h 25quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h
26 cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h 26 cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h
27 27
28targets += flask.h 28targets += flask.h av_permissions.h
29$(obj)/flask.h: $(src)/include/classmap.h FORCE 29$(obj)/flask.h: $(src)/include/classmap.h FORCE
30 $(call if_changed,flask) 30 $(call if_changed,flask)
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 7f1a304712a..9da6420e205 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -288,7 +288,6 @@ static struct avc_node *avc_alloc_node(void)
288 if (!node) 288 if (!node)
289 goto out; 289 goto out;
290 290
291 INIT_RCU_HEAD(&node->rhead);
292 INIT_HLIST_NODE(&node->list); 291 INIT_HLIST_NODE(&node->list);
293 avc_cache_stats_incr(allocations); 292 avc_cache_stats_incr(allocations);
294 293
@@ -489,9 +488,29 @@ void avc_audit(u32 ssid, u32 tsid,
489 struct common_audit_data stack_data; 488 struct common_audit_data stack_data;
490 u32 denied, audited; 489 u32 denied, audited;
491 denied = requested & ~avd->allowed; 490 denied = requested & ~avd->allowed;
492 if (denied) 491 if (denied) {
493 audited = denied & avd->auditdeny; 492 audited = denied & avd->auditdeny;
494 else if (result) 493 /*
494 * a->selinux_audit_data.auditdeny is TRICKY! Setting a bit in
495 * this field means that ANY denials should NOT be audited if
496 * the policy contains an explicit dontaudit rule for that
497 * permission. Take notice that this is unrelated to the
498 * actual permissions that were denied. As an example lets
499 * assume:
500 *
501 * denied == READ
502 * avd.auditdeny & ACCESS == 0 (not set means explicit rule)
503 * selinux_audit_data.auditdeny & ACCESS == 1
504 *
505 * We will NOT audit the denial even though the denied
506 * permission was READ and the auditdeny checks were for
507 * ACCESS
508 */
509 if (a &&
510 a->selinux_audit_data.auditdeny &&
511 !(a->selinux_audit_data.auditdeny & avd->auditdeny))
512 audited = 0;
513 } else if (result)
495 audited = denied = requested; 514 audited = denied = requested;
496 else 515 else
497 audited = requested & avd->auditallow; 516 audited = requested & avd->auditallow;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2a8a0a915ff..42043f96e54 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -87,9 +87,6 @@
87#include "netlabel.h" 87#include "netlabel.h"
88#include "audit.h" 88#include "audit.h"
89 89
90#define XATTR_SELINUX_SUFFIX "selinux"
91#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
92
93#define NUM_SEL_MNT_OPTS 5 90#define NUM_SEL_MNT_OPTS 5
94 91
95extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); 92extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
@@ -188,7 +185,7 @@ static inline u32 task_sid(const struct task_struct *task)
188 */ 185 */
189static inline u32 current_sid(void) 186static inline u32 current_sid(void)
190{ 187{
191 const struct task_security_struct *tsec = current_cred()->security; 188 const struct task_security_struct *tsec = current_security();
192 189
193 return tsec->sid; 190 return tsec->sid;
194} 191}
@@ -279,32 +276,6 @@ static void superblock_free_security(struct super_block *sb)
279 kfree(sbsec); 276 kfree(sbsec);
280} 277}
281 278
282static int sk_alloc_security(struct sock *sk, int family, gfp_t priority)
283{
284 struct sk_security_struct *sksec;
285
286 sksec = kzalloc(sizeof(*sksec), priority);
287 if (!sksec)
288 return -ENOMEM;
289
290 sksec->peer_sid = SECINITSID_UNLABELED;
291 sksec->sid = SECINITSID_UNLABELED;
292 sk->sk_security = sksec;
293
294 selinux_netlbl_sk_security_reset(sksec);
295
296 return 0;
297}
298
299static void sk_free_security(struct sock *sk)
300{
301 struct sk_security_struct *sksec = sk->sk_security;
302
303 sk->sk_security = NULL;
304 selinux_netlbl_sk_security_free(sksec);
305 kfree(sksec);
306}
307
308/* The security server must be initialized before 279/* The security server must be initialized before
309 any labeling or access decisions can be provided. */ 280 any labeling or access decisions can be provided. */
310extern int ss_initialized; 281extern int ss_initialized;
@@ -1584,8 +1555,7 @@ static int may_create(struct inode *dir,
1584 struct dentry *dentry, 1555 struct dentry *dentry,
1585 u16 tclass) 1556 u16 tclass)
1586{ 1557{
1587 const struct cred *cred = current_cred(); 1558 const struct task_security_struct *tsec = current_security();
1588 const struct task_security_struct *tsec = cred->security;
1589 struct inode_security_struct *dsec; 1559 struct inode_security_struct *dsec;
1590 struct superblock_security_struct *sbsec; 1560 struct superblock_security_struct *sbsec;
1591 u32 sid, newsid; 1561 u32 sid, newsid;
@@ -1806,27 +1776,9 @@ static inline u32 open_file_to_av(struct file *file)
1806{ 1776{
1807 u32 av = file_to_av(file); 1777 u32 av = file_to_av(file);
1808 1778
1809 if (selinux_policycap_openperm) { 1779 if (selinux_policycap_openperm)
1810 mode_t mode = file->f_path.dentry->d_inode->i_mode; 1780 av |= FILE__OPEN;
1811 /* 1781
1812 * lnk files and socks do not really have an 'open'
1813 */
1814 if (S_ISREG(mode))
1815 av |= FILE__OPEN;
1816 else if (S_ISCHR(mode))
1817 av |= CHR_FILE__OPEN;
1818 else if (S_ISBLK(mode))
1819 av |= BLK_FILE__OPEN;
1820 else if (S_ISFIFO(mode))
1821 av |= FIFO_FILE__OPEN;
1822 else if (S_ISDIR(mode))
1823 av |= DIR__OPEN;
1824 else if (S_ISSOCK(mode))
1825 av |= SOCK_FILE__OPEN;
1826 else
1827 printk(KERN_ERR "SELinux: WARNING: inside %s with "
1828 "unknown mode:%o\n", __func__, mode);
1829 }
1830 return av; 1782 return av;
1831} 1783}
1832 1784
@@ -2183,8 +2135,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
2183 2135
2184static int selinux_bprm_secureexec(struct linux_binprm *bprm) 2136static int selinux_bprm_secureexec(struct linux_binprm *bprm)
2185{ 2137{
2186 const struct cred *cred = current_cred(); 2138 const struct task_security_struct *tsec = current_security();
2187 const struct task_security_struct *tsec = cred->security;
2188 u32 sid, osid; 2139 u32 sid, osid;
2189 int atsecure = 0; 2140 int atsecure = 0;
2190 2141
@@ -2562,8 +2513,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2562 char **name, void **value, 2513 char **name, void **value,
2563 size_t *len) 2514 size_t *len)
2564{ 2515{
2565 const struct cred *cred = current_cred(); 2516 const struct task_security_struct *tsec = current_security();
2566 const struct task_security_struct *tsec = cred->security;
2567 struct inode_security_struct *dsec; 2517 struct inode_security_struct *dsec;
2568 struct superblock_security_struct *sbsec; 2518 struct superblock_security_struct *sbsec;
2569 u32 sid, newsid, clen; 2519 u32 sid, newsid, clen;
@@ -2679,14 +2629,26 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
2679static int selinux_inode_permission(struct inode *inode, int mask) 2629static int selinux_inode_permission(struct inode *inode, int mask)
2680{ 2630{
2681 const struct cred *cred = current_cred(); 2631 const struct cred *cred = current_cred();
2632 struct common_audit_data ad;
2633 u32 perms;
2634 bool from_access;
2682 2635
2683 if (!mask) { 2636 from_access = mask & MAY_ACCESS;
2684 /* No permission to check. Existence test. */ 2637 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
2638
2639 /* No permission to check. Existence test. */
2640 if (!mask)
2685 return 0; 2641 return 0;
2686 }
2687 2642
2688 return inode_has_perm(cred, inode, 2643 COMMON_AUDIT_DATA_INIT(&ad, FS);
2689 file_mask_to_av(inode->i_mode, mask), NULL); 2644 ad.u.fs.inode = inode;
2645
2646 if (from_access)
2647 ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS;
2648
2649 perms = file_mask_to_av(inode->i_mode, mask);
2650
2651 return inode_has_perm(cred, inode, perms, &ad);
2690} 2652}
2691 2653
2692static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) 2654static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
@@ -3675,71 +3637,54 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
3675} 3637}
3676 3638
3677/* socket security operations */ 3639/* socket security operations */
3678static int socket_has_perm(struct task_struct *task, struct socket *sock, 3640
3679 u32 perms) 3641static u32 socket_sockcreate_sid(const struct task_security_struct *tsec)
3680{ 3642{
3681 struct inode_security_struct *isec; 3643 return tsec->sockcreate_sid ? : tsec->sid;
3682 struct common_audit_data ad; 3644}
3683 u32 sid;
3684 int err = 0;
3685 3645
3686 isec = SOCK_INODE(sock)->i_security; 3646static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
3647{
3648 struct sk_security_struct *sksec = sk->sk_security;
3649 struct common_audit_data ad;
3650 u32 tsid = task_sid(task);
3687 3651
3688 if (isec->sid == SECINITSID_KERNEL) 3652 if (sksec->sid == SECINITSID_KERNEL)
3689 goto out; 3653 return 0;
3690 sid = task_sid(task);
3691 3654
3692 COMMON_AUDIT_DATA_INIT(&ad, NET); 3655 COMMON_AUDIT_DATA_INIT(&ad, NET);
3693 ad.u.net.sk = sock->sk; 3656 ad.u.net.sk = sk;
3694 err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
3695 3657
3696out: 3658 return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
3697 return err;
3698} 3659}
3699 3660
3700static int selinux_socket_create(int family, int type, 3661static int selinux_socket_create(int family, int type,
3701 int protocol, int kern) 3662 int protocol, int kern)
3702{ 3663{
3703 const struct cred *cred = current_cred(); 3664 const struct task_security_struct *tsec = current_security();
3704 const struct task_security_struct *tsec = cred->security; 3665 u32 newsid;
3705 u32 sid, newsid;
3706 u16 secclass; 3666 u16 secclass;
3707 int err = 0;
3708 3667
3709 if (kern) 3668 if (kern)
3710 goto out; 3669 return 0;
3711
3712 sid = tsec->sid;
3713 newsid = tsec->sockcreate_sid ?: sid;
3714 3670
3671 newsid = socket_sockcreate_sid(tsec);
3715 secclass = socket_type_to_security_class(family, type, protocol); 3672 secclass = socket_type_to_security_class(family, type, protocol);
3716 err = avc_has_perm(sid, newsid, secclass, SOCKET__CREATE, NULL); 3673 return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
3717
3718out:
3719 return err;
3720} 3674}
3721 3675
3722static int selinux_socket_post_create(struct socket *sock, int family, 3676static int selinux_socket_post_create(struct socket *sock, int family,
3723 int type, int protocol, int kern) 3677 int type, int protocol, int kern)
3724{ 3678{
3725 const struct cred *cred = current_cred(); 3679 const struct task_security_struct *tsec = current_security();
3726 const struct task_security_struct *tsec = cred->security; 3680 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
3727 struct inode_security_struct *isec;
3728 struct sk_security_struct *sksec; 3681 struct sk_security_struct *sksec;
3729 u32 sid, newsid;
3730 int err = 0; 3682 int err = 0;
3731 3683
3732 sid = tsec->sid;
3733 newsid = tsec->sockcreate_sid;
3734
3735 isec = SOCK_INODE(sock)->i_security;
3736
3737 if (kern) 3684 if (kern)
3738 isec->sid = SECINITSID_KERNEL; 3685 isec->sid = SECINITSID_KERNEL;
3739 else if (newsid)
3740 isec->sid = newsid;
3741 else 3686 else
3742 isec->sid = sid; 3687 isec->sid = socket_sockcreate_sid(tsec);
3743 3688
3744 isec->sclass = socket_type_to_security_class(family, type, protocol); 3689 isec->sclass = socket_type_to_security_class(family, type, protocol);
3745 isec->initialized = 1; 3690 isec->initialized = 1;
@@ -3760,10 +3705,11 @@ static int selinux_socket_post_create(struct socket *sock, int family,
3760 3705
3761static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) 3706static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
3762{ 3707{
3708 struct sock *sk = sock->sk;
3763 u16 family; 3709 u16 family;
3764 int err; 3710 int err;
3765 3711
3766 err = socket_has_perm(current, sock, SOCKET__BIND); 3712 err = sock_has_perm(current, sk, SOCKET__BIND);
3767 if (err) 3713 if (err)
3768 goto out; 3714 goto out;
3769 3715
@@ -3772,19 +3718,16 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3772 * Multiple address binding for SCTP is not supported yet: we just 3718 * Multiple address binding for SCTP is not supported yet: we just
3773 * check the first address now. 3719 * check the first address now.
3774 */ 3720 */
3775 family = sock->sk->sk_family; 3721 family = sk->sk_family;
3776 if (family == PF_INET || family == PF_INET6) { 3722 if (family == PF_INET || family == PF_INET6) {
3777 char *addrp; 3723 char *addrp;
3778 struct inode_security_struct *isec; 3724 struct sk_security_struct *sksec = sk->sk_security;
3779 struct common_audit_data ad; 3725 struct common_audit_data ad;
3780 struct sockaddr_in *addr4 = NULL; 3726 struct sockaddr_in *addr4 = NULL;
3781 struct sockaddr_in6 *addr6 = NULL; 3727 struct sockaddr_in6 *addr6 = NULL;
3782 unsigned short snum; 3728 unsigned short snum;
3783 struct sock *sk = sock->sk;
3784 u32 sid, node_perm; 3729 u32 sid, node_perm;
3785 3730
3786 isec = SOCK_INODE(sock)->i_security;
3787
3788 if (family == PF_INET) { 3731 if (family == PF_INET) {
3789 addr4 = (struct sockaddr_in *)address; 3732 addr4 = (struct sockaddr_in *)address;
3790 snum = ntohs(addr4->sin_port); 3733 snum = ntohs(addr4->sin_port);
@@ -3808,15 +3751,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3808 COMMON_AUDIT_DATA_INIT(&ad, NET); 3751 COMMON_AUDIT_DATA_INIT(&ad, NET);
3809 ad.u.net.sport = htons(snum); 3752 ad.u.net.sport = htons(snum);
3810 ad.u.net.family = family; 3753 ad.u.net.family = family;
3811 err = avc_has_perm(isec->sid, sid, 3754 err = avc_has_perm(sksec->sid, sid,
3812 isec->sclass, 3755 sksec->sclass,
3813 SOCKET__NAME_BIND, &ad); 3756 SOCKET__NAME_BIND, &ad);
3814 if (err) 3757 if (err)
3815 goto out; 3758 goto out;
3816 } 3759 }
3817 } 3760 }
3818 3761
3819 switch (isec->sclass) { 3762 switch (sksec->sclass) {
3820 case SECCLASS_TCP_SOCKET: 3763 case SECCLASS_TCP_SOCKET:
3821 node_perm = TCP_SOCKET__NODE_BIND; 3764 node_perm = TCP_SOCKET__NODE_BIND;
3822 break; 3765 break;
@@ -3847,8 +3790,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3847 else 3790 else
3848 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); 3791 ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
3849 3792
3850 err = avc_has_perm(isec->sid, sid, 3793 err = avc_has_perm(sksec->sid, sid,
3851 isec->sclass, node_perm, &ad); 3794 sksec->sclass, node_perm, &ad);
3852 if (err) 3795 if (err)
3853 goto out; 3796 goto out;
3854 } 3797 }
@@ -3859,19 +3802,18 @@ out:
3859static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) 3802static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3860{ 3803{
3861 struct sock *sk = sock->sk; 3804 struct sock *sk = sock->sk;
3862 struct inode_security_struct *isec; 3805 struct sk_security_struct *sksec = sk->sk_security;
3863 int err; 3806 int err;
3864 3807
3865 err = socket_has_perm(current, sock, SOCKET__CONNECT); 3808 err = sock_has_perm(current, sk, SOCKET__CONNECT);
3866 if (err) 3809 if (err)
3867 return err; 3810 return err;
3868 3811
3869 /* 3812 /*
3870 * If a TCP or DCCP socket, check name_connect permission for the port. 3813 * If a TCP or DCCP socket, check name_connect permission for the port.
3871 */ 3814 */
3872 isec = SOCK_INODE(sock)->i_security; 3815 if (sksec->sclass == SECCLASS_TCP_SOCKET ||
3873 if (isec->sclass == SECCLASS_TCP_SOCKET || 3816 sksec->sclass == SECCLASS_DCCP_SOCKET) {
3874 isec->sclass == SECCLASS_DCCP_SOCKET) {
3875 struct common_audit_data ad; 3817 struct common_audit_data ad;
3876 struct sockaddr_in *addr4 = NULL; 3818 struct sockaddr_in *addr4 = NULL;
3877 struct sockaddr_in6 *addr6 = NULL; 3819 struct sockaddr_in6 *addr6 = NULL;
@@ -3894,13 +3836,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
3894 if (err) 3836 if (err)
3895 goto out; 3837 goto out;
3896 3838
3897 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? 3839 perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
3898 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; 3840 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3899 3841
3900 COMMON_AUDIT_DATA_INIT(&ad, NET); 3842 COMMON_AUDIT_DATA_INIT(&ad, NET);
3901 ad.u.net.dport = htons(snum); 3843 ad.u.net.dport = htons(snum);
3902 ad.u.net.family = sk->sk_family; 3844 ad.u.net.family = sk->sk_family;
3903 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); 3845 err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
3904 if (err) 3846 if (err)
3905 goto out; 3847 goto out;
3906 } 3848 }
@@ -3913,7 +3855,7 @@ out:
3913 3855
3914static int selinux_socket_listen(struct socket *sock, int backlog) 3856static int selinux_socket_listen(struct socket *sock, int backlog)
3915{ 3857{
3916 return socket_has_perm(current, sock, SOCKET__LISTEN); 3858 return sock_has_perm(current, sock->sk, SOCKET__LISTEN);
3917} 3859}
3918 3860
3919static int selinux_socket_accept(struct socket *sock, struct socket *newsock) 3861static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
@@ -3922,7 +3864,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3922 struct inode_security_struct *isec; 3864 struct inode_security_struct *isec;
3923 struct inode_security_struct *newisec; 3865 struct inode_security_struct *newisec;
3924 3866
3925 err = socket_has_perm(current, sock, SOCKET__ACCEPT); 3867 err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT);
3926 if (err) 3868 if (err)
3927 return err; 3869 return err;
3928 3870
@@ -3939,30 +3881,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
3939static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, 3881static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
3940 int size) 3882 int size)
3941{ 3883{
3942 return socket_has_perm(current, sock, SOCKET__WRITE); 3884 return sock_has_perm(current, sock->sk, SOCKET__WRITE);
3943} 3885}
3944 3886
3945static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, 3887static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
3946 int size, int flags) 3888 int size, int flags)
3947{ 3889{
3948 return socket_has_perm(current, sock, SOCKET__READ); 3890 return sock_has_perm(current, sock->sk, SOCKET__READ);
3949} 3891}
3950 3892
3951static int selinux_socket_getsockname(struct socket *sock) 3893static int selinux_socket_getsockname(struct socket *sock)
3952{ 3894{
3953 return socket_has_perm(current, sock, SOCKET__GETATTR); 3895 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
3954} 3896}
3955 3897
3956static int selinux_socket_getpeername(struct socket *sock) 3898static int selinux_socket_getpeername(struct socket *sock)
3957{ 3899{
3958 return socket_has_perm(current, sock, SOCKET__GETATTR); 3900 return sock_has_perm(current, sock->sk, SOCKET__GETATTR);
3959} 3901}
3960 3902
3961static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) 3903static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
3962{ 3904{
3963 int err; 3905 int err;
3964 3906
3965 err = socket_has_perm(current, sock, SOCKET__SETOPT); 3907 err = sock_has_perm(current, sock->sk, SOCKET__SETOPT);
3966 if (err) 3908 if (err)
3967 return err; 3909 return err;
3968 3910
@@ -3972,68 +3914,58 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname
3972static int selinux_socket_getsockopt(struct socket *sock, int level, 3914static int selinux_socket_getsockopt(struct socket *sock, int level,
3973 int optname) 3915 int optname)
3974{ 3916{
3975 return socket_has_perm(current, sock, SOCKET__GETOPT); 3917 return sock_has_perm(current, sock->sk, SOCKET__GETOPT);
3976} 3918}
3977 3919
3978static int selinux_socket_shutdown(struct socket *sock, int how) 3920static int selinux_socket_shutdown(struct socket *sock, int how)
3979{ 3921{
3980 return socket_has_perm(current, sock, SOCKET__SHUTDOWN); 3922 return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN);
3981} 3923}
3982 3924
3983static int selinux_socket_unix_stream_connect(struct socket *sock, 3925static int selinux_socket_unix_stream_connect(struct socket *sock,
3984 struct socket *other, 3926 struct socket *other,
3985 struct sock *newsk) 3927 struct sock *newsk)
3986{ 3928{
3987 struct sk_security_struct *sksec; 3929 struct sk_security_struct *sksec_sock = sock->sk->sk_security;
3988 struct inode_security_struct *isec; 3930 struct sk_security_struct *sksec_other = other->sk->sk_security;
3989 struct inode_security_struct *other_isec; 3931 struct sk_security_struct *sksec_new = newsk->sk_security;
3990 struct common_audit_data ad; 3932 struct common_audit_data ad;
3991 int err; 3933 int err;
3992 3934
3993 isec = SOCK_INODE(sock)->i_security;
3994 other_isec = SOCK_INODE(other)->i_security;
3995
3996 COMMON_AUDIT_DATA_INIT(&ad, NET); 3935 COMMON_AUDIT_DATA_INIT(&ad, NET);
3997 ad.u.net.sk = other->sk; 3936 ad.u.net.sk = other->sk;
3998 3937
3999 err = avc_has_perm(isec->sid, other_isec->sid, 3938 err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
4000 isec->sclass, 3939 sksec_other->sclass,
4001 UNIX_STREAM_SOCKET__CONNECTTO, &ad); 3940 UNIX_STREAM_SOCKET__CONNECTTO, &ad);
4002 if (err) 3941 if (err)
4003 return err; 3942 return err;
4004 3943
4005 /* connecting socket */
4006 sksec = sock->sk->sk_security;
4007 sksec->peer_sid = other_isec->sid;
4008
4009 /* server child socket */ 3944 /* server child socket */
4010 sksec = newsk->sk_security; 3945 sksec_new->peer_sid = sksec_sock->sid;
4011 sksec->peer_sid = isec->sid; 3946 err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
4012 err = security_sid_mls_copy(other_isec->sid, sksec->peer_sid, &sksec->sid); 3947 &sksec_new->sid);
3948 if (err)
3949 return err;
4013 3950
4014 return err; 3951 /* connecting socket */
3952 sksec_sock->peer_sid = sksec_new->sid;
3953
3954 return 0;
4015} 3955}
4016 3956
4017static int selinux_socket_unix_may_send(struct socket *sock, 3957static int selinux_socket_unix_may_send(struct socket *sock,
4018 struct socket *other) 3958 struct socket *other)
4019{ 3959{
4020 struct inode_security_struct *isec; 3960 struct sk_security_struct *ssec = sock->sk->sk_security;
4021 struct inode_security_struct *other_isec; 3961 struct sk_security_struct *osec = other->sk->sk_security;
4022 struct common_audit_data ad; 3962 struct common_audit_data ad;
4023 int err;
4024
4025 isec = SOCK_INODE(sock)->i_security;
4026 other_isec = SOCK_INODE(other)->i_security;
4027 3963
4028 COMMON_AUDIT_DATA_INIT(&ad, NET); 3964 COMMON_AUDIT_DATA_INIT(&ad, NET);
4029 ad.u.net.sk = other->sk; 3965 ad.u.net.sk = other->sk;
4030 3966
4031 err = avc_has_perm(isec->sid, other_isec->sid, 3967 return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
4032 isec->sclass, SOCKET__SENDTO, &ad); 3968 &ad);
4033 if (err)
4034 return err;
4035
4036 return 0;
4037} 3969}
4038 3970
4039static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, 3971static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
@@ -4172,26 +4104,18 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
4172 int err = 0; 4104 int err = 0;
4173 char *scontext; 4105 char *scontext;
4174 u32 scontext_len; 4106 u32 scontext_len;
4175 struct sk_security_struct *sksec; 4107 struct sk_security_struct *sksec = sock->sk->sk_security;
4176 struct inode_security_struct *isec;
4177 u32 peer_sid = SECSID_NULL; 4108 u32 peer_sid = SECSID_NULL;
4178 4109
4179 isec = SOCK_INODE(sock)->i_security; 4110 if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4180 4111 sksec->sclass == SECCLASS_TCP_SOCKET)
4181 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
4182 isec->sclass == SECCLASS_TCP_SOCKET) {
4183 sksec = sock->sk->sk_security;
4184 peer_sid = sksec->peer_sid; 4112 peer_sid = sksec->peer_sid;
4185 } 4113 if (peer_sid == SECSID_NULL)
4186 if (peer_sid == SECSID_NULL) { 4114 return -ENOPROTOOPT;
4187 err = -ENOPROTOOPT;
4188 goto out;
4189 }
4190 4115
4191 err = security_sid_to_context(peer_sid, &scontext, &scontext_len); 4116 err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
4192
4193 if (err) 4117 if (err)
4194 goto out; 4118 return err;
4195 4119
4196 if (scontext_len > len) { 4120 if (scontext_len > len) {
4197 err = -ERANGE; 4121 err = -ERANGE;
@@ -4204,9 +4128,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
4204out_len: 4128out_len:
4205 if (put_user(scontext_len, optlen)) 4129 if (put_user(scontext_len, optlen))
4206 err = -EFAULT; 4130 err = -EFAULT;
4207
4208 kfree(scontext); 4131 kfree(scontext);
4209out:
4210 return err; 4132 return err;
4211} 4133}
4212 4134
@@ -4238,12 +4160,27 @@ out:
4238 4160
4239static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) 4161static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
4240{ 4162{
4241 return sk_alloc_security(sk, family, priority); 4163 struct sk_security_struct *sksec;
4164
4165 sksec = kzalloc(sizeof(*sksec), priority);
4166 if (!sksec)
4167 return -ENOMEM;
4168
4169 sksec->peer_sid = SECINITSID_UNLABELED;
4170 sksec->sid = SECINITSID_UNLABELED;
4171 selinux_netlbl_sk_security_reset(sksec);
4172 sk->sk_security = sksec;
4173
4174 return 0;
4242} 4175}
4243 4176
4244static void selinux_sk_free_security(struct sock *sk) 4177static void selinux_sk_free_security(struct sock *sk)
4245{ 4178{
4246 sk_free_security(sk); 4179 struct sk_security_struct *sksec = sk->sk_security;
4180
4181 sk->sk_security = NULL;
4182 selinux_netlbl_sk_security_free(sksec);
4183 kfree(sksec);
4247} 4184}
4248 4185
4249static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) 4186static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
@@ -4403,8 +4340,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4403 int err = 0; 4340 int err = 0;
4404 u32 perm; 4341 u32 perm;
4405 struct nlmsghdr *nlh; 4342 struct nlmsghdr *nlh;
4406 struct socket *sock = sk->sk_socket; 4343 struct sk_security_struct *sksec = sk->sk_security;
4407 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
4408 4344
4409 if (skb->len < NLMSG_SPACE(0)) { 4345 if (skb->len < NLMSG_SPACE(0)) {
4410 err = -EINVAL; 4346 err = -EINVAL;
@@ -4412,13 +4348,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4412 } 4348 }
4413 nlh = nlmsg_hdr(skb); 4349 nlh = nlmsg_hdr(skb);
4414 4350
4415 err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); 4351 err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
4416 if (err) { 4352 if (err) {
4417 if (err == -EINVAL) { 4353 if (err == -EINVAL) {
4418 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, 4354 audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
4419 "SELinux: unrecognized netlink message" 4355 "SELinux: unrecognized netlink message"
4420 " type=%hu for sclass=%hu\n", 4356 " type=%hu for sclass=%hu\n",
4421 nlh->nlmsg_type, isec->sclass); 4357 nlh->nlmsg_type, sksec->sclass);
4422 if (!selinux_enforcing || security_get_allow_unknown()) 4358 if (!selinux_enforcing || security_get_allow_unknown())
4423 err = 0; 4359 err = 0;
4424 } 4360 }
@@ -4429,7 +4365,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
4429 goto out; 4365 goto out;
4430 } 4366 }
4431 4367
4432 err = socket_has_perm(current, sock, perm); 4368 err = sock_has_perm(current, sk, perm);
4433out: 4369out:
4434 return err; 4370 return err;
4435} 4371}
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index 8b32e959bb2..b4c9eb4bd6f 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -2,7 +2,8 @@
2 "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append" 2 "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append"
3 3
4#define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ 4#define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \
5 "rename", "execute", "swapon", "quotaon", "mounton" 5 "rename", "execute", "swapon", "quotaon", "mounton", "audit_access", \
6 "open", "execmod"
6 7
7#define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ 8#define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \
8 "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \ 9 "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \
@@ -43,22 +44,21 @@ struct security_class_mapping secclass_map[] = {
43 "quotaget", NULL } }, 44 "quotaget", NULL } },
44 { "file", 45 { "file",
45 { COMMON_FILE_PERMS, 46 { COMMON_FILE_PERMS,
46 "execute_no_trans", "entrypoint", "execmod", "open", NULL } }, 47 "execute_no_trans", "entrypoint", NULL } },
47 { "dir", 48 { "dir",
48 { COMMON_FILE_PERMS, "add_name", "remove_name", 49 { COMMON_FILE_PERMS, "add_name", "remove_name",
49 "reparent", "search", "rmdir", "open", NULL } }, 50 "reparent", "search", "rmdir", NULL } },
50 { "fd", { "use", NULL } }, 51 { "fd", { "use", NULL } },
51 { "lnk_file", 52 { "lnk_file",
52 { COMMON_FILE_PERMS, NULL } }, 53 { COMMON_FILE_PERMS, NULL } },
53 { "chr_file", 54 { "chr_file",
54 { COMMON_FILE_PERMS, 55 { COMMON_FILE_PERMS, NULL } },
55 "execute_no_trans", "entrypoint", "execmod", "open", NULL } },
56 { "blk_file", 56 { "blk_file",
57 { COMMON_FILE_PERMS, "open", NULL } }, 57 { COMMON_FILE_PERMS, NULL } },
58 { "sock_file", 58 { "sock_file",
59 { COMMON_FILE_PERMS, "open", NULL } }, 59 { COMMON_FILE_PERMS, NULL } },
60 { "fifo_file", 60 { "fifo_file",
61 { COMMON_FILE_PERMS, "open", NULL } }, 61 { COMMON_FILE_PERMS, NULL } },
62 { "socket", 62 { "socket",
63 { COMMON_SOCK_PERMS, NULL } }, 63 { COMMON_SOCK_PERMS, NULL } },
64 { "tcp_socket", 64 { "tcp_socket",
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index dc92792271f..65ebfe954f8 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -183,8 +183,6 @@ static void sel_netnode_insert(struct sel_netnode *node)
183 BUG(); 183 BUG();
184 } 184 }
185 185
186 INIT_RCU_HEAD(&node->rcu);
187
188 /* we need to impose a limit on the growth of the hash table so check 186 /* we need to impose a limit on the growth of the hash table so check
189 * this bucket to make sure it is within the specified bounds */ 187 * this bucket to make sure it is within the specified bounds */
190 list_add_rcu(&node->list, &sel_netnode_hash[idx].list); 188 list_add_rcu(&node->list, &sel_netnode_hash[idx].list);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 0293843f7ed..79a1bb63566 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -184,6 +184,7 @@ out:
184static const struct file_operations sel_enforce_ops = { 184static const struct file_operations sel_enforce_ops = {
185 .read = sel_read_enforce, 185 .read = sel_read_enforce,
186 .write = sel_write_enforce, 186 .write = sel_write_enforce,
187 .llseek = generic_file_llseek,
187}; 188};
188 189
189static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, 190static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf,
@@ -201,6 +202,7 @@ static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf,
201 202
202static const struct file_operations sel_handle_unknown_ops = { 203static const struct file_operations sel_handle_unknown_ops = {
203 .read = sel_read_handle_unknown, 204 .read = sel_read_handle_unknown,
205 .llseek = generic_file_llseek,
204}; 206};
205 207
206#ifdef CONFIG_SECURITY_SELINUX_DISABLE 208#ifdef CONFIG_SECURITY_SELINUX_DISABLE
@@ -251,6 +253,7 @@ out:
251 253
252static const struct file_operations sel_disable_ops = { 254static const struct file_operations sel_disable_ops = {
253 .write = sel_write_disable, 255 .write = sel_write_disable,
256 .llseek = generic_file_llseek,
254}; 257};
255 258
256static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, 259static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
@@ -265,6 +268,7 @@ static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
265 268
266static const struct file_operations sel_policyvers_ops = { 269static const struct file_operations sel_policyvers_ops = {
267 .read = sel_read_policyvers, 270 .read = sel_read_policyvers,
271 .llseek = generic_file_llseek,
268}; 272};
269 273
270/* declaration for sel_write_load */ 274/* declaration for sel_write_load */
@@ -289,6 +293,7 @@ static ssize_t sel_read_mls(struct file *filp, char __user *buf,
289 293
290static const struct file_operations sel_mls_ops = { 294static const struct file_operations sel_mls_ops = {
291 .read = sel_read_mls, 295 .read = sel_read_mls,
296 .llseek = generic_file_llseek,
292}; 297};
293 298
294static ssize_t sel_write_load(struct file *file, const char __user *buf, 299static ssize_t sel_write_load(struct file *file, const char __user *buf,
@@ -356,6 +361,7 @@ out:
356 361
357static const struct file_operations sel_load_ops = { 362static const struct file_operations sel_load_ops = {
358 .write = sel_write_load, 363 .write = sel_write_load,
364 .llseek = generic_file_llseek,
359}; 365};
360 366
361static ssize_t sel_write_context(struct file *file, char *buf, size_t size) 367static ssize_t sel_write_context(struct file *file, char *buf, size_t size)
@@ -437,6 +443,7 @@ out:
437static const struct file_operations sel_checkreqprot_ops = { 443static const struct file_operations sel_checkreqprot_ops = {
438 .read = sel_read_checkreqprot, 444 .read = sel_read_checkreqprot,
439 .write = sel_write_checkreqprot, 445 .write = sel_write_checkreqprot,
446 .llseek = generic_file_llseek,
440}; 447};
441 448
442/* 449/*
@@ -482,6 +489,7 @@ static const struct file_operations transaction_ops = {
482 .write = selinux_transaction_write, 489 .write = selinux_transaction_write,
483 .read = simple_transaction_read, 490 .read = simple_transaction_read,
484 .release = simple_transaction_release, 491 .release = simple_transaction_release,
492 .llseek = generic_file_llseek,
485}; 493};
486 494
487/* 495/*
@@ -883,6 +891,7 @@ out:
883static const struct file_operations sel_bool_ops = { 891static const struct file_operations sel_bool_ops = {
884 .read = sel_read_bool, 892 .read = sel_read_bool,
885 .write = sel_write_bool, 893 .write = sel_write_bool,
894 .llseek = generic_file_llseek,
886}; 895};
887 896
888static ssize_t sel_commit_bools_write(struct file *filep, 897static ssize_t sel_commit_bools_write(struct file *filep,
@@ -935,6 +944,7 @@ out:
935 944
936static const struct file_operations sel_commit_bools_ops = { 945static const struct file_operations sel_commit_bools_ops = {
937 .write = sel_commit_bools_write, 946 .write = sel_commit_bools_write,
947 .llseek = generic_file_llseek,
938}; 948};
939 949
940static void sel_remove_entries(struct dentry *de) 950static void sel_remove_entries(struct dentry *de)
@@ -1127,10 +1137,12 @@ out:
1127static const struct file_operations sel_avc_cache_threshold_ops = { 1137static const struct file_operations sel_avc_cache_threshold_ops = {
1128 .read = sel_read_avc_cache_threshold, 1138 .read = sel_read_avc_cache_threshold,
1129 .write = sel_write_avc_cache_threshold, 1139 .write = sel_write_avc_cache_threshold,
1140 .llseek = generic_file_llseek,
1130}; 1141};
1131 1142
1132static const struct file_operations sel_avc_hash_stats_ops = { 1143static const struct file_operations sel_avc_hash_stats_ops = {
1133 .read = sel_read_avc_hash_stats, 1144 .read = sel_read_avc_hash_stats,
1145 .llseek = generic_file_llseek,
1134}; 1146};
1135 1147
1136#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS 1148#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
@@ -1255,6 +1267,7 @@ static ssize_t sel_read_initcon(struct file *file, char __user *buf,
1255 1267
1256static const struct file_operations sel_initcon_ops = { 1268static const struct file_operations sel_initcon_ops = {
1257 .read = sel_read_initcon, 1269 .read = sel_read_initcon,
1270 .llseek = generic_file_llseek,
1258}; 1271};
1259 1272
1260static int sel_make_initcon_files(struct dentry *dir) 1273static int sel_make_initcon_files(struct dentry *dir)
@@ -1330,6 +1343,7 @@ out:
1330 1343
1331static const struct file_operations sel_class_ops = { 1344static const struct file_operations sel_class_ops = {
1332 .read = sel_read_class, 1345 .read = sel_read_class,
1346 .llseek = generic_file_llseek,
1333}; 1347};
1334 1348
1335static ssize_t sel_read_perm(struct file *file, char __user *buf, 1349static ssize_t sel_read_perm(struct file *file, char __user *buf,
@@ -1354,6 +1368,7 @@ out:
1354 1368
1355static const struct file_operations sel_perm_ops = { 1369static const struct file_operations sel_perm_ops = {
1356 .read = sel_read_perm, 1370 .read = sel_read_perm,
1371 .llseek = generic_file_llseek,
1357}; 1372};
1358 1373
1359static ssize_t sel_read_policycap(struct file *file, char __user *buf, 1374static ssize_t sel_read_policycap(struct file *file, char __user *buf,
@@ -1372,6 +1387,7 @@ static ssize_t sel_read_policycap(struct file *file, char __user *buf,
1372 1387
1373static const struct file_operations sel_policycap_ops = { 1388static const struct file_operations sel_policycap_ops = {
1374 .read = sel_read_policycap, 1389 .read = sel_read_policycap,
1390 .llseek = generic_file_llseek,
1375}; 1391};
1376 1392
1377static int sel_make_perm_files(char *objclass, int classvalue, 1393static int sel_make_perm_files(char *objclass, int classvalue,
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 1215b8e47db..929480c6c43 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -342,20 +342,20 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
342 342
343 if (vers < POLICYDB_VERSION_AVTAB) { 343 if (vers < POLICYDB_VERSION_AVTAB) {
344 rc = next_entry(buf32, fp, sizeof(u32)); 344 rc = next_entry(buf32, fp, sizeof(u32));
345 if (rc < 0) { 345 if (rc) {
346 printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 346 printk(KERN_ERR "SELinux: avtab: truncated entry\n");
347 return -1; 347 return rc;
348 } 348 }
349 items2 = le32_to_cpu(buf32[0]); 349 items2 = le32_to_cpu(buf32[0]);
350 if (items2 > ARRAY_SIZE(buf32)) { 350 if (items2 > ARRAY_SIZE(buf32)) {
351 printk(KERN_ERR "SELinux: avtab: entry overflow\n"); 351 printk(KERN_ERR "SELinux: avtab: entry overflow\n");
352 return -1; 352 return -EINVAL;
353 353
354 } 354 }
355 rc = next_entry(buf32, fp, sizeof(u32)*items2); 355 rc = next_entry(buf32, fp, sizeof(u32)*items2);
356 if (rc < 0) { 356 if (rc) {
357 printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 357 printk(KERN_ERR "SELinux: avtab: truncated entry\n");
358 return -1; 358 return rc;
359 } 359 }
360 items = 0; 360 items = 0;
361 361
@@ -363,19 +363,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
363 key.source_type = (u16)val; 363 key.source_type = (u16)val;
364 if (key.source_type != val) { 364 if (key.source_type != val) {
365 printk(KERN_ERR "SELinux: avtab: truncated source type\n"); 365 printk(KERN_ERR "SELinux: avtab: truncated source type\n");
366 return -1; 366 return -EINVAL;
367 } 367 }
368 val = le32_to_cpu(buf32[items++]); 368 val = le32_to_cpu(buf32[items++]);
369 key.target_type = (u16)val; 369 key.target_type = (u16)val;
370 if (key.target_type != val) { 370 if (key.target_type != val) {
371 printk(KERN_ERR "SELinux: avtab: truncated target type\n"); 371 printk(KERN_ERR "SELinux: avtab: truncated target type\n");
372 return -1; 372 return -EINVAL;
373 } 373 }
374 val = le32_to_cpu(buf32[items++]); 374 val = le32_to_cpu(buf32[items++]);
375 key.target_class = (u16)val; 375 key.target_class = (u16)val;
376 if (key.target_class != val) { 376 if (key.target_class != val) {
377 printk(KERN_ERR "SELinux: avtab: truncated target class\n"); 377 printk(KERN_ERR "SELinux: avtab: truncated target class\n");
378 return -1; 378 return -EINVAL;
379 } 379 }
380 380
381 val = le32_to_cpu(buf32[items++]); 381 val = le32_to_cpu(buf32[items++]);
@@ -383,12 +383,12 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
383 383
384 if (!(val & (AVTAB_AV | AVTAB_TYPE))) { 384 if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
385 printk(KERN_ERR "SELinux: avtab: null entry\n"); 385 printk(KERN_ERR "SELinux: avtab: null entry\n");
386 return -1; 386 return -EINVAL;
387 } 387 }
388 if ((val & AVTAB_AV) && 388 if ((val & AVTAB_AV) &&
389 (val & AVTAB_TYPE)) { 389 (val & AVTAB_TYPE)) {
390 printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n"); 390 printk(KERN_ERR "SELinux: avtab: entry has both access vectors and types\n");
391 return -1; 391 return -EINVAL;
392 } 392 }
393 393
394 for (i = 0; i < ARRAY_SIZE(spec_order); i++) { 394 for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
@@ -403,15 +403,15 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
403 403
404 if (items != items2) { 404 if (items != items2) {
405 printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items); 405 printk(KERN_ERR "SELinux: avtab: entry only had %d items, expected %d\n", items2, items);
406 return -1; 406 return -EINVAL;
407 } 407 }
408 return 0; 408 return 0;
409 } 409 }
410 410
411 rc = next_entry(buf16, fp, sizeof(u16)*4); 411 rc = next_entry(buf16, fp, sizeof(u16)*4);
412 if (rc < 0) { 412 if (rc) {
413 printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 413 printk(KERN_ERR "SELinux: avtab: truncated entry\n");
414 return -1; 414 return rc;
415 } 415 }
416 416
417 items = 0; 417 items = 0;
@@ -424,7 +424,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
424 !policydb_type_isvalid(pol, key.target_type) || 424 !policydb_type_isvalid(pol, key.target_type) ||
425 !policydb_class_isvalid(pol, key.target_class)) { 425 !policydb_class_isvalid(pol, key.target_class)) {
426 printk(KERN_ERR "SELinux: avtab: invalid type or class\n"); 426 printk(KERN_ERR "SELinux: avtab: invalid type or class\n");
427 return -1; 427 return -EINVAL;
428 } 428 }
429 429
430 set = 0; 430 set = 0;
@@ -434,19 +434,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
434 } 434 }
435 if (!set || set > 1) { 435 if (!set || set > 1) {
436 printk(KERN_ERR "SELinux: avtab: more than one specifier\n"); 436 printk(KERN_ERR "SELinux: avtab: more than one specifier\n");
437 return -1; 437 return -EINVAL;
438 } 438 }
439 439
440 rc = next_entry(buf32, fp, sizeof(u32)); 440 rc = next_entry(buf32, fp, sizeof(u32));
441 if (rc < 0) { 441 if (rc) {
442 printk(KERN_ERR "SELinux: avtab: truncated entry\n"); 442 printk(KERN_ERR "SELinux: avtab: truncated entry\n");
443 return -1; 443 return rc;
444 } 444 }
445 datum.data = le32_to_cpu(*buf32); 445 datum.data = le32_to_cpu(*buf32);
446 if ((key.specified & AVTAB_TYPE) && 446 if ((key.specified & AVTAB_TYPE) &&
447 !policydb_type_isvalid(pol, datum.data)) { 447 !policydb_type_isvalid(pol, datum.data)) {
448 printk(KERN_ERR "SELinux: avtab: invalid type\n"); 448 printk(KERN_ERR "SELinux: avtab: invalid type\n");
449 return -1; 449 return -EINVAL;
450 } 450 }
451 return insertf(a, &key, &datum, p); 451 return insertf(a, &key, &datum, p);
452} 452}
@@ -487,8 +487,7 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
487 printk(KERN_ERR "SELinux: avtab: out of memory\n"); 487 printk(KERN_ERR "SELinux: avtab: out of memory\n");
488 else if (rc == -EEXIST) 488 else if (rc == -EEXIST)
489 printk(KERN_ERR "SELinux: avtab: duplicate entry\n"); 489 printk(KERN_ERR "SELinux: avtab: duplicate entry\n");
490 else 490
491 rc = -EINVAL;
492 goto bad; 491 goto bad;
493 } 492 }
494 } 493 }
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index 4a4e35cac22..c91e150c308 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -117,10 +117,14 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
117 117
118int cond_policydb_init(struct policydb *p) 118int cond_policydb_init(struct policydb *p)
119{ 119{
120 int rc;
121
120 p->bool_val_to_struct = NULL; 122 p->bool_val_to_struct = NULL;
121 p->cond_list = NULL; 123 p->cond_list = NULL;
122 if (avtab_init(&p->te_cond_avtab)) 124
123 return -1; 125 rc = avtab_init(&p->te_cond_avtab);
126 if (rc)
127 return rc;
124 128
125 return 0; 129 return 0;
126} 130}
@@ -219,34 +223,37 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
219 223
220 booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); 224 booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
221 if (!booldatum) 225 if (!booldatum)
222 return -1; 226 return -ENOMEM;
223 227
224 rc = next_entry(buf, fp, sizeof buf); 228 rc = next_entry(buf, fp, sizeof buf);
225 if (rc < 0) 229 if (rc)
226 goto err; 230 goto err;
227 231
228 booldatum->value = le32_to_cpu(buf[0]); 232 booldatum->value = le32_to_cpu(buf[0]);
229 booldatum->state = le32_to_cpu(buf[1]); 233 booldatum->state = le32_to_cpu(buf[1]);
230 234
235 rc = -EINVAL;
231 if (!bool_isvalid(booldatum)) 236 if (!bool_isvalid(booldatum))
232 goto err; 237 goto err;
233 238
234 len = le32_to_cpu(buf[2]); 239 len = le32_to_cpu(buf[2]);
235 240
241 rc = -ENOMEM;
236 key = kmalloc(len + 1, GFP_KERNEL); 242 key = kmalloc(len + 1, GFP_KERNEL);
237 if (!key) 243 if (!key)
238 goto err; 244 goto err;
239 rc = next_entry(key, fp, len); 245 rc = next_entry(key, fp, len);
240 if (rc < 0) 246 if (rc)
241 goto err; 247 goto err;
242 key[len] = '\0'; 248 key[len] = '\0';
243 if (hashtab_insert(h, key, booldatum)) 249 rc = hashtab_insert(h, key, booldatum);
250 if (rc)
244 goto err; 251 goto err;
245 252
246 return 0; 253 return 0;
247err: 254err:
248 cond_destroy_bool(key, booldatum, NULL); 255 cond_destroy_bool(key, booldatum, NULL);
249 return -1; 256 return rc;
250} 257}
251 258
252struct cond_insertf_data { 259struct cond_insertf_data {
@@ -263,7 +270,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
263 struct cond_av_list *other = data->other, *list, *cur; 270 struct cond_av_list *other = data->other, *list, *cur;
264 struct avtab_node *node_ptr; 271 struct avtab_node *node_ptr;
265 u8 found; 272 u8 found;
266 273 int rc = -EINVAL;
267 274
268 /* 275 /*
269 * For type rules we have to make certain there aren't any 276 * For type rules we have to make certain there aren't any
@@ -313,12 +320,15 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
313 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); 320 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
314 if (!node_ptr) { 321 if (!node_ptr) {
315 printk(KERN_ERR "SELinux: could not insert rule.\n"); 322 printk(KERN_ERR "SELinux: could not insert rule.\n");
323 rc = -ENOMEM;
316 goto err; 324 goto err;
317 } 325 }
318 326
319 list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL); 327 list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL);
320 if (!list) 328 if (!list) {
329 rc = -ENOMEM;
321 goto err; 330 goto err;
331 }
322 332
323 list->node = node_ptr; 333 list->node = node_ptr;
324 if (!data->head) 334 if (!data->head)
@@ -331,7 +341,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
331err: 341err:
332 cond_av_list_destroy(data->head); 342 cond_av_list_destroy(data->head);
333 data->head = NULL; 343 data->head = NULL;
334 return -1; 344 return rc;
335} 345}
336 346
337static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) 347static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other)
@@ -345,8 +355,8 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
345 355
346 len = 0; 356 len = 0;
347 rc = next_entry(buf, fp, sizeof(u32)); 357 rc = next_entry(buf, fp, sizeof(u32));
348 if (rc < 0) 358 if (rc)
349 return -1; 359 return rc;
350 360
351 len = le32_to_cpu(buf[0]); 361 len = le32_to_cpu(buf[0]);
352 if (len == 0) 362 if (len == 0)
@@ -361,7 +371,6 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
361 &data); 371 &data);
362 if (rc) 372 if (rc)
363 return rc; 373 return rc;
364
365 } 374 }
366 375
367 *ret_list = data.head; 376 *ret_list = data.head;
@@ -390,24 +399,25 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
390 struct cond_expr *expr = NULL, *last = NULL; 399 struct cond_expr *expr = NULL, *last = NULL;
391 400
392 rc = next_entry(buf, fp, sizeof(u32)); 401 rc = next_entry(buf, fp, sizeof(u32));
393 if (rc < 0) 402 if (rc)
394 return -1; 403 return rc;
395 404
396 node->cur_state = le32_to_cpu(buf[0]); 405 node->cur_state = le32_to_cpu(buf[0]);
397 406
398 len = 0; 407 len = 0;
399 rc = next_entry(buf, fp, sizeof(u32)); 408 rc = next_entry(buf, fp, sizeof(u32));
400 if (rc < 0) 409 if (rc)
401 return -1; 410 return rc;
402 411
403 /* expr */ 412 /* expr */
404 len = le32_to_cpu(buf[0]); 413 len = le32_to_cpu(buf[0]);
405 414
406 for (i = 0; i < len; i++) { 415 for (i = 0; i < len; i++) {
407 rc = next_entry(buf, fp, sizeof(u32) * 2); 416 rc = next_entry(buf, fp, sizeof(u32) * 2);
408 if (rc < 0) 417 if (rc)
409 goto err; 418 goto err;
410 419
420 rc = -ENOMEM;
411 expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL); 421 expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL);
412 if (!expr) 422 if (!expr)
413 goto err; 423 goto err;
@@ -416,6 +426,7 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
416 expr->bool = le32_to_cpu(buf[1]); 426 expr->bool = le32_to_cpu(buf[1]);
417 427
418 if (!expr_isvalid(p, expr)) { 428 if (!expr_isvalid(p, expr)) {
429 rc = -EINVAL;
419 kfree(expr); 430 kfree(expr);
420 goto err; 431 goto err;
421 } 432 }
@@ -427,14 +438,16 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
427 last = expr; 438 last = expr;
428 } 439 }
429 440
430 if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0) 441 rc = cond_read_av_list(p, fp, &node->true_list, NULL);
442 if (rc)
431 goto err; 443 goto err;
432 if (cond_read_av_list(p, fp, &node->false_list, node->true_list) != 0) 444 rc = cond_read_av_list(p, fp, &node->false_list, node->true_list);
445 if (rc)
433 goto err; 446 goto err;
434 return 0; 447 return 0;
435err: 448err:
436 cond_node_destroy(node); 449 cond_node_destroy(node);
437 return -1; 450 return rc;
438} 451}
439 452
440int cond_read_list(struct policydb *p, void *fp) 453int cond_read_list(struct policydb *p, void *fp)
@@ -445,8 +458,8 @@ int cond_read_list(struct policydb *p, void *fp)
445 int rc; 458 int rc;
446 459
447 rc = next_entry(buf, fp, sizeof buf); 460 rc = next_entry(buf, fp, sizeof buf);
448 if (rc < 0) 461 if (rc)
449 return -1; 462 return rc;
450 463
451 len = le32_to_cpu(buf[0]); 464 len = le32_to_cpu(buf[0]);
452 465
@@ -455,11 +468,13 @@ int cond_read_list(struct policydb *p, void *fp)
455 goto err; 468 goto err;
456 469
457 for (i = 0; i < len; i++) { 470 for (i = 0; i < len; i++) {
471 rc = -ENOMEM;
458 node = kzalloc(sizeof(struct cond_node), GFP_KERNEL); 472 node = kzalloc(sizeof(struct cond_node), GFP_KERNEL);
459 if (!node) 473 if (!node)
460 goto err; 474 goto err;
461 475
462 if (cond_read_node(p, node, fp) != 0) 476 rc = cond_read_node(p, node, fp);
477 if (rc)
463 goto err; 478 goto err;
464 479
465 if (i == 0) 480 if (i == 0)
@@ -472,7 +487,7 @@ int cond_read_list(struct policydb *p, void *fp)
472err: 487err:
473 cond_list_destroy(p->cond_list); 488 cond_list_destroy(p->cond_list);
474 p->cond_list = NULL; 489 p->cond_list = NULL;
475 return -1; 490 return rc;
476} 491}
477 492
478/* Determine whether additional permissions are granted by the conditional 493/* Determine whether additional permissions are granted by the conditional
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index c57802a164d..3a29704be8c 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -31,6 +31,7 @@
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/errno.h> 32#include <linux/errno.h>
33#include <linux/audit.h> 33#include <linux/audit.h>
34#include <linux/flex_array.h>
34#include "security.h" 35#include "security.h"
35 36
36#include "policydb.h" 37#include "policydb.h"
@@ -655,6 +656,9 @@ static int range_tr_destroy(void *key, void *datum, void *p)
655 656
656static void ocontext_destroy(struct ocontext *c, int i) 657static void ocontext_destroy(struct ocontext *c, int i)
657{ 658{
659 if (!c)
660 return;
661
658 context_destroy(&c->context[0]); 662 context_destroy(&c->context[0]);
659 context_destroy(&c->context[1]); 663 context_destroy(&c->context[1]);
660 if (i == OCON_ISID || i == OCON_FS || 664 if (i == OCON_ISID || i == OCON_FS ||
@@ -736,11 +740,17 @@ void policydb_destroy(struct policydb *p)
736 hashtab_map(p->range_tr, range_tr_destroy, NULL); 740 hashtab_map(p->range_tr, range_tr_destroy, NULL);
737 hashtab_destroy(p->range_tr); 741 hashtab_destroy(p->range_tr);
738 742
739 if (p->type_attr_map) { 743 if (p->type_attr_map_array) {
740 for (i = 0; i < p->p_types.nprim; i++) 744 for (i = 0; i < p->p_types.nprim; i++) {
741 ebitmap_destroy(&p->type_attr_map[i]); 745 struct ebitmap *e;
746
747 e = flex_array_get(p->type_attr_map_array, i);
748 if (!e)
749 continue;
750 ebitmap_destroy(e);
751 }
752 flex_array_free(p->type_attr_map_array);
742 } 753 }
743 kfree(p->type_attr_map);
744 ebitmap_destroy(&p->policycaps); 754 ebitmap_destroy(&p->policycaps);
745 ebitmap_destroy(&p->permissive_map); 755 ebitmap_destroy(&p->permissive_map);
746 756
@@ -1701,6 +1711,333 @@ u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name)
1701 return 1U << (perdatum->value-1); 1711 return 1U << (perdatum->value-1);
1702} 1712}
1703 1713
1714static int range_read(struct policydb *p, void *fp)
1715{
1716 struct range_trans *rt = NULL;
1717 struct mls_range *r = NULL;
1718 int i, rc;
1719 __le32 buf[2];
1720 u32 nel;
1721
1722 if (p->policyvers < POLICYDB_VERSION_MLS)
1723 return 0;
1724
1725 rc = next_entry(buf, fp, sizeof(u32));
1726 if (rc)
1727 goto out;
1728
1729 nel = le32_to_cpu(buf[0]);
1730 for (i = 0; i < nel; i++) {
1731 rc = -ENOMEM;
1732 rt = kzalloc(sizeof(*rt), GFP_KERNEL);
1733 if (!rt)
1734 goto out;
1735
1736 rc = next_entry(buf, fp, (sizeof(u32) * 2));
1737 if (rc)
1738 goto out;
1739
1740 rt->source_type = le32_to_cpu(buf[0]);
1741 rt->target_type = le32_to_cpu(buf[1]);
1742 if (p->policyvers >= POLICYDB_VERSION_RANGETRANS) {
1743 rc = next_entry(buf, fp, sizeof(u32));
1744 if (rc)
1745 goto out;
1746 rt->target_class = le32_to_cpu(buf[0]);
1747 } else
1748 rt->target_class = p->process_class;
1749
1750 rc = -EINVAL;
1751 if (!policydb_type_isvalid(p, rt->source_type) ||
1752 !policydb_type_isvalid(p, rt->target_type) ||
1753 !policydb_class_isvalid(p, rt->target_class))
1754 goto out;
1755
1756 rc = -ENOMEM;
1757 r = kzalloc(sizeof(*r), GFP_KERNEL);
1758 if (!r)
1759 goto out;
1760
1761 rc = mls_read_range_helper(r, fp);
1762 if (rc)
1763 goto out;
1764
1765 rc = -EINVAL;
1766 if (!mls_range_isvalid(p, r)) {
1767 printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
1768 goto out;
1769 }
1770
1771 rc = hashtab_insert(p->range_tr, rt, r);
1772 if (rc)
1773 goto out;
1774
1775 rt = NULL;
1776 r = NULL;
1777 }
1778 rangetr_hash_eval(p->range_tr);
1779 rc = 0;
1780out:
1781 kfree(rt);
1782 kfree(r);
1783 return rc;
1784}
1785
1786static int genfs_read(struct policydb *p, void *fp)
1787{
1788 int i, j, rc;
1789 u32 nel, nel2, len, len2;
1790 __le32 buf[1];
1791 struct ocontext *l, *c;
1792 struct ocontext *newc = NULL;
1793 struct genfs *genfs_p, *genfs;
1794 struct genfs *newgenfs = NULL;
1795
1796 rc = next_entry(buf, fp, sizeof(u32));
1797 if (rc)
1798 goto out;
1799 nel = le32_to_cpu(buf[0]);
1800
1801 for (i = 0; i < nel; i++) {
1802 rc = next_entry(buf, fp, sizeof(u32));
1803 if (rc)
1804 goto out;
1805 len = le32_to_cpu(buf[0]);
1806
1807 rc = -ENOMEM;
1808 newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
1809 if (!newgenfs)
1810 goto out;
1811
1812 rc = -ENOMEM;
1813 newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL);
1814 if (!newgenfs->fstype)
1815 goto out;
1816
1817 rc = next_entry(newgenfs->fstype, fp, len);
1818 if (rc)
1819 goto out;
1820
1821 newgenfs->fstype[len] = 0;
1822
1823 for (genfs_p = NULL, genfs = p->genfs; genfs;
1824 genfs_p = genfs, genfs = genfs->next) {
1825 rc = -EINVAL;
1826 if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
1827 printk(KERN_ERR "SELinux: dup genfs fstype %s\n",
1828 newgenfs->fstype);
1829 goto out;
1830 }
1831 if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
1832 break;
1833 }
1834 newgenfs->next = genfs;
1835 if (genfs_p)
1836 genfs_p->next = newgenfs;
1837 else
1838 p->genfs = newgenfs;
1839 genfs = newgenfs;
1840 newgenfs = NULL;
1841
1842 rc = next_entry(buf, fp, sizeof(u32));
1843 if (rc)
1844 goto out;
1845
1846 nel2 = le32_to_cpu(buf[0]);
1847 for (j = 0; j < nel2; j++) {
1848 rc = next_entry(buf, fp, sizeof(u32));
1849 if (rc)
1850 goto out;
1851 len = le32_to_cpu(buf[0]);
1852
1853 rc = -ENOMEM;
1854 newc = kzalloc(sizeof(*newc), GFP_KERNEL);
1855 if (!newc)
1856 goto out;
1857
1858 rc = -ENOMEM;
1859 newc->u.name = kmalloc(len + 1, GFP_KERNEL);
1860 if (!newc->u.name)
1861 goto out;
1862
1863 rc = next_entry(newc->u.name, fp, len);
1864 if (rc)
1865 goto out;
1866 newc->u.name[len] = 0;
1867
1868 rc = next_entry(buf, fp, sizeof(u32));
1869 if (rc)
1870 goto out;
1871
1872 newc->v.sclass = le32_to_cpu(buf[0]);
1873 rc = context_read_and_validate(&newc->context[0], p, fp);
1874 if (rc)
1875 goto out;
1876
1877 for (l = NULL, c = genfs->head; c;
1878 l = c, c = c->next) {
1879 rc = -EINVAL;
1880 if (!strcmp(newc->u.name, c->u.name) &&
1881 (!c->v.sclass || !newc->v.sclass ||
1882 newc->v.sclass == c->v.sclass)) {
1883 printk(KERN_ERR "SELinux: dup genfs entry (%s,%s)\n",
1884 genfs->fstype, c->u.name);
1885 goto out;
1886 }
1887 len = strlen(newc->u.name);
1888 len2 = strlen(c->u.name);
1889 if (len > len2)
1890 break;
1891 }
1892
1893 newc->next = c;
1894 if (l)
1895 l->next = newc;
1896 else
1897 genfs->head = newc;
1898 newc = NULL;
1899 }
1900 }
1901 rc = 0;
1902out:
1903 if (newgenfs)
1904 kfree(newgenfs->fstype);
1905 kfree(newgenfs);
1906 ocontext_destroy(newc, OCON_FSUSE);
1907
1908 return rc;
1909}
1910
1911static int ocontext_read(struct policydb *p, struct policydb_compat_info *info,
1912 void *fp)
1913{
1914 int i, j, rc;
1915 u32 nel, len;
1916 __le32 buf[3];
1917 struct ocontext *l, *c;
1918 u32 nodebuf[8];
1919
1920 for (i = 0; i < info->ocon_num; i++) {
1921 rc = next_entry(buf, fp, sizeof(u32));
1922 if (rc)
1923 goto out;
1924 nel = le32_to_cpu(buf[0]);
1925
1926 l = NULL;
1927 for (j = 0; j < nel; j++) {
1928 rc = -ENOMEM;
1929 c = kzalloc(sizeof(*c), GFP_KERNEL);
1930 if (!c)
1931 goto out;
1932 if (l)
1933 l->next = c;
1934 else
1935 p->ocontexts[i] = c;
1936 l = c;
1937
1938 switch (i) {
1939 case OCON_ISID:
1940 rc = next_entry(buf, fp, sizeof(u32));
1941 if (rc)
1942 goto out;
1943
1944 c->sid[0] = le32_to_cpu(buf[0]);
1945 rc = context_read_and_validate(&c->context[0], p, fp);
1946 if (rc)
1947 goto out;
1948 break;
1949 case OCON_FS:
1950 case OCON_NETIF:
1951 rc = next_entry(buf, fp, sizeof(u32));
1952 if (rc)
1953 goto out;
1954 len = le32_to_cpu(buf[0]);
1955
1956 rc = -ENOMEM;
1957 c->u.name = kmalloc(len + 1, GFP_KERNEL);
1958 if (!c->u.name)
1959 goto out;
1960
1961 rc = next_entry(c->u.name, fp, len);
1962 if (rc)
1963 goto out;
1964
1965 c->u.name[len] = 0;
1966 rc = context_read_and_validate(&c->context[0], p, fp);
1967 if (rc)
1968 goto out;
1969 rc = context_read_and_validate(&c->context[1], p, fp);
1970 if (rc)
1971 goto out;
1972 break;
1973 case OCON_PORT:
1974 rc = next_entry(buf, fp, sizeof(u32)*3);
1975 if (rc)
1976 goto out;
1977 c->u.port.protocol = le32_to_cpu(buf[0]);
1978 c->u.port.low_port = le32_to_cpu(buf[1]);
1979 c->u.port.high_port = le32_to_cpu(buf[2]);
1980 rc = context_read_and_validate(&c->context[0], p, fp);
1981 if (rc)
1982 goto out;
1983 break;
1984 case OCON_NODE:
1985 rc = next_entry(nodebuf, fp, sizeof(u32) * 2);
1986 if (rc)
1987 goto out;
1988 c->u.node.addr = nodebuf[0]; /* network order */
1989 c->u.node.mask = nodebuf[1]; /* network order */
1990 rc = context_read_and_validate(&c->context[0], p, fp);
1991 if (rc)
1992 goto out;
1993 break;
1994 case OCON_FSUSE:
1995 rc = next_entry(buf, fp, sizeof(u32)*2);
1996 if (rc)
1997 goto out;
1998
1999 rc = -EINVAL;
2000 c->v.behavior = le32_to_cpu(buf[0]);
2001 if (c->v.behavior > SECURITY_FS_USE_NONE)
2002 goto out;
2003
2004 rc = -ENOMEM;
2005 len = le32_to_cpu(buf[1]);
2006 c->u.name = kmalloc(len + 1, GFP_KERNEL);
2007 if (!c->u.name)
2008 goto out;
2009
2010 rc = next_entry(c->u.name, fp, len);
2011 if (rc)
2012 goto out;
2013 c->u.name[len] = 0;
2014 rc = context_read_and_validate(&c->context[0], p, fp);
2015 if (rc)
2016 goto out;
2017 break;
2018 case OCON_NODE6: {
2019 int k;
2020
2021 rc = next_entry(nodebuf, fp, sizeof(u32) * 8);
2022 if (rc)
2023 goto out;
2024 for (k = 0; k < 4; k++)
2025 c->u.node6.addr[k] = nodebuf[k];
2026 for (k = 0; k < 4; k++)
2027 c->u.node6.mask[k] = nodebuf[k+4];
2028 rc = context_read_and_validate(&c->context[0], p, fp);
2029 if (rc)
2030 goto out;
2031 break;
2032 }
2033 }
2034 }
2035 }
2036 rc = 0;
2037out:
2038 return rc;
2039}
2040
1704/* 2041/*
1705 * Read the configuration data from a policy database binary 2042 * Read the configuration data from a policy database binary
1706 * representation file into a policy database structure. 2043 * representation file into a policy database structure.
@@ -1709,16 +2046,12 @@ int policydb_read(struct policydb *p, void *fp)
1709{ 2046{
1710 struct role_allow *ra, *lra; 2047 struct role_allow *ra, *lra;
1711 struct role_trans *tr, *ltr; 2048 struct role_trans *tr, *ltr;
1712 struct ocontext *l, *c, *newc;
1713 struct genfs *genfs_p, *genfs, *newgenfs;
1714 int i, j, rc; 2049 int i, j, rc;
1715 __le32 buf[4]; 2050 __le32 buf[4];
1716 u32 nodebuf[8]; 2051 u32 len, nprim, nel;
1717 u32 len, len2, nprim, nel, nel2; 2052
1718 char *policydb_str; 2053 char *policydb_str;
1719 struct policydb_compat_info *info; 2054 struct policydb_compat_info *info;
1720 struct range_trans *rt;
1721 struct mls_range *r;
1722 2055
1723 rc = policydb_init(p); 2056 rc = policydb_init(p);
1724 if (rc) 2057 if (rc)
@@ -1919,294 +2252,45 @@ int policydb_read(struct policydb *p, void *fp)
1919 if (!p->process_trans_perms) 2252 if (!p->process_trans_perms)
1920 goto bad; 2253 goto bad;
1921 2254
1922 for (i = 0; i < info->ocon_num; i++) { 2255 rc = ocontext_read(p, info, fp);
1923 rc = next_entry(buf, fp, sizeof(u32)); 2256 if (rc)
1924 if (rc < 0)
1925 goto bad;
1926 nel = le32_to_cpu(buf[0]);
1927 l = NULL;
1928 for (j = 0; j < nel; j++) {
1929 c = kzalloc(sizeof(*c), GFP_KERNEL);
1930 if (!c) {
1931 rc = -ENOMEM;
1932 goto bad;
1933 }
1934 if (l)
1935 l->next = c;
1936 else
1937 p->ocontexts[i] = c;
1938 l = c;
1939 rc = -EINVAL;
1940 switch (i) {
1941 case OCON_ISID:
1942 rc = next_entry(buf, fp, sizeof(u32));
1943 if (rc < 0)
1944 goto bad;
1945 c->sid[0] = le32_to_cpu(buf[0]);
1946 rc = context_read_and_validate(&c->context[0], p, fp);
1947 if (rc)
1948 goto bad;
1949 break;
1950 case OCON_FS:
1951 case OCON_NETIF:
1952 rc = next_entry(buf, fp, sizeof(u32));
1953 if (rc < 0)
1954 goto bad;
1955 len = le32_to_cpu(buf[0]);
1956 c->u.name = kmalloc(len + 1, GFP_KERNEL);
1957 if (!c->u.name) {
1958 rc = -ENOMEM;
1959 goto bad;
1960 }
1961 rc = next_entry(c->u.name, fp, len);
1962 if (rc < 0)
1963 goto bad;
1964 c->u.name[len] = 0;
1965 rc = context_read_and_validate(&c->context[0], p, fp);
1966 if (rc)
1967 goto bad;
1968 rc = context_read_and_validate(&c->context[1], p, fp);
1969 if (rc)
1970 goto bad;
1971 break;
1972 case OCON_PORT:
1973 rc = next_entry(buf, fp, sizeof(u32)*3);
1974 if (rc < 0)
1975 goto bad;
1976 c->u.port.protocol = le32_to_cpu(buf[0]);
1977 c->u.port.low_port = le32_to_cpu(buf[1]);
1978 c->u.port.high_port = le32_to_cpu(buf[2]);
1979 rc = context_read_and_validate(&c->context[0], p, fp);
1980 if (rc)
1981 goto bad;
1982 break;
1983 case OCON_NODE:
1984 rc = next_entry(nodebuf, fp, sizeof(u32) * 2);
1985 if (rc < 0)
1986 goto bad;
1987 c->u.node.addr = nodebuf[0]; /* network order */
1988 c->u.node.mask = nodebuf[1]; /* network order */
1989 rc = context_read_and_validate(&c->context[0], p, fp);
1990 if (rc)
1991 goto bad;
1992 break;
1993 case OCON_FSUSE:
1994 rc = next_entry(buf, fp, sizeof(u32)*2);
1995 if (rc < 0)
1996 goto bad;
1997 c->v.behavior = le32_to_cpu(buf[0]);
1998 if (c->v.behavior > SECURITY_FS_USE_NONE)
1999 goto bad;
2000 len = le32_to_cpu(buf[1]);
2001 c->u.name = kmalloc(len + 1, GFP_KERNEL);
2002 if (!c->u.name) {
2003 rc = -ENOMEM;
2004 goto bad;
2005 }
2006 rc = next_entry(c->u.name, fp, len);
2007 if (rc < 0)
2008 goto bad;
2009 c->u.name[len] = 0;
2010 rc = context_read_and_validate(&c->context[0], p, fp);
2011 if (rc)
2012 goto bad;
2013 break;
2014 case OCON_NODE6: {
2015 int k;
2016
2017 rc = next_entry(nodebuf, fp, sizeof(u32) * 8);
2018 if (rc < 0)
2019 goto bad;
2020 for (k = 0; k < 4; k++)
2021 c->u.node6.addr[k] = nodebuf[k];
2022 for (k = 0; k < 4; k++)
2023 c->u.node6.mask[k] = nodebuf[k+4];
2024 if (context_read_and_validate(&c->context[0], p, fp))
2025 goto bad;
2026 break;
2027 }
2028 }
2029 }
2030 }
2031
2032 rc = next_entry(buf, fp, sizeof(u32));
2033 if (rc < 0)
2034 goto bad; 2257 goto bad;
2035 nel = le32_to_cpu(buf[0]);
2036 genfs_p = NULL;
2037 rc = -EINVAL;
2038 for (i = 0; i < nel; i++) {
2039 rc = next_entry(buf, fp, sizeof(u32));
2040 if (rc < 0)
2041 goto bad;
2042 len = le32_to_cpu(buf[0]);
2043 newgenfs = kzalloc(sizeof(*newgenfs), GFP_KERNEL);
2044 if (!newgenfs) {
2045 rc = -ENOMEM;
2046 goto bad;
2047 }
2048 2258
2049 newgenfs->fstype = kmalloc(len + 1, GFP_KERNEL); 2259 rc = genfs_read(p, fp);
2050 if (!newgenfs->fstype) { 2260 if (rc)
2051 rc = -ENOMEM; 2261 goto bad;
2052 kfree(newgenfs);
2053 goto bad;
2054 }
2055 rc = next_entry(newgenfs->fstype, fp, len);
2056 if (rc < 0) {
2057 kfree(newgenfs->fstype);
2058 kfree(newgenfs);
2059 goto bad;
2060 }
2061 newgenfs->fstype[len] = 0;
2062 for (genfs_p = NULL, genfs = p->genfs; genfs;
2063 genfs_p = genfs, genfs = genfs->next) {
2064 if (strcmp(newgenfs->fstype, genfs->fstype) == 0) {
2065 printk(KERN_ERR "SELinux: dup genfs "
2066 "fstype %s\n", newgenfs->fstype);
2067 kfree(newgenfs->fstype);
2068 kfree(newgenfs);
2069 goto bad;
2070 }
2071 if (strcmp(newgenfs->fstype, genfs->fstype) < 0)
2072 break;
2073 }
2074 newgenfs->next = genfs;
2075 if (genfs_p)
2076 genfs_p->next = newgenfs;
2077 else
2078 p->genfs = newgenfs;
2079 rc = next_entry(buf, fp, sizeof(u32));
2080 if (rc < 0)
2081 goto bad;
2082 nel2 = le32_to_cpu(buf[0]);
2083 for (j = 0; j < nel2; j++) {
2084 rc = next_entry(buf, fp, sizeof(u32));
2085 if (rc < 0)
2086 goto bad;
2087 len = le32_to_cpu(buf[0]);
2088
2089 newc = kzalloc(sizeof(*newc), GFP_KERNEL);
2090 if (!newc) {
2091 rc = -ENOMEM;
2092 goto bad;
2093 }
2094
2095 newc->u.name = kmalloc(len + 1, GFP_KERNEL);
2096 if (!newc->u.name) {
2097 rc = -ENOMEM;
2098 goto bad_newc;
2099 }
2100 rc = next_entry(newc->u.name, fp, len);
2101 if (rc < 0)
2102 goto bad_newc;
2103 newc->u.name[len] = 0;
2104 rc = next_entry(buf, fp, sizeof(u32));
2105 if (rc < 0)
2106 goto bad_newc;
2107 newc->v.sclass = le32_to_cpu(buf[0]);
2108 if (context_read_and_validate(&newc->context[0], p, fp))
2109 goto bad_newc;
2110 for (l = NULL, c = newgenfs->head; c;
2111 l = c, c = c->next) {
2112 if (!strcmp(newc->u.name, c->u.name) &&
2113 (!c->v.sclass || !newc->v.sclass ||
2114 newc->v.sclass == c->v.sclass)) {
2115 printk(KERN_ERR "SELinux: dup genfs "
2116 "entry (%s,%s)\n",
2117 newgenfs->fstype, c->u.name);
2118 goto bad_newc;
2119 }
2120 len = strlen(newc->u.name);
2121 len2 = strlen(c->u.name);
2122 if (len > len2)
2123 break;
2124 }
2125 2262
2126 newc->next = c; 2263 rc = range_read(p, fp);
2127 if (l) 2264 if (rc)
2128 l->next = newc; 2265 goto bad;
2129 else
2130 newgenfs->head = newc;
2131 }
2132 }
2133 2266
2134 if (p->policyvers >= POLICYDB_VERSION_MLS) { 2267 rc = -ENOMEM;
2135 int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS; 2268 p->type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap),
2136 rc = next_entry(buf, fp, sizeof(u32)); 2269 p->p_types.nprim,
2137 if (rc < 0) 2270 GFP_KERNEL | __GFP_ZERO);
2138 goto bad; 2271 if (!p->type_attr_map_array)
2139 nel = le32_to_cpu(buf[0]); 2272 goto bad;
2140 for (i = 0; i < nel; i++) {
2141 rt = kzalloc(sizeof(*rt), GFP_KERNEL);
2142 if (!rt) {
2143 rc = -ENOMEM;
2144 goto bad;
2145 }
2146 rc = next_entry(buf, fp, (sizeof(u32) * 2));
2147 if (rc < 0) {
2148 kfree(rt);
2149 goto bad;
2150 }
2151 rt->source_type = le32_to_cpu(buf[0]);
2152 rt->target_type = le32_to_cpu(buf[1]);
2153 if (new_rangetr) {
2154 rc = next_entry(buf, fp, sizeof(u32));
2155 if (rc < 0) {
2156 kfree(rt);
2157 goto bad;
2158 }
2159 rt->target_class = le32_to_cpu(buf[0]);
2160 } else
2161 rt->target_class = p->process_class;
2162 if (!policydb_type_isvalid(p, rt->source_type) ||
2163 !policydb_type_isvalid(p, rt->target_type) ||
2164 !policydb_class_isvalid(p, rt->target_class)) {
2165 kfree(rt);
2166 rc = -EINVAL;
2167 goto bad;
2168 }
2169 r = kzalloc(sizeof(*r), GFP_KERNEL);
2170 if (!r) {
2171 kfree(rt);
2172 rc = -ENOMEM;
2173 goto bad;
2174 }
2175 rc = mls_read_range_helper(r, fp);
2176 if (rc) {
2177 kfree(rt);
2178 kfree(r);
2179 goto bad;
2180 }
2181 if (!mls_range_isvalid(p, r)) {
2182 printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
2183 kfree(rt);
2184 kfree(r);
2185 goto bad;
2186 }
2187 rc = hashtab_insert(p->range_tr, rt, r);
2188 if (rc) {
2189 kfree(rt);
2190 kfree(r);
2191 goto bad;
2192 }
2193 }
2194 rangetr_hash_eval(p->range_tr);
2195 }
2196 2273
2197 p->type_attr_map = kmalloc(p->p_types.nprim * sizeof(struct ebitmap), GFP_KERNEL); 2274 /* preallocate so we don't have to worry about the put ever failing */
2198 if (!p->type_attr_map) 2275 rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1,
2276 GFP_KERNEL | __GFP_ZERO);
2277 if (rc)
2199 goto bad; 2278 goto bad;
2200 2279
2201 for (i = 0; i < p->p_types.nprim; i++) { 2280 for (i = 0; i < p->p_types.nprim; i++) {
2202 ebitmap_init(&p->type_attr_map[i]); 2281 struct ebitmap *e = flex_array_get(p->type_attr_map_array, i);
2282
2283 BUG_ON(!e);
2284 ebitmap_init(e);
2203 if (p->policyvers >= POLICYDB_VERSION_AVTAB) { 2285 if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
2204 if (ebitmap_read(&p->type_attr_map[i], fp)) 2286 rc = ebitmap_read(e, fp);
2287 if (rc)
2205 goto bad; 2288 goto bad;
2206 } 2289 }
2207 /* add the type itself as the degenerate case */ 2290 /* add the type itself as the degenerate case */
2208 if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) 2291 rc = ebitmap_set_bit(e, i, 1);
2209 goto bad; 2292 if (rc)
2293 goto bad;
2210 } 2294 }
2211 2295
2212 rc = policydb_bounds_sanity_check(p); 2296 rc = policydb_bounds_sanity_check(p);
@@ -2216,8 +2300,6 @@ int policydb_read(struct policydb *p, void *fp)
2216 rc = 0; 2300 rc = 0;
2217out: 2301out:
2218 return rc; 2302 return rc;
2219bad_newc:
2220 ocontext_destroy(newc, OCON_FSUSE);
2221bad: 2303bad:
2222 if (!rc) 2304 if (!rc)
2223 rc = -EINVAL; 2305 rc = -EINVAL;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 26d9adf8542..310e94442cb 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -24,6 +24,8 @@
24#ifndef _SS_POLICYDB_H_ 24#ifndef _SS_POLICYDB_H_
25#define _SS_POLICYDB_H_ 25#define _SS_POLICYDB_H_
26 26
27#include <linux/flex_array.h>
28
27#include "symtab.h" 29#include "symtab.h"
28#include "avtab.h" 30#include "avtab.h"
29#include "sidtab.h" 31#include "sidtab.h"
@@ -246,7 +248,7 @@ struct policydb {
246 struct hashtab *range_tr; 248 struct hashtab *range_tr;
247 249
248 /* type -> attribute reverse mapping */ 250 /* type -> attribute reverse mapping */
249 struct ebitmap *type_attr_map; 251 struct flex_array *type_attr_map_array;
250 252
251 struct ebitmap policycaps; 253 struct ebitmap policycaps;
252 254
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 1de60ce90d9..9ea2feca3cd 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -50,6 +50,7 @@
50#include <linux/audit.h> 50#include <linux/audit.h>
51#include <linux/mutex.h> 51#include <linux/mutex.h>
52#include <linux/selinux.h> 52#include <linux/selinux.h>
53#include <linux/flex_array.h>
53#include <net/netlabel.h> 54#include <net/netlabel.h>
54 55
55#include "flask.h" 56#include "flask.h"
@@ -626,8 +627,10 @@ static void context_struct_compute_av(struct context *scontext,
626 */ 627 */
627 avkey.target_class = tclass; 628 avkey.target_class = tclass;
628 avkey.specified = AVTAB_AV; 629 avkey.specified = AVTAB_AV;
629 sattr = &policydb.type_attr_map[scontext->type - 1]; 630 sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1);
630 tattr = &policydb.type_attr_map[tcontext->type - 1]; 631 BUG_ON(!sattr);
632 tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1);
633 BUG_ON(!tattr);
631 ebitmap_for_each_positive_bit(sattr, snode, i) { 634 ebitmap_for_each_positive_bit(sattr, snode, i) {
632 ebitmap_for_each_positive_bit(tattr, tnode, j) { 635 ebitmap_for_each_positive_bit(tattr, tnode, j) {
633 avkey.source_type = i + 1; 636 avkey.source_type = i + 1;
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c
index bcf9f620426..160326ee99e 100644
--- a/security/selinux/ss/symtab.c
+++ b/security/selinux/ss/symtab.c
@@ -36,7 +36,7 @@ int symtab_init(struct symtab *s, unsigned int size)
36{ 36{
37 s->table = hashtab_create(symhash, symcmp, size); 37 s->table = hashtab_create(symhash, symcmp, size);
38 if (!s->table) 38 if (!s->table)
39 return -1; 39 return -ENOMEM;
40 s->nprim = 0; 40 s->nprim = 0;
41 return 0; 41 return 0;
42} 42}
diff --git a/security/smack/smack.h b/security/smack/smack.h
index c6e9acae72e..43ae747a5aa 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -123,16 +123,6 @@ struct smack_known {
123#define SMK_FSHAT "smackfshat=" 123#define SMK_FSHAT "smackfshat="
124#define SMK_FSROOT "smackfsroot=" 124#define SMK_FSROOT "smackfsroot="
125 125
126/*
127 * xattr names
128 */
129#define XATTR_SMACK_SUFFIX "SMACK64"
130#define XATTR_SMACK_IPIN "SMACK64IPIN"
131#define XATTR_SMACK_IPOUT "SMACK64IPOUT"
132#define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX
133#define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
134#define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
135
136#define SMACK_CIPSO_OPTION "-CIPSO" 126#define SMACK_CIPSO_OPTION "-CIPSO"
137 127
138/* 128/*
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 0f2fc480fc6..c448d57ae2b 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -598,6 +598,8 @@ static int smack_inode_rename(struct inode *old_inode,
598static int smack_inode_permission(struct inode *inode, int mask) 598static int smack_inode_permission(struct inode *inode, int mask)
599{ 599{
600 struct smk_audit_info ad; 600 struct smk_audit_info ad;
601
602 mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
601 /* 603 /*
602 * No permission to check. Existence test. Yup, it's there. 604 * No permission to check. Existence test. Yup, it's there.
603 */ 605 */
@@ -2191,7 +2193,7 @@ static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid)
2191 2193
2192/** 2194/**
2193 * smack_d_instantiate - Make sure the blob is correct on an inode 2195 * smack_d_instantiate - Make sure the blob is correct on an inode
2194 * @opt_dentry: unused 2196 * @opt_dentry: dentry where inode will be attached
2195 * @inode: the object 2197 * @inode: the object
2196 * 2198 *
2197 * Set the inode's security blob if it hasn't been done already. 2199 * Set the inode's security blob if it hasn't been done already.
@@ -2310,20 +2312,10 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
2310 /* 2312 /*
2311 * Get the dentry for xattr. 2313 * Get the dentry for xattr.
2312 */ 2314 */
2313 if (opt_dentry == NULL) { 2315 dp = dget(opt_dentry);
2314 dp = d_find_alias(inode);
2315 if (dp == NULL)
2316 break;
2317 } else {
2318 dp = dget(opt_dentry);
2319 if (dp == NULL)
2320 break;
2321 }
2322
2323 fetched = smk_fetch(inode, dp); 2316 fetched = smk_fetch(inode, dp);
2324 if (fetched != NULL) 2317 if (fetched != NULL)
2325 final = fetched; 2318 final = fetched;
2326
2327 dput(dp); 2319 dput(dp);
2328 break; 2320 break;
2329 } 2321 }
@@ -3227,7 +3219,7 @@ static __init int smack_init(void)
3227 cred = (struct cred *) current->cred; 3219 cred = (struct cred *) current->cred;
3228 cred->security = &smack_known_floor.smk_known; 3220 cred->security = &smack_known_floor.smk_known;
3229 3221
3230 /* initilize the smack_know_list */ 3222 /* initialize the smack_know_list */
3231 init_smack_know_list(); 3223 init_smack_know_list();
3232 /* 3224 /*
3233 * Initialize locks 3225 * Initialize locks
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
index 4fb39030f6b..91640e96bd0 100644
--- a/security/tomoyo/Makefile
+++ b/security/tomoyo/Makefile
@@ -1 +1 @@
obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o obj-y = common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index b5dbdc9ff73..ef43995119a 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -3,974 +3,424 @@
3 * 3 *
4 * Common functions for TOMOYO. 4 * Common functions for TOMOYO.
5 * 5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION 6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0 2009/04/01
9 *
10 */ 7 */
11 8
12#include <linux/uaccess.h> 9#include <linux/uaccess.h>
13#include <linux/slab.h> 10#include <linux/slab.h>
14#include <linux/security.h> 11#include <linux/security.h>
15#include <linux/hardirq.h>
16#include "common.h" 12#include "common.h"
17 13
18/* Lock for protecting policy. */ 14static struct tomoyo_profile tomoyo_default_profile = {
19DEFINE_MUTEX(tomoyo_policy_lock); 15 .learning = &tomoyo_default_profile.preference,
16 .permissive = &tomoyo_default_profile.preference,
17 .enforcing = &tomoyo_default_profile.preference,
18 .preference.enforcing_verbose = true,
19 .preference.learning_max_entry = 2048,
20 .preference.learning_verbose = false,
21 .preference.permissive_verbose = true
22};
23
24/* Profile version. Currently only 20090903 is defined. */
25static unsigned int tomoyo_profile_version;
20 26
21/* Has loading policy done? */ 27/* Profile table. Memory is allocated as needed. */
22bool tomoyo_policy_loaded; 28static struct tomoyo_profile *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES];
23 29
24/* String table for functionality that takes 4 modes. */ 30/* String table for functionality that takes 4 modes. */
25static const char *tomoyo_mode_4[4] = { 31static const char *tomoyo_mode[4] = {
26 "disabled", "learning", "permissive", "enforcing" 32 "disabled", "learning", "permissive", "enforcing"
27}; 33};
28/* String table for functionality that takes 2 modes. */
29static const char *tomoyo_mode_2[4] = {
30 "disabled", "enabled", "enabled", "enabled"
31};
32 34
33/* 35/* String table for /sys/kernel/security/tomoyo/profile */
34 * tomoyo_control_array is a static data which contains 36static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
35 * 37 + TOMOYO_MAX_MAC_CATEGORY_INDEX] = {
36 * (1) functionality name used by /sys/kernel/security/tomoyo/profile . 38 [TOMOYO_MAC_FILE_EXECUTE] = "file::execute",
37 * (2) initial values for "struct tomoyo_profile". 39 [TOMOYO_MAC_FILE_OPEN] = "file::open",
38 * (3) max values for "struct tomoyo_profile". 40 [TOMOYO_MAC_FILE_CREATE] = "file::create",
39 */ 41 [TOMOYO_MAC_FILE_UNLINK] = "file::unlink",
40static struct { 42 [TOMOYO_MAC_FILE_MKDIR] = "file::mkdir",
41 const char *keyword; 43 [TOMOYO_MAC_FILE_RMDIR] = "file::rmdir",
42 unsigned int current_value; 44 [TOMOYO_MAC_FILE_MKFIFO] = "file::mkfifo",
43 const unsigned int max_value; 45 [TOMOYO_MAC_FILE_MKSOCK] = "file::mksock",
44} tomoyo_control_array[TOMOYO_MAX_CONTROL_INDEX] = { 46 [TOMOYO_MAC_FILE_TRUNCATE] = "file::truncate",
45 [TOMOYO_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 }, 47 [TOMOYO_MAC_FILE_SYMLINK] = "file::symlink",
46 [TOMOYO_MAX_ACCEPT_ENTRY] = { "MAX_ACCEPT_ENTRY", 2048, INT_MAX }, 48 [TOMOYO_MAC_FILE_REWRITE] = "file::rewrite",
47 [TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 }, 49 [TOMOYO_MAC_FILE_MKBLOCK] = "file::mkblock",
50 [TOMOYO_MAC_FILE_MKCHAR] = "file::mkchar",
51 [TOMOYO_MAC_FILE_LINK] = "file::link",
52 [TOMOYO_MAC_FILE_RENAME] = "file::rename",
53 [TOMOYO_MAC_FILE_CHMOD] = "file::chmod",
54 [TOMOYO_MAC_FILE_CHOWN] = "file::chown",
55 [TOMOYO_MAC_FILE_CHGRP] = "file::chgrp",
56 [TOMOYO_MAC_FILE_IOCTL] = "file::ioctl",
57 [TOMOYO_MAC_FILE_CHROOT] = "file::chroot",
58 [TOMOYO_MAC_FILE_MOUNT] = "file::mount",
59 [TOMOYO_MAC_FILE_UMOUNT] = "file::umount",
60 [TOMOYO_MAC_FILE_PIVOT_ROOT] = "file::pivot_root",
61 [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
48}; 62};
49 63
50/*
51 * tomoyo_profile is a structure which is used for holding the mode of access
52 * controls. TOMOYO has 4 modes: disabled, learning, permissive, enforcing.
53 * An administrator can define up to 256 profiles.
54 * The ->profile of "struct tomoyo_domain_info" is used for remembering
55 * the profile's number (0 - 255) assigned to that domain.
56 */
57static struct tomoyo_profile {
58 unsigned int value[TOMOYO_MAX_CONTROL_INDEX];
59 const struct tomoyo_path_info *comment;
60} *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES];
61
62/* Permit policy management by non-root user? */ 64/* Permit policy management by non-root user? */
63static bool tomoyo_manage_by_non_root; 65static bool tomoyo_manage_by_non_root;
64 66
65/* Utility functions. */ 67/* Utility functions. */
66 68
67/* Open operation for /sys/kernel/security/tomoyo/ interface. */
68static int tomoyo_open_control(const u8 type, struct file *file);
69/* Close /sys/kernel/security/tomoyo/ interface. */
70static int tomoyo_close_control(struct file *file);
71/* Read operation for /sys/kernel/security/tomoyo/ interface. */
72static int tomoyo_read_control(struct file *file, char __user *buffer,
73 const int buffer_len);
74/* Write operation for /sys/kernel/security/tomoyo/ interface. */
75static int tomoyo_write_control(struct file *file, const char __user *buffer,
76 const int buffer_len);
77
78/** 69/**
79 * tomoyo_parse_name_union - Parse a tomoyo_name_union. 70 * tomoyo_yesno - Return "yes" or "no".
80 * 71 *
81 * @filename: Name or name group. 72 * @value: Bool value.
82 * @ptr: Pointer to "struct tomoyo_name_union".
83 *
84 * Returns true on success, false otherwise.
85 */ 73 */
86bool tomoyo_parse_name_union(const char *filename, 74static const char *tomoyo_yesno(const unsigned int value)
87 struct tomoyo_name_union *ptr)
88{ 75{
89 if (!tomoyo_is_correct_path(filename, 0, 0, 0)) 76 return value ? "yes" : "no";
90 return false;
91 if (filename[0] == '@') {
92 ptr->group = tomoyo_get_path_group(filename + 1);
93 ptr->is_group = true;
94 return ptr->group != NULL;
95 }
96 ptr->filename = tomoyo_get_name(filename);
97 ptr->is_group = false;
98 return ptr->filename != NULL;
99} 77}
100 78
101/** 79static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...)
102 * tomoyo_print_name_union - Print a tomoyo_name_union.
103 *
104 * @head: Pointer to "struct tomoyo_io_buffer".
105 * @ptr: Pointer to "struct tomoyo_name_union".
106 *
107 * Returns true on success, false otherwise.
108 */
109static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head,
110 const struct tomoyo_name_union *ptr)
111{ 80{
112 int pos = head->read_avail; 81 va_list args;
113 if (pos && head->read_buf[pos - 1] == ' ') 82 const int pos = strlen(buffer);
114 head->read_avail--; 83 va_start(args, fmt);
115 if (ptr->is_group) 84 vsnprintf(buffer + pos, len - pos - 1, fmt, args);
116 return tomoyo_io_printf(head, " @%s", 85 va_end(args);
117 ptr->group->group_name->name);
118 return tomoyo_io_printf(head, " %s", ptr->filename->name);
119} 86}
120 87
121/** 88/**
122 * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value. 89 * tomoyo_flush - Flush queued string to userspace's buffer.
123 *
124 * @str: Pointer to the string.
125 * 90 *
126 * Returns true if @str is a \ooo style octal value, false otherwise. 91 * @head: Pointer to "struct tomoyo_io_buffer".
127 * 92 *
128 * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF. 93 * Returns true if all data was flushed, false otherwise.
129 * This function verifies that \ooo is in valid range.
130 */ 94 */
131static inline bool tomoyo_is_byte_range(const char *str) 95static bool tomoyo_flush(struct tomoyo_io_buffer *head)
132{ 96{
133 return *str >= '0' && *str++ <= '3' && 97 while (head->r.w_pos) {
134 *str >= '0' && *str++ <= '7' && 98 const char *w = head->r.w[0];
135 *str >= '0' && *str <= '7'; 99 int len = strlen(w);
100 if (len) {
101 if (len > head->read_user_buf_avail)
102 len = head->read_user_buf_avail;
103 if (!len)
104 return false;
105 if (copy_to_user(head->read_user_buf, w, len))
106 return false;
107 head->read_user_buf_avail -= len;
108 head->read_user_buf += len;
109 w += len;
110 }
111 if (*w) {
112 head->r.w[0] = w;
113 return false;
114 }
115 /* Add '\0' for query. */
116 if (head->poll) {
117 if (!head->read_user_buf_avail ||
118 copy_to_user(head->read_user_buf, "", 1))
119 return false;
120 head->read_user_buf_avail--;
121 head->read_user_buf++;
122 }
123 head->r.w_pos--;
124 for (len = 0; len < head->r.w_pos; len++)
125 head->r.w[len] = head->r.w[len + 1];
126 }
127 head->r.avail = 0;
128 return true;
136} 129}
137 130
138/** 131/**
139 * tomoyo_is_alphabet_char - Check whether the character is an alphabet. 132 * tomoyo_set_string - Queue string to "struct tomoyo_io_buffer" structure.
140 * 133 *
141 * @c: The character to check. 134 * @head: Pointer to "struct tomoyo_io_buffer".
135 * @string: String to print.
142 * 136 *
143 * Returns true if @c is an alphabet character, false otherwise. 137 * Note that @string has to be kept valid until @head is kfree()d.
138 * This means that char[] allocated on stack memory cannot be passed to
139 * this function. Use tomoyo_io_printf() for char[] allocated on stack memory.
144 */ 140 */
145static inline bool tomoyo_is_alphabet_char(const char c) 141static void tomoyo_set_string(struct tomoyo_io_buffer *head, const char *string)
146{ 142{
147 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); 143 if (head->r.w_pos < TOMOYO_MAX_IO_READ_QUEUE) {
144 head->r.w[head->r.w_pos++] = string;
145 tomoyo_flush(head);
146 } else
147 WARN_ON(1);
148} 148}
149 149
150/** 150/**
151 * tomoyo_make_byte - Make byte value from three octal characters. 151 * tomoyo_io_printf - printf() to "struct tomoyo_io_buffer" structure.
152 * 152 *
153 * @c1: The first character. 153 * @head: Pointer to "struct tomoyo_io_buffer".
154 * @c2: The second character. 154 * @fmt: The printf()'s format string, followed by parameters.
155 * @c3: The third character.
156 *
157 * Returns byte value.
158 */ 155 */
159static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3) 156void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
160{ 157{
161 return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0'); 158 va_list args;
159 int len;
160 int pos = head->r.avail;
161 int size = head->readbuf_size - pos;
162 if (size <= 0)
163 return;
164 va_start(args, fmt);
165 len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1;
166 va_end(args);
167 if (pos + len >= head->readbuf_size) {
168 WARN_ON(1);
169 return;
170 }
171 head->r.avail += len;
172 tomoyo_set_string(head, head->read_buf + pos);
162} 173}
163 174
164/** 175static void tomoyo_set_space(struct tomoyo_io_buffer *head)
165 * tomoyo_str_starts - Check whether the given string starts with the given keyword.
166 *
167 * @src: Pointer to pointer to the string.
168 * @find: Pointer to the keyword.
169 *
170 * Returns true if @src starts with @find, false otherwise.
171 *
172 * The @src is updated to point the first character after the @find
173 * if @src starts with @find.
174 */
175static bool tomoyo_str_starts(char **src, const char *find)
176{ 176{
177 const int len = strlen(find); 177 tomoyo_set_string(head, " ");
178 char *tmp = *src;
179
180 if (strncmp(tmp, find, len))
181 return false;
182 tmp += len;
183 *src = tmp;
184 return true;
185} 178}
186 179
187/** 180static bool tomoyo_set_lf(struct tomoyo_io_buffer *head)
188 * tomoyo_normalize_line - Format string.
189 *
190 * @buffer: The line to normalize.
191 *
192 * Leading and trailing whitespaces are removed.
193 * Multiple whitespaces are packed into single space.
194 *
195 * Returns nothing.
196 */
197static void tomoyo_normalize_line(unsigned char *buffer)
198{ 181{
199 unsigned char *sp = buffer; 182 tomoyo_set_string(head, "\n");
200 unsigned char *dp = buffer; 183 return !head->r.w_pos;
201 bool first = true;
202
203 while (tomoyo_is_invalid(*sp))
204 sp++;
205 while (*sp) {
206 if (!first)
207 *dp++ = ' ';
208 first = false;
209 while (tomoyo_is_valid(*sp))
210 *dp++ = *sp++;
211 while (tomoyo_is_invalid(*sp))
212 sp++;
213 }
214 *dp = '\0';
215} 184}
216 185
217/** 186/**
218 * tomoyo_tokenize - Tokenize string. 187 * tomoyo_print_name_union - Print a tomoyo_name_union.
219 *
220 * @buffer: The line to tokenize.
221 * @w: Pointer to "char *".
222 * @size: Sizeof @w .
223 * 188 *
224 * Returns true on success, false otherwise. 189 * @head: Pointer to "struct tomoyo_io_buffer".
190 * @ptr: Pointer to "struct tomoyo_name_union".
225 */ 191 */
226bool tomoyo_tokenize(char *buffer, char *w[], size_t size) 192static void tomoyo_print_name_union(struct tomoyo_io_buffer *head,
193 const struct tomoyo_name_union *ptr)
227{ 194{
228 int count = size / sizeof(char *); 195 tomoyo_set_space(head);
229 int i; 196 if (ptr->is_group) {
230 for (i = 0; i < count; i++) 197 tomoyo_set_string(head, "@");
231 w[i] = ""; 198 tomoyo_set_string(head, ptr->group->group_name->name);
232 for (i = 0; i < count; i++) { 199 } else {
233 char *cp = strchr(buffer, ' '); 200 tomoyo_set_string(head, ptr->filename->name);
234 if (cp)
235 *cp = '\0';
236 w[i] = buffer;
237 if (!cp)
238 break;
239 buffer = cp + 1;
240 } 201 }
241 return i < count || !*buffer;
242} 202}
243 203
244/** 204/**
245 * tomoyo_is_correct_path - Validate a pathname. 205 * tomoyo_print_number_union - Print a tomoyo_number_union.
246 * @filename: The pathname to check. 206 *
247 * @start_type: Should the pathname start with '/'? 207 * @head: Pointer to "struct tomoyo_io_buffer".
248 * 1 = must / -1 = must not / 0 = don't care 208 * @ptr: Pointer to "struct tomoyo_number_union".
249 * @pattern_type: Can the pathname contain a wildcard?
250 * 1 = must / -1 = must not / 0 = don't care
251 * @end_type: Should the pathname end with '/'?
252 * 1 = must / -1 = must not / 0 = don't care
253 *
254 * Check whether the given filename follows the naming rules.
255 * Returns true if @filename follows the naming rules, false otherwise.
256 */ 209 */
257bool tomoyo_is_correct_path(const char *filename, const s8 start_type, 210static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
258 const s8 pattern_type, const s8 end_type) 211 const struct tomoyo_number_union *ptr)
259{ 212{
260 const char *const start = filename; 213 tomoyo_set_space(head);
261 bool in_repetition = false; 214 if (ptr->is_group) {
262 bool contains_pattern = false; 215 tomoyo_set_string(head, "@");
263 unsigned char c; 216 tomoyo_set_string(head, ptr->group->group_name->name);
264 unsigned char d; 217 } else {
265 unsigned char e; 218 int i;
266 219 unsigned long min = ptr->values[0];
267 if (!filename) 220 const unsigned long max = ptr->values[1];
268 goto out; 221 u8 min_type = ptr->min_type;
269 c = *filename; 222 const u8 max_type = ptr->max_type;
270 if (start_type == 1) { /* Must start with '/' */ 223 char buffer[128];
271 if (c != '/') 224 buffer[0] = '\0';
272 goto out; 225 for (i = 0; i < 2; i++) {
273 } else if (start_type == -1) { /* Must not start with '/' */ 226 switch (min_type) {
274 if (c == '/') 227 case TOMOYO_VALUE_TYPE_HEXADECIMAL:
275 goto out; 228 tomoyo_addprintf(buffer, sizeof(buffer),
276 } 229 "0x%lX", min);
277 if (c) 230 break;
278 c = *(filename + strlen(filename) - 1); 231 case TOMOYO_VALUE_TYPE_OCTAL:
279 if (end_type == 1) { /* Must end with '/' */ 232 tomoyo_addprintf(buffer, sizeof(buffer),
280 if (c != '/') 233 "0%lo", min);
281 goto out; 234 break;
282 } else if (end_type == -1) { /* Must not end with '/' */ 235 default:
283 if (c == '/') 236 tomoyo_addprintf(buffer, sizeof(buffer),
284 goto out; 237 "%lu", min);
285 } 238 break;
286 while (1) {
287 c = *filename++;
288 if (!c)
289 break;
290 if (c == '\\') {
291 c = *filename++;
292 switch (c) {
293 case '\\': /* "\\" */
294 continue;
295 case '$': /* "\$" */
296 case '+': /* "\+" */
297 case '?': /* "\?" */
298 case '*': /* "\*" */
299 case '@': /* "\@" */
300 case 'x': /* "\x" */
301 case 'X': /* "\X" */
302 case 'a': /* "\a" */
303 case 'A': /* "\A" */
304 case '-': /* "\-" */
305 if (pattern_type == -1)
306 break; /* Must not contain pattern */
307 contains_pattern = true;
308 continue;
309 case '{': /* "/\{" */
310 if (filename - 3 < start ||
311 *(filename - 3) != '/')
312 break;
313 if (pattern_type == -1)
314 break; /* Must not contain pattern */
315 contains_pattern = true;
316 in_repetition = true;
317 continue;
318 case '}': /* "\}/" */
319 if (*filename != '/')
320 break;
321 if (!in_repetition)
322 break;
323 in_repetition = false;
324 continue;
325 case '0': /* "\ooo" */
326 case '1':
327 case '2':
328 case '3':
329 d = *filename++;
330 if (d < '0' || d > '7')
331 break;
332 e = *filename++;
333 if (e < '0' || e > '7')
334 break;
335 c = tomoyo_make_byte(c, d, e);
336 if (tomoyo_is_invalid(c))
337 continue; /* pattern is not \000 */
338 } 239 }
339 goto out; 240 if (min == max && min_type == max_type)
340 } else if (in_repetition && c == '/') { 241 break;
341 goto out; 242 tomoyo_addprintf(buffer, sizeof(buffer), "-");
342 } else if (tomoyo_is_invalid(c)) { 243 min_type = max_type;
343 goto out; 244 min = max;
344 } 245 }
246 tomoyo_io_printf(head, "%s", buffer);
345 } 247 }
346 if (pattern_type == 1) { /* Must contain pattern */
347 if (!contains_pattern)
348 goto out;
349 }
350 if (in_repetition)
351 goto out;
352 return true;
353 out:
354 return false;
355} 248}
356 249
357/** 250/**
358 * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules. 251 * tomoyo_assign_profile - Create a new profile.
359 * @domainname: The domainname to check.
360 * 252 *
361 * Returns true if @domainname follows the naming rules, false otherwise. 253 * @profile: Profile number to create.
254 *
255 * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise.
362 */ 256 */
363bool tomoyo_is_correct_domain(const unsigned char *domainname) 257static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile)
364{ 258{
365 unsigned char c; 259 struct tomoyo_profile *ptr;
366 unsigned char d; 260 struct tomoyo_profile *entry;
367 unsigned char e; 261 if (profile >= TOMOYO_MAX_PROFILES)
368 262 return NULL;
369 if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, 263 ptr = tomoyo_profile_ptr[profile];
370 TOMOYO_ROOT_NAME_LEN)) 264 if (ptr)
265 return ptr;
266 entry = kzalloc(sizeof(*entry), GFP_NOFS);
267 if (mutex_lock_interruptible(&tomoyo_policy_lock))
371 goto out; 268 goto out;
372 domainname += TOMOYO_ROOT_NAME_LEN; 269 ptr = tomoyo_profile_ptr[profile];
373 if (!*domainname) 270 if (!ptr && tomoyo_memory_ok(entry)) {
374 return true; 271 ptr = entry;
375 do { 272 ptr->learning = &tomoyo_default_profile.preference;
376 if (*domainname++ != ' ') 273 ptr->permissive = &tomoyo_default_profile.preference;
377 goto out; 274 ptr->enforcing = &tomoyo_default_profile.preference;
378 if (*domainname++ != '/') 275 ptr->default_config = TOMOYO_CONFIG_DISABLED;
379 goto out; 276 memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT,
380 while ((c = *domainname) != '\0' && c != ' ') { 277 sizeof(ptr->config));
381 domainname++; 278 mb(); /* Avoid out-of-order execution. */
382 if (c == '\\') { 279 tomoyo_profile_ptr[profile] = ptr;
383 c = *domainname++; 280 entry = NULL;
384 switch ((c)) { 281 }
385 case '\\': /* "\\" */ 282 mutex_unlock(&tomoyo_policy_lock);
386 continue;
387 case '0': /* "\ooo" */
388 case '1':
389 case '2':
390 case '3':
391 d = *domainname++;
392 if (d < '0' || d > '7')
393 break;
394 e = *domainname++;
395 if (e < '0' || e > '7')
396 break;
397 c = tomoyo_make_byte(c, d, e);
398 if (tomoyo_is_invalid(c))
399 /* pattern is not \000 */
400 continue;
401 }
402 goto out;
403 } else if (tomoyo_is_invalid(c)) {
404 goto out;
405 }
406 }
407 } while (*domainname);
408 return true;
409 out: 283 out:
410 return false; 284 kfree(entry);
285 return ptr;
411} 286}
412 287
413/** 288/**
414 * tomoyo_is_domain_def - Check whether the given token can be a domainname. 289 * tomoyo_profile - Find a profile.
415 * 290 *
416 * @buffer: The token to check. 291 * @profile: Profile number to find.
417 * 292 *
418 * Returns true if @buffer possibly be a domainname, false otherwise. 293 * Returns pointer to "struct tomoyo_profile".
419 */ 294 */
420bool tomoyo_is_domain_def(const unsigned char *buffer) 295struct tomoyo_profile *tomoyo_profile(const u8 profile)
421{ 296{
422 return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN); 297 struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile];
298 if (!tomoyo_policy_loaded)
299 return &tomoyo_default_profile;
300 BUG_ON(!ptr);
301 return ptr;
423} 302}
424 303
425/** 304static s8 tomoyo_find_yesno(const char *string, const char *find)
426 * tomoyo_find_domain - Find a domain by the given name.
427 *
428 * @domainname: The domainname to find.
429 *
430 * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
431 *
432 * Caller holds tomoyo_read_lock().
433 */
434struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
435{ 305{
436 struct tomoyo_domain_info *domain; 306 const char *cp = strstr(string, find);
437 struct tomoyo_path_info name; 307 if (cp) {
438 308 cp += strlen(find);
439 name.name = domainname; 309 if (!strncmp(cp, "=yes", 4))
440 tomoyo_fill_path_info(&name); 310 return 1;
441 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 311 else if (!strncmp(cp, "=no", 3))
442 if (!domain->is_deleted && 312 return 0;
443 !tomoyo_pathcmp(&name, domain->domainname))
444 return domain;
445 } 313 }
446 return NULL; 314 return -1;
447} 315}
448 316
449/** 317static void tomoyo_set_bool(bool *b, const char *string, const char *find)
450 * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
451 *
452 * @filename: The string to evaluate.
453 *
454 * Returns the initial length without a pattern in @filename.
455 */
456static int tomoyo_const_part_length(const char *filename)
457{ 318{
458 char c; 319 switch (tomoyo_find_yesno(string, find)) {
459 int len = 0; 320 case 1:
460 321 *b = true;
461 if (!filename) 322 break;
462 return 0; 323 case 0:
463 while ((c = *filename++) != '\0') { 324 *b = false;
464 if (c != '\\') {
465 len++;
466 continue;
467 }
468 c = *filename++;
469 switch (c) {
470 case '\\': /* "\\" */
471 len += 2;
472 continue;
473 case '0': /* "\ooo" */
474 case '1':
475 case '2':
476 case '3':
477 c = *filename++;
478 if (c < '0' || c > '7')
479 break;
480 c = *filename++;
481 if (c < '0' || c > '7')
482 break;
483 len += 4;
484 continue;
485 }
486 break; 325 break;
487 } 326 }
488 return len;
489} 327}
490 328
491/** 329static void tomoyo_set_uint(unsigned int *i, const char *string,
492 * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members. 330 const char *find)
493 *
494 * @ptr: Pointer to "struct tomoyo_path_info" to fill in.
495 *
496 * The caller sets "struct tomoyo_path_info"->name.
497 */
498void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
499{ 331{
500 const char *name = ptr->name; 332 const char *cp = strstr(string, find);
501 const int len = strlen(name); 333 if (cp)
502 334 sscanf(cp + strlen(find), "=%u", i);
503 ptr->const_len = tomoyo_const_part_length(name);
504 ptr->is_dir = len && (name[len - 1] == '/');
505 ptr->is_patterned = (ptr->const_len < len);
506 ptr->hash = full_name_hash(name, len);
507} 335}
508 336
509/** 337static void tomoyo_set_pref(const char *name, const char *value,
510 * tomoyo_file_matches_pattern2 - Pattern matching without '/' character 338 const bool use_default,
511 * and "\-" pattern. 339 struct tomoyo_profile *profile)
512 *
513 * @filename: The start of string to check.
514 * @filename_end: The end of string to check.
515 * @pattern: The start of pattern to compare.
516 * @pattern_end: The end of pattern to compare.
517 *
518 * Returns true if @filename matches @pattern, false otherwise.
519 */
520static bool tomoyo_file_matches_pattern2(const char *filename,
521 const char *filename_end,
522 const char *pattern,
523 const char *pattern_end)
524{ 340{
525 while (filename < filename_end && pattern < pattern_end) { 341 struct tomoyo_preference **pref;
526 char c; 342 bool *verbose;
527 if (*pattern != '\\') { 343 if (!strcmp(name, "enforcing")) {
528 if (*filename++ != *pattern++) 344 if (use_default) {
529 return false; 345 pref = &profile->enforcing;
530 continue; 346 goto set_default;
531 } 347 }
532 c = *filename; 348 profile->enforcing = &profile->preference;
533 pattern++; 349 verbose = &profile->preference.enforcing_verbose;
534 switch (*pattern) { 350 goto set_verbose;
535 int i;
536 int j;
537 case '?':
538 if (c == '/') {
539 return false;
540 } else if (c == '\\') {
541 if (filename[1] == '\\')
542 filename++;
543 else if (tomoyo_is_byte_range(filename + 1))
544 filename += 3;
545 else
546 return false;
547 }
548 break;
549 case '\\':
550 if (c != '\\')
551 return false;
552 if (*++filename != '\\')
553 return false;
554 break;
555 case '+':
556 if (!isdigit(c))
557 return false;
558 break;
559 case 'x':
560 if (!isxdigit(c))
561 return false;
562 break;
563 case 'a':
564 if (!tomoyo_is_alphabet_char(c))
565 return false;
566 break;
567 case '0':
568 case '1':
569 case '2':
570 case '3':
571 if (c == '\\' && tomoyo_is_byte_range(filename + 1)
572 && strncmp(filename + 1, pattern, 3) == 0) {
573 filename += 3;
574 pattern += 2;
575 break;
576 }
577 return false; /* Not matched. */
578 case '*':
579 case '@':
580 for (i = 0; i <= filename_end - filename; i++) {
581 if (tomoyo_file_matches_pattern2(
582 filename + i, filename_end,
583 pattern + 1, pattern_end))
584 return true;
585 c = filename[i];
586 if (c == '.' && *pattern == '@')
587 break;
588 if (c != '\\')
589 continue;
590 if (filename[i + 1] == '\\')
591 i++;
592 else if (tomoyo_is_byte_range(filename + i + 1))
593 i += 3;
594 else
595 break; /* Bad pattern. */
596 }
597 return false; /* Not matched. */
598 default:
599 j = 0;
600 c = *pattern;
601 if (c == '$') {
602 while (isdigit(filename[j]))
603 j++;
604 } else if (c == 'X') {
605 while (isxdigit(filename[j]))
606 j++;
607 } else if (c == 'A') {
608 while (tomoyo_is_alphabet_char(filename[j]))
609 j++;
610 }
611 for (i = 1; i <= j; i++) {
612 if (tomoyo_file_matches_pattern2(
613 filename + i, filename_end,
614 pattern + 1, pattern_end))
615 return true;
616 }
617 return false; /* Not matched or bad pattern. */
618 }
619 filename++;
620 pattern++;
621 }
622 while (*pattern == '\\' &&
623 (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
624 pattern += 2;
625 return filename == filename_end && pattern == pattern_end;
626}
627
628/**
629 * tomoyo_file_matches_pattern - Pattern matching without without '/' character.
630 *
631 * @filename: The start of string to check.
632 * @filename_end: The end of string to check.
633 * @pattern: The start of pattern to compare.
634 * @pattern_end: The end of pattern to compare.
635 *
636 * Returns true if @filename matches @pattern, false otherwise.
637 */
638static bool tomoyo_file_matches_pattern(const char *filename,
639 const char *filename_end,
640 const char *pattern,
641 const char *pattern_end)
642{
643 const char *pattern_start = pattern;
644 bool first = true;
645 bool result;
646
647 while (pattern < pattern_end - 1) {
648 /* Split at "\-" pattern. */
649 if (*pattern++ != '\\' || *pattern++ != '-')
650 continue;
651 result = tomoyo_file_matches_pattern2(filename,
652 filename_end,
653 pattern_start,
654 pattern - 2);
655 if (first)
656 result = !result;
657 if (result)
658 return false;
659 first = false;
660 pattern_start = pattern;
661 } 351 }
662 result = tomoyo_file_matches_pattern2(filename, filename_end, 352 if (!strcmp(name, "permissive")) {
663 pattern_start, pattern_end); 353 if (use_default) {
664 return first ? result : !result; 354 pref = &profile->permissive;
665} 355 goto set_default;
666 356 }
667/** 357 profile->permissive = &profile->preference;
668 * tomoyo_path_matches_pattern2 - Do pathname pattern matching. 358 verbose = &profile->preference.permissive_verbose;
669 * 359 goto set_verbose;
670 * @f: The start of string to check.
671 * @p: The start of pattern to compare.
672 *
673 * Returns true if @f matches @p, false otherwise.
674 */
675static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
676{
677 const char *f_delimiter;
678 const char *p_delimiter;
679
680 while (*f && *p) {
681 f_delimiter = strchr(f, '/');
682 if (!f_delimiter)
683 f_delimiter = f + strlen(f);
684 p_delimiter = strchr(p, '/');
685 if (!p_delimiter)
686 p_delimiter = p + strlen(p);
687 if (*p == '\\' && *(p + 1) == '{')
688 goto recursive;
689 if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
690 p_delimiter))
691 return false;
692 f = f_delimiter;
693 if (*f)
694 f++;
695 p = p_delimiter;
696 if (*p)
697 p++;
698 } 360 }
699 /* Ignore trailing "\*" and "\@" in @pattern. */ 361 if (!strcmp(name, "learning")) {
700 while (*p == '\\' && 362 if (use_default) {
701 (*(p + 1) == '*' || *(p + 1) == '@')) 363 pref = &profile->learning;
702 p += 2; 364 goto set_default;
703 return !*f && !*p;
704 recursive:
705 /*
706 * The "\{" pattern is permitted only after '/' character.
707 * This guarantees that below "*(p - 1)" is safe.
708 * Also, the "\}" pattern is permitted only before '/' character
709 * so that "\{" + "\}" pair will not break the "\-" operator.
710 */
711 if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
712 *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
713 return false; /* Bad pattern. */
714 do {
715 /* Compare current component with pattern. */
716 if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
717 p_delimiter - 2))
718 break;
719 /* Proceed to next component. */
720 f = f_delimiter;
721 if (!*f)
722 break;
723 f++;
724 /* Continue comparison. */
725 if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
726 return true;
727 f_delimiter = strchr(f, '/');
728 } while (f_delimiter);
729 return false; /* Not matched. */
730}
731
732/**
733 * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
734 *
735 * @filename: The filename to check.
736 * @pattern: The pattern to compare.
737 *
738 * Returns true if matches, false otherwise.
739 *
740 * The following patterns are available.
741 * \\ \ itself.
742 * \ooo Octal representation of a byte.
743 * \* Zero or more repetitions of characters other than '/'.
744 * \@ Zero or more repetitions of characters other than '/' or '.'.
745 * \? 1 byte character other than '/'.
746 * \$ One or more repetitions of decimal digits.
747 * \+ 1 decimal digit.
748 * \X One or more repetitions of hexadecimal digits.
749 * \x 1 hexadecimal digit.
750 * \A One or more repetitions of alphabet characters.
751 * \a 1 alphabet character.
752 *
753 * \- Subtraction operator.
754 *
755 * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
756 * /dir/dir/dir/ ).
757 */
758bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
759 const struct tomoyo_path_info *pattern)
760{
761 const char *f = filename->name;
762 const char *p = pattern->name;
763 const int len = pattern->const_len;
764
765 /* If @pattern doesn't contain pattern, I can use strcmp(). */
766 if (!pattern->is_patterned)
767 return !tomoyo_pathcmp(filename, pattern);
768 /* Don't compare directory and non-directory. */
769 if (filename->is_dir != pattern->is_dir)
770 return false;
771 /* Compare the initial length without patterns. */
772 if (strncmp(f, p, len))
773 return false;
774 f += len;
775 p += len;
776 return tomoyo_path_matches_pattern2(f, p);
777}
778
779/**
780 * tomoyo_io_printf - Transactional printf() to "struct tomoyo_io_buffer" structure.
781 *
782 * @head: Pointer to "struct tomoyo_io_buffer".
783 * @fmt: The printf()'s format string, followed by parameters.
784 *
785 * Returns true if output was written, false otherwise.
786 *
787 * The snprintf() will truncate, but tomoyo_io_printf() won't.
788 */
789bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
790{
791 va_list args;
792 int len;
793 int pos = head->read_avail;
794 int size = head->readbuf_size - pos;
795
796 if (size <= 0)
797 return false;
798 va_start(args, fmt);
799 len = vsnprintf(head->read_buf + pos, size, fmt, args);
800 va_end(args);
801 if (pos + len >= head->readbuf_size)
802 return false;
803 head->read_avail += len;
804 return true;
805}
806
807/**
808 * tomoyo_get_exe - Get tomoyo_realpath() of current process.
809 *
810 * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
811 *
812 * This function uses kzalloc(), so the caller must call kfree()
813 * if this function didn't return NULL.
814 */
815static const char *tomoyo_get_exe(void)
816{
817 struct mm_struct *mm = current->mm;
818 struct vm_area_struct *vma;
819 const char *cp = NULL;
820
821 if (!mm)
822 return NULL;
823 down_read(&mm->mmap_sem);
824 for (vma = mm->mmap; vma; vma = vma->vm_next) {
825 if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
826 cp = tomoyo_realpath_from_path(&vma->vm_file->f_path);
827 break;
828 } 365 }
366 profile->learning = &profile->preference;
367 tomoyo_set_uint(&profile->preference.learning_max_entry, value,
368 "max_entry");
369 verbose = &profile->preference.learning_verbose;
370 goto set_verbose;
829 } 371 }
830 up_read(&mm->mmap_sem); 372 return;
831 return cp; 373 set_default:
374 *pref = &tomoyo_default_profile.preference;
375 return;
376 set_verbose:
377 tomoyo_set_bool(verbose, value, "verbose");
832} 378}
833 379
834/** 380static int tomoyo_set_mode(char *name, const char *value,
835 * tomoyo_get_msg - Get warning message. 381 const bool use_default,
836 * 382 struct tomoyo_profile *profile)
837 * @is_enforce: Is it enforcing mode?
838 *
839 * Returns "ERROR" or "WARNING".
840 */
841const char *tomoyo_get_msg(const bool is_enforce)
842{ 383{
843 if (is_enforce) 384 u8 i;
844 return "ERROR"; 385 u8 config;
845 else 386 if (!strcmp(name, "CONFIG")) {
846 return "WARNING"; 387 i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX;
847} 388 config = profile->default_config;
848 389 } else if (tomoyo_str_starts(&name, "CONFIG::")) {
849/** 390 config = 0;
850 * tomoyo_check_flags - Check mode for specified functionality. 391 for (i = 0; i < TOMOYO_MAX_MAC_INDEX
851 * 392 + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) {
852 * @domain: Pointer to "struct tomoyo_domain_info". 393 if (strcmp(name, tomoyo_mac_keywords[i]))
853 * @index: The functionality to check mode. 394 continue;
854 * 395 config = profile->config[i];
855 * TOMOYO checks only process context.
856 * This code disables TOMOYO's enforcement in case the function is called from
857 * interrupt context.
858 */
859unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
860 const u8 index)
861{
862 const u8 profile = domain->profile;
863
864 if (WARN_ON(in_interrupt()))
865 return 0;
866 return tomoyo_policy_loaded && index < TOMOYO_MAX_CONTROL_INDEX
867#if TOMOYO_MAX_PROFILES != 256
868 && profile < TOMOYO_MAX_PROFILES
869#endif
870 && tomoyo_profile_ptr[profile] ?
871 tomoyo_profile_ptr[profile]->value[index] : 0;
872}
873
874/**
875 * tomoyo_verbose_mode - Check whether TOMOYO is verbose mode.
876 *
877 * @domain: Pointer to "struct tomoyo_domain_info".
878 *
879 * Returns true if domain policy violation warning should be printed to
880 * console.
881 */
882bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
883{
884 return tomoyo_check_flags(domain, TOMOYO_VERBOSE) != 0;
885}
886
887/**
888 * tomoyo_domain_quota_is_ok - Check for domain's quota.
889 *
890 * @domain: Pointer to "struct tomoyo_domain_info".
891 *
892 * Returns true if the domain is not exceeded quota, false otherwise.
893 *
894 * Caller holds tomoyo_read_lock().
895 */
896bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
897{
898 unsigned int count = 0;
899 struct tomoyo_acl_info *ptr;
900
901 if (!domain)
902 return true;
903 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
904 switch (ptr->type) {
905 struct tomoyo_path_acl *acl;
906 u32 perm;
907 u8 i;
908 case TOMOYO_TYPE_PATH_ACL:
909 acl = container_of(ptr, struct tomoyo_path_acl, head);
910 perm = acl->perm | (((u32) acl->perm_high) << 16);
911 for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++)
912 if (perm & (1 << i))
913 count++;
914 if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
915 count -= 2;
916 break;
917 case TOMOYO_TYPE_PATH2_ACL:
918 perm = container_of(ptr, struct tomoyo_path2_acl, head)
919 ->perm;
920 for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++)
921 if (perm & (1 << i))
922 count++;
923 break; 396 break;
924 } 397 }
398 if (i == TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX)
399 return -EINVAL;
400 } else {
401 return -EINVAL;
925 } 402 }
926 if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) 403 if (use_default) {
927 return true; 404 config = TOMOYO_CONFIG_USE_DEFAULT;
928 if (!domain->quota_warned) { 405 } else {
929 domain->quota_warned = true; 406 u8 mode;
930 printk(KERN_WARNING "TOMOYO-WARNING: " 407 for (mode = 0; mode < 4; mode++)
931 "Domain '%s' has so many ACLs to hold. " 408 if (strstr(value, tomoyo_mode[mode]))
932 "Stopped learning mode.\n", domain->domainname->name); 409 /*
933 } 410 * Update lower 3 bits in order to distinguish
934 return false; 411 * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'.
935} 412 */
936 413 config = (config & ~7) | mode;
937/**
938 * tomoyo_find_or_assign_new_profile - Create a new profile.
939 *
940 * @profile: Profile number to create.
941 *
942 * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise.
943 */
944static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned
945 int profile)
946{
947 struct tomoyo_profile *ptr = NULL;
948 int i;
949
950 if (profile >= TOMOYO_MAX_PROFILES)
951 return NULL;
952 if (mutex_lock_interruptible(&tomoyo_policy_lock))
953 return NULL;
954 ptr = tomoyo_profile_ptr[profile];
955 if (ptr)
956 goto ok;
957 ptr = kmalloc(sizeof(*ptr), GFP_NOFS);
958 if (!tomoyo_memory_ok(ptr)) {
959 kfree(ptr);
960 ptr = NULL;
961 goto ok;
962 } 414 }
963 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) 415 if (i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX)
964 ptr->value[i] = tomoyo_control_array[i].current_value; 416 profile->config[i] = config;
965 mb(); /* Avoid out-of-order execution. */ 417 else if (config != TOMOYO_CONFIG_USE_DEFAULT)
966 tomoyo_profile_ptr[profile] = ptr; 418 profile->default_config = config;
967 ok: 419 return 0;
968 mutex_unlock(&tomoyo_policy_lock);
969 return ptr;
970} 420}
971 421
972/** 422/**
973 * tomoyo_write_profile - Write to profile table. 423 * tomoyo_write_profile - Write profile table.
974 * 424 *
975 * @head: Pointer to "struct tomoyo_io_buffer". 425 * @head: Pointer to "struct tomoyo_io_buffer".
976 * 426 *
@@ -980,153 +430,165 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
980{ 430{
981 char *data = head->write_buf; 431 char *data = head->write_buf;
982 unsigned int i; 432 unsigned int i;
983 unsigned int value; 433 bool use_default = false;
984 char *cp; 434 char *cp;
985 struct tomoyo_profile *profile; 435 struct tomoyo_profile *profile;
986 unsigned long num; 436 if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1)
987 437 return 0;
988 cp = strchr(data, '-'); 438 i = simple_strtoul(data, &cp, 10);
989 if (cp) 439 if (data == cp) {
990 *cp = '\0'; 440 profile = &tomoyo_default_profile;
991 if (strict_strtoul(data, 10, &num)) 441 } else {
992 return -EINVAL; 442 if (*cp != '-')
993 if (cp) 443 return -EINVAL;
994 data = cp + 1; 444 data = cp + 1;
995 profile = tomoyo_find_or_assign_new_profile(num); 445 profile = tomoyo_assign_profile(i);
996 if (!profile) 446 if (!profile)
997 return -EINVAL; 447 return -EINVAL;
448 }
998 cp = strchr(data, '='); 449 cp = strchr(data, '=');
999 if (!cp) 450 if (!cp)
1000 return -EINVAL; 451 return -EINVAL;
1001 *cp = '\0'; 452 *cp++ = '\0';
453 if (profile != &tomoyo_default_profile)
454 use_default = strstr(cp, "use_default") != NULL;
455 if (tomoyo_str_starts(&data, "PREFERENCE::")) {
456 tomoyo_set_pref(data, cp, use_default, profile);
457 return 0;
458 }
459 if (profile == &tomoyo_default_profile)
460 return -EINVAL;
1002 if (!strcmp(data, "COMMENT")) { 461 if (!strcmp(data, "COMMENT")) {
1003 const struct tomoyo_path_info *old_comment = profile->comment; 462 const struct tomoyo_path_info *old_comment = profile->comment;
1004 profile->comment = tomoyo_get_name(cp + 1); 463 profile->comment = tomoyo_get_name(cp);
1005 tomoyo_put_name(old_comment); 464 tomoyo_put_name(old_comment);
1006 return 0; 465 return 0;
1007 } 466 }
1008 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { 467 return tomoyo_set_mode(data, cp, use_default, profile);
1009 if (strcmp(data, tomoyo_control_array[i].keyword)) 468}
1010 continue; 469
1011 if (sscanf(cp + 1, "%u", &value) != 1) { 470static void tomoyo_print_preference(struct tomoyo_io_buffer *head,
1012 int j; 471 const int idx)
1013 const char **modes; 472{
1014 switch (i) { 473 struct tomoyo_preference *pref = &tomoyo_default_profile.preference;
1015 case TOMOYO_VERBOSE: 474 const struct tomoyo_profile *profile = idx >= 0 ?
1016 modes = tomoyo_mode_2; 475 tomoyo_profile_ptr[idx] : NULL;
1017 break; 476 char buffer[16] = "";
1018 default: 477 if (profile) {
1019 modes = tomoyo_mode_4; 478 buffer[sizeof(buffer) - 1] = '\0';
1020 break; 479 snprintf(buffer, sizeof(buffer) - 1, "%u-", idx);
1021 }
1022 for (j = 0; j < 4; j++) {
1023 if (strcmp(cp + 1, modes[j]))
1024 continue;
1025 value = j;
1026 break;
1027 }
1028 if (j == 4)
1029 return -EINVAL;
1030 } else if (value > tomoyo_control_array[i].max_value) {
1031 value = tomoyo_control_array[i].max_value;
1032 }
1033 profile->value[i] = value;
1034 return 0;
1035 } 480 }
1036 return -EINVAL; 481 if (profile) {
482 pref = profile->learning;
483 if (pref == &tomoyo_default_profile.preference)
484 goto skip1;
485 }
486 tomoyo_io_printf(head, "%sPREFERENCE::%s={ "
487 "verbose=%s max_entry=%u }\n",
488 buffer, "learning",
489 tomoyo_yesno(pref->learning_verbose),
490 pref->learning_max_entry);
491 skip1:
492 if (profile) {
493 pref = profile->permissive;
494 if (pref == &tomoyo_default_profile.preference)
495 goto skip2;
496 }
497 tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
498 buffer, "permissive",
499 tomoyo_yesno(pref->permissive_verbose));
500 skip2:
501 if (profile) {
502 pref = profile->enforcing;
503 if (pref == &tomoyo_default_profile.preference)
504 return;
505 }
506 tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
507 buffer, "enforcing",
508 tomoyo_yesno(pref->enforcing_verbose));
509}
510
511static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config)
512{
513 tomoyo_io_printf(head, "={ mode=%s }\n", tomoyo_mode[config & 3]);
1037} 514}
1038 515
1039/** 516/**
1040 * tomoyo_read_profile - Read from profile table. 517 * tomoyo_read_profile - Read profile table.
1041 * 518 *
1042 * @head: Pointer to "struct tomoyo_io_buffer". 519 * @head: Pointer to "struct tomoyo_io_buffer".
1043 *
1044 * Returns 0.
1045 */ 520 */
1046static int tomoyo_read_profile(struct tomoyo_io_buffer *head) 521static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
1047{ 522{
1048 static const int total = TOMOYO_MAX_CONTROL_INDEX + 1; 523 u8 index;
1049 int step; 524 const struct tomoyo_profile *profile;
1050 525 next:
1051 if (head->read_eof) 526 index = head->r.index;
1052 return 0; 527 profile = tomoyo_profile_ptr[index];
1053 for (step = head->read_step; step < TOMOYO_MAX_PROFILES * total; 528 switch (head->r.step) {
1054 step++) { 529 case 0:
1055 const u8 index = step / total; 530 tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
1056 u8 type = step % total; 531 tomoyo_print_preference(head, -1);
1057 const struct tomoyo_profile *profile 532 head->r.step++;
1058 = tomoyo_profile_ptr[index]; 533 break;
1059 head->read_step = step; 534 case 1:
1060 if (!profile) 535 for ( ; head->r.index < TOMOYO_MAX_PROFILES;
1061 continue; 536 head->r.index++)
1062 if (!type) { /* Print profile' comment tag. */ 537 if (tomoyo_profile_ptr[head->r.index])
1063 if (!tomoyo_io_printf(head, "%u-COMMENT=%s\n",
1064 index, profile->comment ?
1065 profile->comment->name : ""))
1066 break; 538 break;
1067 continue; 539 if (head->r.index == TOMOYO_MAX_PROFILES)
540 return;
541 head->r.step++;
542 break;
543 case 2:
544 {
545 const struct tomoyo_path_info *comment =
546 profile->comment;
547 tomoyo_io_printf(head, "%u-COMMENT=", index);
548 tomoyo_set_string(head, comment ? comment->name : "");
549 tomoyo_set_lf(head);
550 head->r.step++;
1068 } 551 }
1069 type--; 552 break;
1070 if (type < TOMOYO_MAX_CONTROL_INDEX) { 553 case 3:
1071 const unsigned int value = profile->value[type]; 554 {
1072 const char **modes = NULL; 555 tomoyo_io_printf(head, "%u-%s", index, "CONFIG");
1073 const char *keyword 556 tomoyo_print_config(head, profile->default_config);
1074 = tomoyo_control_array[type].keyword; 557 head->r.bit = 0;
1075 switch (tomoyo_control_array[type].max_value) { 558 head->r.step++;
1076 case 3: 559 }
1077 modes = tomoyo_mode_4; 560 break;
1078 break; 561 case 4:
1079 case 1: 562 for ( ; head->r.bit < TOMOYO_MAX_MAC_INDEX
1080 modes = tomoyo_mode_2; 563 + TOMOYO_MAX_MAC_CATEGORY_INDEX; head->r.bit++) {
1081 break; 564 const u8 i = head->r.bit;
1082 } 565 const u8 config = profile->config[i];
1083 if (modes) { 566 if (config == TOMOYO_CONFIG_USE_DEFAULT)
1084 if (!tomoyo_io_printf(head, "%u-%s=%s\n", index, 567 continue;
1085 keyword, modes[value])) 568 tomoyo_io_printf(head, "%u-%s%s", index, "CONFIG::",
1086 break; 569 tomoyo_mac_keywords[i]);
1087 } else { 570 tomoyo_print_config(head, config);
1088 if (!tomoyo_io_printf(head, "%u-%s=%u\n", index, 571 head->r.bit++;
1089 keyword, value)) 572 break;
1090 break; 573 }
1091 } 574 if (head->r.bit == TOMOYO_MAX_MAC_INDEX
575 + TOMOYO_MAX_MAC_CATEGORY_INDEX) {
576 tomoyo_print_preference(head, index);
577 head->r.index++;
578 head->r.step = 1;
1092 } 579 }
580 break;
1093 } 581 }
1094 if (step == TOMOYO_MAX_PROFILES * total) 582 if (tomoyo_flush(head))
1095 head->read_eof = true; 583 goto next;
1096 return 0;
1097} 584}
1098 585
1099/* 586static bool tomoyo_same_manager(const struct tomoyo_acl_head *a,
1100 * tomoyo_policy_manager_list is used for holding list of domainnames or 587 const struct tomoyo_acl_head *b)
1101 * programs which are permitted to modify configuration via 588{
1102 * /sys/kernel/security/tomoyo/ interface. 589 return container_of(a, struct tomoyo_manager, head)->manager ==
1103 * 590 container_of(b, struct tomoyo_manager, head)->manager;
1104 * An entry is added by 591}
1105 *
1106 * # echo '<kernel> /sbin/mingetty /bin/login /bin/bash' > \
1107 * /sys/kernel/security/tomoyo/manager
1108 * (if you want to specify by a domainname)
1109 *
1110 * or
1111 *
1112 * # echo '/usr/lib/ccs/editpolicy' > /sys/kernel/security/tomoyo/manager
1113 * (if you want to specify by a program's location)
1114 *
1115 * and is deleted by
1116 *
1117 * # echo 'delete <kernel> /sbin/mingetty /bin/login /bin/bash' > \
1118 * /sys/kernel/security/tomoyo/manager
1119 *
1120 * or
1121 *
1122 * # echo 'delete /usr/lib/ccs/editpolicy' > \
1123 * /sys/kernel/security/tomoyo/manager
1124 *
1125 * and all entries are retrieved by
1126 *
1127 * # cat /sys/kernel/security/tomoyo/manager
1128 */
1129LIST_HEAD(tomoyo_policy_manager_list);
1130 592
1131/** 593/**
1132 * tomoyo_update_manager_entry - Add a manager entry. 594 * tomoyo_update_manager_entry - Add a manager entry.
@@ -1141,47 +603,29 @@ LIST_HEAD(tomoyo_policy_manager_list);
1141static int tomoyo_update_manager_entry(const char *manager, 603static int tomoyo_update_manager_entry(const char *manager,
1142 const bool is_delete) 604 const bool is_delete)
1143{ 605{
1144 struct tomoyo_policy_manager_entry *ptr; 606 struct tomoyo_manager e = { };
1145 struct tomoyo_policy_manager_entry e = { }; 607 int error;
1146 int error = is_delete ? -ENOENT : -ENOMEM;
1147 608
1148 if (tomoyo_is_domain_def(manager)) { 609 if (tomoyo_domain_def(manager)) {
1149 if (!tomoyo_is_correct_domain(manager)) 610 if (!tomoyo_correct_domain(manager))
1150 return -EINVAL; 611 return -EINVAL;
1151 e.is_domain = true; 612 e.is_domain = true;
1152 } else { 613 } else {
1153 if (!tomoyo_is_correct_path(manager, 1, -1, -1)) 614 if (!tomoyo_correct_path(manager))
1154 return -EINVAL; 615 return -EINVAL;
1155 } 616 }
1156 e.manager = tomoyo_get_name(manager); 617 e.manager = tomoyo_get_name(manager);
1157 if (!e.manager) 618 if (!e.manager)
1158 return -ENOMEM; 619 return -ENOMEM;
1159 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 620 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
1160 goto out; 621 &tomoyo_policy_list[TOMOYO_ID_MANAGER],
1161 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { 622 tomoyo_same_manager);
1162 if (ptr->manager != e.manager)
1163 continue;
1164 ptr->is_deleted = is_delete;
1165 error = 0;
1166 break;
1167 }
1168 if (!is_delete && error) {
1169 struct tomoyo_policy_manager_entry *entry =
1170 tomoyo_commit_ok(&e, sizeof(e));
1171 if (entry) {
1172 list_add_tail_rcu(&entry->list,
1173 &tomoyo_policy_manager_list);
1174 error = 0;
1175 }
1176 }
1177 mutex_unlock(&tomoyo_policy_lock);
1178 out:
1179 tomoyo_put_name(e.manager); 623 tomoyo_put_name(e.manager);
1180 return error; 624 return error;
1181} 625}
1182 626
1183/** 627/**
1184 * tomoyo_write_manager_policy - Write manager policy. 628 * tomoyo_write_manager - Write manager policy.
1185 * 629 *
1186 * @head: Pointer to "struct tomoyo_io_buffer". 630 * @head: Pointer to "struct tomoyo_io_buffer".
1187 * 631 *
@@ -1189,7 +633,7 @@ static int tomoyo_update_manager_entry(const char *manager,
1189 * 633 *
1190 * Caller holds tomoyo_read_lock(). 634 * Caller holds tomoyo_read_lock().
1191 */ 635 */
1192static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) 636static int tomoyo_write_manager(struct tomoyo_io_buffer *head)
1193{ 637{
1194 char *data = head->write_buf; 638 char *data = head->write_buf;
1195 bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE); 639 bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
@@ -1202,47 +646,41 @@ static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
1202} 646}
1203 647
1204/** 648/**
1205 * tomoyo_read_manager_policy - Read manager policy. 649 * tomoyo_read_manager - Read manager policy.
1206 * 650 *
1207 * @head: Pointer to "struct tomoyo_io_buffer". 651 * @head: Pointer to "struct tomoyo_io_buffer".
1208 * 652 *
1209 * Returns 0.
1210 *
1211 * Caller holds tomoyo_read_lock(). 653 * Caller holds tomoyo_read_lock().
1212 */ 654 */
1213static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) 655static void tomoyo_read_manager(struct tomoyo_io_buffer *head)
1214{ 656{
1215 struct list_head *pos; 657 if (head->r.eof)
1216 bool done = true; 658 return;
1217 659 list_for_each_cookie(head->r.acl,
1218 if (head->read_eof) 660 &tomoyo_policy_list[TOMOYO_ID_MANAGER]) {
1219 return 0; 661 struct tomoyo_manager *ptr =
1220 list_for_each_cookie(pos, head->read_var2, 662 list_entry(head->r.acl, typeof(*ptr), head.list);
1221 &tomoyo_policy_manager_list) { 663 if (ptr->head.is_deleted)
1222 struct tomoyo_policy_manager_entry *ptr;
1223 ptr = list_entry(pos, struct tomoyo_policy_manager_entry,
1224 list);
1225 if (ptr->is_deleted)
1226 continue; 664 continue;
1227 done = tomoyo_io_printf(head, "%s\n", ptr->manager->name); 665 if (!tomoyo_flush(head))
1228 if (!done) 666 return;
1229 break; 667 tomoyo_set_string(head, ptr->manager->name);
668 tomoyo_set_lf(head);
1230 } 669 }
1231 head->read_eof = done; 670 head->r.eof = true;
1232 return 0;
1233} 671}
1234 672
1235/** 673/**
1236 * tomoyo_is_policy_manager - Check whether the current process is a policy manager. 674 * tomoyo_manager - Check whether the current process is a policy manager.
1237 * 675 *
1238 * Returns true if the current process is permitted to modify policy 676 * Returns true if the current process is permitted to modify policy
1239 * via /sys/kernel/security/tomoyo/ interface. 677 * via /sys/kernel/security/tomoyo/ interface.
1240 * 678 *
1241 * Caller holds tomoyo_read_lock(). 679 * Caller holds tomoyo_read_lock().
1242 */ 680 */
1243static bool tomoyo_is_policy_manager(void) 681static bool tomoyo_manager(void)
1244{ 682{
1245 struct tomoyo_policy_manager_entry *ptr; 683 struct tomoyo_manager *ptr;
1246 const char *exe; 684 const char *exe;
1247 const struct task_struct *task = current; 685 const struct task_struct *task = current;
1248 const struct tomoyo_path_info *domainname = tomoyo_domain()->domainname; 686 const struct tomoyo_path_info *domainname = tomoyo_domain()->domainname;
@@ -1252,8 +690,9 @@ static bool tomoyo_is_policy_manager(void)
1252 return true; 690 return true;
1253 if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) 691 if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
1254 return false; 692 return false;
1255 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { 693 list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_MANAGER],
1256 if (!ptr->is_deleted && ptr->is_domain 694 head.list) {
695 if (!ptr->head.is_deleted && ptr->is_domain
1257 && !tomoyo_pathcmp(domainname, ptr->manager)) { 696 && !tomoyo_pathcmp(domainname, ptr->manager)) {
1258 found = true; 697 found = true;
1259 break; 698 break;
@@ -1264,8 +703,9 @@ static bool tomoyo_is_policy_manager(void)
1264 exe = tomoyo_get_exe(); 703 exe = tomoyo_get_exe();
1265 if (!exe) 704 if (!exe)
1266 return false; 705 return false;
1267 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { 706 list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_MANAGER],
1268 if (!ptr->is_deleted && !ptr->is_domain 707 head.list) {
708 if (!ptr->head.is_deleted && !ptr->is_domain
1269 && !strcmp(exe, ptr->manager->name)) { 709 && !strcmp(exe, ptr->manager->name)) {
1270 found = true; 710 found = true;
1271 break; 711 break;
@@ -1285,7 +725,7 @@ static bool tomoyo_is_policy_manager(void)
1285} 725}
1286 726
1287/** 727/**
1288 * tomoyo_is_select_one - Parse select command. 728 * tomoyo_select_one - Parse select command.
1289 * 729 *
1290 * @head: Pointer to "struct tomoyo_io_buffer". 730 * @head: Pointer to "struct tomoyo_io_buffer".
1291 * @data: String to parse. 731 * @data: String to parse.
@@ -1294,23 +734,31 @@ static bool tomoyo_is_policy_manager(void)
1294 * 734 *
1295 * Caller holds tomoyo_read_lock(). 735 * Caller holds tomoyo_read_lock().
1296 */ 736 */
1297static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, 737static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data)
1298 const char *data)
1299{ 738{
1300 unsigned int pid; 739 unsigned int pid;
1301 struct tomoyo_domain_info *domain = NULL; 740 struct tomoyo_domain_info *domain = NULL;
741 bool global_pid = false;
1302 742
1303 if (sscanf(data, "pid=%u", &pid) == 1) { 743 if (!strcmp(data, "allow_execute")) {
744 head->r.print_execute_only = true;
745 return true;
746 }
747 if (sscanf(data, "pid=%u", &pid) == 1 ||
748 (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
1304 struct task_struct *p; 749 struct task_struct *p;
1305 rcu_read_lock(); 750 rcu_read_lock();
1306 read_lock(&tasklist_lock); 751 read_lock(&tasklist_lock);
1307 p = find_task_by_vpid(pid); 752 if (global_pid)
753 p = find_task_by_pid_ns(pid, &init_pid_ns);
754 else
755 p = find_task_by_vpid(pid);
1308 if (p) 756 if (p)
1309 domain = tomoyo_real_domain(p); 757 domain = tomoyo_real_domain(p);
1310 read_unlock(&tasklist_lock); 758 read_unlock(&tasklist_lock);
1311 rcu_read_unlock(); 759 rcu_read_unlock();
1312 } else if (!strncmp(data, "domain=", 7)) { 760 } else if (!strncmp(data, "domain=", 7)) {
1313 if (tomoyo_is_domain_def(data + 7)) 761 if (tomoyo_domain_def(data + 7))
1314 domain = tomoyo_find_domain(data + 7); 762 domain = tomoyo_find_domain(data + 7);
1315 } else 763 } else
1316 return false; 764 return false;
@@ -1318,24 +766,13 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1318 /* Accessing read_buf is safe because head->io_sem is held. */ 766 /* Accessing read_buf is safe because head->io_sem is held. */
1319 if (!head->read_buf) 767 if (!head->read_buf)
1320 return true; /* Do nothing if open(O_WRONLY). */ 768 return true; /* Do nothing if open(O_WRONLY). */
1321 head->read_avail = 0; 769 memset(&head->r, 0, sizeof(head->r));
770 head->r.print_this_domain_only = true;
771 head->r.eof = !domain;
772 head->r.domain = &domain->list;
1322 tomoyo_io_printf(head, "# select %s\n", data); 773 tomoyo_io_printf(head, "# select %s\n", data);
1323 head->read_single_domain = true; 774 if (domain && domain->is_deleted)
1324 head->read_eof = !domain; 775 tomoyo_io_printf(head, "# This is a deleted domain.\n");
1325 if (domain) {
1326 struct tomoyo_domain_info *d;
1327 head->read_var1 = NULL;
1328 list_for_each_entry_rcu(d, &tomoyo_domain_list, list) {
1329 if (d == domain)
1330 break;
1331 head->read_var1 = &d->list;
1332 }
1333 head->read_var2 = NULL;
1334 head->read_bit = 0;
1335 head->read_step = 0;
1336 if (domain->is_deleted)
1337 tomoyo_io_printf(head, "# This is a deleted domain.\n");
1338 }
1339 return true; 776 return true;
1340} 777}
1341 778
@@ -1373,7 +810,7 @@ static int tomoyo_delete_domain(char *domainname)
1373} 810}
1374 811
1375/** 812/**
1376 * tomoyo_write_domain_policy - Write domain policy. 813 * tomoyo_write_domain2 - Write domain policy.
1377 * 814 *
1378 * @head: Pointer to "struct tomoyo_io_buffer". 815 * @head: Pointer to "struct tomoyo_io_buffer".
1379 * 816 *
@@ -1381,7 +818,24 @@ static int tomoyo_delete_domain(char *domainname)
1381 * 818 *
1382 * Caller holds tomoyo_read_lock(). 819 * Caller holds tomoyo_read_lock().
1383 */ 820 */
1384static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) 821static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain,
822 const bool is_delete)
823{
824 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_MOUNT))
825 return tomoyo_write_mount(data, domain, is_delete);
826 return tomoyo_write_file(data, domain, is_delete);
827}
828
829/**
830 * tomoyo_write_domain - Write domain policy.
831 *
832 * @head: Pointer to "struct tomoyo_io_buffer".
833 *
834 * Returns 0 on success, negative value otherwise.
835 *
836 * Caller holds tomoyo_read_lock().
837 */
838static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
1385{ 839{
1386 char *data = head->write_buf; 840 char *data = head->write_buf;
1387 struct tomoyo_domain_info *domain = head->write_var1; 841 struct tomoyo_domain_info *domain = head->write_var1;
@@ -1393,19 +847,19 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1393 is_delete = true; 847 is_delete = true;
1394 else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_SELECT)) 848 else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_SELECT))
1395 is_select = true; 849 is_select = true;
1396 if (is_select && tomoyo_is_select_one(head, data)) 850 if (is_select && tomoyo_select_one(head, data))
1397 return 0; 851 return 0;
1398 /* Don't allow updating policies by non manager programs. */ 852 /* Don't allow updating policies by non manager programs. */
1399 if (!tomoyo_is_policy_manager()) 853 if (!tomoyo_manager())
1400 return -EPERM; 854 return -EPERM;
1401 if (tomoyo_is_domain_def(data)) { 855 if (tomoyo_domain_def(data)) {
1402 domain = NULL; 856 domain = NULL;
1403 if (is_delete) 857 if (is_delete)
1404 tomoyo_delete_domain(data); 858 tomoyo_delete_domain(data);
1405 else if (is_select) 859 else if (is_select)
1406 domain = tomoyo_find_domain(data); 860 domain = tomoyo_find_domain(data);
1407 else 861 else
1408 domain = tomoyo_find_or_assign_new_domain(data, 0); 862 domain = tomoyo_assign_domain(data, 0);
1409 head->write_var1 = domain; 863 head->write_var1 = domain;
1410 return 0; 864 return 0;
1411 } 865 }
@@ -1422,179 +876,198 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1422 domain->ignore_global_allow_read = !is_delete; 876 domain->ignore_global_allow_read = !is_delete;
1423 return 0; 877 return 0;
1424 } 878 }
1425 return tomoyo_write_file_policy(data, domain, is_delete); 879 if (!strcmp(data, TOMOYO_KEYWORD_QUOTA_EXCEEDED)) {
880 domain->quota_warned = !is_delete;
881 return 0;
882 }
883 if (!strcmp(data, TOMOYO_KEYWORD_TRANSITION_FAILED)) {
884 domain->transition_failed = !is_delete;
885 return 0;
886 }
887 return tomoyo_write_domain2(data, domain, is_delete);
1426} 888}
1427 889
1428/** 890/**
1429 * tomoyo_print_path_acl - Print a single path ACL entry. 891 * tomoyo_fns - Find next set bit.
1430 * 892 *
1431 * @head: Pointer to "struct tomoyo_io_buffer". 893 * @perm: 8 bits value.
1432 * @ptr: Pointer to "struct tomoyo_path_acl". 894 * @bit: First bit to find.
1433 * 895 *
1434 * Returns true on success, false otherwise. 896 * Returns next on-bit on success, 8 otherwise.
1435 */ 897 */
1436static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head, 898static u8 tomoyo_fns(const u8 perm, u8 bit)
1437 struct tomoyo_path_acl *ptr)
1438{ 899{
1439 int pos; 900 for ( ; bit < 8; bit++)
1440 u8 bit; 901 if (perm & (1 << bit))
1441 const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16); 902 break;
1442 903 return bit;
1443 for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
1444 if (!(perm & (1 << bit)))
1445 continue;
1446 /* Print "read/write" instead of "read" and "write". */
1447 if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE)
1448 && (perm & (1 << TOMOYO_TYPE_READ_WRITE)))
1449 continue;
1450 pos = head->read_avail;
1451 if (!tomoyo_io_printf(head, "allow_%s ",
1452 tomoyo_path2keyword(bit)) ||
1453 !tomoyo_print_name_union(head, &ptr->name) ||
1454 !tomoyo_io_printf(head, "\n"))
1455 goto out;
1456 }
1457 head->read_bit = 0;
1458 return true;
1459 out:
1460 head->read_bit = bit;
1461 head->read_avail = pos;
1462 return false;
1463} 904}
1464 905
1465/** 906/**
1466 * tomoyo_print_path2_acl - Print a double path ACL entry. 907 * tomoyo_print_entry - Print an ACL entry.
1467 * 908 *
1468 * @head: Pointer to "struct tomoyo_io_buffer". 909 * @head: Pointer to "struct tomoyo_io_buffer".
1469 * @ptr: Pointer to "struct tomoyo_path2_acl". 910 * @acl: Pointer to an ACL entry.
1470 * 911 *
1471 * Returns true on success, false otherwise. 912 * Returns true on success, false otherwise.
1472 */ 913 */
1473static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head, 914static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1474 struct tomoyo_path2_acl *ptr) 915 struct tomoyo_acl_info *acl)
1475{ 916{
1476 int pos; 917 const u8 acl_type = acl->type;
1477 const u8 perm = ptr->perm;
1478 u8 bit; 918 u8 bit;
1479 919
1480 for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { 920 if (acl->is_deleted)
1481 if (!(perm & (1 << bit))) 921 return true;
1482 continue; 922 next:
1483 pos = head->read_avail; 923 bit = head->r.bit;
1484 if (!tomoyo_io_printf(head, "allow_%s ", 924 if (!tomoyo_flush(head))
1485 tomoyo_path22keyword(bit)) || 925 return false;
1486 !tomoyo_print_name_union(head, &ptr->name1) || 926 else if (acl_type == TOMOYO_TYPE_PATH_ACL) {
1487 !tomoyo_print_name_union(head, &ptr->name2) || 927 struct tomoyo_path_acl *ptr =
1488 !tomoyo_io_printf(head, "\n")) 928 container_of(acl, typeof(*ptr), head);
1489 goto out; 929 const u16 perm = ptr->perm;
930 for ( ; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
931 if (!(perm & (1 << bit)))
932 continue;
933 if (head->r.print_execute_only &&
934 bit != TOMOYO_TYPE_EXECUTE)
935 continue;
936 /* Print "read/write" instead of "read" and "write". */
937 if ((bit == TOMOYO_TYPE_READ ||
938 bit == TOMOYO_TYPE_WRITE)
939 && (perm & (1 << TOMOYO_TYPE_READ_WRITE)))
940 continue;
941 break;
942 }
943 if (bit >= TOMOYO_MAX_PATH_OPERATION)
944 goto done;
945 tomoyo_io_printf(head, "allow_%s", tomoyo_path_keyword[bit]);
946 tomoyo_print_name_union(head, &ptr->name);
947 } else if (head->r.print_execute_only) {
948 return true;
949 } else if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
950 struct tomoyo_path2_acl *ptr =
951 container_of(acl, typeof(*ptr), head);
952 bit = tomoyo_fns(ptr->perm, bit);
953 if (bit >= TOMOYO_MAX_PATH2_OPERATION)
954 goto done;
955 tomoyo_io_printf(head, "allow_%s", tomoyo_path2_keyword[bit]);
956 tomoyo_print_name_union(head, &ptr->name1);
957 tomoyo_print_name_union(head, &ptr->name2);
958 } else if (acl_type == TOMOYO_TYPE_PATH_NUMBER_ACL) {
959 struct tomoyo_path_number_acl *ptr =
960 container_of(acl, typeof(*ptr), head);
961 bit = tomoyo_fns(ptr->perm, bit);
962 if (bit >= TOMOYO_MAX_PATH_NUMBER_OPERATION)
963 goto done;
964 tomoyo_io_printf(head, "allow_%s",
965 tomoyo_path_number_keyword[bit]);
966 tomoyo_print_name_union(head, &ptr->name);
967 tomoyo_print_number_union(head, &ptr->number);
968 } else if (acl_type == TOMOYO_TYPE_MKDEV_ACL) {
969 struct tomoyo_mkdev_acl *ptr =
970 container_of(acl, typeof(*ptr), head);
971 bit = tomoyo_fns(ptr->perm, bit);
972 if (bit >= TOMOYO_MAX_MKDEV_OPERATION)
973 goto done;
974 tomoyo_io_printf(head, "allow_%s", tomoyo_mkdev_keyword[bit]);
975 tomoyo_print_name_union(head, &ptr->name);
976 tomoyo_print_number_union(head, &ptr->mode);
977 tomoyo_print_number_union(head, &ptr->major);
978 tomoyo_print_number_union(head, &ptr->minor);
979 } else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) {
980 struct tomoyo_mount_acl *ptr =
981 container_of(acl, typeof(*ptr), head);
982 tomoyo_io_printf(head, "allow_mount");
983 tomoyo_print_name_union(head, &ptr->dev_name);
984 tomoyo_print_name_union(head, &ptr->dir_name);
985 tomoyo_print_name_union(head, &ptr->fs_type);
986 tomoyo_print_number_union(head, &ptr->flags);
1490 } 987 }
1491 head->read_bit = 0; 988 head->r.bit = bit + 1;
989 tomoyo_io_printf(head, "\n");
990 if (acl_type != TOMOYO_TYPE_MOUNT_ACL)
991 goto next;
992 done:
993 head->r.bit = 0;
1492 return true; 994 return true;
1493 out:
1494 head->read_bit = bit;
1495 head->read_avail = pos;
1496 return false;
1497} 995}
1498 996
1499/** 997/**
1500 * tomoyo_print_entry - Print an ACL entry. 998 * tomoyo_read_domain2 - Read domain policy.
1501 * 999 *
1502 * @head: Pointer to "struct tomoyo_io_buffer". 1000 * @head: Pointer to "struct tomoyo_io_buffer".
1503 * @ptr: Pointer to an ACL entry. 1001 * @domain: Pointer to "struct tomoyo_domain_info".
1002 *
1003 * Caller holds tomoyo_read_lock().
1504 * 1004 *
1505 * Returns true on success, false otherwise. 1005 * Returns true on success, false otherwise.
1506 */ 1006 */
1507static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, 1007static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head,
1508 struct tomoyo_acl_info *ptr) 1008 struct tomoyo_domain_info *domain)
1509{ 1009{
1510 const u8 acl_type = ptr->type; 1010 list_for_each_cookie(head->r.acl, &domain->acl_info_list) {
1511 1011 struct tomoyo_acl_info *ptr =
1512 if (acl_type == TOMOYO_TYPE_PATH_ACL) { 1012 list_entry(head->r.acl, typeof(*ptr), list);
1513 struct tomoyo_path_acl *acl 1013 if (!tomoyo_print_entry(head, ptr))
1514 = container_of(ptr, struct tomoyo_path_acl, head); 1014 return false;
1515 return tomoyo_print_path_acl(head, acl);
1516 }
1517 if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
1518 struct tomoyo_path2_acl *acl
1519 = container_of(ptr, struct tomoyo_path2_acl, head);
1520 return tomoyo_print_path2_acl(head, acl);
1521 } 1015 }
1522 BUG(); /* This must not happen. */ 1016 head->r.acl = NULL;
1523 return false; 1017 return true;
1524} 1018}
1525 1019
1526/** 1020/**
1527 * tomoyo_read_domain_policy - Read domain policy. 1021 * tomoyo_read_domain - Read domain policy.
1528 * 1022 *
1529 * @head: Pointer to "struct tomoyo_io_buffer". 1023 * @head: Pointer to "struct tomoyo_io_buffer".
1530 * 1024 *
1531 * Returns 0.
1532 *
1533 * Caller holds tomoyo_read_lock(). 1025 * Caller holds tomoyo_read_lock().
1534 */ 1026 */
1535static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) 1027static void tomoyo_read_domain(struct tomoyo_io_buffer *head)
1536{ 1028{
1537 struct list_head *dpos; 1029 if (head->r.eof)
1538 struct list_head *apos; 1030 return;
1539 bool done = true; 1031 list_for_each_cookie(head->r.domain, &tomoyo_domain_list) {
1540 1032 struct tomoyo_domain_info *domain =
1541 if (head->read_eof) 1033 list_entry(head->r.domain, typeof(*domain), list);
1542 return 0; 1034 switch (head->r.step) {
1543 if (head->read_step == 0) 1035 case 0:
1544 head->read_step = 1; 1036 if (domain->is_deleted &&
1545 list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) { 1037 !head->r.print_this_domain_only)
1546 struct tomoyo_domain_info *domain; 1038 continue;
1547 const char *quota_exceeded = ""; 1039 /* Print domainname and flags. */
1548 const char *transition_failed = ""; 1040 tomoyo_set_string(head, domain->domainname->name);
1549 const char *ignore_global_allow_read = ""; 1041 tomoyo_set_lf(head);
1550 domain = list_entry(dpos, struct tomoyo_domain_info, list); 1042 tomoyo_io_printf(head,
1551 if (head->read_step != 1) 1043 TOMOYO_KEYWORD_USE_PROFILE "%u\n",
1552 goto acl_loop; 1044 domain->profile);
1553 if (domain->is_deleted && !head->read_single_domain) 1045 if (domain->quota_warned)
1554 continue; 1046 tomoyo_set_string(head, "quota_exceeded\n");
1555 /* Print domainname and flags. */ 1047 if (domain->transition_failed)
1556 if (domain->quota_warned) 1048 tomoyo_set_string(head, "transition_failed\n");
1557 quota_exceeded = "quota_exceeded\n"; 1049 if (domain->ignore_global_allow_read)
1558 if (domain->transition_failed) 1050 tomoyo_set_string(head,
1559 transition_failed = "transition_failed\n"; 1051 TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ
1560 if (domain->ignore_global_allow_read) 1052 "\n");
1561 ignore_global_allow_read 1053 head->r.step++;
1562 = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; 1054 tomoyo_set_lf(head);
1563 done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE 1055 /* fall through */
1564 "%u\n%s%s%s\n", 1056 case 1:
1565 domain->domainname->name, 1057 if (!tomoyo_read_domain2(head, domain))
1566 domain->profile, quota_exceeded, 1058 return;
1567 transition_failed, 1059 head->r.step++;
1568 ignore_global_allow_read); 1060 if (!tomoyo_set_lf(head))
1569 if (!done) 1061 return;
1570 break; 1062 /* fall through */
1571 head->read_step = 2; 1063 case 2:
1572acl_loop: 1064 head->r.step = 0;
1573 if (head->read_step == 3) 1065 if (head->r.print_this_domain_only)
1574 goto tail_mark; 1066 goto done;
1575 /* Print ACL entries in the domain. */
1576 list_for_each_cookie(apos, head->read_var2,
1577 &domain->acl_info_list) {
1578 struct tomoyo_acl_info *ptr
1579 = list_entry(apos, struct tomoyo_acl_info,
1580 list);
1581 done = tomoyo_print_entry(head, ptr);
1582 if (!done)
1583 break;
1584 } 1067 }
1585 if (!done)
1586 break;
1587 head->read_step = 3;
1588tail_mark:
1589 done = tomoyo_io_printf(head, "\n");
1590 if (!done)
1591 break;
1592 head->read_step = 1;
1593 if (head->read_single_domain)
1594 break;
1595 } 1068 }
1596 head->read_eof = done; 1069 done:
1597 return 0; 1070 head->r.eof = true;
1598} 1071}
1599 1072
1600/** 1073/**
@@ -1607,7 +1080,7 @@ tail_mark:
1607 * This is equivalent to doing 1080 * This is equivalent to doing
1608 * 1081 *
1609 * ( echo "select " $domainname; echo "use_profile " $profile ) | 1082 * ( echo "select " $domainname; echo "use_profile " $profile ) |
1610 * /usr/lib/ccs/loadpolicy -d 1083 * /usr/sbin/tomoyo-loadpolicy -d
1611 * 1084 *
1612 * Caller holds tomoyo_read_lock(). 1085 * Caller holds tomoyo_read_lock().
1613 */ 1086 */
@@ -1646,25 +1119,22 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
1646 * 1119 *
1647 * Caller holds tomoyo_read_lock(). 1120 * Caller holds tomoyo_read_lock().
1648 */ 1121 */
1649static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) 1122static void tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1650{ 1123{
1651 struct list_head *pos; 1124 if (head->r.eof)
1652 bool done = true; 1125 return;
1653 1126 list_for_each_cookie(head->r.domain, &tomoyo_domain_list) {
1654 if (head->read_eof) 1127 struct tomoyo_domain_info *domain =
1655 return 0; 1128 list_entry(head->r.domain, typeof(*domain), list);
1656 list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) {
1657 struct tomoyo_domain_info *domain;
1658 domain = list_entry(pos, struct tomoyo_domain_info, list);
1659 if (domain->is_deleted) 1129 if (domain->is_deleted)
1660 continue; 1130 continue;
1661 done = tomoyo_io_printf(head, "%u %s\n", domain->profile, 1131 if (!tomoyo_flush(head))
1662 domain->domainname->name); 1132 return;
1663 if (!done) 1133 tomoyo_io_printf(head, "%u ", domain->profile);
1664 break; 1134 tomoyo_set_string(head, domain->domainname->name);
1135 tomoyo_set_lf(head);
1665 } 1136 }
1666 head->read_eof = done; 1137 head->r.eof = true;
1667 return 0;
1668} 1138}
1669 1139
1670/** 1140/**
@@ -1676,11 +1146,7 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1676 */ 1146 */
1677static int tomoyo_write_pid(struct tomoyo_io_buffer *head) 1147static int tomoyo_write_pid(struct tomoyo_io_buffer *head)
1678{ 1148{
1679 unsigned long pid; 1149 head->r.eof = false;
1680 /* No error check. */
1681 strict_strtoul(head->write_buf, 10, &pid);
1682 head->read_step = (int) pid;
1683 head->read_eof = false;
1684 return 0; 1150 return 0;
1685} 1151}
1686 1152
@@ -1694,29 +1160,57 @@ static int tomoyo_write_pid(struct tomoyo_io_buffer *head)
1694 * The PID is specified by tomoyo_write_pid() so that the user can obtain 1160 * The PID is specified by tomoyo_write_pid() so that the user can obtain
1695 * using read()/write() interface rather than sysctl() interface. 1161 * using read()/write() interface rather than sysctl() interface.
1696 */ 1162 */
1697static int tomoyo_read_pid(struct tomoyo_io_buffer *head) 1163static void tomoyo_read_pid(struct tomoyo_io_buffer *head)
1698{ 1164{
1699 if (head->read_avail == 0 && !head->read_eof) { 1165 char *buf = head->write_buf;
1700 const int pid = head->read_step; 1166 bool global_pid = false;
1701 struct task_struct *p; 1167 unsigned int pid;
1702 struct tomoyo_domain_info *domain = NULL; 1168 struct task_struct *p;
1703 rcu_read_lock(); 1169 struct tomoyo_domain_info *domain = NULL;
1704 read_lock(&tasklist_lock); 1170
1705 p = find_task_by_vpid(pid); 1171 /* Accessing write_buf is safe because head->io_sem is held. */
1706 if (p) 1172 if (!buf) {
1707 domain = tomoyo_real_domain(p); 1173 head->r.eof = true;
1708 read_unlock(&tasklist_lock); 1174 return; /* Do nothing if open(O_RDONLY). */
1709 rcu_read_unlock();
1710 if (domain)
1711 tomoyo_io_printf(head, "%d %u %s", pid, domain->profile,
1712 domain->domainname->name);
1713 head->read_eof = true;
1714 } 1175 }
1715 return 0; 1176 if (head->r.w_pos || head->r.eof)
1177 return;
1178 head->r.eof = true;
1179 if (tomoyo_str_starts(&buf, "global-pid "))
1180 global_pid = true;
1181 pid = (unsigned int) simple_strtoul(buf, NULL, 10);
1182 rcu_read_lock();
1183 read_lock(&tasklist_lock);
1184 if (global_pid)
1185 p = find_task_by_pid_ns(pid, &init_pid_ns);
1186 else
1187 p = find_task_by_vpid(pid);
1188 if (p)
1189 domain = tomoyo_real_domain(p);
1190 read_unlock(&tasklist_lock);
1191 rcu_read_unlock();
1192 if (!domain)
1193 return;
1194 tomoyo_io_printf(head, "%u %u ", pid, domain->profile);
1195 tomoyo_set_string(head, domain->domainname->name);
1716} 1196}
1717 1197
1198static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = {
1199 [TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE]
1200 = TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN,
1201 [TOMOYO_TRANSITION_CONTROL_INITIALIZE]
1202 = TOMOYO_KEYWORD_INITIALIZE_DOMAIN,
1203 [TOMOYO_TRANSITION_CONTROL_NO_KEEP] = TOMOYO_KEYWORD_NO_KEEP_DOMAIN,
1204 [TOMOYO_TRANSITION_CONTROL_KEEP] = TOMOYO_KEYWORD_KEEP_DOMAIN
1205};
1206
1207static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = {
1208 [TOMOYO_PATH_GROUP] = TOMOYO_KEYWORD_PATH_GROUP,
1209 [TOMOYO_NUMBER_GROUP] = TOMOYO_KEYWORD_NUMBER_GROUP
1210};
1211
1718/** 1212/**
1719 * tomoyo_write_exception_policy - Write exception policy. 1213 * tomoyo_write_exception - Write exception policy.
1720 * 1214 *
1721 * @head: Pointer to "struct tomoyo_io_buffer". 1215 * @head: Pointer to "struct tomoyo_io_buffer".
1722 * 1216 *
@@ -1724,186 +1218,523 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head)
1724 * 1218 *
1725 * Caller holds tomoyo_read_lock(). 1219 * Caller holds tomoyo_read_lock().
1726 */ 1220 */
1727static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) 1221static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
1728{ 1222{
1729 char *data = head->write_buf; 1223 char *data = head->write_buf;
1730 bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE); 1224 bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
1731 1225 u8 i;
1732 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_KEEP_DOMAIN)) 1226 static const struct {
1733 return tomoyo_write_domain_keeper_policy(data, false, 1227 const char *keyword;
1734 is_delete); 1228 int (*write) (char *, const bool);
1735 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_KEEP_DOMAIN)) 1229 } tomoyo_callback[4] = {
1736 return tomoyo_write_domain_keeper_policy(data, true, is_delete); 1230 { TOMOYO_KEYWORD_AGGREGATOR, tomoyo_write_aggregator },
1737 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_INITIALIZE_DOMAIN)) 1231 { TOMOYO_KEYWORD_FILE_PATTERN, tomoyo_write_pattern },
1738 return tomoyo_write_domain_initializer_policy(data, false, 1232 { TOMOYO_KEYWORD_DENY_REWRITE, tomoyo_write_no_rewrite },
1739 is_delete); 1233 { TOMOYO_KEYWORD_ALLOW_READ, tomoyo_write_globally_readable },
1740 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN)) 1234 };
1741 return tomoyo_write_domain_initializer_policy(data, true, 1235
1742 is_delete); 1236 for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++)
1743 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALIAS)) 1237 if (tomoyo_str_starts(&data, tomoyo_transition_type[i]))
1744 return tomoyo_write_alias_policy(data, is_delete); 1238 return tomoyo_write_transition_control(data, is_delete,
1745 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_READ)) 1239 i);
1746 return tomoyo_write_globally_readable_policy(data, is_delete); 1240 for (i = 0; i < 4; i++)
1747 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_FILE_PATTERN)) 1241 if (tomoyo_str_starts(&data, tomoyo_callback[i].keyword))
1748 return tomoyo_write_pattern_policy(data, is_delete); 1242 return tomoyo_callback[i].write(data, is_delete);
1749 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE)) 1243 for (i = 0; i < TOMOYO_MAX_GROUP; i++)
1750 return tomoyo_write_no_rewrite_policy(data, is_delete); 1244 if (tomoyo_str_starts(&data, tomoyo_group_name[i]))
1751 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) 1245 return tomoyo_write_group(data, is_delete, i);
1752 return tomoyo_write_path_group_policy(data, is_delete);
1753 return -EINVAL; 1246 return -EINVAL;
1754} 1247}
1755 1248
1756/** 1249/**
1757 * tomoyo_read_exception_policy - Read exception policy. 1250 * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group" list.
1758 * 1251 *
1759 * @head: Pointer to "struct tomoyo_io_buffer". 1252 * @head: Pointer to "struct tomoyo_io_buffer".
1253 * @idx: Index number.
1760 * 1254 *
1761 * Returns 0 on success, -EINVAL otherwise. 1255 * Returns true on success, false otherwise.
1762 * 1256 *
1763 * Caller holds tomoyo_read_lock(). 1257 * Caller holds tomoyo_read_lock().
1764 */ 1258 */
1765static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) 1259static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
1766{ 1260{
1767 if (!head->read_eof) { 1261 list_for_each_cookie(head->r.group, &tomoyo_group_list[idx]) {
1768 switch (head->read_step) { 1262 struct tomoyo_group *group =
1769 case 0: 1263 list_entry(head->r.group, typeof(*group), list);
1770 head->read_var2 = NULL; 1264 list_for_each_cookie(head->r.acl, &group->member_list) {
1771 head->read_step = 1; 1265 struct tomoyo_acl_head *ptr =
1772 case 1: 1266 list_entry(head->r.acl, typeof(*ptr), list);
1773 if (!tomoyo_read_domain_keeper_policy(head)) 1267 if (ptr->is_deleted)
1774 break; 1268 continue;
1775 head->read_var2 = NULL; 1269 if (!tomoyo_flush(head))
1776 head->read_step = 2; 1270 return false;
1777 case 2: 1271 tomoyo_set_string(head, tomoyo_group_name[idx]);
1778 if (!tomoyo_read_globally_readable_policy(head)) 1272 tomoyo_set_string(head, group->group_name->name);
1779 break; 1273 if (idx == TOMOYO_PATH_GROUP) {
1780 head->read_var2 = NULL; 1274 tomoyo_set_space(head);
1781 head->read_step = 3; 1275 tomoyo_set_string(head, container_of
1782 case 3: 1276 (ptr, struct tomoyo_path_group,
1783 head->read_var2 = NULL; 1277 head)->member_name->name);
1784 head->read_step = 4; 1278 } else if (idx == TOMOYO_NUMBER_GROUP) {
1785 case 4: 1279 tomoyo_print_number_union(head, &container_of
1786 if (!tomoyo_read_domain_initializer_policy(head)) 1280 (ptr,
1787 break; 1281 struct tomoyo_number_group,
1788 head->read_var2 = NULL; 1282 head)->number);
1789 head->read_step = 5; 1283 }
1790 case 5: 1284 tomoyo_set_lf(head);
1791 if (!tomoyo_read_alias_policy(head)) 1285 }
1792 break; 1286 head->r.acl = NULL;
1793 head->read_var2 = NULL; 1287 }
1794 head->read_step = 6; 1288 head->r.group = NULL;
1795 case 6: 1289 return true;
1796 head->read_var2 = NULL; 1290}
1797 head->read_step = 7; 1291
1798 case 7: 1292/**
1799 if (!tomoyo_read_file_pattern(head)) 1293 * tomoyo_read_policy - Read "struct tomoyo_..._entry" list.
1800 break; 1294 *
1801 head->read_var2 = NULL; 1295 * @head: Pointer to "struct tomoyo_io_buffer".
1802 head->read_step = 8; 1296 * @idx: Index number.
1803 case 8: 1297 *
1804 if (!tomoyo_read_no_rewrite_policy(head)) 1298 * Returns true on success, false otherwise.
1805 break; 1299 *
1806 head->read_var2 = NULL; 1300 * Caller holds tomoyo_read_lock().
1807 head->read_step = 9; 1301 */
1808 case 9: 1302static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
1809 if (!tomoyo_read_path_group_policy(head)) 1303{
1810 break; 1304 list_for_each_cookie(head->r.acl, &tomoyo_policy_list[idx]) {
1811 head->read_var1 = NULL; 1305 struct tomoyo_acl_head *acl =
1812 head->read_var2 = NULL; 1306 container_of(head->r.acl, typeof(*acl), list);
1813 head->read_step = 10; 1307 if (acl->is_deleted)
1814 case 10: 1308 continue;
1815 head->read_eof = true; 1309 if (!tomoyo_flush(head))
1310 return false;
1311 switch (idx) {
1312 case TOMOYO_ID_TRANSITION_CONTROL:
1313 {
1314 struct tomoyo_transition_control *ptr =
1315 container_of(acl, typeof(*ptr), head);
1316 tomoyo_set_string(head,
1317 tomoyo_transition_type
1318 [ptr->type]);
1319 if (ptr->program)
1320 tomoyo_set_string(head,
1321 ptr->program->name);
1322 if (ptr->program && ptr->domainname)
1323 tomoyo_set_string(head, " from ");
1324 if (ptr->domainname)
1325 tomoyo_set_string(head,
1326 ptr->domainname->
1327 name);
1328 }
1329 break;
1330 case TOMOYO_ID_GLOBALLY_READABLE:
1331 {
1332 struct tomoyo_readable_file *ptr =
1333 container_of(acl, typeof(*ptr), head);
1334 tomoyo_set_string(head,
1335 TOMOYO_KEYWORD_ALLOW_READ);
1336 tomoyo_set_string(head, ptr->filename->name);
1337 }
1338 break;
1339 case TOMOYO_ID_AGGREGATOR:
1340 {
1341 struct tomoyo_aggregator *ptr =
1342 container_of(acl, typeof(*ptr), head);
1343 tomoyo_set_string(head,
1344 TOMOYO_KEYWORD_AGGREGATOR);
1345 tomoyo_set_string(head,
1346 ptr->original_name->name);
1347 tomoyo_set_space(head);
1348 tomoyo_set_string(head,
1349 ptr->aggregated_name->name);
1350 }
1351 break;
1352 case TOMOYO_ID_PATTERN:
1353 {
1354 struct tomoyo_no_pattern *ptr =
1355 container_of(acl, typeof(*ptr), head);
1356 tomoyo_set_string(head,
1357 TOMOYO_KEYWORD_FILE_PATTERN);
1358 tomoyo_set_string(head, ptr->pattern->name);
1359 }
1360 break;
1361 case TOMOYO_ID_NO_REWRITE:
1362 {
1363 struct tomoyo_no_rewrite *ptr =
1364 container_of(acl, typeof(*ptr), head);
1365 tomoyo_set_string(head,
1366 TOMOYO_KEYWORD_DENY_REWRITE);
1367 tomoyo_set_string(head, ptr->pattern->name);
1368 }
1816 break; 1369 break;
1817 default: 1370 default:
1818 return -EINVAL; 1371 continue;
1819 } 1372 }
1373 tomoyo_set_lf(head);
1820 } 1374 }
1821 return 0; 1375 head->r.acl = NULL;
1376 return true;
1822} 1377}
1823 1378
1824/* path to policy loader */ 1379/**
1825static const char *tomoyo_loader = "/sbin/tomoyo-init"; 1380 * tomoyo_read_exception - Read exception policy.
1381 *
1382 * @head: Pointer to "struct tomoyo_io_buffer".
1383 *
1384 * Caller holds tomoyo_read_lock().
1385 */
1386static void tomoyo_read_exception(struct tomoyo_io_buffer *head)
1387{
1388 if (head->r.eof)
1389 return;
1390 while (head->r.step < TOMOYO_MAX_POLICY &&
1391 tomoyo_read_policy(head, head->r.step))
1392 head->r.step++;
1393 if (head->r.step < TOMOYO_MAX_POLICY)
1394 return;
1395 while (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP &&
1396 tomoyo_read_group(head, head->r.step - TOMOYO_MAX_POLICY))
1397 head->r.step++;
1398 if (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP)
1399 return;
1400 head->r.eof = true;
1401}
1826 1402
1827/** 1403/**
1828 * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists. 1404 * tomoyo_print_header - Get header line of audit log.
1405 *
1406 * @r: Pointer to "struct tomoyo_request_info".
1829 * 1407 *
1830 * Returns true if /sbin/tomoyo-init exists, false otherwise. 1408 * Returns string representation.
1409 *
1410 * This function uses kmalloc(), so caller must kfree() if this function
1411 * didn't return NULL.
1831 */ 1412 */
1832static bool tomoyo_policy_loader_exists(void) 1413static char *tomoyo_print_header(struct tomoyo_request_info *r)
1833{ 1414{
1834 /* 1415 struct timeval tv;
1835 * Don't activate MAC if the policy loader doesn't exist. 1416 const pid_t gpid = task_pid_nr(current);
1836 * If the initrd includes /sbin/init but real-root-dev has not 1417 static const int tomoyo_buffer_len = 4096;
1837 * mounted on / yet, activating MAC will block the system since 1418 char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
1838 * policies are not loaded yet. 1419 if (!buffer)
1839 * Thus, let do_execve() call this function everytime. 1420 return NULL;
1840 */ 1421 do_gettimeofday(&tv);
1841 struct path path; 1422 snprintf(buffer, tomoyo_buffer_len - 1,
1423 "#timestamp=%lu profile=%u mode=%s (global-pid=%u)"
1424 " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u"
1425 " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }",
1426 tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid,
1427 (pid_t) sys_getpid(), (pid_t) sys_getppid(),
1428 current_uid(), current_gid(), current_euid(),
1429 current_egid(), current_suid(), current_sgid(),
1430 current_fsuid(), current_fsgid());
1431 return buffer;
1432}
1842 1433
1843 if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) { 1434/**
1844 printk(KERN_INFO "Not activating Mandatory Access Control now " 1435 * tomoyo_init_audit_log - Allocate buffer for audit logs.
1845 "since %s doesn't exist.\n", tomoyo_loader); 1436 *
1846 return false; 1437 * @len: Required size.
1438 * @r: Pointer to "struct tomoyo_request_info".
1439 *
1440 * Returns pointer to allocated memory.
1441 *
1442 * The @len is updated to add the header lines' size on success.
1443 *
1444 * This function uses kzalloc(), so caller must kfree() if this function
1445 * didn't return NULL.
1446 */
1447static char *tomoyo_init_audit_log(int *len, struct tomoyo_request_info *r)
1448{
1449 char *buf = NULL;
1450 const char *header;
1451 const char *domainname;
1452 if (!r->domain)
1453 r->domain = tomoyo_domain();
1454 domainname = r->domain->domainname->name;
1455 header = tomoyo_print_header(r);
1456 if (!header)
1457 return NULL;
1458 *len += strlen(domainname) + strlen(header) + 10;
1459 buf = kzalloc(*len, GFP_NOFS);
1460 if (buf)
1461 snprintf(buf, (*len) - 1, "%s\n%s\n", header, domainname);
1462 kfree(header);
1463 return buf;
1464}
1465
1466/* Wait queue for tomoyo_query_list. */
1467static DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait);
1468
1469/* Lock for manipulating tomoyo_query_list. */
1470static DEFINE_SPINLOCK(tomoyo_query_list_lock);
1471
1472/* Structure for query. */
1473struct tomoyo_query {
1474 struct list_head list;
1475 char *query;
1476 int query_len;
1477 unsigned int serial;
1478 int timer;
1479 int answer;
1480};
1481
1482/* The list for "struct tomoyo_query". */
1483static LIST_HEAD(tomoyo_query_list);
1484
1485/*
1486 * Number of "struct file" referring /sys/kernel/security/tomoyo/query
1487 * interface.
1488 */
1489static atomic_t tomoyo_query_observers = ATOMIC_INIT(0);
1490
1491/**
1492 * tomoyo_supervisor - Ask for the supervisor's decision.
1493 *
1494 * @r: Pointer to "struct tomoyo_request_info".
1495 * @fmt: The printf()'s format string, followed by parameters.
1496 *
1497 * Returns 0 if the supervisor decided to permit the access request which
1498 * violated the policy in enforcing mode, TOMOYO_RETRY_REQUEST if the
1499 * supervisor decided to retry the access request which violated the policy in
1500 * enforcing mode, 0 if it is not in enforcing mode, -EPERM otherwise.
1501 */
1502int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
1503{
1504 va_list args;
1505 int error = -EPERM;
1506 int pos;
1507 int len;
1508 static unsigned int tomoyo_serial;
1509 struct tomoyo_query *entry = NULL;
1510 bool quota_exceeded = false;
1511 char *header;
1512 switch (r->mode) {
1513 char *buffer;
1514 case TOMOYO_CONFIG_LEARNING:
1515 if (!tomoyo_domain_quota_is_ok(r))
1516 return 0;
1517 va_start(args, fmt);
1518 len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;
1519 va_end(args);
1520 buffer = kmalloc(len, GFP_NOFS);
1521 if (!buffer)
1522 return 0;
1523 va_start(args, fmt);
1524 vsnprintf(buffer, len - 1, fmt, args);
1525 va_end(args);
1526 tomoyo_normalize_line(buffer);
1527 tomoyo_write_domain2(buffer, r->domain, false);
1528 kfree(buffer);
1529 /* fall through */
1530 case TOMOYO_CONFIG_PERMISSIVE:
1531 return 0;
1847 } 1532 }
1848 path_put(&path); 1533 if (!r->domain)
1849 return true; 1534 r->domain = tomoyo_domain();
1535 if (!atomic_read(&tomoyo_query_observers))
1536 return -EPERM;
1537 va_start(args, fmt);
1538 len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
1539 va_end(args);
1540 header = tomoyo_init_audit_log(&len, r);
1541 if (!header)
1542 goto out;
1543 entry = kzalloc(sizeof(*entry), GFP_NOFS);
1544 if (!entry)
1545 goto out;
1546 entry->query = kzalloc(len, GFP_NOFS);
1547 if (!entry->query)
1548 goto out;
1549 len = ksize(entry->query);
1550 spin_lock(&tomoyo_query_list_lock);
1551 if (tomoyo_quota_for_query && tomoyo_query_memory_size + len +
1552 sizeof(*entry) >= tomoyo_quota_for_query) {
1553 quota_exceeded = true;
1554 } else {
1555 tomoyo_query_memory_size += len + sizeof(*entry);
1556 entry->serial = tomoyo_serial++;
1557 }
1558 spin_unlock(&tomoyo_query_list_lock);
1559 if (quota_exceeded)
1560 goto out;
1561 pos = snprintf(entry->query, len - 1, "Q%u-%hu\n%s",
1562 entry->serial, r->retry, header);
1563 kfree(header);
1564 header = NULL;
1565 va_start(args, fmt);
1566 vsnprintf(entry->query + pos, len - 1 - pos, fmt, args);
1567 entry->query_len = strlen(entry->query) + 1;
1568 va_end(args);
1569 spin_lock(&tomoyo_query_list_lock);
1570 list_add_tail(&entry->list, &tomoyo_query_list);
1571 spin_unlock(&tomoyo_query_list_lock);
1572 /* Give 10 seconds for supervisor's opinion. */
1573 for (entry->timer = 0;
1574 atomic_read(&tomoyo_query_observers) && entry->timer < 100;
1575 entry->timer++) {
1576 wake_up(&tomoyo_query_wait);
1577 set_current_state(TASK_INTERRUPTIBLE);
1578 schedule_timeout(HZ / 10);
1579 if (entry->answer)
1580 break;
1581 }
1582 spin_lock(&tomoyo_query_list_lock);
1583 list_del(&entry->list);
1584 tomoyo_query_memory_size -= len + sizeof(*entry);
1585 spin_unlock(&tomoyo_query_list_lock);
1586 switch (entry->answer) {
1587 case 3: /* Asked to retry by administrator. */
1588 error = TOMOYO_RETRY_REQUEST;
1589 r->retry++;
1590 break;
1591 case 1:
1592 /* Granted by administrator. */
1593 error = 0;
1594 break;
1595 case 0:
1596 /* Timed out. */
1597 break;
1598 default:
1599 /* Rejected by administrator. */
1600 break;
1601 }
1602 out:
1603 if (entry)
1604 kfree(entry->query);
1605 kfree(entry);
1606 kfree(header);
1607 return error;
1850} 1608}
1851 1609
1852/** 1610/**
1853 * tomoyo_load_policy - Run external policy loader to load policy. 1611 * tomoyo_poll_query - poll() for /sys/kernel/security/tomoyo/query.
1854 * 1612 *
1855 * @filename: The program about to start. 1613 * @file: Pointer to "struct file".
1614 * @wait: Pointer to "poll_table".
1856 * 1615 *
1857 * This function checks whether @filename is /sbin/init , and if so 1616 * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise.
1858 * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init
1859 * and then continues invocation of /sbin/init.
1860 * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and
1861 * writes to /sys/kernel/security/tomoyo/ interfaces.
1862 * 1617 *
1863 * Returns nothing. 1618 * Waits for access requests which violated policy in enforcing mode.
1864 */ 1619 */
1865void tomoyo_load_policy(const char *filename) 1620static int tomoyo_poll_query(struct file *file, poll_table *wait)
1866{ 1621{
1867 char *argv[2]; 1622 struct list_head *tmp;
1868 char *envp[3]; 1623 bool found = false;
1624 u8 i;
1625 for (i = 0; i < 2; i++) {
1626 spin_lock(&tomoyo_query_list_lock);
1627 list_for_each(tmp, &tomoyo_query_list) {
1628 struct tomoyo_query *ptr =
1629 list_entry(tmp, typeof(*ptr), list);
1630 if (ptr->answer)
1631 continue;
1632 found = true;
1633 break;
1634 }
1635 spin_unlock(&tomoyo_query_list_lock);
1636 if (found)
1637 return POLLIN | POLLRDNORM;
1638 if (i)
1639 break;
1640 poll_wait(file, &tomoyo_query_wait, wait);
1641 }
1642 return 0;
1643}
1869 1644
1870 if (tomoyo_policy_loaded) 1645/**
1646 * tomoyo_read_query - Read access requests which violated policy in enforcing mode.
1647 *
1648 * @head: Pointer to "struct tomoyo_io_buffer".
1649 */
1650static void tomoyo_read_query(struct tomoyo_io_buffer *head)
1651{
1652 struct list_head *tmp;
1653 int pos = 0;
1654 int len = 0;
1655 char *buf;
1656 if (head->r.w_pos)
1871 return; 1657 return;
1872 /* 1658 if (head->read_buf) {
1873 * Check filename is /sbin/init or /sbin/tomoyo-start. 1659 kfree(head->read_buf);
1874 * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't 1660 head->read_buf = NULL;
1875 * be passed. 1661 }
1876 * You can create /sbin/tomoyo-start by 1662 spin_lock(&tomoyo_query_list_lock);
1877 * "ln -s /bin/true /sbin/tomoyo-start". 1663 list_for_each(tmp, &tomoyo_query_list) {
1878 */ 1664 struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
1879 if (strcmp(filename, "/sbin/init") && 1665 if (ptr->answer)
1880 strcmp(filename, "/sbin/tomoyo-start")) 1666 continue;
1667 if (pos++ != head->r.query_index)
1668 continue;
1669 len = ptr->query_len;
1670 break;
1671 }
1672 spin_unlock(&tomoyo_query_list_lock);
1673 if (!len) {
1674 head->r.query_index = 0;
1881 return; 1675 return;
1882 if (!tomoyo_policy_loader_exists()) 1676 }
1677 buf = kzalloc(len, GFP_NOFS);
1678 if (!buf)
1883 return; 1679 return;
1680 pos = 0;
1681 spin_lock(&tomoyo_query_list_lock);
1682 list_for_each(tmp, &tomoyo_query_list) {
1683 struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
1684 if (ptr->answer)
1685 continue;
1686 if (pos++ != head->r.query_index)
1687 continue;
1688 /*
1689 * Some query can be skipped because tomoyo_query_list
1690 * can change, but I don't care.
1691 */
1692 if (len == ptr->query_len)
1693 memmove(buf, ptr->query, len);
1694 break;
1695 }
1696 spin_unlock(&tomoyo_query_list_lock);
1697 if (buf[0]) {
1698 head->read_buf = buf;
1699 head->r.w[head->r.w_pos++] = buf;
1700 head->r.query_index++;
1701 } else {
1702 kfree(buf);
1703 }
1704}
1884 1705
1885 printk(KERN_INFO "Calling %s to load policy. Please wait.\n", 1706/**
1886 tomoyo_loader); 1707 * tomoyo_write_answer - Write the supervisor's decision.
1887 argv[0] = (char *) tomoyo_loader; 1708 *
1888 argv[1] = NULL; 1709 * @head: Pointer to "struct tomoyo_io_buffer".
1889 envp[0] = "HOME=/"; 1710 *
1890 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; 1711 * Returns 0 on success, -EINVAL otherwise.
1891 envp[2] = NULL; 1712 */
1892 call_usermodehelper(argv[0], argv, envp, 1); 1713static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
1893 1714{
1894 printk(KERN_INFO "TOMOYO: 2.2.0 2009/04/01\n"); 1715 char *data = head->write_buf;
1895 printk(KERN_INFO "Mandatory Access Control activated.\n"); 1716 struct list_head *tmp;
1896 tomoyo_policy_loaded = true; 1717 unsigned int serial;
1897 { /* Check all profiles currently assigned to domains are defined. */ 1718 unsigned int answer;
1898 struct tomoyo_domain_info *domain; 1719 spin_lock(&tomoyo_query_list_lock);
1899 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 1720 list_for_each(tmp, &tomoyo_query_list) {
1900 const u8 profile = domain->profile; 1721 struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
1901 if (tomoyo_profile_ptr[profile]) 1722 ptr->timer = 0;
1902 continue; 1723 }
1903 panic("Profile %u (used by '%s') not defined.\n", 1724 spin_unlock(&tomoyo_query_list_lock);
1904 profile, domain->domainname->name); 1725 if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
1905 } 1726 return -EINVAL;
1727 spin_lock(&tomoyo_query_list_lock);
1728 list_for_each(tmp, &tomoyo_query_list) {
1729 struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
1730 if (ptr->serial != serial)
1731 continue;
1732 if (!ptr->answer)
1733 ptr->answer = answer;
1734 break;
1906 } 1735 }
1736 spin_unlock(&tomoyo_query_list_lock);
1737 return 0;
1907} 1738}
1908 1739
1909/** 1740/**
@@ -1913,13 +1744,12 @@ void tomoyo_load_policy(const char *filename)
1913 * 1744 *
1914 * Returns version information. 1745 * Returns version information.
1915 */ 1746 */
1916static int tomoyo_read_version(struct tomoyo_io_buffer *head) 1747static void tomoyo_read_version(struct tomoyo_io_buffer *head)
1917{ 1748{
1918 if (!head->read_eof) { 1749 if (!head->r.eof) {
1919 tomoyo_io_printf(head, "2.2.0"); 1750 tomoyo_io_printf(head, "2.3.0");
1920 head->read_eof = true; 1751 head->r.eof = true;
1921 } 1752 }
1922 return 0;
1923} 1753}
1924 1754
1925/** 1755/**
@@ -1929,18 +1759,17 @@ static int tomoyo_read_version(struct tomoyo_io_buffer *head)
1929 * 1759 *
1930 * Returns the current process's domainname. 1760 * Returns the current process's domainname.
1931 */ 1761 */
1932static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head) 1762static void tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
1933{ 1763{
1934 if (!head->read_eof) { 1764 if (!head->r.eof) {
1935 /* 1765 /*
1936 * tomoyo_domain()->domainname != NULL 1766 * tomoyo_domain()->domainname != NULL
1937 * because every process belongs to a domain and 1767 * because every process belongs to a domain and
1938 * the domain's name cannot be NULL. 1768 * the domain's name cannot be NULL.
1939 */ 1769 */
1940 tomoyo_io_printf(head, "%s", tomoyo_domain()->domainname->name); 1770 tomoyo_io_printf(head, "%s", tomoyo_domain()->domainname->name);
1941 head->read_eof = true; 1771 head->r.eof = true;
1942 } 1772 }
1943 return 0;
1944} 1773}
1945 1774
1946/** 1775/**
@@ -1953,23 +1782,24 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
1953 * 1782 *
1954 * Caller acquires tomoyo_read_lock(). 1783 * Caller acquires tomoyo_read_lock().
1955 */ 1784 */
1956static int tomoyo_open_control(const u8 type, struct file *file) 1785int tomoyo_open_control(const u8 type, struct file *file)
1957{ 1786{
1958 struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_NOFS); 1787 struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_NOFS);
1959 1788
1960 if (!head) 1789 if (!head)
1961 return -ENOMEM; 1790 return -ENOMEM;
1962 mutex_init(&head->io_sem); 1791 mutex_init(&head->io_sem);
1792 head->type = type;
1963 switch (type) { 1793 switch (type) {
1964 case TOMOYO_DOMAINPOLICY: 1794 case TOMOYO_DOMAINPOLICY:
1965 /* /sys/kernel/security/tomoyo/domain_policy */ 1795 /* /sys/kernel/security/tomoyo/domain_policy */
1966 head->write = tomoyo_write_domain_policy; 1796 head->write = tomoyo_write_domain;
1967 head->read = tomoyo_read_domain_policy; 1797 head->read = tomoyo_read_domain;
1968 break; 1798 break;
1969 case TOMOYO_EXCEPTIONPOLICY: 1799 case TOMOYO_EXCEPTIONPOLICY:
1970 /* /sys/kernel/security/tomoyo/exception_policy */ 1800 /* /sys/kernel/security/tomoyo/exception_policy */
1971 head->write = tomoyo_write_exception_policy; 1801 head->write = tomoyo_write_exception;
1972 head->read = tomoyo_read_exception_policy; 1802 head->read = tomoyo_read_exception;
1973 break; 1803 break;
1974 case TOMOYO_SELFDOMAIN: 1804 case TOMOYO_SELFDOMAIN:
1975 /* /sys/kernel/security/tomoyo/self_domain */ 1805 /* /sys/kernel/security/tomoyo/self_domain */
@@ -2001,10 +1831,15 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2001 head->write = tomoyo_write_profile; 1831 head->write = tomoyo_write_profile;
2002 head->read = tomoyo_read_profile; 1832 head->read = tomoyo_read_profile;
2003 break; 1833 break;
1834 case TOMOYO_QUERY: /* /sys/kernel/security/tomoyo/query */
1835 head->poll = tomoyo_poll_query;
1836 head->write = tomoyo_write_answer;
1837 head->read = tomoyo_read_query;
1838 break;
2004 case TOMOYO_MANAGER: 1839 case TOMOYO_MANAGER:
2005 /* /sys/kernel/security/tomoyo/manager */ 1840 /* /sys/kernel/security/tomoyo/manager */
2006 head->write = tomoyo_write_manager_policy; 1841 head->write = tomoyo_write_manager;
2007 head->read = tomoyo_read_manager_policy; 1842 head->read = tomoyo_read_manager;
2008 break; 1843 break;
2009 } 1844 }
2010 if (!(file->f_mode & FMODE_READ)) { 1845 if (!(file->f_mode & FMODE_READ)) {
@@ -2013,7 +1848,9 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2013 * for reading. 1848 * for reading.
2014 */ 1849 */
2015 head->read = NULL; 1850 head->read = NULL;
2016 } else { 1851 head->poll = NULL;
1852 } else if (!head->poll) {
1853 /* Don't allocate read_buf for poll() access. */
2017 if (!head->readbuf_size) 1854 if (!head->readbuf_size)
2018 head->readbuf_size = 4096 * 2; 1855 head->readbuf_size = 4096 * 2;
2019 head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS); 1856 head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS);
@@ -2037,7 +1874,8 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2037 return -ENOMEM; 1874 return -ENOMEM;
2038 } 1875 }
2039 } 1876 }
2040 head->reader_idx = tomoyo_read_lock(); 1877 if (type != TOMOYO_QUERY)
1878 head->reader_idx = tomoyo_read_lock();
2041 file->private_data = head; 1879 file->private_data = head;
2042 /* 1880 /*
2043 * Call the handler now if the file is 1881 * Call the handler now if the file is
@@ -2048,10 +1886,35 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2048 */ 1886 */
2049 if (type == TOMOYO_SELFDOMAIN) 1887 if (type == TOMOYO_SELFDOMAIN)
2050 tomoyo_read_control(file, NULL, 0); 1888 tomoyo_read_control(file, NULL, 0);
1889 /*
1890 * If the file is /sys/kernel/security/tomoyo/query , increment the
1891 * observer counter.
1892 * The obserber counter is used by tomoyo_supervisor() to see if
1893 * there is some process monitoring /sys/kernel/security/tomoyo/query.
1894 */
1895 else if (type == TOMOYO_QUERY)
1896 atomic_inc(&tomoyo_query_observers);
2051 return 0; 1897 return 0;
2052} 1898}
2053 1899
2054/** 1900/**
1901 * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface.
1902 *
1903 * @file: Pointer to "struct file".
1904 * @wait: Pointer to "poll_table".
1905 *
1906 * Waits for read readiness.
1907 * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd .
1908 */
1909int tomoyo_poll_control(struct file *file, poll_table *wait)
1910{
1911 struct tomoyo_io_buffer *head = file->private_data;
1912 if (!head->poll)
1913 return -ENOSYS;
1914 return head->poll(file, wait);
1915}
1916
1917/**
2055 * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. 1918 * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface.
2056 * 1919 *
2057 * @file: Pointer to "struct file". 1920 * @file: Pointer to "struct file".
@@ -2062,36 +1925,23 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2062 * 1925 *
2063 * Caller holds tomoyo_read_lock(). 1926 * Caller holds tomoyo_read_lock().
2064 */ 1927 */
2065static int tomoyo_read_control(struct file *file, char __user *buffer, 1928int tomoyo_read_control(struct file *file, char __user *buffer,
2066 const int buffer_len) 1929 const int buffer_len)
2067{ 1930{
2068 int len = 0; 1931 int len;
2069 struct tomoyo_io_buffer *head = file->private_data; 1932 struct tomoyo_io_buffer *head = file->private_data;
2070 char *cp;
2071 1933
2072 if (!head->read) 1934 if (!head->read)
2073 return -ENOSYS; 1935 return -ENOSYS;
2074 if (mutex_lock_interruptible(&head->io_sem)) 1936 if (mutex_lock_interruptible(&head->io_sem))
2075 return -EINTR; 1937 return -EINTR;
2076 /* Call the policy handler. */ 1938 head->read_user_buf = buffer;
2077 len = head->read(head); 1939 head->read_user_buf_avail = buffer_len;
2078 if (len < 0) 1940 if (tomoyo_flush(head))
2079 goto out; 1941 /* Call the policy handler. */
2080 /* Write to buffer. */ 1942 head->read(head);
2081 len = head->read_avail; 1943 tomoyo_flush(head);
2082 if (len > buffer_len) 1944 len = head->read_user_buf - buffer;
2083 len = buffer_len;
2084 if (!len)
2085 goto out;
2086 /* head->read_buf changes by some functions. */
2087 cp = head->read_buf;
2088 if (copy_to_user(buffer, cp, len)) {
2089 len = -EFAULT;
2090 goto out;
2091 }
2092 head->read_avail -= len;
2093 memmove(cp, cp + len, head->read_avail);
2094 out:
2095 mutex_unlock(&head->io_sem); 1945 mutex_unlock(&head->io_sem);
2096 return len; 1946 return len;
2097} 1947}
@@ -2107,8 +1957,8 @@ static int tomoyo_read_control(struct file *file, char __user *buffer,
2107 * 1957 *
2108 * Caller holds tomoyo_read_lock(). 1958 * Caller holds tomoyo_read_lock().
2109 */ 1959 */
2110static int tomoyo_write_control(struct file *file, const char __user *buffer, 1960int tomoyo_write_control(struct file *file, const char __user *buffer,
2111 const int buffer_len) 1961 const int buffer_len)
2112{ 1962{
2113 struct tomoyo_io_buffer *head = file->private_data; 1963 struct tomoyo_io_buffer *head = file->private_data;
2114 int error = buffer_len; 1964 int error = buffer_len;
@@ -2121,8 +1971,7 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer,
2121 return -EFAULT; 1971 return -EFAULT;
2122 /* Don't allow updating policies by non manager programs. */ 1972 /* Don't allow updating policies by non manager programs. */
2123 if (head->write != tomoyo_write_pid && 1973 if (head->write != tomoyo_write_pid &&
2124 head->write != tomoyo_write_domain_policy && 1974 head->write != tomoyo_write_domain && !tomoyo_manager())
2125 !tomoyo_is_policy_manager())
2126 return -EPERM; 1975 return -EPERM;
2127 if (mutex_lock_interruptible(&head->io_sem)) 1976 if (mutex_lock_interruptible(&head->io_sem))
2128 return -EINTR; 1977 return -EINTR;
@@ -2159,12 +2008,19 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer,
2159 * 2008 *
2160 * Caller looses tomoyo_read_lock(). 2009 * Caller looses tomoyo_read_lock().
2161 */ 2010 */
2162static int tomoyo_close_control(struct file *file) 2011int tomoyo_close_control(struct file *file)
2163{ 2012{
2164 struct tomoyo_io_buffer *head = file->private_data; 2013 struct tomoyo_io_buffer *head = file->private_data;
2165 const bool is_write = !!head->write_buf; 2014 const bool is_write = !!head->write_buf;
2166 2015
2167 tomoyo_read_unlock(head->reader_idx); 2016 /*
2017 * If the file is /sys/kernel/security/tomoyo/query , decrement the
2018 * observer counter.
2019 */
2020 if (head->type == TOMOYO_QUERY)
2021 atomic_dec(&tomoyo_query_observers);
2022 else
2023 tomoyo_read_unlock(head->reader_idx);
2168 /* Release memory used for policy I/O. */ 2024 /* Release memory used for policy I/O. */
2169 kfree(head->read_buf); 2025 kfree(head->read_buf);
2170 head->read_buf = NULL; 2026 head->read_buf = NULL;
@@ -2179,129 +2035,25 @@ static int tomoyo_close_control(struct file *file)
2179} 2035}
2180 2036
2181/** 2037/**
2182 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. 2038 * tomoyo_check_profile - Check all profiles currently assigned to domains are defined.
2183 *
2184 * @inode: Pointer to "struct inode".
2185 * @file: Pointer to "struct file".
2186 *
2187 * Returns 0 on success, negative value otherwise.
2188 */
2189static int tomoyo_open(struct inode *inode, struct file *file)
2190{
2191 const int key = ((u8 *) file->f_path.dentry->d_inode->i_private)
2192 - ((u8 *) NULL);
2193 return tomoyo_open_control(key, file);
2194}
2195
2196/**
2197 * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface.
2198 *
2199 * @inode: Pointer to "struct inode".
2200 * @file: Pointer to "struct file".
2201 *
2202 * Returns 0 on success, negative value otherwise.
2203 */
2204static int tomoyo_release(struct inode *inode, struct file *file)
2205{
2206 return tomoyo_close_control(file);
2207}
2208
2209/**
2210 * tomoyo_read - read() for /sys/kernel/security/tomoyo/ interface.
2211 *
2212 * @file: Pointer to "struct file".
2213 * @buf: Pointer to buffer.
2214 * @count: Size of @buf.
2215 * @ppos: Unused.
2216 *
2217 * Returns bytes read on success, negative value otherwise.
2218 */ 2039 */
2219static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, 2040void tomoyo_check_profile(void)
2220 loff_t *ppos)
2221{ 2041{
2222 return tomoyo_read_control(file, buf, count); 2042 struct tomoyo_domain_info *domain;
2223} 2043 const int idx = tomoyo_read_lock();
2224 2044 tomoyo_policy_loaded = true;
2225/** 2045 /* Check all profiles currently assigned to domains are defined. */
2226 * tomoyo_write - write() for /sys/kernel/security/tomoyo/ interface. 2046 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
2227 * 2047 const u8 profile = domain->profile;
2228 * @file: Pointer to "struct file". 2048 if (tomoyo_profile_ptr[profile])
2229 * @buf: Pointer to buffer. 2049 continue;
2230 * @count: Size of @buf. 2050 panic("Profile %u (used by '%s') not defined.\n",
2231 * @ppos: Unused. 2051 profile, domain->domainname->name);
2232 * 2052 }
2233 * Returns @count on success, negative value otherwise. 2053 tomoyo_read_unlock(idx);
2234 */ 2054 if (tomoyo_profile_version != 20090903)
2235static ssize_t tomoyo_write(struct file *file, const char __user *buf, 2055 panic("Profile version %u is not supported.\n",
2236 size_t count, loff_t *ppos) 2056 tomoyo_profile_version);
2237{ 2057 printk(KERN_INFO "TOMOYO: 2.3.0\n");
2238 return tomoyo_write_control(file, buf, count); 2058 printk(KERN_INFO "Mandatory Access Control activated.\n");
2239}
2240
2241/*
2242 * tomoyo_operations is a "struct file_operations" which is used for handling
2243 * /sys/kernel/security/tomoyo/ interface.
2244 *
2245 * Some files under /sys/kernel/security/tomoyo/ directory accept open(O_RDWR).
2246 * See tomoyo_io_buffer for internals.
2247 */
2248static const struct file_operations tomoyo_operations = {
2249 .open = tomoyo_open,
2250 .release = tomoyo_release,
2251 .read = tomoyo_read,
2252 .write = tomoyo_write,
2253};
2254
2255/**
2256 * tomoyo_create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory.
2257 *
2258 * @name: The name of the interface file.
2259 * @mode: The permission of the interface file.
2260 * @parent: The parent directory.
2261 * @key: Type of interface.
2262 *
2263 * Returns nothing.
2264 */
2265static void __init tomoyo_create_entry(const char *name, const mode_t mode,
2266 struct dentry *parent, const u8 key)
2267{
2268 securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
2269 &tomoyo_operations);
2270}
2271
2272/**
2273 * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface.
2274 *
2275 * Returns 0.
2276 */
2277static int __init tomoyo_initerface_init(void)
2278{
2279 struct dentry *tomoyo_dir;
2280
2281 /* Don't create securityfs entries unless registered. */
2282 if (current_cred()->security != &tomoyo_kernel_domain)
2283 return 0;
2284
2285 tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
2286 tomoyo_create_entry("domain_policy", 0600, tomoyo_dir,
2287 TOMOYO_DOMAINPOLICY);
2288 tomoyo_create_entry("exception_policy", 0600, tomoyo_dir,
2289 TOMOYO_EXCEPTIONPOLICY);
2290 tomoyo_create_entry("self_domain", 0400, tomoyo_dir,
2291 TOMOYO_SELFDOMAIN);
2292 tomoyo_create_entry(".domain_status", 0600, tomoyo_dir,
2293 TOMOYO_DOMAIN_STATUS);
2294 tomoyo_create_entry(".process_status", 0600, tomoyo_dir,
2295 TOMOYO_PROCESS_STATUS);
2296 tomoyo_create_entry("meminfo", 0600, tomoyo_dir,
2297 TOMOYO_MEMINFO);
2298 tomoyo_create_entry("profile", 0600, tomoyo_dir,
2299 TOMOYO_PROFILE);
2300 tomoyo_create_entry("manager", 0600, tomoyo_dir,
2301 TOMOYO_MANAGER);
2302 tomoyo_create_entry("version", 0400, tomoyo_dir,
2303 TOMOYO_VERSION);
2304 return 0;
2305} 2059}
2306
2307fs_initcall(tomoyo_initerface_init);
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 9f1ae5e3ba5..04454cb7b24 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -20,6 +20,7 @@
20#include <linux/mount.h> 20#include <linux/mount.h>
21#include <linux/list.h> 21#include <linux/list.h>
22#include <linux/cred.h> 22#include <linux/cred.h>
23#include <linux/poll.h>
23struct linux_binprm; 24struct linux_binprm;
24 25
25/********** Constants definitions. **********/ 26/********** Constants definitions. **********/
@@ -32,20 +33,44 @@ struct linux_binprm;
32#define TOMOYO_HASH_BITS 8 33#define TOMOYO_HASH_BITS 8
33#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) 34#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)
34 35
35/* 36#define TOMOYO_EXEC_TMPSIZE 4096
36 * This is the max length of a token.
37 *
38 * A token consists of only ASCII printable characters.
39 * Non printable characters in a token is represented in \ooo style
40 * octal string. Thus, \ itself is represented as \\.
41 */
42#define TOMOYO_MAX_PATHNAME_LEN 4000
43 37
44/* Profile number is an integer between 0 and 255. */ 38/* Profile number is an integer between 0 and 255. */
45#define TOMOYO_MAX_PROFILES 256 39#define TOMOYO_MAX_PROFILES 256
46 40
41enum tomoyo_mode_index {
42 TOMOYO_CONFIG_DISABLED,
43 TOMOYO_CONFIG_LEARNING,
44 TOMOYO_CONFIG_PERMISSIVE,
45 TOMOYO_CONFIG_ENFORCING,
46 TOMOYO_CONFIG_USE_DEFAULT = 255
47};
48
49enum tomoyo_policy_id {
50 TOMOYO_ID_GROUP,
51 TOMOYO_ID_PATH_GROUP,
52 TOMOYO_ID_NUMBER_GROUP,
53 TOMOYO_ID_TRANSITION_CONTROL,
54 TOMOYO_ID_AGGREGATOR,
55 TOMOYO_ID_GLOBALLY_READABLE,
56 TOMOYO_ID_PATTERN,
57 TOMOYO_ID_NO_REWRITE,
58 TOMOYO_ID_MANAGER,
59 TOMOYO_ID_NAME,
60 TOMOYO_ID_ACL,
61 TOMOYO_ID_DOMAIN,
62 TOMOYO_MAX_POLICY
63};
64
65enum tomoyo_group_id {
66 TOMOYO_PATH_GROUP,
67 TOMOYO_NUMBER_GROUP,
68 TOMOYO_MAX_GROUP
69};
70
47/* Keywords for ACLs. */ 71/* Keywords for ACLs. */
48#define TOMOYO_KEYWORD_ALIAS "alias " 72#define TOMOYO_KEYWORD_AGGREGATOR "aggregator "
73#define TOMOYO_KEYWORD_ALLOW_MOUNT "allow_mount "
49#define TOMOYO_KEYWORD_ALLOW_READ "allow_read " 74#define TOMOYO_KEYWORD_ALLOW_READ "allow_read "
50#define TOMOYO_KEYWORD_DELETE "delete " 75#define TOMOYO_KEYWORD_DELETE "delete "
51#define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite " 76#define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite "
@@ -55,36 +80,51 @@ struct linux_binprm;
55#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " 80#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain "
56#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " 81#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain "
57#define TOMOYO_KEYWORD_PATH_GROUP "path_group " 82#define TOMOYO_KEYWORD_PATH_GROUP "path_group "
83#define TOMOYO_KEYWORD_NUMBER_GROUP "number_group "
58#define TOMOYO_KEYWORD_SELECT "select " 84#define TOMOYO_KEYWORD_SELECT "select "
59#define TOMOYO_KEYWORD_USE_PROFILE "use_profile " 85#define TOMOYO_KEYWORD_USE_PROFILE "use_profile "
60#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" 86#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read"
87#define TOMOYO_KEYWORD_QUOTA_EXCEEDED "quota_exceeded"
88#define TOMOYO_KEYWORD_TRANSITION_FAILED "transition_failed"
61/* A domain definition starts with <kernel>. */ 89/* A domain definition starts with <kernel>. */
62#define TOMOYO_ROOT_NAME "<kernel>" 90#define TOMOYO_ROOT_NAME "<kernel>"
63#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) 91#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1)
64 92
65/* Index numbers for Access Controls. */ 93/* Value type definition. */
66enum tomoyo_mac_index { 94#define TOMOYO_VALUE_TYPE_INVALID 0
67 TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */ 95#define TOMOYO_VALUE_TYPE_DECIMAL 1
68 TOMOYO_MAX_ACCEPT_ENTRY, 96#define TOMOYO_VALUE_TYPE_OCTAL 2
69 TOMOYO_VERBOSE, 97#define TOMOYO_VALUE_TYPE_HEXADECIMAL 3
70 TOMOYO_MAX_CONTROL_INDEX 98
99enum tomoyo_transition_type {
100 /* Do not change this order, */
101 TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE,
102 TOMOYO_TRANSITION_CONTROL_INITIALIZE,
103 TOMOYO_TRANSITION_CONTROL_NO_KEEP,
104 TOMOYO_TRANSITION_CONTROL_KEEP,
105 TOMOYO_MAX_TRANSITION_TYPE
71}; 106};
72 107
73/* Index numbers for Access Controls. */ 108/* Index numbers for Access Controls. */
74enum tomoyo_acl_entry_type_index { 109enum tomoyo_acl_entry_type_index {
75 TOMOYO_TYPE_PATH_ACL, 110 TOMOYO_TYPE_PATH_ACL,
76 TOMOYO_TYPE_PATH2_ACL, 111 TOMOYO_TYPE_PATH2_ACL,
112 TOMOYO_TYPE_PATH_NUMBER_ACL,
113 TOMOYO_TYPE_MKDEV_ACL,
114 TOMOYO_TYPE_MOUNT_ACL,
77}; 115};
78 116
79/* Index numbers for File Controls. */ 117/* Index numbers for File Controls. */
80 118
81/* 119/*
82 * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set 120 * TOMOYO_TYPE_READ_WRITE is special. TOMOYO_TYPE_READ_WRITE is automatically
83 * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and 121 * set if both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are set.
84 * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set. 122 * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically set if
85 * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or 123 * TOMOYO_TYPE_READ_WRITE is set.
86 * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are 124 * TOMOYO_TYPE_READ_WRITE is automatically cleared if either TOMOYO_TYPE_READ
87 * automatically cleared if TYPE_READ_WRITE_ACL is cleared. 125 * or TOMOYO_TYPE_WRITE is cleared.
126 * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically cleared if
127 * TOMOYO_TYPE_READ_WRITE is cleared.
88 */ 128 */
89 129
90enum tomoyo_path_acl_index { 130enum tomoyo_path_acl_index {
@@ -92,27 +132,24 @@ enum tomoyo_path_acl_index {
92 TOMOYO_TYPE_EXECUTE, 132 TOMOYO_TYPE_EXECUTE,
93 TOMOYO_TYPE_READ, 133 TOMOYO_TYPE_READ,
94 TOMOYO_TYPE_WRITE, 134 TOMOYO_TYPE_WRITE,
95 TOMOYO_TYPE_CREATE,
96 TOMOYO_TYPE_UNLINK, 135 TOMOYO_TYPE_UNLINK,
97 TOMOYO_TYPE_MKDIR,
98 TOMOYO_TYPE_RMDIR, 136 TOMOYO_TYPE_RMDIR,
99 TOMOYO_TYPE_MKFIFO,
100 TOMOYO_TYPE_MKSOCK,
101 TOMOYO_TYPE_MKBLOCK,
102 TOMOYO_TYPE_MKCHAR,
103 TOMOYO_TYPE_TRUNCATE, 137 TOMOYO_TYPE_TRUNCATE,
104 TOMOYO_TYPE_SYMLINK, 138 TOMOYO_TYPE_SYMLINK,
105 TOMOYO_TYPE_REWRITE, 139 TOMOYO_TYPE_REWRITE,
106 TOMOYO_TYPE_IOCTL,
107 TOMOYO_TYPE_CHMOD,
108 TOMOYO_TYPE_CHOWN,
109 TOMOYO_TYPE_CHGRP,
110 TOMOYO_TYPE_CHROOT, 140 TOMOYO_TYPE_CHROOT,
111 TOMOYO_TYPE_MOUNT,
112 TOMOYO_TYPE_UMOUNT, 141 TOMOYO_TYPE_UMOUNT,
113 TOMOYO_MAX_PATH_OPERATION 142 TOMOYO_MAX_PATH_OPERATION
114}; 143};
115 144
145#define TOMOYO_RW_MASK ((1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE))
146
147enum tomoyo_mkdev_acl_index {
148 TOMOYO_TYPE_MKBLOCK,
149 TOMOYO_TYPE_MKCHAR,
150 TOMOYO_MAX_MKDEV_OPERATION
151};
152
116enum tomoyo_path2_acl_index { 153enum tomoyo_path2_acl_index {
117 TOMOYO_TYPE_LINK, 154 TOMOYO_TYPE_LINK,
118 TOMOYO_TYPE_RENAME, 155 TOMOYO_TYPE_RENAME,
@@ -120,6 +157,18 @@ enum tomoyo_path2_acl_index {
120 TOMOYO_MAX_PATH2_OPERATION 157 TOMOYO_MAX_PATH2_OPERATION
121}; 158};
122 159
160enum tomoyo_path_number_acl_index {
161 TOMOYO_TYPE_CREATE,
162 TOMOYO_TYPE_MKDIR,
163 TOMOYO_TYPE_MKFIFO,
164 TOMOYO_TYPE_MKSOCK,
165 TOMOYO_TYPE_IOCTL,
166 TOMOYO_TYPE_CHMOD,
167 TOMOYO_TYPE_CHOWN,
168 TOMOYO_TYPE_CHGRP,
169 TOMOYO_MAX_PATH_NUMBER_OPERATION
170};
171
123enum tomoyo_securityfs_interface_index { 172enum tomoyo_securityfs_interface_index {
124 TOMOYO_DOMAINPOLICY, 173 TOMOYO_DOMAINPOLICY,
125 TOMOYO_EXCEPTIONPOLICY, 174 TOMOYO_EXCEPTIONPOLICY,
@@ -129,20 +178,109 @@ enum tomoyo_securityfs_interface_index {
129 TOMOYO_SELFDOMAIN, 178 TOMOYO_SELFDOMAIN,
130 TOMOYO_VERSION, 179 TOMOYO_VERSION,
131 TOMOYO_PROFILE, 180 TOMOYO_PROFILE,
181 TOMOYO_QUERY,
132 TOMOYO_MANAGER 182 TOMOYO_MANAGER
133}; 183};
134 184
185enum tomoyo_mac_index {
186 TOMOYO_MAC_FILE_EXECUTE,
187 TOMOYO_MAC_FILE_OPEN,
188 TOMOYO_MAC_FILE_CREATE,
189 TOMOYO_MAC_FILE_UNLINK,
190 TOMOYO_MAC_FILE_MKDIR,
191 TOMOYO_MAC_FILE_RMDIR,
192 TOMOYO_MAC_FILE_MKFIFO,
193 TOMOYO_MAC_FILE_MKSOCK,
194 TOMOYO_MAC_FILE_TRUNCATE,
195 TOMOYO_MAC_FILE_SYMLINK,
196 TOMOYO_MAC_FILE_REWRITE,
197 TOMOYO_MAC_FILE_MKBLOCK,
198 TOMOYO_MAC_FILE_MKCHAR,
199 TOMOYO_MAC_FILE_LINK,
200 TOMOYO_MAC_FILE_RENAME,
201 TOMOYO_MAC_FILE_CHMOD,
202 TOMOYO_MAC_FILE_CHOWN,
203 TOMOYO_MAC_FILE_CHGRP,
204 TOMOYO_MAC_FILE_IOCTL,
205 TOMOYO_MAC_FILE_CHROOT,
206 TOMOYO_MAC_FILE_MOUNT,
207 TOMOYO_MAC_FILE_UMOUNT,
208 TOMOYO_MAC_FILE_PIVOT_ROOT,
209 TOMOYO_MAX_MAC_INDEX
210};
211
212enum tomoyo_mac_category_index {
213 TOMOYO_MAC_CATEGORY_FILE,
214 TOMOYO_MAX_MAC_CATEGORY_INDEX
215};
216
217#define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */
218
135/********** Structure definitions. **********/ 219/********** Structure definitions. **********/
136 220
137/* 221/*
138 * tomoyo_page_buffer is a structure which is used for holding a pathname 222 * tomoyo_acl_head is a structure which is used for holding elements not in
139 * obtained from "struct dentry" and "struct vfsmount" pair. 223 * domain policy.
140 * As of now, it is 4096 bytes. If users complain that 4096 bytes is too small 224 * It has following fields.
141 * (because TOMOYO escapes non ASCII printable characters using \ooo format), 225 *
142 * we will make the buffer larger. 226 * (1) "list" which is linked to tomoyo_policy_list[] .
227 * (2) "is_deleted" is a bool which is true if marked as deleted, false
228 * otherwise.
143 */ 229 */
144struct tomoyo_page_buffer { 230struct tomoyo_acl_head {
145 char buffer[4096]; 231 struct list_head list;
232 bool is_deleted;
233} __packed;
234
235/*
236 * tomoyo_request_info is a structure which is used for holding
237 *
238 * (1) Domain information of current process.
239 * (2) How many retries are made for this request.
240 * (3) Profile number used for this request.
241 * (4) Access control mode of the profile.
242 */
243struct tomoyo_request_info {
244 struct tomoyo_domain_info *domain;
245 /* For holding parameters. */
246 union {
247 struct {
248 const struct tomoyo_path_info *filename;
249 /* For using wildcards at tomoyo_find_next_domain(). */
250 const struct tomoyo_path_info *matched_path;
251 u8 operation;
252 } path;
253 struct {
254 const struct tomoyo_path_info *filename1;
255 const struct tomoyo_path_info *filename2;
256 u8 operation;
257 } path2;
258 struct {
259 const struct tomoyo_path_info *filename;
260 unsigned int mode;
261 unsigned int major;
262 unsigned int minor;
263 u8 operation;
264 } mkdev;
265 struct {
266 const struct tomoyo_path_info *filename;
267 unsigned long number;
268 u8 operation;
269 } path_number;
270 struct {
271 const struct tomoyo_path_info *type;
272 const struct tomoyo_path_info *dir;
273 const struct tomoyo_path_info *dev;
274 unsigned long flags;
275 int need_dev;
276 } mount;
277 } param;
278 u8 param_type;
279 bool granted;
280 u8 retry;
281 u8 profile;
282 u8 mode; /* One of tomoyo_mode_index . */
283 u8 type;
146}; 284};
147 285
148/* 286/*
@@ -174,45 +312,31 @@ struct tomoyo_path_info {
174}; 312};
175 313
176/* 314/*
177 * tomoyo_name_entry is a structure which is used for linking 315 * tomoyo_name is a structure which is used for linking
178 * "struct tomoyo_path_info" into tomoyo_name_list . 316 * "struct tomoyo_path_info" into tomoyo_name_list .
179 */ 317 */
180struct tomoyo_name_entry { 318struct tomoyo_name {
181 struct list_head list; 319 struct list_head list;
182 atomic_t users; 320 atomic_t users;
183 struct tomoyo_path_info entry; 321 struct tomoyo_path_info entry;
184}; 322};
185 323
186/*
187 * tomoyo_path_info_with_data is a structure which is used for holding a
188 * pathname obtained from "struct dentry" and "struct vfsmount" pair.
189 *
190 * "struct tomoyo_path_info_with_data" consists of "struct tomoyo_path_info"
191 * and buffer for the pathname, while "struct tomoyo_page_buffer" consists of
192 * buffer for the pathname only.
193 *
194 * "struct tomoyo_path_info_with_data" is intended to allow TOMOYO to release
195 * both "struct tomoyo_path_info" and buffer for the pathname by single kfree()
196 * so that we don't need to return two pointers to the caller. If the caller
197 * puts "struct tomoyo_path_info" on stack memory, we will be able to remove
198 * "struct tomoyo_path_info_with_data".
199 */
200struct tomoyo_path_info_with_data {
201 /* Keep "head" first, for this pointer is passed to kfree(). */
202 struct tomoyo_path_info head;
203 char barrier1[16]; /* Safeguard for overrun. */
204 char body[TOMOYO_MAX_PATHNAME_LEN];
205 char barrier2[16]; /* Safeguard for overrun. */
206};
207
208struct tomoyo_name_union { 324struct tomoyo_name_union {
209 const struct tomoyo_path_info *filename; 325 const struct tomoyo_path_info *filename;
210 struct tomoyo_path_group *group; 326 struct tomoyo_group *group;
211 u8 is_group; 327 u8 is_group;
212}; 328};
213 329
214/* Structure for "path_group" directive. */ 330struct tomoyo_number_union {
215struct tomoyo_path_group { 331 unsigned long values[2];
332 struct tomoyo_group *group;
333 u8 min_type;
334 u8 max_type;
335 u8 is_group;
336};
337
338/* Structure for "path_group"/"number_group" directive. */
339struct tomoyo_group {
216 struct list_head list; 340 struct list_head list;
217 const struct tomoyo_path_info *group_name; 341 const struct tomoyo_path_info *group_name;
218 struct list_head member_list; 342 struct list_head member_list;
@@ -220,28 +344,35 @@ struct tomoyo_path_group {
220}; 344};
221 345
222/* Structure for "path_group" directive. */ 346/* Structure for "path_group" directive. */
223struct tomoyo_path_group_member { 347struct tomoyo_path_group {
224 struct list_head list; 348 struct tomoyo_acl_head head;
225 bool is_deleted;
226 const struct tomoyo_path_info *member_name; 349 const struct tomoyo_path_info *member_name;
227}; 350};
228 351
352/* Structure for "number_group" directive. */
353struct tomoyo_number_group {
354 struct tomoyo_acl_head head;
355 struct tomoyo_number_union number;
356};
357
229/* 358/*
230 * tomoyo_acl_info is a structure which is used for holding 359 * tomoyo_acl_info is a structure which is used for holding
231 * 360 *
232 * (1) "list" which is linked to the ->acl_info_list of 361 * (1) "list" which is linked to the ->acl_info_list of
233 * "struct tomoyo_domain_info" 362 * "struct tomoyo_domain_info"
234 * (2) "type" which tells type of the entry (either 363 * (2) "is_deleted" is a bool which is true if this domain is marked as
235 * "struct tomoyo_path_acl" or "struct tomoyo_path2_acl"). 364 * "deleted", false otherwise.
365 * (3) "type" which tells type of the entry.
236 * 366 *
237 * Packing "struct tomoyo_acl_info" allows 367 * Packing "struct tomoyo_acl_info" allows
238 * "struct tomoyo_path_acl" to embed "u8" + "u16" and 368 * "struct tomoyo_path_acl" to embed "u16" and "struct tomoyo_path2_acl"
239 * "struct tomoyo_path2_acl" to embed "u8" 369 * "struct tomoyo_path_number_acl" "struct tomoyo_mkdev_acl" to embed
240 * without enlarging their structure size. 370 * "u8" without enlarging their structure size.
241 */ 371 */
242struct tomoyo_acl_info { 372struct tomoyo_acl_info {
243 struct list_head list; 373 struct list_head list;
244 u8 type; 374 bool is_deleted;
375 u8 type; /* = one of values in "enum tomoyo_acl_entry_type_index". */
245} __packed; 376} __packed;
246 377
247/* 378/*
@@ -299,20 +430,62 @@ struct tomoyo_domain_info {
299 * (3) "name" is the pathname. 430 * (3) "name" is the pathname.
300 * 431 *
301 * Directives held by this structure are "allow_read/write", "allow_execute", 432 * Directives held by this structure are "allow_read/write", "allow_execute",
302 * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", 433 * "allow_read", "allow_write", "allow_unlink", "allow_rmdir",
303 * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock", 434 * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_chroot" and
304 * "allow_mkchar", "allow_truncate", "allow_symlink", "allow_rewrite", 435 * "allow_unmount".
305 * "allow_chmod", "allow_chown", "allow_chgrp", "allow_chroot", "allow_mount"
306 * and "allow_unmount".
307 */ 436 */
308struct tomoyo_path_acl { 437struct tomoyo_path_acl {
309 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ 438 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */
310 u8 perm_high;
311 u16 perm; 439 u16 perm;
312 struct tomoyo_name_union name; 440 struct tomoyo_name_union name;
313}; 441};
314 442
315/* 443/*
444 * tomoyo_path_number_acl is a structure which is used for holding an
445 * entry with one pathname and one number operation.
446 * It has following fields.
447 *
448 * (1) "head" which is a "struct tomoyo_acl_info".
449 * (2) "perm" which is a bitmask of permitted operations.
450 * (3) "name" is the pathname.
451 * (4) "number" is the numeric value.
452 *
453 * Directives held by this structure are "allow_create", "allow_mkdir",
454 * "allow_ioctl", "allow_mkfifo", "allow_mksock", "allow_chmod", "allow_chown"
455 * and "allow_chgrp".
456 *
457 */
458struct tomoyo_path_number_acl {
459 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_NUMBER_ACL */
460 u8 perm;
461 struct tomoyo_name_union name;
462 struct tomoyo_number_union number;
463};
464
465/*
466 * tomoyo_mkdev_acl is a structure which is used for holding an
467 * entry with one pathname and three numbers operation.
468 * It has following fields.
469 *
470 * (1) "head" which is a "struct tomoyo_acl_info".
471 * (2) "perm" which is a bitmask of permitted operations.
472 * (3) "mode" is the create mode.
473 * (4) "major" is the major number of device node.
474 * (5) "minor" is the minor number of device node.
475 *
476 * Directives held by this structure are "allow_mkchar", "allow_mkblock".
477 *
478 */
479struct tomoyo_mkdev_acl {
480 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MKDEV_ACL */
481 u8 perm;
482 struct tomoyo_name_union name;
483 struct tomoyo_number_union mode;
484 struct tomoyo_number_union major;
485 struct tomoyo_number_union minor;
486};
487
488/*
316 * tomoyo_path2_acl is a structure which is used for holding an 489 * tomoyo_path2_acl is a structure which is used for holding an
317 * entry with two pathnames operation (i.e. link(), rename() and pivot_root()). 490 * entry with two pathnames operation (i.e. link(), rename() and pivot_root()).
318 * It has following fields. 491 * It has following fields.
@@ -333,53 +506,61 @@ struct tomoyo_path2_acl {
333}; 506};
334 507
335/* 508/*
336 * tomoyo_io_buffer is a structure which is used for reading and modifying 509 * tomoyo_mount_acl is a structure which is used for holding an
337 * configuration via /sys/kernel/security/tomoyo/ interface. 510 * entry for mount operation.
338 * It has many fields. ->read_var1 , ->read_var2 , ->write_var1 are used as 511 * It has following fields.
339 * cursors.
340 * 512 *
341 * Since the content of /sys/kernel/security/tomoyo/domain_policy is a list of 513 * (1) "head" which is a "struct tomoyo_acl_info".
342 * "struct tomoyo_domain_info" entries and each "struct tomoyo_domain_info" 514 * (2) "dev_name" is the device name.
343 * entry has a list of "struct tomoyo_acl_info", we need two cursors when 515 * (3) "dir_name" is the mount point.
344 * reading (one is for traversing tomoyo_domain_list and the other is for 516 * (4) "fs_type" is the filesystem type.
345 * traversing "struct tomoyo_acl_info"->acl_info_list ). 517 * (5) "flags" is the mount flags.
346 * 518 *
347 * If a line written to /sys/kernel/security/tomoyo/domain_policy starts with 519 * Directive held by this structure is "allow_mount".
348 * "select ", TOMOYO seeks the cursor ->read_var1 and ->write_var1 to the 520 */
349 * domain with the domainname specified by the rest of that line (NULL is set 521struct tomoyo_mount_acl {
350 * if seek failed). 522 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MOUNT_ACL */
351 * If a line written to /sys/kernel/security/tomoyo/domain_policy starts with 523 struct tomoyo_name_union dev_name;
352 * "delete ", TOMOYO deletes an entry or a domain specified by the rest of that 524 struct tomoyo_name_union dir_name;
353 * line (->write_var1 is set to NULL if a domain was deleted). 525 struct tomoyo_name_union fs_type;
354 * If a line written to /sys/kernel/security/tomoyo/domain_policy starts with 526 struct tomoyo_number_union flags;
355 * neither "select " nor "delete ", an entry or a domain specified by that line 527};
356 * is appended. 528
529#define TOMOYO_MAX_IO_READ_QUEUE 32
530
531/*
532 * Structure for reading/writing policy via /sys/kernel/security/tomoyo
533 * interfaces.
357 */ 534 */
358struct tomoyo_io_buffer { 535struct tomoyo_io_buffer {
359 int (*read) (struct tomoyo_io_buffer *); 536 void (*read) (struct tomoyo_io_buffer *);
360 int (*write) (struct tomoyo_io_buffer *); 537 int (*write) (struct tomoyo_io_buffer *);
538 int (*poll) (struct file *file, poll_table *wait);
361 /* Exclusive lock for this structure. */ 539 /* Exclusive lock for this structure. */
362 struct mutex io_sem; 540 struct mutex io_sem;
363 /* Index returned by tomoyo_read_lock(). */ 541 /* Index returned by tomoyo_read_lock(). */
364 int reader_idx; 542 int reader_idx;
365 /* The position currently reading from. */ 543 char __user *read_user_buf;
366 struct list_head *read_var1; 544 int read_user_buf_avail;
367 /* Extra variables for reading. */ 545 struct {
368 struct list_head *read_var2; 546 struct list_head *domain;
547 struct list_head *group;
548 struct list_head *acl;
549 int avail;
550 int step;
551 int query_index;
552 u16 index;
553 u8 bit;
554 u8 w_pos;
555 bool eof;
556 bool print_this_domain_only;
557 bool print_execute_only;
558 const char *w[TOMOYO_MAX_IO_READ_QUEUE];
559 } r;
369 /* The position currently writing to. */ 560 /* The position currently writing to. */
370 struct tomoyo_domain_info *write_var1; 561 struct tomoyo_domain_info *write_var1;
371 /* The step for reading. */
372 int read_step;
373 /* Buffer for reading. */ 562 /* Buffer for reading. */
374 char *read_buf; 563 char *read_buf;
375 /* EOF flag for reading. */
376 bool read_eof;
377 /* Read domain ACL of specified PID? */
378 bool read_single_domain;
379 /* Extra variable for reading. */
380 u8 read_bit;
381 /* Bytes available for reading. */
382 int read_avail;
383 /* Size of read buffer. */ 564 /* Size of read buffer. */
384 int readbuf_size; 565 int readbuf_size;
385 /* Buffer for writing. */ 566 /* Buffer for writing. */
@@ -388,215 +569,203 @@ struct tomoyo_io_buffer {
388 int write_avail; 569 int write_avail;
389 /* Size of write buffer. */ 570 /* Size of write buffer. */
390 int writebuf_size; 571 int writebuf_size;
572 /* Type of this interface. */
573 u8 type;
391}; 574};
392 575
393/* 576/*
394 * tomoyo_globally_readable_file_entry is a structure which is used for holding 577 * tomoyo_readable_file is a structure which is used for holding
395 * "allow_read" entries. 578 * "allow_read" entries.
396 * It has following fields. 579 * It has following fields.
397 * 580 *
398 * (1) "list" which is linked to tomoyo_globally_readable_list . 581 * (1) "head" is "struct tomoyo_acl_head".
399 * (2) "filename" is a pathname which is allowed to open(O_RDONLY). 582 * (2) "filename" is a pathname which is allowed to open(O_RDONLY).
400 * (3) "is_deleted" is a bool which is true if marked as deleted, false
401 * otherwise.
402 */ 583 */
403struct tomoyo_globally_readable_file_entry { 584struct tomoyo_readable_file {
404 struct list_head list; 585 struct tomoyo_acl_head head;
405 const struct tomoyo_path_info *filename; 586 const struct tomoyo_path_info *filename;
406 bool is_deleted;
407}; 587};
408 588
409/* 589/*
410 * tomoyo_pattern_entry is a structure which is used for holding 590 * tomoyo_no_pattern is a structure which is used for holding
411 * "tomoyo_pattern_list" entries. 591 * "file_pattern" entries.
412 * It has following fields. 592 * It has following fields.
413 * 593 *
414 * (1) "list" which is linked to tomoyo_pattern_list . 594 * (1) "head" is "struct tomoyo_acl_head".
415 * (2) "pattern" is a pathname pattern which is used for converting pathnames 595 * (2) "pattern" is a pathname pattern which is used for converting pathnames
416 * to pathname patterns during learning mode. 596 * to pathname patterns during learning mode.
417 * (3) "is_deleted" is a bool which is true if marked as deleted, false
418 * otherwise.
419 */ 597 */
420struct tomoyo_pattern_entry { 598struct tomoyo_no_pattern {
421 struct list_head list; 599 struct tomoyo_acl_head head;
422 const struct tomoyo_path_info *pattern; 600 const struct tomoyo_path_info *pattern;
423 bool is_deleted;
424}; 601};
425 602
426/* 603/*
427 * tomoyo_no_rewrite_entry is a structure which is used for holding 604 * tomoyo_no_rewrite is a structure which is used for holding
428 * "deny_rewrite" entries. 605 * "deny_rewrite" entries.
429 * It has following fields. 606 * It has following fields.
430 * 607 *
431 * (1) "list" which is linked to tomoyo_no_rewrite_list . 608 * (1) "head" is "struct tomoyo_acl_head".
432 * (2) "pattern" is a pathname which is by default not permitted to modify 609 * (2) "pattern" is a pathname which is by default not permitted to modify
433 * already existing content. 610 * already existing content.
434 * (3) "is_deleted" is a bool which is true if marked as deleted, false
435 * otherwise.
436 */ 611 */
437struct tomoyo_no_rewrite_entry { 612struct tomoyo_no_rewrite {
438 struct list_head list; 613 struct tomoyo_acl_head head;
439 const struct tomoyo_path_info *pattern; 614 const struct tomoyo_path_info *pattern;
440 bool is_deleted;
441}; 615};
442 616
443/* 617/*
444 * tomoyo_domain_initializer_entry is a structure which is used for holding 618 * tomoyo_transition_control is a structure which is used for holding
445 * "initialize_domain" and "no_initialize_domain" entries. 619 * "initialize_domain"/"no_initialize_domain"/"keep_domain"/"no_keep_domain"
620 * entries.
446 * It has following fields. 621 * It has following fields.
447 * 622 *
448 * (1) "list" which is linked to tomoyo_domain_initializer_list . 623 * (1) "head" is "struct tomoyo_acl_head".
449 * (2) "domainname" which is "a domainname" or "the last component of a 624 * (2) "type" is type of this entry.
450 * domainname". This field is NULL if "from" clause is not specified. 625 * (3) "is_last_name" is a bool which is true if "domainname" is "the last
451 * (3) "program" which is a program's pathname.
452 * (4) "is_deleted" is a bool which is true if marked as deleted, false
453 * otherwise.
454 * (5) "is_not" is a bool which is true if "no_initialize_domain", false
455 * otherwise.
456 * (6) "is_last_name" is a bool which is true if "domainname" is "the last
457 * component of a domainname", false otherwise. 626 * component of a domainname", false otherwise.
458 */ 627 * (4) "domainname" which is "a domainname" or "the last component of a
459struct tomoyo_domain_initializer_entry {
460 struct list_head list;
461 const struct tomoyo_path_info *domainname; /* This may be NULL */
462 const struct tomoyo_path_info *program;
463 bool is_deleted;
464 bool is_not; /* True if this entry is "no_initialize_domain". */
465 /* True if the domainname is tomoyo_get_last_name(). */
466 bool is_last_name;
467};
468
469/*
470 * tomoyo_domain_keeper_entry is a structure which is used for holding
471 * "keep_domain" and "no_keep_domain" entries.
472 * It has following fields.
473 *
474 * (1) "list" which is linked to tomoyo_domain_keeper_list .
475 * (2) "domainname" which is "a domainname" or "the last component of a
476 * domainname". 628 * domainname".
477 * (3) "program" which is a program's pathname. 629 * (5) "program" which is a program's pathname.
478 * This field is NULL if "from" clause is not specified.
479 * (4) "is_deleted" is a bool which is true if marked as deleted, false
480 * otherwise.
481 * (5) "is_not" is a bool which is true if "no_initialize_domain", false
482 * otherwise.
483 * (6) "is_last_name" is a bool which is true if "domainname" is "the last
484 * component of a domainname", false otherwise.
485 */ 630 */
486struct tomoyo_domain_keeper_entry { 631struct tomoyo_transition_control {
487 struct list_head list; 632 struct tomoyo_acl_head head;
488 const struct tomoyo_path_info *domainname; 633 u8 type; /* One of values in "enum tomoyo_transition_type". */
489 const struct tomoyo_path_info *program; /* This may be NULL */
490 bool is_deleted;
491 bool is_not; /* True if this entry is "no_keep_domain". */
492 /* True if the domainname is tomoyo_get_last_name(). */ 634 /* True if the domainname is tomoyo_get_last_name(). */
493 bool is_last_name; 635 bool is_last_name;
636 const struct tomoyo_path_info *domainname; /* Maybe NULL */
637 const struct tomoyo_path_info *program; /* Maybe NULL */
494}; 638};
495 639
496/* 640/*
497 * tomoyo_alias_entry is a structure which is used for holding "alias" entries. 641 * tomoyo_aggregator is a structure which is used for holding
642 * "aggregator" entries.
498 * It has following fields. 643 * It has following fields.
499 * 644 *
500 * (1) "list" which is linked to tomoyo_alias_list . 645 * (1) "head" is "struct tomoyo_acl_head".
501 * (2) "original_name" which is a dereferenced pathname. 646 * (2) "original_name" which is originally requested name.
502 * (3) "aliased_name" which is a symlink's pathname. 647 * (3) "aggregated_name" which is name to rewrite.
503 * (4) "is_deleted" is a bool which is true if marked as deleted, false
504 * otherwise.
505 */ 648 */
506struct tomoyo_alias_entry { 649struct tomoyo_aggregator {
507 struct list_head list; 650 struct tomoyo_acl_head head;
508 const struct tomoyo_path_info *original_name; 651 const struct tomoyo_path_info *original_name;
509 const struct tomoyo_path_info *aliased_name; 652 const struct tomoyo_path_info *aggregated_name;
510 bool is_deleted;
511}; 653};
512 654
513/* 655/*
514 * tomoyo_policy_manager_entry is a structure which is used for holding list of 656 * tomoyo_manager is a structure which is used for holding list of
515 * domainnames or programs which are permitted to modify configuration via 657 * domainnames or programs which are permitted to modify configuration via
516 * /sys/kernel/security/tomoyo/ interface. 658 * /sys/kernel/security/tomoyo/ interface.
517 * It has following fields. 659 * It has following fields.
518 * 660 *
519 * (1) "list" which is linked to tomoyo_policy_manager_list . 661 * (1) "head" is "struct tomoyo_acl_head".
520 * (2) "manager" is a domainname or a program's pathname. 662 * (2) "is_domain" is a bool which is true if "manager" is a domainname, false
521 * (3) "is_domain" is a bool which is true if "manager" is a domainname, false
522 * otherwise.
523 * (4) "is_deleted" is a bool which is true if marked as deleted, false
524 * otherwise. 663 * otherwise.
664 * (3) "manager" is a domainname or a program's pathname.
525 */ 665 */
526struct tomoyo_policy_manager_entry { 666struct tomoyo_manager {
527 struct list_head list; 667 struct tomoyo_acl_head head;
668 bool is_domain; /* True if manager is a domainname. */
528 /* A path to program or a domainname. */ 669 /* A path to program or a domainname. */
529 const struct tomoyo_path_info *manager; 670 const struct tomoyo_path_info *manager;
530 bool is_domain; /* True if manager is a domainname. */ 671};
531 bool is_deleted; /* True if this entry is deleted. */ 672
673struct tomoyo_preference {
674 unsigned int learning_max_entry;
675 bool enforcing_verbose;
676 bool learning_verbose;
677 bool permissive_verbose;
678};
679
680struct tomoyo_profile {
681 const struct tomoyo_path_info *comment;
682 struct tomoyo_preference *learning;
683 struct tomoyo_preference *permissive;
684 struct tomoyo_preference *enforcing;
685 struct tomoyo_preference preference;
686 u8 default_config;
687 u8 config[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX];
532}; 688};
533 689
534/********** Function prototypes. **********/ 690/********** Function prototypes. **********/
535 691
536/* Check whether the given name matches the given name_union. */ 692extern asmlinkage long sys_getpid(void);
537bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, 693extern asmlinkage long sys_getppid(void);
538 const struct tomoyo_name_union *ptr); 694
695/* Check whether the given string starts with the given keyword. */
696bool tomoyo_str_starts(char **src, const char *find);
697/* Get tomoyo_realpath() of current process. */
698const char *tomoyo_get_exe(void);
699/* Format string. */
700void tomoyo_normalize_line(unsigned char *buffer);
701/* Print warning or error message on console. */
702void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
703 __attribute__ ((format(printf, 2, 3)));
704/* Check all profiles currently assigned to domains are defined. */
705void tomoyo_check_profile(void);
706/* Open operation for /sys/kernel/security/tomoyo/ interface. */
707int tomoyo_open_control(const u8 type, struct file *file);
708/* Close /sys/kernel/security/tomoyo/ interface. */
709int tomoyo_close_control(struct file *file);
710/* Poll operation for /sys/kernel/security/tomoyo/ interface. */
711int tomoyo_poll_control(struct file *file, poll_table *wait);
712/* Read operation for /sys/kernel/security/tomoyo/ interface. */
713int tomoyo_read_control(struct file *file, char __user *buffer,
714 const int buffer_len);
715/* Write operation for /sys/kernel/security/tomoyo/ interface. */
716int tomoyo_write_control(struct file *file, const char __user *buffer,
717 const int buffer_len);
539/* Check whether the domain has too many ACL entries to hold. */ 718/* Check whether the domain has too many ACL entries to hold. */
540bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); 719bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r);
541/* Transactional sprintf() for policy dump. */ 720/* Print out of memory warning message. */
542bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 721void tomoyo_warn_oom(const char *function);
722/* Check whether the given name matches the given name_union. */
723const struct tomoyo_path_info *
724tomoyo_compare_name_union(const struct tomoyo_path_info *name,
725 const struct tomoyo_name_union *ptr);
726/* Check whether the given number matches the given number_union. */
727bool tomoyo_compare_number_union(const unsigned long value,
728 const struct tomoyo_number_union *ptr);
729int tomoyo_get_mode(const u8 profile, const u8 index);
730void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
543 __attribute__ ((format(printf, 2, 3))); 731 __attribute__ ((format(printf, 2, 3)));
544/* Check whether the domainname is correct. */ 732/* Check whether the domainname is correct. */
545bool tomoyo_is_correct_domain(const unsigned char *domainname); 733bool tomoyo_correct_domain(const unsigned char *domainname);
546/* Check whether the token is correct. */ 734/* Check whether the token is correct. */
547bool tomoyo_is_correct_path(const char *filename, const s8 start_type, 735bool tomoyo_correct_path(const char *filename);
548 const s8 pattern_type, const s8 end_type); 736bool tomoyo_correct_word(const char *string);
549/* Check whether the token can be a domainname. */ 737/* Check whether the token can be a domainname. */
550bool tomoyo_is_domain_def(const unsigned char *buffer); 738bool tomoyo_domain_def(const unsigned char *buffer);
551bool tomoyo_parse_name_union(const char *filename, 739bool tomoyo_parse_name_union(const char *filename,
552 struct tomoyo_name_union *ptr); 740 struct tomoyo_name_union *ptr);
553/* Check whether the given filename matches the given path_group. */ 741/* Check whether the given filename matches the given path_group. */
554bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, 742const struct tomoyo_path_info *
555 const struct tomoyo_path_group *group, 743tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
556 const bool may_use_pattern); 744 const struct tomoyo_group *group);
745/* Check whether the given value matches the given number_group. */
746bool tomoyo_number_matches_group(const unsigned long min,
747 const unsigned long max,
748 const struct tomoyo_group *group);
557/* Check whether the given filename matches the given pattern. */ 749/* Check whether the given filename matches the given pattern. */
558bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 750bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
559 const struct tomoyo_path_info *pattern); 751 const struct tomoyo_path_info *pattern);
560/* Read "alias" entry in exception policy. */ 752
561bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head); 753bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num);
562/*
563 * Read "initialize_domain" and "no_initialize_domain" entry
564 * in exception policy.
565 */
566bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head);
567/* Read "keep_domain" and "no_keep_domain" entry in exception policy. */
568bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head);
569/* Read "file_pattern" entry in exception policy. */
570bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head);
571/* Read "path_group" entry in exception policy. */
572bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head);
573/* Read "allow_read" entry in exception policy. */
574bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head);
575/* Read "deny_rewrite" entry in exception policy. */
576bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head);
577/* Tokenize a line. */ 754/* Tokenize a line. */
578bool tomoyo_tokenize(char *buffer, char *w[], size_t size); 755bool tomoyo_tokenize(char *buffer, char *w[], size_t size);
579/* Write domain policy violation warning message to console? */ 756/* Write domain policy violation warning message to console? */
580bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); 757bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain);
581/* Convert double path operation to operation name. */ 758/* Fill "struct tomoyo_request_info". */
582const char *tomoyo_path22keyword(const u8 operation); 759int tomoyo_init_request_info(struct tomoyo_request_info *r,
583/* Get the last component of the given domainname. */ 760 struct tomoyo_domain_info *domain,
584const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); 761 const u8 index);
585/* Get warning message. */ 762/* Check permission for mount operation. */
586const char *tomoyo_get_msg(const bool is_enforce); 763int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,
587/* Convert single path operation to operation name. */ 764 unsigned long flags, void *data_page);
588const char *tomoyo_path2keyword(const u8 operation); 765/* Create "aggregator" entry in exception policy. */
589/* Create "alias" entry in exception policy. */ 766int tomoyo_write_aggregator(char *data, const bool is_delete);
590int tomoyo_write_alias_policy(char *data, const bool is_delete); 767int tomoyo_write_transition_control(char *data, const bool is_delete,
591/* 768 const u8 type);
592 * Create "initialize_domain" and "no_initialize_domain" entry
593 * in exception policy.
594 */
595int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
596 const bool is_delete);
597/* Create "keep_domain" and "no_keep_domain" entry in exception policy. */
598int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
599 const bool is_delete);
600/* 769/*
601 * Create "allow_read/write", "allow_execute", "allow_read", "allow_write", 770 * Create "allow_read/write", "allow_execute", "allow_read", "allow_write",
602 * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir", 771 * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir",
@@ -604,25 +773,31 @@ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
604 * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and 773 * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and
605 * "allow_link" entry in domain policy. 774 * "allow_link" entry in domain policy.
606 */ 775 */
607int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, 776int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain,
608 const bool is_delete); 777 const bool is_delete);
609/* Create "allow_read" entry in exception policy. */ 778/* Create "allow_read" entry in exception policy. */
610int tomoyo_write_globally_readable_policy(char *data, const bool is_delete); 779int tomoyo_write_globally_readable(char *data, const bool is_delete);
780/* Create "allow_mount" entry in domain policy. */
781int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain,
782 const bool is_delete);
611/* Create "deny_rewrite" entry in exception policy. */ 783/* Create "deny_rewrite" entry in exception policy. */
612int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); 784int tomoyo_write_no_rewrite(char *data, const bool is_delete);
613/* Create "file_pattern" entry in exception policy. */ 785/* Create "file_pattern" entry in exception policy. */
614int tomoyo_write_pattern_policy(char *data, const bool is_delete); 786int tomoyo_write_pattern(char *data, const bool is_delete);
615/* Create "path_group" entry in exception policy. */ 787/* Create "path_group"/"number_group" entry in exception policy. */
616int tomoyo_write_path_group_policy(char *data, const bool is_delete); 788int tomoyo_write_group(char *data, const bool is_delete, const u8 type);
789int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
790 __attribute__ ((format(printf, 2, 3)));
617/* Find a domain by the given name. */ 791/* Find a domain by the given name. */
618struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); 792struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
619/* Find or create a domain by the given name. */ 793/* Find or create a domain by the given name. */
620struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 794struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
621 domainname, 795 const u8 profile);
622 const u8 profile); 796struct tomoyo_profile *tomoyo_profile(const u8 profile);
623 797/*
624/* Allocate memory for "struct tomoyo_path_group". */ 798 * Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
625struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); 799 */
800struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 type);
626 801
627/* Check mode for specified functionality. */ 802/* Check mode for specified functionality. */
628unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, 803unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
@@ -632,25 +807,23 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
632/* Run policy loader when /sbin/init starts. */ 807/* Run policy loader when /sbin/init starts. */
633void tomoyo_load_policy(const char *filename); 808void tomoyo_load_policy(const char *filename);
634 809
635/* Convert binary string to ascii string. */ 810void tomoyo_put_number_union(struct tomoyo_number_union *ptr);
636int tomoyo_encode(char *buffer, int buflen, const char *str);
637 811
638/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */ 812/* Convert binary string to ascii string. */
639int tomoyo_realpath_from_path2(struct path *path, char *newname, 813char *tomoyo_encode(const char *str);
640 int newname_len);
641 814
642/* 815/*
643 * Returns realpath(3) of the given pathname but ignores chroot'ed root. 816 * Returns realpath(3) of the given pathname except that
644 * These functions use kzalloc(), so the caller must call kfree() 817 * ignores chroot'ed root and does not follow the final symlink.
645 * if these functions didn't return NULL.
646 */ 818 */
647char *tomoyo_realpath(const char *pathname); 819char *tomoyo_realpath_nofollow(const char *pathname);
648/* 820/*
649 * Same with tomoyo_realpath() except that it doesn't follow the final symlink. 821 * Returns realpath(3) of the given pathname except that
822 * ignores chroot'ed root and the pathname is already solved.
650 */ 823 */
651char *tomoyo_realpath_nofollow(const char *pathname);
652/* Same with tomoyo_realpath() except that the pathname is already solved. */
653char *tomoyo_realpath_from_path(struct path *path); 824char *tomoyo_realpath_from_path(struct path *path);
825/* Get patterned pathname. */
826const char *tomoyo_pattern(const struct tomoyo_path_info *filename);
654 827
655/* Check memory quota. */ 828/* Check memory quota. */
656bool tomoyo_memory_ok(void *ptr); 829bool tomoyo_memory_ok(void *ptr);
@@ -663,23 +836,29 @@ void *tomoyo_commit_ok(void *data, const unsigned int size);
663const struct tomoyo_path_info *tomoyo_get_name(const char *name); 836const struct tomoyo_path_info *tomoyo_get_name(const char *name);
664 837
665/* Check for memory usage. */ 838/* Check for memory usage. */
666int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); 839void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head);
667 840
668/* Set memory quota. */ 841/* Set memory quota. */
669int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); 842int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
670 843
671/* Initialize realpath related code. */ 844/* Initialize mm related code. */
672void __init tomoyo_realpath_init(void); 845void __init tomoyo_mm_init(void);
673int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, 846int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
674 const struct tomoyo_path_info *filename); 847 const struct tomoyo_path_info *filename);
675int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, 848int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
676 struct path *path, const int flag); 849 struct path *path, const int flag);
850int tomoyo_path_number_perm(const u8 operation, struct path *path,
851 unsigned long number);
852int tomoyo_mkdev_perm(const u8 operation, struct path *path,
853 const unsigned int mode, unsigned int dev);
677int tomoyo_path_perm(const u8 operation, struct path *path); 854int tomoyo_path_perm(const u8 operation, struct path *path);
678int tomoyo_path2_perm(const u8 operation, struct path *path1, 855int tomoyo_path2_perm(const u8 operation, struct path *path1,
679 struct path *path2); 856 struct path *path2);
680int tomoyo_check_rewrite_permission(struct file *filp);
681int tomoyo_find_next_domain(struct linux_binprm *bprm); 857int tomoyo_find_next_domain(struct linux_binprm *bprm);
682 858
859void tomoyo_print_ulong(char *buffer, const int buffer_len,
860 const unsigned long value, const u8 type);
861
683/* Drop refcount on tomoyo_name_union. */ 862/* Drop refcount on tomoyo_name_union. */
684void tomoyo_put_name_union(struct tomoyo_name_union *ptr); 863void tomoyo_put_name_union(struct tomoyo_name_union *ptr);
685 864
@@ -688,6 +867,25 @@ void tomoyo_run_gc(void);
688 867
689void tomoyo_memory_free(void *ptr); 868void tomoyo_memory_free(void *ptr);
690 869
870int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
871 bool is_delete, struct tomoyo_domain_info *domain,
872 bool (*check_duplicate) (const struct tomoyo_acl_info
873 *,
874 const struct tomoyo_acl_info
875 *),
876 bool (*merge_duplicate) (struct tomoyo_acl_info *,
877 struct tomoyo_acl_info *,
878 const bool));
879int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
880 bool is_delete, struct list_head *list,
881 bool (*check_duplicate) (const struct tomoyo_acl_head
882 *,
883 const struct tomoyo_acl_head
884 *));
885void tomoyo_check_acl(struct tomoyo_request_info *r,
886 bool (*check_entry) (struct tomoyo_request_info *,
887 const struct tomoyo_acl_info *));
888
691/********** External variable definitions. **********/ 889/********** External variable definitions. **********/
692 890
693/* Lock for GC. */ 891/* Lock for GC. */
@@ -696,14 +894,8 @@ extern struct srcu_struct tomoyo_ss;
696/* The list for "struct tomoyo_domain_info". */ 894/* The list for "struct tomoyo_domain_info". */
697extern struct list_head tomoyo_domain_list; 895extern struct list_head tomoyo_domain_list;
698 896
699extern struct list_head tomoyo_path_group_list; 897extern struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY];
700extern struct list_head tomoyo_domain_initializer_list; 898extern struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP];
701extern struct list_head tomoyo_domain_keeper_list;
702extern struct list_head tomoyo_alias_list;
703extern struct list_head tomoyo_globally_readable_list;
704extern struct list_head tomoyo_pattern_list;
705extern struct list_head tomoyo_no_rewrite_list;
706extern struct list_head tomoyo_policy_manager_list;
707extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; 899extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
708 900
709/* Lock for protecting policy. */ 901/* Lock for protecting policy. */
@@ -715,6 +907,14 @@ extern bool tomoyo_policy_loaded;
715/* The kernel's domain. */ 907/* The kernel's domain. */
716extern struct tomoyo_domain_info tomoyo_kernel_domain; 908extern struct tomoyo_domain_info tomoyo_kernel_domain;
717 909
910extern const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION];
911extern const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION];
912extern const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION];
913extern const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION];
914
915extern unsigned int tomoyo_quota_for_query;
916extern unsigned int tomoyo_query_memory_size;
917
718/********** Inlined functions. **********/ 918/********** Inlined functions. **********/
719 919
720static inline int tomoyo_read_lock(void) 920static inline int tomoyo_read_lock(void)
@@ -735,25 +935,25 @@ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
735} 935}
736 936
737/** 937/**
738 * tomoyo_is_valid - Check whether the character is a valid char. 938 * tomoyo_valid - Check whether the character is a valid char.
739 * 939 *
740 * @c: The character to check. 940 * @c: The character to check.
741 * 941 *
742 * Returns true if @c is a valid character, false otherwise. 942 * Returns true if @c is a valid character, false otherwise.
743 */ 943 */
744static inline bool tomoyo_is_valid(const unsigned char c) 944static inline bool tomoyo_valid(const unsigned char c)
745{ 945{
746 return c > ' ' && c < 127; 946 return c > ' ' && c < 127;
747} 947}
748 948
749/** 949/**
750 * tomoyo_is_invalid - Check whether the character is an invalid char. 950 * tomoyo_invalid - Check whether the character is an invalid char.
751 * 951 *
752 * @c: The character to check. 952 * @c: The character to check.
753 * 953 *
754 * Returns true if @c is an invalid character, false otherwise. 954 * Returns true if @c is an invalid character, false otherwise.
755 */ 955 */
756static inline bool tomoyo_is_invalid(const unsigned char c) 956static inline bool tomoyo_invalid(const unsigned char c)
757{ 957{
758 return c && (c <= ' ' || c >= 127); 958 return c && (c <= ' ' || c >= 127);
759} 959}
@@ -761,13 +961,13 @@ static inline bool tomoyo_is_invalid(const unsigned char c)
761static inline void tomoyo_put_name(const struct tomoyo_path_info *name) 961static inline void tomoyo_put_name(const struct tomoyo_path_info *name)
762{ 962{
763 if (name) { 963 if (name) {
764 struct tomoyo_name_entry *ptr = 964 struct tomoyo_name *ptr =
765 container_of(name, struct tomoyo_name_entry, entry); 965 container_of(name, typeof(*ptr), entry);
766 atomic_dec(&ptr->users); 966 atomic_dec(&ptr->users);
767 } 967 }
768} 968}
769 969
770static inline void tomoyo_put_path_group(struct tomoyo_path_group *group) 970static inline void tomoyo_put_group(struct tomoyo_group *group)
771{ 971{
772 if (group) 972 if (group)
773 atomic_dec(&group->users); 973 atomic_dec(&group->users);
@@ -784,75 +984,35 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
784 return task_cred_xxx(task, security); 984 return task_cred_xxx(task, security);
785} 985}
786 986
787static inline bool tomoyo_is_same_acl_head(const struct tomoyo_acl_info *p1, 987static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *p1,
788 const struct tomoyo_acl_info *p2) 988 const struct tomoyo_acl_info *p2)
789{ 989{
790 return p1->type == p2->type; 990 return p1->type == p2->type;
791} 991}
792 992
793static inline bool tomoyo_is_same_name_union 993static inline bool tomoyo_same_name_union
794(const struct tomoyo_name_union *p1, const struct tomoyo_name_union *p2) 994(const struct tomoyo_name_union *p1, const struct tomoyo_name_union *p2)
795{ 995{
796 return p1->filename == p2->filename && p1->group == p2->group && 996 return p1->filename == p2->filename && p1->group == p2->group &&
797 p1->is_group == p2->is_group; 997 p1->is_group == p2->is_group;
798} 998}
799 999
800static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1, 1000static inline bool tomoyo_same_number_union
801 const struct tomoyo_path_acl *p2) 1001(const struct tomoyo_number_union *p1, const struct tomoyo_number_union *p2)
802{
803 return tomoyo_is_same_acl_head(&p1->head, &p2->head) &&
804 tomoyo_is_same_name_union(&p1->name, &p2->name);
805}
806
807static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1,
808 const struct tomoyo_path2_acl *p2)
809{ 1002{
810 return tomoyo_is_same_acl_head(&p1->head, &p2->head) && 1003 return p1->values[0] == p2->values[0] && p1->values[1] == p2->values[1]
811 tomoyo_is_same_name_union(&p1->name1, &p2->name1) && 1004 && p1->group == p2->group && p1->min_type == p2->min_type &&
812 tomoyo_is_same_name_union(&p1->name2, &p2->name2); 1005 p1->max_type == p2->max_type && p1->is_group == p2->is_group;
813}
814
815static inline bool tomoyo_is_same_domain_initializer_entry
816(const struct tomoyo_domain_initializer_entry *p1,
817 const struct tomoyo_domain_initializer_entry *p2)
818{
819 return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
820 && p1->domainname == p2->domainname
821 && p1->program == p2->program;
822}
823
824static inline bool tomoyo_is_same_domain_keeper_entry
825(const struct tomoyo_domain_keeper_entry *p1,
826 const struct tomoyo_domain_keeper_entry *p2)
827{
828 return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
829 && p1->domainname == p2->domainname
830 && p1->program == p2->program;
831}
832
833static inline bool tomoyo_is_same_alias_entry
834(const struct tomoyo_alias_entry *p1, const struct tomoyo_alias_entry *p2)
835{
836 return p1->original_name == p2->original_name &&
837 p1->aliased_name == p2->aliased_name;
838} 1006}
839 1007
840/** 1008/**
841 * list_for_each_cookie - iterate over a list with cookie. 1009 * list_for_each_cookie - iterate over a list with cookie.
842 * @pos: the &struct list_head to use as a loop cursor. 1010 * @pos: the &struct list_head to use as a loop cursor.
843 * @cookie: the &struct list_head to use as a cookie.
844 * @head: the head for your list. 1011 * @head: the head for your list.
845 *
846 * Same with list_for_each_rcu() except that this primitive uses @cookie
847 * so that we can continue iteration.
848 * @cookie must be NULL when iteration starts, and @cookie will become
849 * NULL when iteration finishes.
850 */ 1012 */
851#define list_for_each_cookie(pos, cookie, head) \ 1013#define list_for_each_cookie(pos, head) \
852 for (({ if (!cookie) \ 1014 if (!pos) \
853 cookie = head; }), \ 1015 pos = srcu_dereference((head)->next, &tomoyo_ss); \
854 pos = rcu_dereference((cookie)->next); \ 1016 for ( ; pos != (head); pos = srcu_dereference(pos->next, &tomoyo_ss))
855 prefetch(pos->next), pos != (head) || ((cookie) = NULL); \
856 (cookie) = pos, pos = rcu_dereference(pos->next))
857 1017
858#endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ 1018#endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index cd8ba444676..35388408e47 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -1,12 +1,9 @@
1/* 1/*
2 * security/tomoyo/domain.c 2 * security/tomoyo/domain.c
3 * 3 *
4 * Implementation of the Domain-Based Mandatory Access Control. 4 * Domain transition functions for TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0 2009/04/01
9 * 5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
10 */ 7 */
11 8
12#include "common.h" 9#include "common.h"
@@ -18,366 +15,191 @@
18/* The initial domain. */ 15/* The initial domain. */
19struct tomoyo_domain_info tomoyo_kernel_domain; 16struct tomoyo_domain_info tomoyo_kernel_domain;
20 17
21/*
22 * tomoyo_domain_list is used for holding list of domains.
23 * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding
24 * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
25 *
26 * An entry is added by
27 *
28 * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \
29 * /sys/kernel/security/tomoyo/domain_policy
30 *
31 * and is deleted by
32 *
33 * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \
34 * /sys/kernel/security/tomoyo/domain_policy
35 *
36 * and all entries are retrieved by
37 *
38 * # cat /sys/kernel/security/tomoyo/domain_policy
39 *
40 * A domain is added by
41 *
42 * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy
43 *
44 * and is deleted by
45 *
46 * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy
47 *
48 * and all domains are retrieved by
49 *
50 * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy
51 *
52 * Normally, a domainname is monotonically getting longer because a domainname
53 * which the process will belong to if an execve() operation succeeds is
54 * defined as a concatenation of "current domainname" + "pathname passed to
55 * execve()".
56 * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for
57 * exceptions.
58 */
59LIST_HEAD(tomoyo_domain_list);
60
61/** 18/**
62 * tomoyo_get_last_name - Get last component of a domainname. 19 * tomoyo_update_policy - Update an entry for exception policy.
63 *
64 * @domain: Pointer to "struct tomoyo_domain_info".
65 *
66 * Returns the last component of the domainname.
67 */
68const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
69{
70 const char *cp0 = domain->domainname->name;
71 const char *cp1 = strrchr(cp0, ' ');
72
73 if (cp1)
74 return cp1 + 1;
75 return cp0;
76}
77
78/*
79 * tomoyo_domain_initializer_list is used for holding list of programs which
80 * triggers reinitialization of domainname. Normally, a domainname is
81 * monotonically getting longer. But sometimes, we restart daemon programs.
82 * It would be convenient for us that "a daemon started upon system boot" and
83 * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO
84 * provides a way to shorten domainnames.
85 * 20 *
86 * An entry is added by 21 * @new_entry: Pointer to "struct tomoyo_acl_info".
87 * 22 * @size: Size of @new_entry in bytes.
88 * # echo 'initialize_domain /usr/sbin/httpd' > \ 23 * @is_delete: True if it is a delete request.
89 * /sys/kernel/security/tomoyo/exception_policy 24 * @list: Pointer to "struct list_head".
90 * 25 * @check_duplicate: Callback function to find duplicated entry.
91 * and is deleted by
92 *
93 * # echo 'delete initialize_domain /usr/sbin/httpd' > \
94 * /sys/kernel/security/tomoyo/exception_policy
95 *
96 * and all entries are retrieved by
97 *
98 * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy
99 *
100 * In the example above, /usr/sbin/httpd will belong to
101 * "<kernel> /usr/sbin/httpd" domain.
102 *
103 * You may specify a domainname using "from" keyword.
104 * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
105 * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd"
106 * domain to belong to "<kernel> /usr/sbin/httpd" domain.
107 *
108 * You may add "no_" prefix to "initialize_domain".
109 * "initialize_domain /usr/sbin/httpd" and
110 * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
111 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
112 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
113 */
114LIST_HEAD(tomoyo_domain_initializer_list);
115
116/**
117 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
118 *
119 * @domainname: The name of domain. May be NULL.
120 * @program: The name of program.
121 * @is_not: True if it is "no_initialize_domain" entry.
122 * @is_delete: True if it is a delete request.
123 * 26 *
124 * Returns 0 on success, negative value otherwise. 27 * Returns 0 on success, negative value otherwise.
125 * 28 *
126 * Caller holds tomoyo_read_lock(). 29 * Caller holds tomoyo_read_lock().
127 */ 30 */
128static int tomoyo_update_domain_initializer_entry(const char *domainname, 31int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
129 const char *program, 32 bool is_delete, struct list_head *list,
130 const bool is_not, 33 bool (*check_duplicate) (const struct tomoyo_acl_head
131 const bool is_delete) 34 *,
35 const struct tomoyo_acl_head
36 *))
132{ 37{
133 struct tomoyo_domain_initializer_entry *ptr;
134 struct tomoyo_domain_initializer_entry e = { .is_not = is_not };
135 int error = is_delete ? -ENOENT : -ENOMEM; 38 int error = is_delete ? -ENOENT : -ENOMEM;
39 struct tomoyo_acl_head *entry;
136 40
137 if (!tomoyo_is_correct_path(program, 1, -1, -1))
138 return -EINVAL; /* No patterns allowed. */
139 if (domainname) {
140 if (!tomoyo_is_domain_def(domainname) &&
141 tomoyo_is_correct_path(domainname, 1, -1, -1))
142 e.is_last_name = true;
143 else if (!tomoyo_is_correct_domain(domainname))
144 return -EINVAL;
145 e.domainname = tomoyo_get_name(domainname);
146 if (!e.domainname)
147 goto out;
148 }
149 e.program = tomoyo_get_name(program);
150 if (!e.program)
151 goto out;
152 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 41 if (mutex_lock_interruptible(&tomoyo_policy_lock))
153 goto out; 42 return -ENOMEM;
154 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { 43 list_for_each_entry_rcu(entry, list, list) {
155 if (!tomoyo_is_same_domain_initializer_entry(ptr, &e)) 44 if (!check_duplicate(entry, new_entry))
156 continue; 45 continue;
157 ptr->is_deleted = is_delete; 46 entry->is_deleted = is_delete;
158 error = 0; 47 error = 0;
159 break; 48 break;
160 } 49 }
161 if (!is_delete && error) { 50 if (error && !is_delete) {
162 struct tomoyo_domain_initializer_entry *entry = 51 entry = tomoyo_commit_ok(new_entry, size);
163 tomoyo_commit_ok(&e, sizeof(e));
164 if (entry) { 52 if (entry) {
165 list_add_tail_rcu(&entry->list, 53 list_add_tail_rcu(&entry->list, list);
166 &tomoyo_domain_initializer_list);
167 error = 0; 54 error = 0;
168 } 55 }
169 } 56 }
170 mutex_unlock(&tomoyo_policy_lock); 57 mutex_unlock(&tomoyo_policy_lock);
171 out:
172 tomoyo_put_name(e.domainname);
173 tomoyo_put_name(e.program);
174 return error; 58 return error;
175} 59}
176 60
177/** 61/**
178 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list. 62 * tomoyo_update_domain - Update an entry for domain policy.
179 * 63 *
180 * @head: Pointer to "struct tomoyo_io_buffer". 64 * @new_entry: Pointer to "struct tomoyo_acl_info".
65 * @size: Size of @new_entry in bytes.
66 * @is_delete: True if it is a delete request.
67 * @domain: Pointer to "struct tomoyo_domain_info".
68 * @check_duplicate: Callback function to find duplicated entry.
69 * @merge_duplicate: Callback function to merge duplicated entry.
181 * 70 *
182 * Returns true on success, false otherwise. 71 * Returns 0 on success, negative value otherwise.
183 * 72 *
184 * Caller holds tomoyo_read_lock(). 73 * Caller holds tomoyo_read_lock().
185 */ 74 */
186bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) 75int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
76 bool is_delete, struct tomoyo_domain_info *domain,
77 bool (*check_duplicate) (const struct tomoyo_acl_info
78 *,
79 const struct tomoyo_acl_info
80 *),
81 bool (*merge_duplicate) (struct tomoyo_acl_info *,
82 struct tomoyo_acl_info *,
83 const bool))
187{ 84{
188 struct list_head *pos; 85 int error = is_delete ? -ENOENT : -ENOMEM;
189 bool done = true; 86 struct tomoyo_acl_info *entry;
190 87
191 list_for_each_cookie(pos, head->read_var2, 88 if (mutex_lock_interruptible(&tomoyo_policy_lock))
192 &tomoyo_domain_initializer_list) { 89 return error;
193 const char *no; 90 list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
194 const char *from = ""; 91 if (!check_duplicate(entry, new_entry))
195 const char *domain = "";
196 struct tomoyo_domain_initializer_entry *ptr;
197 ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
198 list);
199 if (ptr->is_deleted)
200 continue; 92 continue;
201 no = ptr->is_not ? "no_" : ""; 93 if (merge_duplicate)
202 if (ptr->domainname) { 94 entry->is_deleted = merge_duplicate(entry, new_entry,
203 from = " from "; 95 is_delete);
204 domain = ptr->domainname->name; 96 else
97 entry->is_deleted = is_delete;
98 error = 0;
99 break;
100 }
101 if (error && !is_delete) {
102 entry = tomoyo_commit_ok(new_entry, size);
103 if (entry) {
104 list_add_tail_rcu(&entry->list, &domain->acl_info_list);
105 error = 0;
205 } 106 }
206 done = tomoyo_io_printf(head,
207 "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
208 "%s%s%s\n", no, ptr->program->name,
209 from, domain);
210 if (!done)
211 break;
212 } 107 }
213 return done; 108 mutex_unlock(&tomoyo_policy_lock);
109 return error;
214} 110}
215 111
216/** 112void tomoyo_check_acl(struct tomoyo_request_info *r,
217 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list. 113 bool (*check_entry) (struct tomoyo_request_info *,
218 * 114 const struct tomoyo_acl_info *))
219 * @data: String to parse.
220 * @is_not: True if it is "no_initialize_domain" entry.
221 * @is_delete: True if it is a delete request.
222 *
223 * Returns 0 on success, negative value otherwise.
224 *
225 * Caller holds tomoyo_read_lock().
226 */
227int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
228 const bool is_delete)
229{ 115{
230 char *cp = strstr(data, " from "); 116 const struct tomoyo_domain_info *domain = r->domain;
117 struct tomoyo_acl_info *ptr;
231 118
232 if (cp) { 119 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
233 *cp = '\0'; 120 if (ptr->is_deleted || ptr->type != r->param_type)
234 return tomoyo_update_domain_initializer_entry(cp + 6, data, 121 continue;
235 is_not, 122 if (check_entry(r, ptr)) {
236 is_delete); 123 r->granted = true;
124 return;
125 }
237 } 126 }
238 return tomoyo_update_domain_initializer_entry(NULL, data, is_not, 127 r->granted = false;
239 is_delete);
240} 128}
241 129
130/* The list for "struct tomoyo_domain_info". */
131LIST_HEAD(tomoyo_domain_list);
132
133struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY];
134struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP];
135
242/** 136/**
243 * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization. 137 * tomoyo_last_word - Get last component of a domainname.
244 *
245 * @domainname: The name of domain.
246 * @program: The name of program.
247 * @last_name: The last component of @domainname.
248 * 138 *
249 * Returns true if executing @program reinitializes domain transition, 139 * @domainname: Domainname to check.
250 * false otherwise.
251 * 140 *
252 * Caller holds tomoyo_read_lock(). 141 * Returns the last word of @domainname.
253 */ 142 */
254static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * 143static const char *tomoyo_last_word(const char *name)
255 domainname,
256 const struct tomoyo_path_info *program,
257 const struct tomoyo_path_info *
258 last_name)
259{ 144{
260 struct tomoyo_domain_initializer_entry *ptr; 145 const char *cp = strrchr(name, ' ');
261 bool flag = false; 146 if (cp)
262 147 return cp + 1;
263 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { 148 return name;
264 if (ptr->is_deleted)
265 continue;
266 if (ptr->domainname) {
267 if (!ptr->is_last_name) {
268 if (ptr->domainname != domainname)
269 continue;
270 } else {
271 if (tomoyo_pathcmp(ptr->domainname, last_name))
272 continue;
273 }
274 }
275 if (tomoyo_pathcmp(ptr->program, program))
276 continue;
277 if (ptr->is_not) {
278 flag = false;
279 break;
280 }
281 flag = true;
282 }
283 return flag;
284} 149}
285 150
286/* 151static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
287 * tomoyo_domain_keeper_list is used for holding list of domainnames which 152 const struct tomoyo_acl_head *b)
288 * suppresses domain transition. Normally, a domainname is monotonically 153{
289 * getting longer. But sometimes, we want to suppress domain transition. 154 const struct tomoyo_transition_control *p1 = container_of(a,
290 * It would be convenient for us that programs executed from a login session 155 typeof(*p1),
291 * belong to the same domain. Thus, TOMOYO provides a way to suppress domain 156 head);
292 * transition. 157 const struct tomoyo_transition_control *p2 = container_of(b,
293 * 158 typeof(*p2),
294 * An entry is added by 159 head);
295 * 160 return p1->type == p2->type && p1->is_last_name == p2->is_last_name
296 * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \ 161 && p1->domainname == p2->domainname
297 * /sys/kernel/security/tomoyo/exception_policy 162 && p1->program == p2->program;
298 * 163}
299 * and is deleted by
300 *
301 * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
302 * /sys/kernel/security/tomoyo/exception_policy
303 *
304 * and all entries are retrieved by
305 *
306 * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy
307 *
308 * In the example above, any process which belongs to
309 * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain,
310 * unless explicitly specified by "initialize_domain" or "no_keep_domain".
311 *
312 * You may specify a program using "from" keyword.
313 * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash"
314 * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash"
315 * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain.
316 *
317 * You may add "no_" prefix to "keep_domain".
318 * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and
319 * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will
320 * cause "/usr/bin/passwd" to belong to
321 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
322 * explicitly specified by "initialize_domain".
323 */
324LIST_HEAD(tomoyo_domain_keeper_list);
325 164
326/** 165/**
327 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. 166 * tomoyo_update_transition_control_entry - Update "struct tomoyo_transition_control" list.
328 * 167 *
329 * @domainname: The name of domain. 168 * @domainname: The name of domain. Maybe NULL.
330 * @program: The name of program. May be NULL. 169 * @program: The name of program. Maybe NULL.
331 * @is_not: True if it is "no_keep_domain" entry. 170 * @type: Type of transition.
332 * @is_delete: True if it is a delete request. 171 * @is_delete: True if it is a delete request.
333 * 172 *
334 * Returns 0 on success, negative value otherwise. 173 * Returns 0 on success, negative value otherwise.
335 *
336 * Caller holds tomoyo_read_lock().
337 */ 174 */
338static int tomoyo_update_domain_keeper_entry(const char *domainname, 175static int tomoyo_update_transition_control_entry(const char *domainname,
339 const char *program, 176 const char *program,
340 const bool is_not, 177 const u8 type,
341 const bool is_delete) 178 const bool is_delete)
342{ 179{
343 struct tomoyo_domain_keeper_entry *ptr; 180 struct tomoyo_transition_control e = { .type = type };
344 struct tomoyo_domain_keeper_entry e = { .is_not = is_not };
345 int error = is_delete ? -ENOENT : -ENOMEM; 181 int error = is_delete ? -ENOENT : -ENOMEM;
346
347 if (!tomoyo_is_domain_def(domainname) &&
348 tomoyo_is_correct_path(domainname, 1, -1, -1))
349 e.is_last_name = true;
350 else if (!tomoyo_is_correct_domain(domainname))
351 return -EINVAL;
352 if (program) { 182 if (program) {
353 if (!tomoyo_is_correct_path(program, 1, -1, -1)) 183 if (!tomoyo_correct_path(program))
354 return -EINVAL; 184 return -EINVAL;
355 e.program = tomoyo_get_name(program); 185 e.program = tomoyo_get_name(program);
356 if (!e.program) 186 if (!e.program)
357 goto out; 187 goto out;
358 } 188 }
359 e.domainname = tomoyo_get_name(domainname); 189 if (domainname) {
360 if (!e.domainname) 190 if (!tomoyo_correct_domain(domainname)) {
361 goto out; 191 if (!tomoyo_correct_path(domainname))
362 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 192 goto out;
363 goto out; 193 e.is_last_name = true;
364 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
365 if (!tomoyo_is_same_domain_keeper_entry(ptr, &e))
366 continue;
367 ptr->is_deleted = is_delete;
368 error = 0;
369 break;
370 }
371 if (!is_delete && error) {
372 struct tomoyo_domain_keeper_entry *entry =
373 tomoyo_commit_ok(&e, sizeof(e));
374 if (entry) {
375 list_add_tail_rcu(&entry->list,
376 &tomoyo_domain_keeper_list);
377 error = 0;
378 } 194 }
195 e.domainname = tomoyo_get_name(domainname);
196 if (!e.domainname)
197 goto out;
379 } 198 }
380 mutex_unlock(&tomoyo_policy_lock); 199 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
200 &tomoyo_policy_list
201 [TOMOYO_ID_TRANSITION_CONTROL],
202 tomoyo_same_transition_control);
381 out: 203 out:
382 tomoyo_put_name(e.domainname); 204 tomoyo_put_name(e.domainname);
383 tomoyo_put_name(e.program); 205 tomoyo_put_name(e.program);
@@ -385,219 +207,133 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
385} 207}
386 208
387/** 209/**
388 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list. 210 * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
389 * 211 *
390 * @data: String to parse. 212 * @data: String to parse.
391 * @is_not: True if it is "no_keep_domain" entry.
392 * @is_delete: True if it is a delete request. 213 * @is_delete: True if it is a delete request.
214 * @type: Type of this entry.
393 * 215 *
394 * Caller holds tomoyo_read_lock(). 216 * Returns 0 on success, negative value otherwise.
395 */
396int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
397 const bool is_delete)
398{
399 char *cp = strstr(data, " from ");
400
401 if (cp) {
402 *cp = '\0';
403 return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
404 is_delete);
405 }
406 return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
407}
408
409/**
410 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
411 *
412 * @head: Pointer to "struct tomoyo_io_buffer".
413 *
414 * Returns true on success, false otherwise.
415 *
416 * Caller holds tomoyo_read_lock().
417 */ 217 */
418bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) 218int tomoyo_write_transition_control(char *data, const bool is_delete,
219 const u8 type)
419{ 220{
420 struct list_head *pos; 221 char *domainname = strstr(data, " from ");
421 bool done = true; 222 if (domainname) {
422 223 *domainname = '\0';
423 list_for_each_cookie(pos, head->read_var2, 224 domainname += 6;
424 &tomoyo_domain_keeper_list) { 225 } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
425 struct tomoyo_domain_keeper_entry *ptr; 226 type == TOMOYO_TRANSITION_CONTROL_KEEP) {
426 const char *no; 227 domainname = data;
427 const char *from = ""; 228 data = NULL;
428 const char *program = "";
429
430 ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
431 if (ptr->is_deleted)
432 continue;
433 no = ptr->is_not ? "no_" : "";
434 if (ptr->program) {
435 from = " from ";
436 program = ptr->program->name;
437 }
438 done = tomoyo_io_printf(head,
439 "%s" TOMOYO_KEYWORD_KEEP_DOMAIN
440 "%s%s%s\n", no, program, from,
441 ptr->domainname->name);
442 if (!done)
443 break;
444 } 229 }
445 return done; 230 return tomoyo_update_transition_control_entry(domainname, data, type,
231 is_delete);
446} 232}
447 233
448/** 234/**
449 * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression. 235 * tomoyo_transition_type - Get domain transition type.
450 * 236 *
451 * @domainname: The name of domain. 237 * @domainname: The name of domain.
452 * @program: The name of program. 238 * @program: The name of program.
453 * @last_name: The last component of @domainname.
454 * 239 *
455 * Returns true if executing @program supresses domain transition, 240 * Returns TOMOYO_TRANSITION_CONTROL_INITIALIZE if executing @program
456 * false otherwise. 241 * reinitializes domain transition, TOMOYO_TRANSITION_CONTROL_KEEP if executing
242 * @program suppresses domain transition, others otherwise.
457 * 243 *
458 * Caller holds tomoyo_read_lock(). 244 * Caller holds tomoyo_read_lock().
459 */ 245 */
460static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, 246static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
461 const struct tomoyo_path_info *program, 247 const struct tomoyo_path_info *program)
462 const struct tomoyo_path_info *last_name)
463{ 248{
464 struct tomoyo_domain_keeper_entry *ptr; 249 const struct tomoyo_transition_control *ptr;
465 bool flag = false; 250 const char *last_name = tomoyo_last_word(domainname->name);
466 251 u8 type;
467 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { 252 for (type = 0; type < TOMOYO_MAX_TRANSITION_TYPE; type++) {
468 if (ptr->is_deleted) 253 next:
469 continue; 254 list_for_each_entry_rcu(ptr, &tomoyo_policy_list
470 if (!ptr->is_last_name) { 255 [TOMOYO_ID_TRANSITION_CONTROL],
471 if (ptr->domainname != domainname) 256 head.list) {
257 if (ptr->head.is_deleted || ptr->type != type)
472 continue; 258 continue;
473 } else { 259 if (ptr->domainname) {
474 if (tomoyo_pathcmp(ptr->domainname, last_name)) 260 if (!ptr->is_last_name) {
261 if (ptr->domainname != domainname)
262 continue;
263 } else {
264 /*
265 * Use direct strcmp() since this is
266 * unlikely used.
267 */
268 if (strcmp(ptr->domainname->name,
269 last_name))
270 continue;
271 }
272 }
273 if (ptr->program &&
274 tomoyo_pathcmp(ptr->program, program))
475 continue; 275 continue;
276 if (type == TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) {
277 /*
278 * Do not check for initialize_domain if
279 * no_initialize_domain matched.
280 */
281 type = TOMOYO_TRANSITION_CONTROL_NO_KEEP;
282 goto next;
283 }
284 goto done;
476 } 285 }
477 if (ptr->program && tomoyo_pathcmp(ptr->program, program))
478 continue;
479 if (ptr->is_not) {
480 flag = false;
481 break;
482 }
483 flag = true;
484 } 286 }
485 return flag; 287 done:
288 return type;
486} 289}
487 290
488/* 291static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a,
489 * tomoyo_alias_list is used for holding list of symlink's pathnames which are 292 const struct tomoyo_acl_head *b)
490 * allowed to be passed to an execve() request. Normally, the domainname which 293{
491 * the current process will belong to after execve() succeeds is calculated 294 const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), head);
492 * using dereferenced pathnames. But some programs behave differently depending 295 const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), head);
493 * on the name passed to argv[0]. For busybox, calculating domainname using 296 return p1->original_name == p2->original_name &&
494 * dereferenced pathnames will cause all programs in the busybox to belong to 297 p1->aggregated_name == p2->aggregated_name;
495 * the same domain. Thus, TOMOYO provides a way to allow use of symlink's 298}
496 * pathname for checking execve()'s permission and calculating domainname which
497 * the current process will belong to after execve() succeeds.
498 *
499 * An entry is added by
500 *
501 * # echo 'alias /bin/busybox /bin/cat' > \
502 * /sys/kernel/security/tomoyo/exception_policy
503 *
504 * and is deleted by
505 *
506 * # echo 'delete alias /bin/busybox /bin/cat' > \
507 * /sys/kernel/security/tomoyo/exception_policy
508 *
509 * and all entries are retrieved by
510 *
511 * # grep ^alias /sys/kernel/security/tomoyo/exception_policy
512 *
513 * In the example above, if /bin/cat is a symlink to /bin/busybox and execution
514 * of /bin/cat is requested, permission is checked for /bin/cat rather than
515 * /bin/busybox and domainname which the current process will belong to after
516 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
517 */
518LIST_HEAD(tomoyo_alias_list);
519 299
520/** 300/**
521 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. 301 * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator" list.
522 * 302 *
523 * @original_name: The original program's real name. 303 * @original_name: The original program's name.
524 * @aliased_name: The symbolic program's symbolic link's name. 304 * @aggregated_name: The program name to use.
525 * @is_delete: True if it is a delete request. 305 * @is_delete: True if it is a delete request.
526 * 306 *
527 * Returns 0 on success, negative value otherwise. 307 * Returns 0 on success, negative value otherwise.
528 * 308 *
529 * Caller holds tomoyo_read_lock(). 309 * Caller holds tomoyo_read_lock().
530 */ 310 */
531static int tomoyo_update_alias_entry(const char *original_name, 311static int tomoyo_update_aggregator_entry(const char *original_name,
532 const char *aliased_name, 312 const char *aggregated_name,
533 const bool is_delete) 313 const bool is_delete)
534{ 314{
535 struct tomoyo_alias_entry *ptr; 315 struct tomoyo_aggregator e = { };
536 struct tomoyo_alias_entry e = { };
537 int error = is_delete ? -ENOENT : -ENOMEM; 316 int error = is_delete ? -ENOENT : -ENOMEM;
538 317
539 if (!tomoyo_is_correct_path(original_name, 1, -1, -1) || 318 if (!tomoyo_correct_path(original_name) ||
540 !tomoyo_is_correct_path(aliased_name, 1, -1, -1)) 319 !tomoyo_correct_path(aggregated_name))
541 return -EINVAL; /* No patterns allowed. */ 320 return -EINVAL;
542 e.original_name = tomoyo_get_name(original_name); 321 e.original_name = tomoyo_get_name(original_name);
543 e.aliased_name = tomoyo_get_name(aliased_name); 322 e.aggregated_name = tomoyo_get_name(aggregated_name);
544 if (!e.original_name || !e.aliased_name) 323 if (!e.original_name || !e.aggregated_name ||
324 e.aggregated_name->is_patterned) /* No patterns allowed. */
545 goto out; 325 goto out;
546 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 326 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
547 goto out; 327 &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR],
548 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 328 tomoyo_same_aggregator);
549 if (!tomoyo_is_same_alias_entry(ptr, &e))
550 continue;
551 ptr->is_deleted = is_delete;
552 error = 0;
553 break;
554 }
555 if (!is_delete && error) {
556 struct tomoyo_alias_entry *entry =
557 tomoyo_commit_ok(&e, sizeof(e));
558 if (entry) {
559 list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
560 error = 0;
561 }
562 }
563 mutex_unlock(&tomoyo_policy_lock);
564 out: 329 out:
565 tomoyo_put_name(e.original_name); 330 tomoyo_put_name(e.original_name);
566 tomoyo_put_name(e.aliased_name); 331 tomoyo_put_name(e.aggregated_name);
567 return error; 332 return error;
568} 333}
569 334
570/** 335/**
571 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list. 336 * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
572 *
573 * @head: Pointer to "struct tomoyo_io_buffer".
574 *
575 * Returns true on success, false otherwise.
576 *
577 * Caller holds tomoyo_read_lock().
578 */
579bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
580{
581 struct list_head *pos;
582 bool done = true;
583
584 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
585 struct tomoyo_alias_entry *ptr;
586
587 ptr = list_entry(pos, struct tomoyo_alias_entry, list);
588 if (ptr->is_deleted)
589 continue;
590 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
591 ptr->original_name->name,
592 ptr->aliased_name->name);
593 if (!done)
594 break;
595 }
596 return done;
597}
598
599/**
600 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
601 * 337 *
602 * @data: String to parse. 338 * @data: String to parse.
603 * @is_delete: True if it is a delete request. 339 * @is_delete: True if it is a delete request.
@@ -606,18 +342,18 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
606 * 342 *
607 * Caller holds tomoyo_read_lock(). 343 * Caller holds tomoyo_read_lock().
608 */ 344 */
609int tomoyo_write_alias_policy(char *data, const bool is_delete) 345int tomoyo_write_aggregator(char *data, const bool is_delete)
610{ 346{
611 char *cp = strchr(data, ' '); 347 char *cp = strchr(data, ' ');
612 348
613 if (!cp) 349 if (!cp)
614 return -EINVAL; 350 return -EINVAL;
615 *cp++ = '\0'; 351 *cp++ = '\0';
616 return tomoyo_update_alias_entry(data, cp, is_delete); 352 return tomoyo_update_aggregator_entry(data, cp, is_delete);
617} 353}
618 354
619/** 355/**
620 * tomoyo_find_or_assign_new_domain - Create a domain. 356 * tomoyo_assign_domain - Create a domain.
621 * 357 *
622 * @domainname: The name of domain. 358 * @domainname: The name of domain.
623 * @profile: Profile number to assign if the domain was newly created. 359 * @profile: Profile number to assign if the domain was newly created.
@@ -626,16 +362,15 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete)
626 * 362 *
627 * Caller holds tomoyo_read_lock(). 363 * Caller holds tomoyo_read_lock().
628 */ 364 */
629struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 365struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
630 domainname, 366 const u8 profile)
631 const u8 profile)
632{ 367{
633 struct tomoyo_domain_info *entry; 368 struct tomoyo_domain_info *entry;
634 struct tomoyo_domain_info *domain = NULL; 369 struct tomoyo_domain_info *domain = NULL;
635 const struct tomoyo_path_info *saved_domainname; 370 const struct tomoyo_path_info *saved_domainname;
636 bool found = false; 371 bool found = false;
637 372
638 if (!tomoyo_is_correct_domain(domainname)) 373 if (!tomoyo_correct_domain(domainname))
639 return NULL; 374 return NULL;
640 saved_domainname = tomoyo_get_name(domainname); 375 saved_domainname = tomoyo_get_name(domainname);
641 if (!saved_domainname) 376 if (!saved_domainname)
@@ -678,116 +413,118 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
678 */ 413 */
679int tomoyo_find_next_domain(struct linux_binprm *bprm) 414int tomoyo_find_next_domain(struct linux_binprm *bprm)
680{ 415{
681 /* 416 struct tomoyo_request_info r;
682 * This function assumes that the size of buffer returned by 417 char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
683 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
684 */
685 struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_NOFS);
686 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 418 struct tomoyo_domain_info *old_domain = tomoyo_domain();
687 struct tomoyo_domain_info *domain = NULL; 419 struct tomoyo_domain_info *domain = NULL;
688 const char *old_domain_name = old_domain->domainname->name;
689 const char *original_name = bprm->filename; 420 const char *original_name = bprm->filename;
690 char *new_domain_name = NULL; 421 u8 mode;
691 char *real_program_name = NULL; 422 bool is_enforce;
692 char *symlink_program_name = NULL;
693 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
694 const bool is_enforce = (mode == 3);
695 int retval = -ENOMEM; 423 int retval = -ENOMEM;
696 struct tomoyo_path_info r; /* real name */ 424 bool need_kfree = false;
697 struct tomoyo_path_info s; /* symlink name */ 425 struct tomoyo_path_info rn = { }; /* real name */
698 struct tomoyo_path_info l; /* last name */
699 static bool initialized;
700 426
427 mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
428 is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
701 if (!tmp) 429 if (!tmp)
702 goto out; 430 goto out;
703 431
704 if (!initialized) { 432 retry:
705 /* 433 if (need_kfree) {
706 * Built-in initializers. This is needed because policies are 434 kfree(rn.name);
707 * not loaded until starting /sbin/init. 435 need_kfree = false;
708 */
709 tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
710 false, false);
711 tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
712 false, false);
713 initialized = true;
714 } 436 }
715 437 /* Get symlink's pathname of program. */
716 /* Get tomoyo_realpath of program. */
717 retval = -ENOENT; 438 retval = -ENOENT;
718 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */ 439 rn.name = tomoyo_realpath_nofollow(original_name);
719 real_program_name = tomoyo_realpath(original_name); 440 if (!rn.name)
720 if (!real_program_name)
721 goto out;
722 /* Get tomoyo_realpath of symbolic link. */
723 symlink_program_name = tomoyo_realpath_nofollow(original_name);
724 if (!symlink_program_name)
725 goto out; 441 goto out;
726 442 tomoyo_fill_path_info(&rn);
727 r.name = real_program_name; 443 need_kfree = true;
728 tomoyo_fill_path_info(&r); 444
729 s.name = symlink_program_name; 445 /* Check 'aggregator' directive. */
730 tomoyo_fill_path_info(&s); 446 {
731 l.name = tomoyo_get_last_name(old_domain); 447 struct tomoyo_aggregator *ptr;
732 tomoyo_fill_path_info(&l); 448 list_for_each_entry_rcu(ptr, &tomoyo_policy_list
733 449 [TOMOYO_ID_AGGREGATOR], head.list) {
734 /* Check 'alias' directive. */ 450 if (ptr->head.is_deleted ||
735 if (tomoyo_pathcmp(&r, &s)) { 451 !tomoyo_path_matches_pattern(&rn,
736 struct tomoyo_alias_entry *ptr; 452 ptr->original_name))
737 /* Is this program allowed to be called via symbolic links? */
738 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
739 if (ptr->is_deleted ||
740 tomoyo_pathcmp(&r, ptr->original_name) ||
741 tomoyo_pathcmp(&s, ptr->aliased_name))
742 continue; 453 continue;
743 memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN); 454 kfree(rn.name);
744 strncpy(real_program_name, ptr->aliased_name->name, 455 need_kfree = false;
745 TOMOYO_MAX_PATHNAME_LEN - 1); 456 /* This is OK because it is read only. */
746 tomoyo_fill_path_info(&r); 457 rn = *ptr->aggregated_name;
747 break; 458 break;
748 } 459 }
749 } 460 }
750 461
751 /* Check execute permission. */ 462 /* Check execute permission. */
752 retval = tomoyo_check_exec_perm(old_domain, &r); 463 retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn);
464 if (retval == TOMOYO_RETRY_REQUEST)
465 goto retry;
753 if (retval < 0) 466 if (retval < 0)
754 goto out; 467 goto out;
468 /*
469 * To be able to specify domainnames with wildcards, use the
470 * pathname specified in the policy (which may contain
471 * wildcard) rather than the pathname passed to execve()
472 * (which never contains wildcard).
473 */
474 if (r.param.path.matched_path) {
475 if (need_kfree)
476 kfree(rn.name);
477 need_kfree = false;
478 /* This is OK because it is read only. */
479 rn = *r.param.path.matched_path;
480 }
755 481
756 new_domain_name = tmp->buffer; 482 /* Calculate domain to transit to. */
757 if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) { 483 switch (tomoyo_transition_type(old_domain->domainname, &rn)) {
484 case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
758 /* Transit to the child of tomoyo_kernel_domain domain. */ 485 /* Transit to the child of tomoyo_kernel_domain domain. */
759 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 486 snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, TOMOYO_ROOT_NAME " "
760 TOMOYO_ROOT_NAME " " "%s", real_program_name); 487 "%s", rn.name);
761 } else if (old_domain == &tomoyo_kernel_domain && 488 break;
762 !tomoyo_policy_loaded) { 489 case TOMOYO_TRANSITION_CONTROL_KEEP:
763 /*
764 * Needn't to transit from kernel domain before starting
765 * /sbin/init. But transit from kernel domain if executing
766 * initializers because they might start before /sbin/init.
767 */
768 domain = old_domain;
769 } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
770 /* Keep current domain. */ 490 /* Keep current domain. */
771 domain = old_domain; 491 domain = old_domain;
772 } else { 492 break;
773 /* Normal domain transition. */ 493 default:
774 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 494 if (old_domain == &tomoyo_kernel_domain &&
775 "%s %s", old_domain_name, real_program_name); 495 !tomoyo_policy_loaded) {
496 /*
497 * Needn't to transit from kernel domain before
498 * starting /sbin/init. But transit from kernel domain
499 * if executing initializers because they might start
500 * before /sbin/init.
501 */
502 domain = old_domain;
503 } else {
504 /* Normal domain transition. */
505 snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
506 old_domain->domainname->name, rn.name);
507 }
508 break;
776 } 509 }
777 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) 510 if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
778 goto done; 511 goto done;
779 domain = tomoyo_find_domain(new_domain_name); 512 domain = tomoyo_find_domain(tmp);
780 if (domain) 513 if (domain)
781 goto done; 514 goto done;
782 if (is_enforce) 515 if (is_enforce) {
783 goto done; 516 int error = tomoyo_supervisor(&r, "# wants to create domain\n"
784 domain = tomoyo_find_or_assign_new_domain(new_domain_name, 517 "%s\n", tmp);
785 old_domain->profile); 518 if (error == TOMOYO_RETRY_REQUEST)
519 goto retry;
520 if (error < 0)
521 goto done;
522 }
523 domain = tomoyo_assign_domain(tmp, old_domain->profile);
786 done: 524 done:
787 if (domain) 525 if (domain)
788 goto out; 526 goto out;
789 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", 527 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
790 new_domain_name);
791 if (is_enforce) 528 if (is_enforce)
792 retval = -EPERM; 529 retval = -EPERM;
793 else 530 else
@@ -798,8 +535,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
798 /* Update reference count on "struct tomoyo_domain_info". */ 535 /* Update reference count on "struct tomoyo_domain_info". */
799 atomic_inc(&domain->users); 536 atomic_inc(&domain->users);
800 bprm->cred->security = domain; 537 bprm->cred->security = domain;
801 kfree(real_program_name); 538 if (need_kfree)
802 kfree(symlink_program_name); 539 kfree(rn.name);
803 kfree(tmp); 540 kfree(tmp);
804 return retval; 541 return retval;
805} 542}
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 1c6f8238ec4..9d32f182301 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -1,48 +1,88 @@
1/* 1/*
2 * security/tomoyo/file.c 2 * security/tomoyo/file.c
3 * 3 *
4 * Implementation of the Domain-Based Mandatory Access Control. 4 * Pathname restriction functions.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0 2009/04/01
9 * 5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
10 */ 7 */
11 8
12#include "common.h" 9#include "common.h"
13#include <linux/slab.h> 10#include <linux/slab.h>
14 11
15/* Keyword array for single path operations. */ 12/* Keyword array for operations with one pathname. */
16static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { 13const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = {
17 [TOMOYO_TYPE_READ_WRITE] = "read/write", 14 [TOMOYO_TYPE_READ_WRITE] = "read/write",
18 [TOMOYO_TYPE_EXECUTE] = "execute", 15 [TOMOYO_TYPE_EXECUTE] = "execute",
19 [TOMOYO_TYPE_READ] = "read", 16 [TOMOYO_TYPE_READ] = "read",
20 [TOMOYO_TYPE_WRITE] = "write", 17 [TOMOYO_TYPE_WRITE] = "write",
21 [TOMOYO_TYPE_CREATE] = "create",
22 [TOMOYO_TYPE_UNLINK] = "unlink", 18 [TOMOYO_TYPE_UNLINK] = "unlink",
23 [TOMOYO_TYPE_MKDIR] = "mkdir",
24 [TOMOYO_TYPE_RMDIR] = "rmdir", 19 [TOMOYO_TYPE_RMDIR] = "rmdir",
25 [TOMOYO_TYPE_MKFIFO] = "mkfifo",
26 [TOMOYO_TYPE_MKSOCK] = "mksock",
27 [TOMOYO_TYPE_MKBLOCK] = "mkblock",
28 [TOMOYO_TYPE_MKCHAR] = "mkchar",
29 [TOMOYO_TYPE_TRUNCATE] = "truncate", 20 [TOMOYO_TYPE_TRUNCATE] = "truncate",
30 [TOMOYO_TYPE_SYMLINK] = "symlink", 21 [TOMOYO_TYPE_SYMLINK] = "symlink",
31 [TOMOYO_TYPE_REWRITE] = "rewrite", 22 [TOMOYO_TYPE_REWRITE] = "rewrite",
23 [TOMOYO_TYPE_CHROOT] = "chroot",
24 [TOMOYO_TYPE_UMOUNT] = "unmount",
25};
26
27/* Keyword array for operations with one pathname and three numbers. */
28const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION] = {
29 [TOMOYO_TYPE_MKBLOCK] = "mkblock",
30 [TOMOYO_TYPE_MKCHAR] = "mkchar",
31};
32
33/* Keyword array for operations with two pathnames. */
34const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = {
35 [TOMOYO_TYPE_LINK] = "link",
36 [TOMOYO_TYPE_RENAME] = "rename",
37 [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root",
38};
39
40/* Keyword array for operations with one pathname and one number. */
41const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
42 [TOMOYO_TYPE_CREATE] = "create",
43 [TOMOYO_TYPE_MKDIR] = "mkdir",
44 [TOMOYO_TYPE_MKFIFO] = "mkfifo",
45 [TOMOYO_TYPE_MKSOCK] = "mksock",
32 [TOMOYO_TYPE_IOCTL] = "ioctl", 46 [TOMOYO_TYPE_IOCTL] = "ioctl",
33 [TOMOYO_TYPE_CHMOD] = "chmod", 47 [TOMOYO_TYPE_CHMOD] = "chmod",
34 [TOMOYO_TYPE_CHOWN] = "chown", 48 [TOMOYO_TYPE_CHOWN] = "chown",
35 [TOMOYO_TYPE_CHGRP] = "chgrp", 49 [TOMOYO_TYPE_CHGRP] = "chgrp",
36 [TOMOYO_TYPE_CHROOT] = "chroot",
37 [TOMOYO_TYPE_MOUNT] = "mount",
38 [TOMOYO_TYPE_UMOUNT] = "unmount",
39}; 50};
40 51
41/* Keyword array for double path operations. */ 52static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
42static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { 53 [TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN,
43 [TOMOYO_TYPE_LINK] = "link", 54 [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE,
44 [TOMOYO_TYPE_RENAME] = "rename", 55 [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN,
45 [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", 56 [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN,
57 [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK,
58 [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR,
59 [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE,
60 [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK,
61 [TOMOYO_TYPE_REWRITE] = TOMOYO_MAC_FILE_REWRITE,
62 [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT,
63 [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT,
64};
65
66static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
67 [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
68 [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR,
69};
70
71static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
72 [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK,
73 [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME,
74 [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
75};
76
77static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
78 [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
79 [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR,
80 [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
81 [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
82 [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL,
83 [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD,
84 [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN,
85 [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP,
46}; 86};
47 87
48void tomoyo_put_name_union(struct tomoyo_name_union *ptr) 88void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
@@ -50,56 +90,45 @@ void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
50 if (!ptr) 90 if (!ptr)
51 return; 91 return;
52 if (ptr->is_group) 92 if (ptr->is_group)
53 tomoyo_put_path_group(ptr->group); 93 tomoyo_put_group(ptr->group);
54 else 94 else
55 tomoyo_put_name(ptr->filename); 95 tomoyo_put_name(ptr->filename);
56} 96}
57 97
58bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, 98const struct tomoyo_path_info *
59 const struct tomoyo_name_union *ptr) 99tomoyo_compare_name_union(const struct tomoyo_path_info *name,
100 const struct tomoyo_name_union *ptr)
60{ 101{
61 if (ptr->is_group) 102 if (ptr->is_group)
62 return tomoyo_path_matches_group(name, ptr->group, 1); 103 return tomoyo_path_matches_group(name, ptr->group);
63 return tomoyo_path_matches_pattern(name, ptr->filename); 104 if (tomoyo_path_matches_pattern(name, ptr->filename))
105 return ptr->filename;
106 return NULL;
64} 107}
65 108
66static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info 109void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
67 *name,
68 const struct tomoyo_name_union
69 *ptr, const bool may_use_pattern)
70{ 110{
71 if (ptr->is_group) 111 if (ptr && ptr->is_group)
72 return tomoyo_path_matches_group(name, ptr->group, 112 tomoyo_put_group(ptr->group);
73 may_use_pattern);
74 if (may_use_pattern || !ptr->filename->is_patterned)
75 return tomoyo_path_matches_pattern(name, ptr->filename);
76 return false;
77} 113}
78 114
79/** 115bool tomoyo_compare_number_union(const unsigned long value,
80 * tomoyo_path2keyword - Get the name of single path operation. 116 const struct tomoyo_number_union *ptr)
81 *
82 * @operation: Type of operation.
83 *
84 * Returns the name of single path operation.
85 */
86const char *tomoyo_path2keyword(const u8 operation)
87{ 117{
88 return (operation < TOMOYO_MAX_PATH_OPERATION) 118 if (ptr->is_group)
89 ? tomoyo_path_keyword[operation] : NULL; 119 return tomoyo_number_matches_group(value, value, ptr->group);
120 return value >= ptr->values[0] && value <= ptr->values[1];
90} 121}
91 122
92/** 123static void tomoyo_add_slash(struct tomoyo_path_info *buf)
93 * tomoyo_path22keyword - Get the name of double path operation.
94 *
95 * @operation: Type of operation.
96 *
97 * Returns the name of double path operation.
98 */
99const char *tomoyo_path22keyword(const u8 operation)
100{ 124{
101 return (operation < TOMOYO_MAX_PATH2_OPERATION) 125 if (buf->is_dir)
102 ? tomoyo_path2_keyword[operation] : NULL; 126 return;
127 /*
128 * This is OK because tomoyo_encode() reserves space for appending "/".
129 */
130 strcat((char *) buf->name, "/");
131 tomoyo_fill_path_info(buf);
103} 132}
104 133
105/** 134/**
@@ -121,69 +150,134 @@ static bool tomoyo_strendswith(const char *name, const char *tail)
121} 150}
122 151
123/** 152/**
124 * tomoyo_get_path - Get realpath. 153 * tomoyo_get_realpath - Get realpath.
125 * 154 *
155 * @buf: Pointer to "struct tomoyo_path_info".
126 * @path: Pointer to "struct path". 156 * @path: Pointer to "struct path".
127 * 157 *
128 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. 158 * Returns true on success, false otherwise.
129 */ 159 */
130static struct tomoyo_path_info *tomoyo_get_path(struct path *path) 160static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
131{ 161{
132 int error; 162 buf->name = tomoyo_realpath_from_path(path);
133 struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), 163 if (buf->name) {
134 GFP_NOFS); 164 tomoyo_fill_path_info(buf);
135 165 return true;
136 if (!buf)
137 return NULL;
138 /* Reserve one byte for appending "/". */
139 error = tomoyo_realpath_from_path2(path, buf->body,
140 sizeof(buf->body) - 2);
141 if (!error) {
142 buf->head.name = buf->body;
143 tomoyo_fill_path_info(&buf->head);
144 return &buf->head;
145 } 166 }
146 kfree(buf); 167 return false;
147 return NULL;
148} 168}
149 169
150static int tomoyo_update_path2_acl(const u8 type, const char *filename1, 170/**
151 const char *filename2, 171 * tomoyo_audit_path_log - Audit path request log.
152 struct tomoyo_domain_info *const domain, 172 *
153 const bool is_delete); 173 * @r: Pointer to "struct tomoyo_request_info".
154static int tomoyo_update_path_acl(const u8 type, const char *filename,
155 struct tomoyo_domain_info *const domain,
156 const bool is_delete);
157
158/*
159 * tomoyo_globally_readable_list is used for holding list of pathnames which
160 * are by default allowed to be open()ed for reading by any process.
161 * 174 *
162 * An entry is added by 175 * Returns 0 on success, negative value otherwise.
176 */
177static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
178{
179 const char *operation = tomoyo_path_keyword[r->param.path.operation];
180 const struct tomoyo_path_info *filename = r->param.path.filename;
181 if (r->granted)
182 return 0;
183 tomoyo_warn_log(r, "%s %s", operation, filename->name);
184 return tomoyo_supervisor(r, "allow_%s %s\n", operation,
185 tomoyo_pattern(filename));
186}
187
188/**
189 * tomoyo_audit_path2_log - Audit path/path request log.
163 * 190 *
164 * # echo 'allow_read /lib/libc-2.5.so' > \ 191 * @r: Pointer to "struct tomoyo_request_info".
165 * /sys/kernel/security/tomoyo/exception_policy
166 * 192 *
167 * and is deleted by 193 * Returns 0 on success, negative value otherwise.
194 */
195static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
196{
197 const char *operation = tomoyo_path2_keyword[r->param.path2.operation];
198 const struct tomoyo_path_info *filename1 = r->param.path2.filename1;
199 const struct tomoyo_path_info *filename2 = r->param.path2.filename2;
200 if (r->granted)
201 return 0;
202 tomoyo_warn_log(r, "%s %s %s", operation, filename1->name,
203 filename2->name);
204 return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
205 tomoyo_pattern(filename1),
206 tomoyo_pattern(filename2));
207}
208
209/**
210 * tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
168 * 211 *
169 * # echo 'delete allow_read /lib/libc-2.5.so' > \ 212 * @r: Pointer to "struct tomoyo_request_info".
170 * /sys/kernel/security/tomoyo/exception_policy
171 * 213 *
172 * and all entries are retrieved by 214 * Returns 0 on success, negative value otherwise.
215 */
216static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
217{
218 const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation];
219 const struct tomoyo_path_info *filename = r->param.mkdev.filename;
220 const unsigned int major = r->param.mkdev.major;
221 const unsigned int minor = r->param.mkdev.minor;
222 const unsigned int mode = r->param.mkdev.mode;
223 if (r->granted)
224 return 0;
225 tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode,
226 major, minor);
227 return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation,
228 tomoyo_pattern(filename), mode, major, minor);
229}
230
231/**
232 * tomoyo_audit_path_number_log - Audit path/number request log.
173 * 233 *
174 * # grep ^allow_read /sys/kernel/security/tomoyo/exception_policy 234 * @r: Pointer to "struct tomoyo_request_info".
235 * @error: Error code.
175 * 236 *
176 * In the example above, any process is allowed to 237 * Returns 0 on success, negative value otherwise.
177 * open("/lib/libc-2.5.so", O_RDONLY).
178 * One exception is, if the domain which current process belongs to is marked
179 * as "ignore_global_allow_read", current process can't do so unless explicitly
180 * given "allow_read /lib/libc-2.5.so" to the domain which current process
181 * belongs to.
182 */ 238 */
183LIST_HEAD(tomoyo_globally_readable_list); 239static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
240{
241 const u8 type = r->param.path_number.operation;
242 u8 radix;
243 const struct tomoyo_path_info *filename = r->param.path_number.filename;
244 const char *operation = tomoyo_path_number_keyword[type];
245 char buffer[64];
246 if (r->granted)
247 return 0;
248 switch (type) {
249 case TOMOYO_TYPE_CREATE:
250 case TOMOYO_TYPE_MKDIR:
251 case TOMOYO_TYPE_MKFIFO:
252 case TOMOYO_TYPE_MKSOCK:
253 case TOMOYO_TYPE_CHMOD:
254 radix = TOMOYO_VALUE_TYPE_OCTAL;
255 break;
256 case TOMOYO_TYPE_IOCTL:
257 radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
258 break;
259 default:
260 radix = TOMOYO_VALUE_TYPE_DECIMAL;
261 break;
262 }
263 tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
264 radix);
265 tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer);
266 return tomoyo_supervisor(r, "allow_%s %s %s\n", operation,
267 tomoyo_pattern(filename), buffer);
268}
269
270static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a,
271 const struct tomoyo_acl_head *b)
272{
273 return container_of(a, struct tomoyo_readable_file,
274 head)->filename ==
275 container_of(b, struct tomoyo_readable_file,
276 head)->filename;
277}
184 278
185/** 279/**
186 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. 280 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_readable_file" list.
187 * 281 *
188 * @filename: Filename unconditionally permitted to open() for reading. 282 * @filename: Filename unconditionally permitted to open() for reading.
189 * @is_delete: True if it is a delete request. 283 * @is_delete: True if it is a delete request.
@@ -195,41 +289,24 @@ LIST_HEAD(tomoyo_globally_readable_list);
195static int tomoyo_update_globally_readable_entry(const char *filename, 289static int tomoyo_update_globally_readable_entry(const char *filename,
196 const bool is_delete) 290 const bool is_delete)
197{ 291{
198 struct tomoyo_globally_readable_file_entry *ptr; 292 struct tomoyo_readable_file e = { };
199 struct tomoyo_globally_readable_file_entry e = { }; 293 int error;
200 int error = is_delete ? -ENOENT : -ENOMEM;
201 294
202 if (!tomoyo_is_correct_path(filename, 1, 0, -1)) 295 if (!tomoyo_correct_word(filename))
203 return -EINVAL; 296 return -EINVAL;
204 e.filename = tomoyo_get_name(filename); 297 e.filename = tomoyo_get_name(filename);
205 if (!e.filename) 298 if (!e.filename)
206 return -ENOMEM; 299 return -ENOMEM;
207 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 300 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
208 goto out; 301 &tomoyo_policy_list
209 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { 302 [TOMOYO_ID_GLOBALLY_READABLE],
210 if (ptr->filename != e.filename) 303 tomoyo_same_globally_readable);
211 continue;
212 ptr->is_deleted = is_delete;
213 error = 0;
214 break;
215 }
216 if (!is_delete && error) {
217 struct tomoyo_globally_readable_file_entry *entry =
218 tomoyo_commit_ok(&e, sizeof(e));
219 if (entry) {
220 list_add_tail_rcu(&entry->list,
221 &tomoyo_globally_readable_list);
222 error = 0;
223 }
224 }
225 mutex_unlock(&tomoyo_policy_lock);
226 out:
227 tomoyo_put_name(e.filename); 304 tomoyo_put_name(e.filename);
228 return error; 305 return error;
229} 306}
230 307
231/** 308/**
232 * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading. 309 * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
233 * 310 *
234 * @filename: The filename to check. 311 * @filename: The filename to check.
235 * 312 *
@@ -237,14 +314,15 @@ static int tomoyo_update_globally_readable_entry(const char *filename,
237 * 314 *
238 * Caller holds tomoyo_read_lock(). 315 * Caller holds tomoyo_read_lock().
239 */ 316 */
240static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * 317static bool tomoyo_globally_readable_file(const struct tomoyo_path_info *
241 filename) 318 filename)
242{ 319{
243 struct tomoyo_globally_readable_file_entry *ptr; 320 struct tomoyo_readable_file *ptr;
244 bool found = false; 321 bool found = false;
245 322
246 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { 323 list_for_each_entry_rcu(ptr, &tomoyo_policy_list
247 if (!ptr->is_deleted && 324 [TOMOYO_ID_GLOBALLY_READABLE], head.list) {
325 if (!ptr->head.is_deleted &&
248 tomoyo_path_matches_pattern(filename, ptr->filename)) { 326 tomoyo_path_matches_pattern(filename, ptr->filename)) {
249 found = true; 327 found = true;
250 break; 328 break;
@@ -254,7 +332,7 @@ static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
254} 332}
255 333
256/** 334/**
257 * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list. 335 * tomoyo_write_globally_readable - Write "struct tomoyo_readable_file" list.
258 * 336 *
259 * @data: String to parse. 337 * @data: String to parse.
260 * @is_delete: True if it is a delete request. 338 * @is_delete: True if it is a delete request.
@@ -263,74 +341,20 @@ static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
263 * 341 *
264 * Caller holds tomoyo_read_lock(). 342 * Caller holds tomoyo_read_lock().
265 */ 343 */
266int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) 344int tomoyo_write_globally_readable(char *data, const bool is_delete)
267{ 345{
268 return tomoyo_update_globally_readable_entry(data, is_delete); 346 return tomoyo_update_globally_readable_entry(data, is_delete);
269} 347}
270 348
271/** 349static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a,
272 * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list. 350 const struct tomoyo_acl_head *b)
273 *
274 * @head: Pointer to "struct tomoyo_io_buffer".
275 *
276 * Returns true on success, false otherwise.
277 *
278 * Caller holds tomoyo_read_lock().
279 */
280bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
281{ 351{
282 struct list_head *pos; 352 return container_of(a, struct tomoyo_no_pattern, head)->pattern ==
283 bool done = true; 353 container_of(b, struct tomoyo_no_pattern, head)->pattern;
284
285 list_for_each_cookie(pos, head->read_var2,
286 &tomoyo_globally_readable_list) {
287 struct tomoyo_globally_readable_file_entry *ptr;
288 ptr = list_entry(pos,
289 struct tomoyo_globally_readable_file_entry,
290 list);
291 if (ptr->is_deleted)
292 continue;
293 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
294 ptr->filename->name);
295 if (!done)
296 break;
297 }
298 return done;
299} 354}
300 355
301/* tomoyo_pattern_list is used for holding list of pathnames which are used for
302 * converting pathnames to pathname patterns during learning mode.
303 *
304 * An entry is added by
305 *
306 * # echo 'file_pattern /proc/\$/mounts' > \
307 * /sys/kernel/security/tomoyo/exception_policy
308 *
309 * and is deleted by
310 *
311 * # echo 'delete file_pattern /proc/\$/mounts' > \
312 * /sys/kernel/security/tomoyo/exception_policy
313 *
314 * and all entries are retrieved by
315 *
316 * # grep ^file_pattern /sys/kernel/security/tomoyo/exception_policy
317 *
318 * In the example above, if a process which belongs to a domain which is in
319 * learning mode requested open("/proc/1/mounts", O_RDONLY),
320 * "allow_read /proc/\$/mounts" is automatically added to the domain which that
321 * process belongs to.
322 *
323 * It is not a desirable behavior that we have to use /proc/\$/ instead of
324 * /proc/self/ when current process needs to access only current process's
325 * information. As of now, LSM version of TOMOYO is using __d_path() for
326 * calculating pathname. Non LSM version of TOMOYO is using its own function
327 * which pretends as if /proc/self/ is not a symlink; so that we can forbid
328 * current process from accessing other process's information.
329 */
330LIST_HEAD(tomoyo_pattern_list);
331
332/** 356/**
333 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. 357 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_no_pattern" list.
334 * 358 *
335 * @pattern: Pathname pattern. 359 * @pattern: Pathname pattern.
336 * @is_delete: True if it is a delete request. 360 * @is_delete: True if it is a delete request.
@@ -342,39 +366,23 @@ LIST_HEAD(tomoyo_pattern_list);
342static int tomoyo_update_file_pattern_entry(const char *pattern, 366static int tomoyo_update_file_pattern_entry(const char *pattern,
343 const bool is_delete) 367 const bool is_delete)
344{ 368{
345 struct tomoyo_pattern_entry *ptr; 369 struct tomoyo_no_pattern e = { };
346 struct tomoyo_pattern_entry e = { .pattern = tomoyo_get_name(pattern) }; 370 int error;
347 int error = is_delete ? -ENOENT : -ENOMEM;
348 371
372 if (!tomoyo_correct_word(pattern))
373 return -EINVAL;
374 e.pattern = tomoyo_get_name(pattern);
349 if (!e.pattern) 375 if (!e.pattern)
350 return error; 376 return -ENOMEM;
351 if (!e.pattern->is_patterned) 377 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
352 goto out; 378 &tomoyo_policy_list[TOMOYO_ID_PATTERN],
353 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 379 tomoyo_same_pattern);
354 goto out;
355 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
356 if (e.pattern != ptr->pattern)
357 continue;
358 ptr->is_deleted = is_delete;
359 error = 0;
360 break;
361 }
362 if (!is_delete && error) {
363 struct tomoyo_pattern_entry *entry =
364 tomoyo_commit_ok(&e, sizeof(e));
365 if (entry) {
366 list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
367 error = 0;
368 }
369 }
370 mutex_unlock(&tomoyo_policy_lock);
371 out:
372 tomoyo_put_name(e.pattern); 380 tomoyo_put_name(e.pattern);
373 return error; 381 return error;
374} 382}
375 383
376/** 384/**
377 * tomoyo_get_file_pattern - Get patterned pathname. 385 * tomoyo_pattern - Get patterned pathname.
378 * 386 *
379 * @filename: The filename to find patterned pathname. 387 * @filename: The filename to find patterned pathname.
380 * 388 *
@@ -382,14 +390,14 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
382 * 390 *
383 * Caller holds tomoyo_read_lock(). 391 * Caller holds tomoyo_read_lock().
384 */ 392 */
385static const struct tomoyo_path_info * 393const char *tomoyo_pattern(const struct tomoyo_path_info *filename)
386tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
387{ 394{
388 struct tomoyo_pattern_entry *ptr; 395 struct tomoyo_no_pattern *ptr;
389 const struct tomoyo_path_info *pattern = NULL; 396 const struct tomoyo_path_info *pattern = NULL;
390 397
391 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { 398 list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN],
392 if (ptr->is_deleted) 399 head.list) {
400 if (ptr->head.is_deleted)
393 continue; 401 continue;
394 if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) 402 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
395 continue; 403 continue;
@@ -403,11 +411,11 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
403 } 411 }
404 if (pattern) 412 if (pattern)
405 filename = pattern; 413 filename = pattern;
406 return filename; 414 return filename->name;
407} 415}
408 416
409/** 417/**
410 * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list. 418 * tomoyo_write_pattern - Write "struct tomoyo_no_pattern" list.
411 * 419 *
412 * @data: String to parse. 420 * @data: String to parse.
413 * @is_delete: True if it is a delete request. 421 * @is_delete: True if it is a delete request.
@@ -416,71 +424,21 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
416 * 424 *
417 * Caller holds tomoyo_read_lock(). 425 * Caller holds tomoyo_read_lock().
418 */ 426 */
419int tomoyo_write_pattern_policy(char *data, const bool is_delete) 427int tomoyo_write_pattern(char *data, const bool is_delete)
420{ 428{
421 return tomoyo_update_file_pattern_entry(data, is_delete); 429 return tomoyo_update_file_pattern_entry(data, is_delete);
422} 430}
423 431
424/** 432static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a,
425 * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list. 433 const struct tomoyo_acl_head *b)
426 *
427 * @head: Pointer to "struct tomoyo_io_buffer".
428 *
429 * Returns true on success, false otherwise.
430 *
431 * Caller holds tomoyo_read_lock().
432 */
433bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
434{ 434{
435 struct list_head *pos; 435 return container_of(a, struct tomoyo_no_rewrite, head)->pattern
436 bool done = true; 436 == container_of(b, struct tomoyo_no_rewrite, head)
437 437 ->pattern;
438 list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
439 struct tomoyo_pattern_entry *ptr;
440 ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
441 if (ptr->is_deleted)
442 continue;
443 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN
444 "%s\n", ptr->pattern->name);
445 if (!done)
446 break;
447 }
448 return done;
449} 438}
450 439
451/*
452 * tomoyo_no_rewrite_list is used for holding list of pathnames which are by
453 * default forbidden to modify already written content of a file.
454 *
455 * An entry is added by
456 *
457 * # echo 'deny_rewrite /var/log/messages' > \
458 * /sys/kernel/security/tomoyo/exception_policy
459 *
460 * and is deleted by
461 *
462 * # echo 'delete deny_rewrite /var/log/messages' > \
463 * /sys/kernel/security/tomoyo/exception_policy
464 *
465 * and all entries are retrieved by
466 *
467 * # grep ^deny_rewrite /sys/kernel/security/tomoyo/exception_policy
468 *
469 * In the example above, if a process requested to rewrite /var/log/messages ,
470 * the process can't rewrite unless the domain which that process belongs to
471 * has "allow_rewrite /var/log/messages" entry.
472 *
473 * It is not a desirable behavior that we have to add "\040(deleted)" suffix
474 * when we want to allow rewriting already unlink()ed file. As of now,
475 * LSM version of TOMOYO is using __d_path() for calculating pathname.
476 * Non LSM version of TOMOYO is using its own function which doesn't append
477 * " (deleted)" suffix if the file is already unlink()ed; so that we don't
478 * need to worry whether the file is already unlink()ed or not.
479 */
480LIST_HEAD(tomoyo_no_rewrite_list);
481
482/** 440/**
483 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. 441 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite" list.
484 * 442 *
485 * @pattern: Pathname pattern that are not rewritable by default. 443 * @pattern: Pathname pattern that are not rewritable by default.
486 * @is_delete: True if it is a delete request. 444 * @is_delete: True if it is a delete request.
@@ -492,41 +450,23 @@ LIST_HEAD(tomoyo_no_rewrite_list);
492static int tomoyo_update_no_rewrite_entry(const char *pattern, 450static int tomoyo_update_no_rewrite_entry(const char *pattern,
493 const bool is_delete) 451 const bool is_delete)
494{ 452{
495 struct tomoyo_no_rewrite_entry *ptr; 453 struct tomoyo_no_rewrite e = { };
496 struct tomoyo_no_rewrite_entry e = { }; 454 int error;
497 int error = is_delete ? -ENOENT : -ENOMEM;
498 455
499 if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) 456 if (!tomoyo_correct_word(pattern))
500 return -EINVAL; 457 return -EINVAL;
501 e.pattern = tomoyo_get_name(pattern); 458 e.pattern = tomoyo_get_name(pattern);
502 if (!e.pattern) 459 if (!e.pattern)
503 return error; 460 return -ENOMEM;
504 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 461 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
505 goto out; 462 &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
506 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 463 tomoyo_same_no_rewrite);
507 if (ptr->pattern != e.pattern)
508 continue;
509 ptr->is_deleted = is_delete;
510 error = 0;
511 break;
512 }
513 if (!is_delete && error) {
514 struct tomoyo_no_rewrite_entry *entry =
515 tomoyo_commit_ok(&e, sizeof(e));
516 if (entry) {
517 list_add_tail_rcu(&entry->list,
518 &tomoyo_no_rewrite_list);
519 error = 0;
520 }
521 }
522 mutex_unlock(&tomoyo_policy_lock);
523 out:
524 tomoyo_put_name(e.pattern); 464 tomoyo_put_name(e.pattern);
525 return error; 465 return error;
526} 466}
527 467
528/** 468/**
529 * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. 469 * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
530 * 470 *
531 * @filename: Filename to check. 471 * @filename: Filename to check.
532 * 472 *
@@ -535,13 +475,14 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern,
535 * 475 *
536 * Caller holds tomoyo_read_lock(). 476 * Caller holds tomoyo_read_lock().
537 */ 477 */
538static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) 478static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename)
539{ 479{
540 struct tomoyo_no_rewrite_entry *ptr; 480 struct tomoyo_no_rewrite *ptr;
541 bool found = false; 481 bool found = false;
542 482
543 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 483 list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE],
544 if (ptr->is_deleted) 484 head.list) {
485 if (ptr->head.is_deleted)
545 continue; 486 continue;
546 if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) 487 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
547 continue; 488 continue;
@@ -552,7 +493,7 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
552} 493}
553 494
554/** 495/**
555 * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list. 496 * tomoyo_write_no_rewrite - Write "struct tomoyo_no_rewrite" list.
556 * 497 *
557 * @data: String to parse. 498 * @data: String to parse.
558 * @is_delete: True if it is a delete request. 499 * @is_delete: True if it is a delete request.
@@ -561,214 +502,103 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
561 * 502 *
562 * Caller holds tomoyo_read_lock(). 503 * Caller holds tomoyo_read_lock().
563 */ 504 */
564int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) 505int tomoyo_write_no_rewrite(char *data, const bool is_delete)
565{ 506{
566 return tomoyo_update_no_rewrite_entry(data, is_delete); 507 return tomoyo_update_no_rewrite_entry(data, is_delete);
567} 508}
568 509
569/** 510static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
570 * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list. 511 const struct tomoyo_acl_info *ptr)
571 *
572 * @head: Pointer to "struct tomoyo_io_buffer".
573 *
574 * Returns true on success, false otherwise.
575 *
576 * Caller holds tomoyo_read_lock().
577 */
578bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
579{ 512{
580 struct list_head *pos; 513 const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
581 bool done = true; 514 head);
582 515 if (acl->perm & (1 << r->param.path.operation)) {
583 list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) { 516 r->param.path.matched_path =
584 struct tomoyo_no_rewrite_entry *ptr; 517 tomoyo_compare_name_union(r->param.path.filename,
585 ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); 518 &acl->name);
586 if (ptr->is_deleted) 519 return r->param.path.matched_path != NULL;
587 continue;
588 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE
589 "%s\n", ptr->pattern->name);
590 if (!done)
591 break;
592 } 520 }
593 return done; 521 return false;
594} 522}
595 523
596/** 524static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
597 * tomoyo_update_file_acl - Update file's read/write/execute ACL. 525 const struct tomoyo_acl_info *ptr)
598 *
599 * @filename: Filename.
600 * @perm: Permission (between 1 to 7).
601 * @domain: Pointer to "struct tomoyo_domain_info".
602 * @is_delete: True if it is a delete request.
603 *
604 * Returns 0 on success, negative value otherwise.
605 *
606 * This is legacy support interface for older policy syntax.
607 * Current policy syntax uses "allow_read/write" instead of "6",
608 * "allow_read" instead of "4", "allow_write" instead of "2",
609 * "allow_execute" instead of "1".
610 *
611 * Caller holds tomoyo_read_lock().
612 */
613static int tomoyo_update_file_acl(const char *filename, u8 perm,
614 struct tomoyo_domain_info * const domain,
615 const bool is_delete)
616{ 526{
617 if (perm > 7 || !perm) { 527 const struct tomoyo_path_number_acl *acl =
618 printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n", 528 container_of(ptr, typeof(*acl), head);
619 __func__, perm, filename); 529 return (acl->perm & (1 << r->param.path_number.operation)) &&
620 return -EINVAL; 530 tomoyo_compare_number_union(r->param.path_number.number,
621 } 531 &acl->number) &&
622 if (filename[0] != '@' && tomoyo_strendswith(filename, "/")) 532 tomoyo_compare_name_union(r->param.path_number.filename,
623 /* 533 &acl->name);
624 * Only 'allow_mkdir' and 'allow_rmdir' are valid for
625 * directory permissions.
626 */
627 return 0;
628 if (perm & 4)
629 tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain,
630 is_delete);
631 if (perm & 2)
632 tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain,
633 is_delete);
634 if (perm & 1)
635 tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain,
636 is_delete);
637 return 0;
638} 534}
639 535
640/** 536static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
641 * tomoyo_path_acl2 - Check permission for single path operation. 537 const struct tomoyo_acl_info *ptr)
642 *
643 * @domain: Pointer to "struct tomoyo_domain_info".
644 * @filename: Filename to check.
645 * @perm: Permission.
646 * @may_use_pattern: True if patterned ACL is permitted.
647 *
648 * Returns 0 on success, -EPERM otherwise.
649 *
650 * Caller holds tomoyo_read_lock().
651 */
652static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain,
653 const struct tomoyo_path_info *filename,
654 const u32 perm, const bool may_use_pattern)
655{ 538{
656 struct tomoyo_acl_info *ptr; 539 const struct tomoyo_path2_acl *acl =
657 int error = -EPERM; 540 container_of(ptr, typeof(*acl), head);
658 541 return (acl->perm & (1 << r->param.path2.operation)) &&
659 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 542 tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
660 struct tomoyo_path_acl *acl; 543 && tomoyo_compare_name_union(r->param.path2.filename2,
661 if (ptr->type != TOMOYO_TYPE_PATH_ACL) 544 &acl->name2);
662 continue;
663 acl = container_of(ptr, struct tomoyo_path_acl, head);
664 if (perm <= 0xFFFF) {
665 if (!(acl->perm & perm))
666 continue;
667 } else {
668 if (!(acl->perm_high & (perm >> 16)))
669 continue;
670 }
671 if (!tomoyo_compare_name_union_pattern(filename, &acl->name,
672 may_use_pattern))
673 continue;
674 error = 0;
675 break;
676 }
677 return error;
678} 545}
679 546
680/** 547static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
681 * tomoyo_check_file_acl - Check permission for opening files. 548 const struct tomoyo_acl_info *ptr)
682 *
683 * @domain: Pointer to "struct tomoyo_domain_info".
684 * @filename: Filename to check.
685 * @operation: Mode ("read" or "write" or "read/write" or "execute").
686 *
687 * Returns 0 on success, -EPERM otherwise.
688 *
689 * Caller holds tomoyo_read_lock().
690 */
691static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
692 const struct tomoyo_path_info *filename,
693 const u8 operation)
694{ 549{
695 u32 perm = 0; 550 const struct tomoyo_mkdev_acl *acl =
696 551 container_of(ptr, typeof(*acl), head);
697 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) 552 return (acl->perm & (1 << r->param.mkdev.operation)) &&
698 return 0; 553 tomoyo_compare_number_union(r->param.mkdev.mode,
699 if (operation == 6) 554 &acl->mode) &&
700 perm = 1 << TOMOYO_TYPE_READ_WRITE; 555 tomoyo_compare_number_union(r->param.mkdev.major,
701 else if (operation == 4) 556 &acl->major) &&
702 perm = 1 << TOMOYO_TYPE_READ; 557 tomoyo_compare_number_union(r->param.mkdev.minor,
703 else if (operation == 2) 558 &acl->minor) &&
704 perm = 1 << TOMOYO_TYPE_WRITE; 559 tomoyo_compare_name_union(r->param.mkdev.filename,
705 else if (operation == 1) 560 &acl->name);
706 perm = 1 << TOMOYO_TYPE_EXECUTE;
707 else
708 BUG();
709 return tomoyo_path_acl2(domain, filename, perm, operation != 1);
710} 561}
711 562
712/** 563static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
713 * tomoyo_check_file_perm2 - Check permission for opening files. 564 const struct tomoyo_acl_info *b)
714 *
715 * @domain: Pointer to "struct tomoyo_domain_info".
716 * @filename: Filename to check.
717 * @perm: Mode ("read" or "write" or "read/write" or "execute").
718 * @operation: Operation name passed used for verbose mode.
719 * @mode: Access control mode.
720 *
721 * Returns 0 on success, negative value otherwise.
722 *
723 * Caller holds tomoyo_read_lock().
724 */
725static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
726 const struct tomoyo_path_info *filename,
727 const u8 perm, const char *operation,
728 const u8 mode)
729{ 565{
730 const bool is_enforce = (mode == 3); 566 const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
731 const char *msg = "<unknown>"; 567 const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
732 int error = 0; 568 return tomoyo_same_acl_head(&p1->head, &p2->head) &&
569 tomoyo_same_name_union(&p1->name, &p2->name);
570}
733 571
734 if (!filename) 572static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
735 return 0; 573 struct tomoyo_acl_info *b,
736 error = tomoyo_check_file_acl(domain, filename, perm); 574 const bool is_delete)
737 if (error && perm == 4 && !domain->ignore_global_allow_read 575{
738 && tomoyo_is_globally_readable_file(filename)) 576 u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
739 error = 0; 577 ->perm;
740 if (perm == 6) 578 u16 perm = *a_perm;
741 msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE); 579 const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
742 else if (perm == 4) 580 if (is_delete) {
743 msg = tomoyo_path2keyword(TOMOYO_TYPE_READ); 581 perm &= ~b_perm;
744 else if (perm == 2) 582 if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK)
745 msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE); 583 perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
746 else if (perm == 1) 584 else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE)))
747 msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE); 585 perm &= ~TOMOYO_RW_MASK;
748 else 586 } else {
749 BUG(); 587 perm |= b_perm;
750 if (!error) 588 if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK)
751 return 0; 589 perm |= (1 << TOMOYO_TYPE_READ_WRITE);
752 if (tomoyo_verbose_mode(domain)) 590 else if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
753 printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied " 591 perm |= TOMOYO_RW_MASK;
754 "for %s\n", tomoyo_get_msg(is_enforce), msg, operation,
755 filename->name, tomoyo_get_last_name(domain));
756 if (is_enforce)
757 return error;
758 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
759 /* Don't use patterns for execute permission. */
760 const struct tomoyo_path_info *patterned_file = (perm != 1) ?
761 tomoyo_get_file_pattern(filename) : filename;
762 tomoyo_update_file_acl(patterned_file->name, perm,
763 domain, false);
764 } 592 }
765 return 0; 593 *a_perm = perm;
594 return !perm;
766} 595}
767 596
768/** 597/**
769 * tomoyo_write_file_policy - Update file related list. 598 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
770 * 599 *
771 * @data: String to parse. 600 * @type: Type of operation.
601 * @filename: Filename.
772 * @domain: Pointer to "struct tomoyo_domain_info". 602 * @domain: Pointer to "struct tomoyo_domain_info".
773 * @is_delete: True if it is a delete request. 603 * @is_delete: True if it is a delete request.
774 * 604 *
@@ -776,48 +606,65 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
776 * 606 *
777 * Caller holds tomoyo_read_lock(). 607 * Caller holds tomoyo_read_lock().
778 */ 608 */
779int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, 609static int tomoyo_update_path_acl(const u8 type, const char *filename,
780 const bool is_delete) 610 struct tomoyo_domain_info * const domain,
611 const bool is_delete)
781{ 612{
782 char *filename = strchr(data, ' '); 613 struct tomoyo_path_acl e = {
783 char *filename2; 614 .head.type = TOMOYO_TYPE_PATH_ACL,
784 unsigned int perm; 615 .perm = 1 << type
785 u8 type; 616 };
786 617 int error;
787 if (!filename) 618 if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE))
619 e.perm |= TOMOYO_RW_MASK;
620 if (!tomoyo_parse_name_union(filename, &e.name))
788 return -EINVAL; 621 return -EINVAL;
789 *filename++ = '\0'; 622 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
790 if (sscanf(data, "%u", &perm) == 1) 623 tomoyo_same_path_acl,
791 return tomoyo_update_file_acl(filename, (u8) perm, domain, 624 tomoyo_merge_path_acl);
792 is_delete); 625 tomoyo_put_name_union(&e.name);
793 if (strncmp(data, "allow_", 6)) 626 return error;
794 goto out; 627}
795 data += 6; 628
796 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { 629static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
797 if (strcmp(data, tomoyo_path_keyword[type])) 630 const struct tomoyo_acl_info *b)
798 continue; 631{
799 return tomoyo_update_path_acl(type, filename, domain, 632 const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1),
800 is_delete); 633 head);
801 } 634 const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2),
802 filename2 = strchr(filename, ' '); 635 head);
803 if (!filename2) 636 return tomoyo_same_acl_head(&p1->head, &p2->head)
804 goto out; 637 && tomoyo_same_name_union(&p1->name, &p2->name)
805 *filename2++ = '\0'; 638 && tomoyo_same_number_union(&p1->mode, &p2->mode)
806 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { 639 && tomoyo_same_number_union(&p1->major, &p2->major)
807 if (strcmp(data, tomoyo_path2_keyword[type])) 640 && tomoyo_same_number_union(&p1->minor, &p2->minor);
808 continue; 641}
809 return tomoyo_update_path2_acl(type, filename, filename2, 642
810 domain, is_delete); 643static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
811 } 644 struct tomoyo_acl_info *b,
812 out: 645 const bool is_delete)
813 return -EINVAL; 646{
647 u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
648 head)->perm;
649 u8 perm = *a_perm;
650 const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
651 ->perm;
652 if (is_delete)
653 perm &= ~b_perm;
654 else
655 perm |= b_perm;
656 *a_perm = perm;
657 return !perm;
814} 658}
815 659
816/** 660/**
817 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. 661 * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
818 * 662 *
819 * @type: Type of operation. 663 * @type: Type of operation.
820 * @filename: Filename. 664 * @filename: Filename.
665 * @mode: Create mode.
666 * @major: Device major number.
667 * @minor: Device minor number.
821 * @domain: Pointer to "struct tomoyo_domain_info". 668 * @domain: Pointer to "struct tomoyo_domain_info".
822 * @is_delete: True if it is a delete request. 669 * @is_delete: True if it is a delete request.
823 * 670 *
@@ -825,71 +672,58 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
825 * 672 *
826 * Caller holds tomoyo_read_lock(). 673 * Caller holds tomoyo_read_lock().
827 */ 674 */
828static int tomoyo_update_path_acl(const u8 type, const char *filename, 675static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
829 struct tomoyo_domain_info *const domain, 676 char *mode, char *major, char *minor,
830 const bool is_delete) 677 struct tomoyo_domain_info * const
678 domain, const bool is_delete)
831{ 679{
832 static const u32 tomoyo_rw_mask = 680 struct tomoyo_mkdev_acl e = {
833 (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); 681 .head.type = TOMOYO_TYPE_MKDEV_ACL,
834 const u32 perm = 1 << type; 682 .perm = 1 << type
835 struct tomoyo_acl_info *ptr;
836 struct tomoyo_path_acl e = {
837 .head.type = TOMOYO_TYPE_PATH_ACL,
838 .perm_high = perm >> 16,
839 .perm = perm
840 }; 683 };
841 int error = is_delete ? -ENOENT : -ENOMEM; 684 int error = is_delete ? -ENOENT : -ENOMEM;
842 685 if (!tomoyo_parse_name_union(filename, &e.name) ||
843 if (type == TOMOYO_TYPE_READ_WRITE) 686 !tomoyo_parse_number_union(mode, &e.mode) ||
844 e.perm |= tomoyo_rw_mask; 687 !tomoyo_parse_number_union(major, &e.major) ||
845 if (!domain) 688 !tomoyo_parse_number_union(minor, &e.minor))
846 return -EINVAL;
847 if (!tomoyo_parse_name_union(filename, &e.name))
848 return -EINVAL;
849 if (mutex_lock_interruptible(&tomoyo_policy_lock))
850 goto out; 689 goto out;
851 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 690 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
852 struct tomoyo_path_acl *acl = 691 tomoyo_same_mkdev_acl,
853 container_of(ptr, struct tomoyo_path_acl, head); 692 tomoyo_merge_mkdev_acl);
854 if (!tomoyo_is_same_path_acl(acl, &e))
855 continue;
856 if (is_delete) {
857 if (perm <= 0xFFFF)
858 acl->perm &= ~perm;
859 else
860 acl->perm_high &= ~(perm >> 16);
861 if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask)
862 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
863 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)))
864 acl->perm &= ~tomoyo_rw_mask;
865 } else {
866 if (perm <= 0xFFFF)
867 acl->perm |= perm;
868 else
869 acl->perm_high |= (perm >> 16);
870 if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask)
871 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
872 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))
873 acl->perm |= tomoyo_rw_mask;
874 }
875 error = 0;
876 break;
877 }
878 if (!is_delete && error) {
879 struct tomoyo_path_acl *entry =
880 tomoyo_commit_ok(&e, sizeof(e));
881 if (entry) {
882 list_add_tail_rcu(&entry->head.list,
883 &domain->acl_info_list);
884 error = 0;
885 }
886 }
887 mutex_unlock(&tomoyo_policy_lock);
888 out: 693 out:
889 tomoyo_put_name_union(&e.name); 694 tomoyo_put_name_union(&e.name);
695 tomoyo_put_number_union(&e.mode);
696 tomoyo_put_number_union(&e.major);
697 tomoyo_put_number_union(&e.minor);
890 return error; 698 return error;
891} 699}
892 700
701static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
702 const struct tomoyo_acl_info *b)
703{
704 const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
705 const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
706 return tomoyo_same_acl_head(&p1->head, &p2->head)
707 && tomoyo_same_name_union(&p1->name1, &p2->name1)
708 && tomoyo_same_name_union(&p1->name2, &p2->name2);
709}
710
711static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
712 struct tomoyo_acl_info *b,
713 const bool is_delete)
714{
715 u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
716 ->perm;
717 u8 perm = *a_perm;
718 const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
719 if (is_delete)
720 perm &= ~b_perm;
721 else
722 perm |= b_perm;
723 *a_perm = perm;
724 return !perm;
725}
726
893/** 727/**
894 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. 728 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
895 * 729 *
@@ -905,46 +739,20 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
905 */ 739 */
906static int tomoyo_update_path2_acl(const u8 type, const char *filename1, 740static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
907 const char *filename2, 741 const char *filename2,
908 struct tomoyo_domain_info *const domain, 742 struct tomoyo_domain_info * const domain,
909 const bool is_delete) 743 const bool is_delete)
910{ 744{
911 const u8 perm = 1 << type;
912 struct tomoyo_path2_acl e = { 745 struct tomoyo_path2_acl e = {
913 .head.type = TOMOYO_TYPE_PATH2_ACL, 746 .head.type = TOMOYO_TYPE_PATH2_ACL,
914 .perm = perm 747 .perm = 1 << type
915 }; 748 };
916 struct tomoyo_acl_info *ptr;
917 int error = is_delete ? -ENOENT : -ENOMEM; 749 int error = is_delete ? -ENOENT : -ENOMEM;
918
919 if (!domain)
920 return -EINVAL;
921 if (!tomoyo_parse_name_union(filename1, &e.name1) || 750 if (!tomoyo_parse_name_union(filename1, &e.name1) ||
922 !tomoyo_parse_name_union(filename2, &e.name2)) 751 !tomoyo_parse_name_union(filename2, &e.name2))
923 goto out; 752 goto out;
924 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 753 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
925 goto out; 754 tomoyo_same_path2_acl,
926 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 755 tomoyo_merge_path2_acl);
927 struct tomoyo_path2_acl *acl =
928 container_of(ptr, struct tomoyo_path2_acl, head);
929 if (!tomoyo_is_same_path2_acl(acl, &e))
930 continue;
931 if (is_delete)
932 acl->perm &= ~perm;
933 else
934 acl->perm |= perm;
935 error = 0;
936 break;
937 }
938 if (!is_delete && error) {
939 struct tomoyo_path2_acl *entry =
940 tomoyo_commit_ok(&e, sizeof(e));
941 if (entry) {
942 list_add_tail_rcu(&entry->head.list,
943 &domain->acl_info_list);
944 error = 0;
945 }
946 }
947 mutex_unlock(&tomoyo_policy_lock);
948 out: 756 out:
949 tomoyo_put_name_union(&e.name1); 757 tomoyo_put_name_union(&e.name1);
950 tomoyo_put_name_union(&e.name2); 758 tomoyo_put_name_union(&e.name2);
@@ -952,134 +760,158 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
952} 760}
953 761
954/** 762/**
955 * tomoyo_path_acl - Check permission for single path operation. 763 * tomoyo_path_permission - Check permission for single path operation.
956 *
957 * @domain: Pointer to "struct tomoyo_domain_info".
958 * @type: Type of operation.
959 * @filename: Filename to check.
960 *
961 * Returns 0 on success, negative value otherwise.
962 *
963 * Caller holds tomoyo_read_lock().
964 */
965static int tomoyo_path_acl(struct tomoyo_domain_info *domain, const u8 type,
966 const struct tomoyo_path_info *filename)
967{
968 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
969 return 0;
970 return tomoyo_path_acl2(domain, filename, 1 << type, 1);
971}
972
973/**
974 * tomoyo_path2_acl - Check permission for double path operation.
975 * 764 *
976 * @domain: Pointer to "struct tomoyo_domain_info". 765 * @r: Pointer to "struct tomoyo_request_info".
977 * @type: Type of operation.
978 * @filename1: First filename to check.
979 * @filename2: Second filename to check.
980 *
981 * Returns 0 on success, -EPERM otherwise.
982 *
983 * Caller holds tomoyo_read_lock().
984 */
985static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain,
986 const u8 type,
987 const struct tomoyo_path_info *filename1,
988 const struct tomoyo_path_info *filename2)
989{
990 struct tomoyo_acl_info *ptr;
991 const u8 perm = 1 << type;
992 int error = -EPERM;
993
994 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
995 return 0;
996 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
997 struct tomoyo_path2_acl *acl;
998 if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
999 continue;
1000 acl = container_of(ptr, struct tomoyo_path2_acl, head);
1001 if (!(acl->perm & perm))
1002 continue;
1003 if (!tomoyo_compare_name_union(filename1, &acl->name1))
1004 continue;
1005 if (!tomoyo_compare_name_union(filename2, &acl->name2))
1006 continue;
1007 error = 0;
1008 break;
1009 }
1010 return error;
1011}
1012
1013/**
1014 * tomoyo_path_permission2 - Check permission for single path operation.
1015 *
1016 * @domain: Pointer to "struct tomoyo_domain_info".
1017 * @operation: Type of operation. 766 * @operation: Type of operation.
1018 * @filename: Filename to check. 767 * @filename: Filename to check.
1019 * @mode: Access control mode.
1020 * 768 *
1021 * Returns 0 on success, negative value otherwise. 769 * Returns 0 on success, negative value otherwise.
1022 * 770 *
1023 * Caller holds tomoyo_read_lock(). 771 * Caller holds tomoyo_read_lock().
1024 */ 772 */
1025static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain, 773int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
1026 u8 operation, 774 const struct tomoyo_path_info *filename)
1027 const struct tomoyo_path_info *filename,
1028 const u8 mode)
1029{ 775{
1030 const char *msg;
1031 int error; 776 int error;
1032 const bool is_enforce = (mode == 3);
1033 777
1034 if (!mode)
1035 return 0;
1036 next: 778 next:
1037 error = tomoyo_path_acl(domain, operation, filename); 779 r->type = tomoyo_p2mac[operation];
1038 msg = tomoyo_path2keyword(operation); 780 r->mode = tomoyo_get_mode(r->profile, r->type);
1039 if (!error) 781 if (r->mode == TOMOYO_CONFIG_DISABLED)
1040 goto ok; 782 return 0;
1041 if (tomoyo_verbose_mode(domain)) 783 r->param_type = TOMOYO_TYPE_PATH_ACL;
1042 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n", 784 r->param.path.filename = filename;
1043 tomoyo_get_msg(is_enforce), msg, filename->name, 785 r->param.path.operation = operation;
1044 tomoyo_get_last_name(domain)); 786 do {
1045 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { 787 tomoyo_check_acl(r, tomoyo_check_path_acl);
1046 const char *name = tomoyo_get_file_pattern(filename)->name; 788 if (!r->granted && operation == TOMOYO_TYPE_READ &&
1047 tomoyo_update_path_acl(operation, name, domain, false); 789 !r->domain->ignore_global_allow_read &&
1048 } 790 tomoyo_globally_readable_file(filename))
1049 if (!is_enforce) 791 r->granted = true;
1050 error = 0; 792 error = tomoyo_audit_path_log(r);
1051 ok: 793 /*
794 * Do not retry for execute request, for alias may have
795 * changed.
796 */
797 } while (error == TOMOYO_RETRY_REQUEST &&
798 operation != TOMOYO_TYPE_EXECUTE);
1052 /* 799 /*
1053 * Since "allow_truncate" doesn't imply "allow_rewrite" permission, 800 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
1054 * we need to check "allow_rewrite" permission if the filename is 801 * we need to check "allow_rewrite" permission if the filename is
1055 * specified by "deny_rewrite" keyword. 802 * specified by "deny_rewrite" keyword.
1056 */ 803 */
1057 if (!error && operation == TOMOYO_TYPE_TRUNCATE && 804 if (!error && operation == TOMOYO_TYPE_TRUNCATE &&
1058 tomoyo_is_no_rewrite_file(filename)) { 805 tomoyo_no_rewrite_file(filename)) {
1059 operation = TOMOYO_TYPE_REWRITE; 806 operation = TOMOYO_TYPE_REWRITE;
1060 goto next; 807 goto next;
1061 } 808 }
1062 return error; 809 return error;
1063} 810}
1064 811
812static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
813 const struct tomoyo_acl_info *b)
814{
815 const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
816 head);
817 const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
818 head);
819 return tomoyo_same_acl_head(&p1->head, &p2->head)
820 && tomoyo_same_name_union(&p1->name, &p2->name)
821 && tomoyo_same_number_union(&p1->number, &p2->number);
822}
823
824static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
825 struct tomoyo_acl_info *b,
826 const bool is_delete)
827{
828 u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
829 head)->perm;
830 u8 perm = *a_perm;
831 const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
832 ->perm;
833 if (is_delete)
834 perm &= ~b_perm;
835 else
836 perm |= b_perm;
837 *a_perm = perm;
838 return !perm;
839}
840
1065/** 841/**
1066 * tomoyo_check_exec_perm - Check permission for "execute". 842 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
843 *
844 * @type: Type of operation.
845 * @filename: Filename.
846 * @number: Number.
847 * @domain: Pointer to "struct tomoyo_domain_info".
848 * @is_delete: True if it is a delete request.
1067 * 849 *
1068 * @domain: Pointer to "struct tomoyo_domain_info". 850 * Returns 0 on success, negative value otherwise.
1069 * @filename: Check permission for "execute". 851 */
852static int tomoyo_update_path_number_acl(const u8 type, const char *filename,
853 char *number,
854 struct tomoyo_domain_info * const
855 domain,
856 const bool is_delete)
857{
858 struct tomoyo_path_number_acl e = {
859 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
860 .perm = 1 << type
861 };
862 int error = is_delete ? -ENOENT : -ENOMEM;
863 if (!tomoyo_parse_name_union(filename, &e.name))
864 return -EINVAL;
865 if (!tomoyo_parse_number_union(number, &e.number))
866 goto out;
867 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
868 tomoyo_same_path_number_acl,
869 tomoyo_merge_path_number_acl);
870 out:
871 tomoyo_put_name_union(&e.name);
872 tomoyo_put_number_union(&e.number);
873 return error;
874}
875
876/**
877 * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
1070 * 878 *
1071 * Returns 0 on success, negativevalue otherwise. 879 * @type: Type of operation.
880 * @path: Pointer to "struct path".
881 * @number: Number.
1072 * 882 *
1073 * Caller holds tomoyo_read_lock(). 883 * Returns 0 on success, negative value otherwise.
1074 */ 884 */
1075int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, 885int tomoyo_path_number_perm(const u8 type, struct path *path,
1076 const struct tomoyo_path_info *filename) 886 unsigned long number)
1077{ 887{
1078 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 888 struct tomoyo_request_info r;
889 int error = -ENOMEM;
890 struct tomoyo_path_info buf;
891 int idx;
1079 892
1080 if (!mode) 893 if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
894 == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry)
1081 return 0; 895 return 0;
1082 return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode); 896 idx = tomoyo_read_lock();
897 if (!tomoyo_get_realpath(&buf, path))
898 goto out;
899 if (type == TOMOYO_TYPE_MKDIR)
900 tomoyo_add_slash(&buf);
901 r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
902 r.param.path_number.operation = type;
903 r.param.path_number.filename = &buf;
904 r.param.path_number.number = number;
905 do {
906 tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
907 error = tomoyo_audit_path_number_log(&r);
908 } while (error == TOMOYO_RETRY_REQUEST);
909 kfree(buf.name);
910 out:
911 tomoyo_read_unlock(idx);
912 if (r.mode != TOMOYO_CONFIG_ENFORCING)
913 error = 0;
914 return error;
1083} 915}
1084 916
1085/** 917/**
@@ -1096,24 +928,17 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1096{ 928{
1097 const u8 acc_mode = ACC_MODE(flag); 929 const u8 acc_mode = ACC_MODE(flag);
1098 int error = -ENOMEM; 930 int error = -ENOMEM;
1099 struct tomoyo_path_info *buf; 931 struct tomoyo_path_info buf;
1100 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 932 struct tomoyo_request_info r;
1101 const bool is_enforce = (mode == 3);
1102 int idx; 933 int idx;
1103 934
1104 if (!mode || !path->mnt) 935 if (!path->mnt ||
1105 return 0; 936 (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)))
1106 if (acc_mode == 0)
1107 return 0;
1108 if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
1109 /*
1110 * I don't check directories here because mkdir() and rmdir()
1111 * don't call me.
1112 */
1113 return 0; 937 return 0;
938 buf.name = NULL;
939 r.mode = TOMOYO_CONFIG_DISABLED;
1114 idx = tomoyo_read_lock(); 940 idx = tomoyo_read_lock();
1115 buf = tomoyo_get_path(path); 941 if (!tomoyo_get_realpath(&buf, path))
1116 if (!buf)
1117 goto out; 942 goto out;
1118 error = 0; 943 error = 0;
1119 /* 944 /*
@@ -1121,28 +946,43 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1121 * we need to check "allow_rewrite" permission when the filename is not 946 * we need to check "allow_rewrite" permission when the filename is not
1122 * opened for append mode or the filename is truncated at open time. 947 * opened for append mode or the filename is truncated at open time.
1123 */ 948 */
1124 if ((acc_mode & MAY_WRITE) && 949 if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND)
1125 ((flag & O_TRUNC) || !(flag & O_APPEND)) && 950 && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE)
1126 (tomoyo_is_no_rewrite_file(buf))) { 951 != TOMOYO_CONFIG_DISABLED) {
1127 error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, 952 if (!tomoyo_get_realpath(&buf, path)) {
1128 buf, mode); 953 error = -ENOMEM;
954 goto out;
955 }
956 if (tomoyo_no_rewrite_file(&buf))
957 error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE,
958 &buf);
959 }
960 if (!error && acc_mode &&
961 tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
962 != TOMOYO_CONFIG_DISABLED) {
963 u8 operation;
964 if (!buf.name && !tomoyo_get_realpath(&buf, path)) {
965 error = -ENOMEM;
966 goto out;
967 }
968 if (acc_mode == (MAY_READ | MAY_WRITE))
969 operation = TOMOYO_TYPE_READ_WRITE;
970 else if (acc_mode == MAY_READ)
971 operation = TOMOYO_TYPE_READ;
972 else
973 operation = TOMOYO_TYPE_WRITE;
974 error = tomoyo_path_permission(&r, operation, &buf);
1129 } 975 }
1130 if (!error)
1131 error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
1132 mode);
1133 if (!error && (flag & O_TRUNC))
1134 error = tomoyo_path_permission2(domain, TOMOYO_TYPE_TRUNCATE,
1135 buf, mode);
1136 out: 976 out:
1137 kfree(buf); 977 kfree(buf.name);
1138 tomoyo_read_unlock(idx); 978 tomoyo_read_unlock(idx);
1139 if (!is_enforce) 979 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1140 error = 0; 980 error = 0;
1141 return error; 981 return error;
1142} 982}
1143 983
1144/** 984/**
1145 * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount". 985 * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount".
1146 * 986 *
1147 * @operation: Type of operation. 987 * @operation: Type of operation.
1148 * @path: Pointer to "struct path". 988 * @path: Pointer to "struct path".
@@ -1152,71 +992,79 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1152int tomoyo_path_perm(const u8 operation, struct path *path) 992int tomoyo_path_perm(const u8 operation, struct path *path)
1153{ 993{
1154 int error = -ENOMEM; 994 int error = -ENOMEM;
1155 struct tomoyo_path_info *buf; 995 struct tomoyo_path_info buf;
1156 struct tomoyo_domain_info *domain = tomoyo_domain(); 996 struct tomoyo_request_info r;
1157 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1158 const bool is_enforce = (mode == 3);
1159 int idx; 997 int idx;
1160 998
1161 if (!mode || !path->mnt) 999 if (!path->mnt)
1162 return 0; 1000 return 0;
1001 if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
1002 == TOMOYO_CONFIG_DISABLED)
1003 return 0;
1004 buf.name = NULL;
1163 idx = tomoyo_read_lock(); 1005 idx = tomoyo_read_lock();
1164 buf = tomoyo_get_path(path); 1006 if (!tomoyo_get_realpath(&buf, path))
1165 if (!buf)
1166 goto out; 1007 goto out;
1167 switch (operation) { 1008 switch (operation) {
1168 case TOMOYO_TYPE_MKDIR: 1009 case TOMOYO_TYPE_REWRITE:
1010 if (!tomoyo_no_rewrite_file(&buf)) {
1011 error = 0;
1012 goto out;
1013 }
1014 break;
1169 case TOMOYO_TYPE_RMDIR: 1015 case TOMOYO_TYPE_RMDIR:
1170 case TOMOYO_TYPE_CHROOT: 1016 case TOMOYO_TYPE_CHROOT:
1171 if (!buf->is_dir) { 1017 case TOMOYO_TYPE_UMOUNT:
1172 /* 1018 tomoyo_add_slash(&buf);
1173 * tomoyo_get_path() reserves space for appending "/." 1019 break;
1174 */
1175 strcat((char *) buf->name, "/");
1176 tomoyo_fill_path_info(buf);
1177 }
1178 } 1020 }
1179 error = tomoyo_path_permission2(domain, operation, buf, mode); 1021 error = tomoyo_path_permission(&r, operation, &buf);
1180 out: 1022 out:
1181 kfree(buf); 1023 kfree(buf.name);
1182 tomoyo_read_unlock(idx); 1024 tomoyo_read_unlock(idx);
1183 if (!is_enforce) 1025 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1184 error = 0; 1026 error = 0;
1185 return error; 1027 return error;
1186} 1028}
1187 1029
1188/** 1030/**
1189 * tomoyo_check_rewrite_permission - Check permission for "rewrite". 1031 * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
1190 * 1032 *
1191 * @filp: Pointer to "struct file". 1033 * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
1034 * @path: Pointer to "struct path".
1035 * @mode: Create mode.
1036 * @dev: Device number.
1192 * 1037 *
1193 * Returns 0 on success, negative value otherwise. 1038 * Returns 0 on success, negative value otherwise.
1194 */ 1039 */
1195int tomoyo_check_rewrite_permission(struct file *filp) 1040int tomoyo_mkdev_perm(const u8 operation, struct path *path,
1041 const unsigned int mode, unsigned int dev)
1196{ 1042{
1043 struct tomoyo_request_info r;
1197 int error = -ENOMEM; 1044 int error = -ENOMEM;
1198 struct tomoyo_domain_info *domain = tomoyo_domain(); 1045 struct tomoyo_path_info buf;
1199 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1200 const bool is_enforce = (mode == 3);
1201 struct tomoyo_path_info *buf;
1202 int idx; 1046 int idx;
1203 1047
1204 if (!mode || !filp->f_path.mnt) 1048 if (!path->mnt ||
1049 tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
1050 == TOMOYO_CONFIG_DISABLED)
1205 return 0; 1051 return 0;
1206
1207 idx = tomoyo_read_lock(); 1052 idx = tomoyo_read_lock();
1208 buf = tomoyo_get_path(&filp->f_path); 1053 error = -ENOMEM;
1209 if (!buf) 1054 if (tomoyo_get_realpath(&buf, path)) {
1210 goto out; 1055 dev = new_decode_dev(dev);
1211 if (!tomoyo_is_no_rewrite_file(buf)) { 1056 r.param_type = TOMOYO_TYPE_MKDEV_ACL;
1212 error = 0; 1057 r.param.mkdev.filename = &buf;
1213 goto out; 1058 r.param.mkdev.operation = operation;
1059 r.param.mkdev.mode = mode;
1060 r.param.mkdev.major = MAJOR(dev);
1061 r.param.mkdev.minor = MINOR(dev);
1062 tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
1063 error = tomoyo_audit_mkdev_log(&r);
1064 kfree(buf.name);
1214 } 1065 }
1215 error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, buf, mode);
1216 out:
1217 kfree(buf);
1218 tomoyo_read_unlock(idx); 1066 tomoyo_read_unlock(idx);
1219 if (!is_enforce) 1067 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1220 error = 0; 1068 error = 0;
1221 return error; 1069 return error;
1222} 1070}
@@ -1234,56 +1082,99 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
1234 struct path *path2) 1082 struct path *path2)
1235{ 1083{
1236 int error = -ENOMEM; 1084 int error = -ENOMEM;
1237 struct tomoyo_path_info *buf1, *buf2; 1085 struct tomoyo_path_info buf1;
1238 struct tomoyo_domain_info *domain = tomoyo_domain(); 1086 struct tomoyo_path_info buf2;
1239 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 1087 struct tomoyo_request_info r;
1240 const bool is_enforce = (mode == 3);
1241 const char *msg;
1242 int idx; 1088 int idx;
1243 1089
1244 if (!mode || !path1->mnt || !path2->mnt) 1090 if (!path1->mnt || !path2->mnt ||
1091 tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
1092 == TOMOYO_CONFIG_DISABLED)
1245 return 0; 1093 return 0;
1094 buf1.name = NULL;
1095 buf2.name = NULL;
1246 idx = tomoyo_read_lock(); 1096 idx = tomoyo_read_lock();
1247 buf1 = tomoyo_get_path(path1); 1097 if (!tomoyo_get_realpath(&buf1, path1) ||
1248 buf2 = tomoyo_get_path(path2); 1098 !tomoyo_get_realpath(&buf2, path2))
1249 if (!buf1 || !buf2)
1250 goto out;
1251 {
1252 struct dentry *dentry = path1->dentry;
1253 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
1254 /*
1255 * tomoyo_get_path() reserves space for appending "/."
1256 */
1257 if (!buf1->is_dir) {
1258 strcat((char *) buf1->name, "/");
1259 tomoyo_fill_path_info(buf1);
1260 }
1261 if (!buf2->is_dir) {
1262 strcat((char *) buf2->name, "/");
1263 tomoyo_fill_path_info(buf2);
1264 }
1265 }
1266 }
1267 error = tomoyo_path2_acl(domain, operation, buf1, buf2);
1268 msg = tomoyo_path22keyword(operation);
1269 if (!error)
1270 goto out; 1099 goto out;
1271 if (tomoyo_verbose_mode(domain)) 1100 switch (operation) {
1272 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' " 1101 struct dentry *dentry;
1273 "denied for %s\n", tomoyo_get_msg(is_enforce), 1102 case TOMOYO_TYPE_RENAME:
1274 msg, buf1->name, buf2->name, 1103 case TOMOYO_TYPE_LINK:
1275 tomoyo_get_last_name(domain)); 1104 dentry = path1->dentry;
1276 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { 1105 if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
1277 const char *name1 = tomoyo_get_file_pattern(buf1)->name; 1106 break;
1278 const char *name2 = tomoyo_get_file_pattern(buf2)->name; 1107 /* fall through */
1279 tomoyo_update_path2_acl(operation, name1, name2, domain, 1108 case TOMOYO_TYPE_PIVOT_ROOT:
1280 false); 1109 tomoyo_add_slash(&buf1);
1281 } 1110 tomoyo_add_slash(&buf2);
1111 break;
1112 }
1113 r.param_type = TOMOYO_TYPE_PATH2_ACL;
1114 r.param.path2.operation = operation;
1115 r.param.path2.filename1 = &buf1;
1116 r.param.path2.filename2 = &buf2;
1117 do {
1118 tomoyo_check_acl(&r, tomoyo_check_path2_acl);
1119 error = tomoyo_audit_path2_log(&r);
1120 } while (error == TOMOYO_RETRY_REQUEST);
1282 out: 1121 out:
1283 kfree(buf1); 1122 kfree(buf1.name);
1284 kfree(buf2); 1123 kfree(buf2.name);
1285 tomoyo_read_unlock(idx); 1124 tomoyo_read_unlock(idx);
1286 if (!is_enforce) 1125 if (r.mode != TOMOYO_CONFIG_ENFORCING)
1287 error = 0; 1126 error = 0;
1288 return error; 1127 return error;
1289} 1128}
1129
1130/**
1131 * tomoyo_write_file - Update file related list.
1132 *
1133 * @data: String to parse.
1134 * @domain: Pointer to "struct tomoyo_domain_info".
1135 * @is_delete: True if it is a delete request.
1136 *
1137 * Returns 0 on success, negative value otherwise.
1138 *
1139 * Caller holds tomoyo_read_lock().
1140 */
1141int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain,
1142 const bool is_delete)
1143{
1144 char *w[5];
1145 u8 type;
1146 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
1147 return -EINVAL;
1148 if (strncmp(w[0], "allow_", 6))
1149 goto out;
1150 w[0] += 6;
1151 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
1152 if (strcmp(w[0], tomoyo_path_keyword[type]))
1153 continue;
1154 return tomoyo_update_path_acl(type, w[1], domain, is_delete);
1155 }
1156 if (!w[2][0])
1157 goto out;
1158 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) {
1159 if (strcmp(w[0], tomoyo_path2_keyword[type]))
1160 continue;
1161 return tomoyo_update_path2_acl(type, w[1], w[2], domain,
1162 is_delete);
1163 }
1164 for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) {
1165 if (strcmp(w[0], tomoyo_path_number_keyword[type]))
1166 continue;
1167 return tomoyo_update_path_number_acl(type, w[1], w[2], domain,
1168 is_delete);
1169 }
1170 if (!w[3][0] || !w[4][0])
1171 goto out;
1172 for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) {
1173 if (strcmp(w[0], tomoyo_mkdev_keyword[type]))
1174 continue;
1175 return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3],
1176 w[4], domain, is_delete);
1177 }
1178 out:
1179 return -EINVAL;
1180}
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
index b9cc71b0431..a877e4c3b10 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -11,83 +11,75 @@
11#include <linux/kthread.h> 11#include <linux/kthread.h>
12#include <linux/slab.h> 12#include <linux/slab.h>
13 13
14enum tomoyo_gc_id { 14struct tomoyo_gc {
15 TOMOYO_ID_PATH_GROUP,
16 TOMOYO_ID_PATH_GROUP_MEMBER,
17 TOMOYO_ID_DOMAIN_INITIALIZER,
18 TOMOYO_ID_DOMAIN_KEEPER,
19 TOMOYO_ID_ALIAS,
20 TOMOYO_ID_GLOBALLY_READABLE,
21 TOMOYO_ID_PATTERN,
22 TOMOYO_ID_NO_REWRITE,
23 TOMOYO_ID_MANAGER,
24 TOMOYO_ID_NAME,
25 TOMOYO_ID_ACL,
26 TOMOYO_ID_DOMAIN
27};
28
29struct tomoyo_gc_entry {
30 struct list_head list; 15 struct list_head list;
31 int type; 16 int type;
32 void *element; 17 struct list_head *element;
33}; 18};
34static LIST_HEAD(tomoyo_gc_queue); 19static LIST_HEAD(tomoyo_gc_queue);
35static DEFINE_MUTEX(tomoyo_gc_mutex); 20static DEFINE_MUTEX(tomoyo_gc_mutex);
36 21
37/* Caller holds tomoyo_policy_lock mutex. */ 22/* Caller holds tomoyo_policy_lock mutex. */
38static bool tomoyo_add_to_gc(const int type, void *element) 23static bool tomoyo_add_to_gc(const int type, struct list_head *element)
39{ 24{
40 struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 25 struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
41 if (!entry) 26 if (!entry)
42 return false; 27 return false;
43 entry->type = type; 28 entry->type = type;
44 entry->element = element; 29 entry->element = element;
45 list_add(&entry->list, &tomoyo_gc_queue); 30 list_add(&entry->list, &tomoyo_gc_queue);
31 list_del_rcu(element);
46 return true; 32 return true;
47} 33}
48 34
49static void tomoyo_del_allow_read 35static void tomoyo_del_allow_read(struct list_head *element)
50(struct tomoyo_globally_readable_file_entry *ptr)
51{ 36{
37 struct tomoyo_readable_file *ptr =
38 container_of(element, typeof(*ptr), head.list);
52 tomoyo_put_name(ptr->filename); 39 tomoyo_put_name(ptr->filename);
53} 40}
54 41
55static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr) 42static void tomoyo_del_file_pattern(struct list_head *element)
56{ 43{
44 struct tomoyo_no_pattern *ptr =
45 container_of(element, typeof(*ptr), head.list);
57 tomoyo_put_name(ptr->pattern); 46 tomoyo_put_name(ptr->pattern);
58} 47}
59 48
60static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr) 49static void tomoyo_del_no_rewrite(struct list_head *element)
61{ 50{
51 struct tomoyo_no_rewrite *ptr =
52 container_of(element, typeof(*ptr), head.list);
62 tomoyo_put_name(ptr->pattern); 53 tomoyo_put_name(ptr->pattern);
63} 54}
64 55
65static void tomoyo_del_domain_initializer 56static void tomoyo_del_transition_control(struct list_head *element)
66(struct tomoyo_domain_initializer_entry *ptr)
67{ 57{
58 struct tomoyo_transition_control *ptr =
59 container_of(element, typeof(*ptr), head.list);
68 tomoyo_put_name(ptr->domainname); 60 tomoyo_put_name(ptr->domainname);
69 tomoyo_put_name(ptr->program); 61 tomoyo_put_name(ptr->program);
70} 62}
71 63
72static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr) 64static void tomoyo_del_aggregator(struct list_head *element)
73{
74 tomoyo_put_name(ptr->domainname);
75 tomoyo_put_name(ptr->program);
76}
77
78static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr)
79{ 65{
66 struct tomoyo_aggregator *ptr =
67 container_of(element, typeof(*ptr), head.list);
80 tomoyo_put_name(ptr->original_name); 68 tomoyo_put_name(ptr->original_name);
81 tomoyo_put_name(ptr->aliased_name); 69 tomoyo_put_name(ptr->aggregated_name);
82} 70}
83 71
84static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr) 72static void tomoyo_del_manager(struct list_head *element)
85{ 73{
74 struct tomoyo_manager *ptr =
75 container_of(element, typeof(*ptr), head.list);
86 tomoyo_put_name(ptr->manager); 76 tomoyo_put_name(ptr->manager);
87} 77}
88 78
89static void tomoyo_del_acl(struct tomoyo_acl_info *acl) 79static void tomoyo_del_acl(struct list_head *element)
90{ 80{
81 struct tomoyo_acl_info *acl =
82 container_of(element, typeof(*acl), list);
91 switch (acl->type) { 83 switch (acl->type) {
92 case TOMOYO_TYPE_PATH_ACL: 84 case TOMOYO_TYPE_PATH_ACL:
93 { 85 {
@@ -104,14 +96,41 @@ static void tomoyo_del_acl(struct tomoyo_acl_info *acl)
104 tomoyo_put_name_union(&entry->name2); 96 tomoyo_put_name_union(&entry->name2);
105 } 97 }
106 break; 98 break;
107 default: 99 case TOMOYO_TYPE_PATH_NUMBER_ACL:
108 printk(KERN_WARNING "Unknown type\n"); 100 {
101 struct tomoyo_path_number_acl *entry
102 = container_of(acl, typeof(*entry), head);
103 tomoyo_put_name_union(&entry->name);
104 tomoyo_put_number_union(&entry->number);
105 }
106 break;
107 case TOMOYO_TYPE_MKDEV_ACL:
108 {
109 struct tomoyo_mkdev_acl *entry
110 = container_of(acl, typeof(*entry), head);
111 tomoyo_put_name_union(&entry->name);
112 tomoyo_put_number_union(&entry->mode);
113 tomoyo_put_number_union(&entry->major);
114 tomoyo_put_number_union(&entry->minor);
115 }
116 break;
117 case TOMOYO_TYPE_MOUNT_ACL:
118 {
119 struct tomoyo_mount_acl *entry
120 = container_of(acl, typeof(*entry), head);
121 tomoyo_put_name_union(&entry->dev_name);
122 tomoyo_put_name_union(&entry->dir_name);
123 tomoyo_put_name_union(&entry->fs_type);
124 tomoyo_put_number_union(&entry->flags);
125 }
109 break; 126 break;
110 } 127 }
111} 128}
112 129
113static bool tomoyo_del_domain(struct tomoyo_domain_info *domain) 130static bool tomoyo_del_domain(struct list_head *element)
114{ 131{
132 struct tomoyo_domain_info *domain =
133 container_of(element, typeof(*domain), list);
115 struct tomoyo_acl_info *acl; 134 struct tomoyo_acl_info *acl;
116 struct tomoyo_acl_info *tmp; 135 struct tomoyo_acl_info *tmp;
117 /* 136 /*
@@ -139,7 +158,7 @@ static bool tomoyo_del_domain(struct tomoyo_domain_info *domain)
139 if (atomic_read(&domain->users)) 158 if (atomic_read(&domain->users))
140 return false; 159 return false;
141 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { 160 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
142 tomoyo_del_acl(acl); 161 tomoyo_del_acl(&acl->list);
143 tomoyo_memory_free(acl); 162 tomoyo_memory_free(acl);
144 } 163 }
145 tomoyo_put_name(domain->domainname); 164 tomoyo_put_name(domain->domainname);
@@ -147,135 +166,70 @@ static bool tomoyo_del_domain(struct tomoyo_domain_info *domain)
147} 166}
148 167
149 168
150static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) 169static void tomoyo_del_name(struct list_head *element)
151{ 170{
171 const struct tomoyo_name *ptr =
172 container_of(element, typeof(*ptr), list);
152} 173}
153 174
154static void tomoyo_del_path_group_member(struct tomoyo_path_group_member 175static void tomoyo_del_path_group(struct list_head *element)
155 *member)
156{ 176{
177 struct tomoyo_path_group *member =
178 container_of(element, typeof(*member), head.list);
157 tomoyo_put_name(member->member_name); 179 tomoyo_put_name(member->member_name);
158} 180}
159 181
160static void tomoyo_del_path_group(struct tomoyo_path_group *group) 182static void tomoyo_del_group(struct list_head *element)
161{ 183{
184 struct tomoyo_group *group =
185 container_of(element, typeof(*group), list);
162 tomoyo_put_name(group->group_name); 186 tomoyo_put_name(group->group_name);
163} 187}
164 188
189static void tomoyo_del_number_group(struct list_head *element)
190{
191 struct tomoyo_number_group *member =
192 container_of(element, typeof(*member), head.list);
193}
194
195static bool tomoyo_collect_member(struct list_head *member_list, int id)
196{
197 struct tomoyo_acl_head *member;
198 list_for_each_entry(member, member_list, list) {
199 if (!member->is_deleted)
200 continue;
201 if (!tomoyo_add_to_gc(id, &member->list))
202 return false;
203 }
204 return true;
205}
206
207static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain)
208{
209 struct tomoyo_acl_info *acl;
210 list_for_each_entry(acl, &domain->acl_info_list, list) {
211 if (!acl->is_deleted)
212 continue;
213 if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list))
214 return false;
215 }
216 return true;
217}
218
165static void tomoyo_collect_entry(void) 219static void tomoyo_collect_entry(void)
166{ 220{
221 int i;
167 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 222 if (mutex_lock_interruptible(&tomoyo_policy_lock))
168 return; 223 return;
169 { 224 for (i = 0; i < TOMOYO_MAX_POLICY; i++) {
170 struct tomoyo_globally_readable_file_entry *ptr; 225 if (!tomoyo_collect_member(&tomoyo_policy_list[i], i))
171 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, 226 goto unlock;
172 list) {
173 if (!ptr->is_deleted)
174 continue;
175 if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr))
176 list_del_rcu(&ptr->list);
177 else
178 break;
179 }
180 }
181 {
182 struct tomoyo_pattern_entry *ptr;
183 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
184 if (!ptr->is_deleted)
185 continue;
186 if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr))
187 list_del_rcu(&ptr->list);
188 else
189 break;
190 }
191 }
192 {
193 struct tomoyo_no_rewrite_entry *ptr;
194 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
195 if (!ptr->is_deleted)
196 continue;
197 if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr))
198 list_del_rcu(&ptr->list);
199 else
200 break;
201 }
202 }
203 {
204 struct tomoyo_domain_initializer_entry *ptr;
205 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list,
206 list) {
207 if (!ptr->is_deleted)
208 continue;
209 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr))
210 list_del_rcu(&ptr->list);
211 else
212 break;
213 }
214 }
215 {
216 struct tomoyo_domain_keeper_entry *ptr;
217 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
218 if (!ptr->is_deleted)
219 continue;
220 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr))
221 list_del_rcu(&ptr->list);
222 else
223 break;
224 }
225 }
226 {
227 struct tomoyo_alias_entry *ptr;
228 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
229 if (!ptr->is_deleted)
230 continue;
231 if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr))
232 list_del_rcu(&ptr->list);
233 else
234 break;
235 }
236 }
237 {
238 struct tomoyo_policy_manager_entry *ptr;
239 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list,
240 list) {
241 if (!ptr->is_deleted)
242 continue;
243 if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr))
244 list_del_rcu(&ptr->list);
245 else
246 break;
247 }
248 } 227 }
249 { 228 {
250 struct tomoyo_domain_info *domain; 229 struct tomoyo_domain_info *domain;
251 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 230 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
252 struct tomoyo_acl_info *acl; 231 if (!tomoyo_collect_acl(domain))
253 list_for_each_entry_rcu(acl, &domain->acl_info_list, 232 goto unlock;
254 list) {
255 switch (acl->type) {
256 case TOMOYO_TYPE_PATH_ACL:
257 if (container_of(acl,
258 struct tomoyo_path_acl,
259 head)->perm ||
260 container_of(acl,
261 struct tomoyo_path_acl,
262 head)->perm_high)
263 continue;
264 break;
265 case TOMOYO_TYPE_PATH2_ACL:
266 if (container_of(acl,
267 struct tomoyo_path2_acl,
268 head)->perm)
269 continue;
270 break;
271 default:
272 continue;
273 }
274 if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl))
275 list_del_rcu(&acl->list);
276 else
277 break;
278 }
279 if (!domain->is_deleted || atomic_read(&domain->users)) 233 if (!domain->is_deleted || atomic_read(&domain->users))
280 continue; 234 continue;
281 /* 235 /*
@@ -283,104 +237,92 @@ static void tomoyo_collect_entry(void)
283 * refer this domain after successful execve(). 237 * refer this domain after successful execve().
284 * We recheck domain->users after SRCU synchronization. 238 * We recheck domain->users after SRCU synchronization.
285 */ 239 */
286 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain)) 240 if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list))
287 list_del_rcu(&domain->list); 241 goto unlock;
288 else
289 break;
290 } 242 }
291 } 243 }
292 { 244 for (i = 0; i < TOMOYO_MAX_HASH; i++) {
293 int i; 245 struct tomoyo_name *ptr;
294 for (i = 0; i < TOMOYO_MAX_HASH; i++) { 246 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], list) {
295 struct tomoyo_name_entry *ptr; 247 if (atomic_read(&ptr->users))
296 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], 248 continue;
297 list) { 249 if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list))
298 if (atomic_read(&ptr->users)) 250 goto unlock;
299 continue;
300 if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr))
301 list_del_rcu(&ptr->list);
302 else {
303 i = TOMOYO_MAX_HASH;
304 break;
305 }
306 }
307 } 251 }
308 } 252 }
309 { 253 for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
310 struct tomoyo_path_group *group; 254 struct list_head *list = &tomoyo_group_list[i];
311 list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { 255 int id;
312 struct tomoyo_path_group_member *member; 256 struct tomoyo_group *group;
313 list_for_each_entry_rcu(member, &group->member_list, 257 switch (i) {
314 list) { 258 case 0:
315 if (!member->is_deleted) 259 id = TOMOYO_ID_PATH_GROUP;
316 continue; 260 break;
317 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER, 261 default:
318 member)) 262 id = TOMOYO_ID_NUMBER_GROUP;
319 list_del_rcu(&member->list); 263 break;
320 else 264 }
321 break; 265 list_for_each_entry(group, list, list) {
322 } 266 if (!tomoyo_collect_member(&group->member_list, id))
267 goto unlock;
323 if (!list_empty(&group->member_list) || 268 if (!list_empty(&group->member_list) ||
324 atomic_read(&group->users)) 269 atomic_read(&group->users))
325 continue; 270 continue;
326 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group)) 271 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list))
327 list_del_rcu(&group->list); 272 goto unlock;
328 else
329 break;
330 } 273 }
331 } 274 }
275 unlock:
332 mutex_unlock(&tomoyo_policy_lock); 276 mutex_unlock(&tomoyo_policy_lock);
333} 277}
334 278
335static void tomoyo_kfree_entry(void) 279static void tomoyo_kfree_entry(void)
336{ 280{
337 struct tomoyo_gc_entry *p; 281 struct tomoyo_gc *p;
338 struct tomoyo_gc_entry *tmp; 282 struct tomoyo_gc *tmp;
339 283
340 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { 284 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
285 struct list_head *element = p->element;
341 switch (p->type) { 286 switch (p->type) {
342 case TOMOYO_ID_DOMAIN_INITIALIZER: 287 case TOMOYO_ID_TRANSITION_CONTROL:
343 tomoyo_del_domain_initializer(p->element); 288 tomoyo_del_transition_control(element);
344 break;
345 case TOMOYO_ID_DOMAIN_KEEPER:
346 tomoyo_del_domain_keeper(p->element);
347 break; 289 break;
348 case TOMOYO_ID_ALIAS: 290 case TOMOYO_ID_AGGREGATOR:
349 tomoyo_del_alias(p->element); 291 tomoyo_del_aggregator(element);
350 break; 292 break;
351 case TOMOYO_ID_GLOBALLY_READABLE: 293 case TOMOYO_ID_GLOBALLY_READABLE:
352 tomoyo_del_allow_read(p->element); 294 tomoyo_del_allow_read(element);
353 break; 295 break;
354 case TOMOYO_ID_PATTERN: 296 case TOMOYO_ID_PATTERN:
355 tomoyo_del_file_pattern(p->element); 297 tomoyo_del_file_pattern(element);
356 break; 298 break;
357 case TOMOYO_ID_NO_REWRITE: 299 case TOMOYO_ID_NO_REWRITE:
358 tomoyo_del_no_rewrite(p->element); 300 tomoyo_del_no_rewrite(element);
359 break; 301 break;
360 case TOMOYO_ID_MANAGER: 302 case TOMOYO_ID_MANAGER:
361 tomoyo_del_manager(p->element); 303 tomoyo_del_manager(element);
362 break; 304 break;
363 case TOMOYO_ID_NAME: 305 case TOMOYO_ID_NAME:
364 tomoyo_del_name(p->element); 306 tomoyo_del_name(element);
365 break; 307 break;
366 case TOMOYO_ID_ACL: 308 case TOMOYO_ID_ACL:
367 tomoyo_del_acl(p->element); 309 tomoyo_del_acl(element);
368 break; 310 break;
369 case TOMOYO_ID_DOMAIN: 311 case TOMOYO_ID_DOMAIN:
370 if (!tomoyo_del_domain(p->element)) 312 if (!tomoyo_del_domain(element))
371 continue; 313 continue;
372 break; 314 break;
373 case TOMOYO_ID_PATH_GROUP_MEMBER:
374 tomoyo_del_path_group_member(p->element);
375 break;
376 case TOMOYO_ID_PATH_GROUP: 315 case TOMOYO_ID_PATH_GROUP:
377 tomoyo_del_path_group(p->element); 316 tomoyo_del_path_group(element);
378 break; 317 break;
379 default: 318 case TOMOYO_ID_GROUP:
380 printk(KERN_WARNING "Unknown type\n"); 319 tomoyo_del_group(element);
320 break;
321 case TOMOYO_ID_NUMBER_GROUP:
322 tomoyo_del_number_group(element);
381 break; 323 break;
382 } 324 }
383 tomoyo_memory_free(p->element); 325 tomoyo_memory_free(element);
384 list_del(&p->list); 326 list_del(&p->list);
385 kfree(p); 327 kfree(p);
386 } 328 }
diff --git a/security/tomoyo/group.c b/security/tomoyo/group.c
new file mode 100644
index 00000000000..e94352ce723
--- /dev/null
+++ b/security/tomoyo/group.c
@@ -0,0 +1,130 @@
1/*
2 * security/tomoyo/group.c
3 *
4 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 */
6
7#include <linux/slab.h>
8#include "common.h"
9
10static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
11 const struct tomoyo_acl_head *b)
12{
13 return container_of(a, struct tomoyo_path_group, head)->member_name ==
14 container_of(b, struct tomoyo_path_group, head)->member_name;
15}
16
17static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
18 const struct tomoyo_acl_head *b)
19{
20 return !memcmp(&container_of(a, struct tomoyo_number_group, head)
21 ->number,
22 &container_of(b, struct tomoyo_number_group, head)
23 ->number,
24 sizeof(container_of(a, struct tomoyo_number_group, head)
25 ->number));
26}
27
28/**
29 * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list.
30 *
31 * @data: String to parse.
32 * @is_delete: True if it is a delete request.
33 * @type: Type of this group.
34 *
35 * Returns 0 on success, negative value otherwise.
36 */
37int tomoyo_write_group(char *data, const bool is_delete, const u8 type)
38{
39 struct tomoyo_group *group;
40 struct list_head *member;
41 char *w[2];
42 int error = -EINVAL;
43 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
44 return -EINVAL;
45 group = tomoyo_get_group(w[0], type);
46 if (!group)
47 return -ENOMEM;
48 member = &group->member_list;
49 if (type == TOMOYO_PATH_GROUP) {
50 struct tomoyo_path_group e = { };
51 e.member_name = tomoyo_get_name(w[1]);
52 if (!e.member_name) {
53 error = -ENOMEM;
54 goto out;
55 }
56 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
57 member, tomoyo_same_path_group);
58 tomoyo_put_name(e.member_name);
59 } else if (type == TOMOYO_NUMBER_GROUP) {
60 struct tomoyo_number_group e = { };
61 if (w[1][0] == '@'
62 || !tomoyo_parse_number_union(w[1], &e.number)
63 || e.number.values[0] > e.number.values[1])
64 goto out;
65 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
66 member, tomoyo_same_number_group);
67 /*
68 * tomoyo_put_number_union() is not needed because
69 * w[1][0] != '@'.
70 */
71 }
72 out:
73 tomoyo_put_group(group);
74 return error;
75}
76
77/**
78 * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group.
79 *
80 * @pathname: The name of pathname.
81 * @group: Pointer to "struct tomoyo_path_group".
82 *
83 * Returns matched member's pathname if @pathname matches pathnames in @group,
84 * NULL otherwise.
85 *
86 * Caller holds tomoyo_read_lock().
87 */
88const struct tomoyo_path_info *
89tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
90 const struct tomoyo_group *group)
91{
92 struct tomoyo_path_group *member;
93 list_for_each_entry_rcu(member, &group->member_list, head.list) {
94 if (member->head.is_deleted)
95 continue;
96 if (!tomoyo_path_matches_pattern(pathname, member->member_name))
97 continue;
98 return member->member_name;
99 }
100 return NULL;
101}
102
103/**
104 * tomoyo_number_matches_group - Check whether the given number matches members of the given number group.
105 *
106 * @min: Min number.
107 * @max: Max number.
108 * @group: Pointer to "struct tomoyo_number_group".
109 *
110 * Returns true if @min and @max partially overlaps @group, false otherwise.
111 *
112 * Caller holds tomoyo_read_lock().
113 */
114bool tomoyo_number_matches_group(const unsigned long min,
115 const unsigned long max,
116 const struct tomoyo_group *group)
117{
118 struct tomoyo_number_group *member;
119 bool matched = false;
120 list_for_each_entry_rcu(member, &group->member_list, head.list) {
121 if (member->head.is_deleted)
122 continue;
123 if (min > member->number.values[1] ||
124 max < member->number.values[0])
125 continue;
126 matched = true;
127 break;
128 }
129 return matched;
130}
diff --git a/security/tomoyo/load_policy.c b/security/tomoyo/load_policy.c
new file mode 100644
index 00000000000..bbada7ca1b9
--- /dev/null
+++ b/security/tomoyo/load_policy.c
@@ -0,0 +1,81 @@
1/*
2 * security/tomoyo/load_policy.c
3 *
4 * Policy loader launcher for TOMOYO.
5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 */
8
9#include "common.h"
10
11/* path to policy loader */
12static const char *tomoyo_loader = "/sbin/tomoyo-init";
13
14/**
15 * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists.
16 *
17 * Returns true if /sbin/tomoyo-init exists, false otherwise.
18 */
19static bool tomoyo_policy_loader_exists(void)
20{
21 /*
22 * Don't activate MAC if the policy loader doesn't exist.
23 * If the initrd includes /sbin/init but real-root-dev has not
24 * mounted on / yet, activating MAC will block the system since
25 * policies are not loaded yet.
26 * Thus, let do_execve() call this function everytime.
27 */
28 struct path path;
29
30 if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) {
31 printk(KERN_INFO "Not activating Mandatory Access Control now "
32 "since %s doesn't exist.\n", tomoyo_loader);
33 return false;
34 }
35 path_put(&path);
36 return true;
37}
38
39/**
40 * tomoyo_load_policy - Run external policy loader to load policy.
41 *
42 * @filename: The program about to start.
43 *
44 * This function checks whether @filename is /sbin/init , and if so
45 * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init
46 * and then continues invocation of /sbin/init.
47 * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and
48 * writes to /sys/kernel/security/tomoyo/ interfaces.
49 *
50 * Returns nothing.
51 */
52void tomoyo_load_policy(const char *filename)
53{
54 char *argv[2];
55 char *envp[3];
56
57 if (tomoyo_policy_loaded)
58 return;
59 /*
60 * Check filename is /sbin/init or /sbin/tomoyo-start.
61 * /sbin/tomoyo-start is a dummy filename in case where /sbin/init can't
62 * be passed.
63 * You can create /sbin/tomoyo-start by
64 * "ln -s /bin/true /sbin/tomoyo-start".
65 */
66 if (strcmp(filename, "/sbin/init") &&
67 strcmp(filename, "/sbin/tomoyo-start"))
68 return;
69 if (!tomoyo_policy_loader_exists())
70 return;
71
72 printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
73 tomoyo_loader);
74 argv[0] = (char *) tomoyo_loader;
75 argv[1] = NULL;
76 envp[0] = "HOME=/";
77 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
78 envp[2] = NULL;
79 call_usermodehelper(argv[0], argv, envp, 1);
80 tomoyo_check_profile();
81}
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c
new file mode 100644
index 00000000000..297612669c7
--- /dev/null
+++ b/security/tomoyo/memory.c
@@ -0,0 +1,282 @@
1/*
2 * security/tomoyo/memory.c
3 *
4 * Memory management functions for TOMOYO.
5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 */
8
9#include <linux/hash.h>
10#include <linux/slab.h>
11#include "common.h"
12
13/**
14 * tomoyo_warn_oom - Print out of memory warning message.
15 *
16 * @function: Function's name.
17 */
18void tomoyo_warn_oom(const char *function)
19{
20 /* Reduce error messages. */
21 static pid_t tomoyo_last_pid;
22 const pid_t pid = current->pid;
23 if (tomoyo_last_pid != pid) {
24 printk(KERN_WARNING "ERROR: Out of memory at %s.\n",
25 function);
26 tomoyo_last_pid = pid;
27 }
28 if (!tomoyo_policy_loaded)
29 panic("MAC Initialization failed.\n");
30}
31
32/* Memory allocated for policy. */
33static atomic_t tomoyo_policy_memory_size;
34/* Quota for holding policy. */
35static unsigned int tomoyo_quota_for_policy;
36
37/**
38 * tomoyo_memory_ok - Check memory quota.
39 *
40 * @ptr: Pointer to allocated memory.
41 *
42 * Returns true on success, false otherwise.
43 *
44 * Returns true if @ptr is not NULL and quota not exceeded, false otherwise.
45 */
46bool tomoyo_memory_ok(void *ptr)
47{
48 size_t s = ptr ? ksize(ptr) : 0;
49 atomic_add(s, &tomoyo_policy_memory_size);
50 if (ptr && (!tomoyo_quota_for_policy ||
51 atomic_read(&tomoyo_policy_memory_size)
52 <= tomoyo_quota_for_policy)) {
53 memset(ptr, 0, s);
54 return true;
55 }
56 atomic_sub(s, &tomoyo_policy_memory_size);
57 tomoyo_warn_oom(__func__);
58 return false;
59}
60
61/**
62 * tomoyo_commit_ok - Check memory quota.
63 *
64 * @data: Data to copy from.
65 * @size: Size in byte.
66 *
67 * Returns pointer to allocated memory on success, NULL otherwise.
68 * @data is zero-cleared on success.
69 */
70void *tomoyo_commit_ok(void *data, const unsigned int size)
71{
72 void *ptr = kzalloc(size, GFP_NOFS);
73 if (tomoyo_memory_ok(ptr)) {
74 memmove(ptr, data, size);
75 memset(data, 0, size);
76 return ptr;
77 }
78 return NULL;
79}
80
81/**
82 * tomoyo_memory_free - Free memory for elements.
83 *
84 * @ptr: Pointer to allocated memory.
85 */
86void tomoyo_memory_free(void *ptr)
87{
88 atomic_sub(ksize(ptr), &tomoyo_policy_memory_size);
89 kfree(ptr);
90}
91
92/**
93 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
94 *
95 * @group_name: The name of address group.
96 * @idx: Index number.
97 *
98 * Returns pointer to "struct tomoyo_group" on success, NULL otherwise.
99 */
100struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
101{
102 struct tomoyo_group e = { };
103 struct tomoyo_group *group = NULL;
104 bool found = false;
105 if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)
106 return NULL;
107 e.group_name = tomoyo_get_name(group_name);
108 if (!e.group_name)
109 return NULL;
110 if (mutex_lock_interruptible(&tomoyo_policy_lock))
111 goto out;
112 list_for_each_entry(group, &tomoyo_group_list[idx], list) {
113 if (e.group_name != group->group_name)
114 continue;
115 atomic_inc(&group->users);
116 found = true;
117 break;
118 }
119 if (!found) {
120 struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e));
121 if (entry) {
122 INIT_LIST_HEAD(&entry->member_list);
123 atomic_set(&entry->users, 1);
124 list_add_tail_rcu(&entry->list,
125 &tomoyo_group_list[idx]);
126 group = entry;
127 found = true;
128 }
129 }
130 mutex_unlock(&tomoyo_policy_lock);
131 out:
132 tomoyo_put_name(e.group_name);
133 return found ? group : NULL;
134}
135
136/*
137 * tomoyo_name_list is used for holding string data used by TOMOYO.
138 * Since same string data is likely used for multiple times (e.g.
139 * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
140 * "const struct tomoyo_path_info *".
141 */
142struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
143
144/**
145 * tomoyo_get_name - Allocate permanent memory for string data.
146 *
147 * @name: The string to store into the permernent memory.
148 *
149 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
150 */
151const struct tomoyo_path_info *tomoyo_get_name(const char *name)
152{
153 struct tomoyo_name *ptr;
154 unsigned int hash;
155 int len;
156 int allocated_len;
157 struct list_head *head;
158
159 if (!name)
160 return NULL;
161 len = strlen(name) + 1;
162 hash = full_name_hash((const unsigned char *) name, len - 1);
163 head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
164 if (mutex_lock_interruptible(&tomoyo_policy_lock))
165 return NULL;
166 list_for_each_entry(ptr, head, list) {
167 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
168 continue;
169 atomic_inc(&ptr->users);
170 goto out;
171 }
172 ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
173 allocated_len = ptr ? ksize(ptr) : 0;
174 if (!ptr || (tomoyo_quota_for_policy &&
175 atomic_read(&tomoyo_policy_memory_size) + allocated_len
176 > tomoyo_quota_for_policy)) {
177 kfree(ptr);
178 ptr = NULL;
179 tomoyo_warn_oom(__func__);
180 goto out;
181 }
182 atomic_add(allocated_len, &tomoyo_policy_memory_size);
183 ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
184 memmove((char *) ptr->entry.name, name, len);
185 atomic_set(&ptr->users, 1);
186 tomoyo_fill_path_info(&ptr->entry);
187 list_add_tail(&ptr->list, head);
188 out:
189 mutex_unlock(&tomoyo_policy_lock);
190 return ptr ? &ptr->entry : NULL;
191}
192
193/**
194 * tomoyo_mm_init - Initialize mm related code.
195 */
196void __init tomoyo_mm_init(void)
197{
198 int idx;
199
200 for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++)
201 INIT_LIST_HEAD(&tomoyo_policy_list[idx]);
202 for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++)
203 INIT_LIST_HEAD(&tomoyo_group_list[idx]);
204 for (idx = 0; idx < TOMOYO_MAX_HASH; idx++)
205 INIT_LIST_HEAD(&tomoyo_name_list[idx]);
206 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
207 tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME);
208 list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
209 idx = tomoyo_read_lock();
210 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
211 panic("Can't register tomoyo_kernel_domain");
212 {
213 /* Load built-in policy. */
214 tomoyo_write_transition_control("/sbin/hotplug", false,
215 TOMOYO_TRANSITION_CONTROL_INITIALIZE);
216 tomoyo_write_transition_control("/sbin/modprobe", false,
217 TOMOYO_TRANSITION_CONTROL_INITIALIZE);
218 }
219 tomoyo_read_unlock(idx);
220}
221
222
223/* Memory allocated for query lists. */
224unsigned int tomoyo_query_memory_size;
225/* Quota for holding query lists. */
226unsigned int tomoyo_quota_for_query;
227
228/**
229 * tomoyo_read_memory_counter - Check for memory usage in bytes.
230 *
231 * @head: Pointer to "struct tomoyo_io_buffer".
232 *
233 * Returns memory usage.
234 */
235void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
236{
237 if (!head->r.eof) {
238 const unsigned int policy
239 = atomic_read(&tomoyo_policy_memory_size);
240 const unsigned int query = tomoyo_query_memory_size;
241 char buffer[64];
242
243 memset(buffer, 0, sizeof(buffer));
244 if (tomoyo_quota_for_policy)
245 snprintf(buffer, sizeof(buffer) - 1,
246 " (Quota: %10u)",
247 tomoyo_quota_for_policy);
248 else
249 buffer[0] = '\0';
250 tomoyo_io_printf(head, "Policy: %10u%s\n", policy,
251 buffer);
252 if (tomoyo_quota_for_query)
253 snprintf(buffer, sizeof(buffer) - 1,
254 " (Quota: %10u)",
255 tomoyo_quota_for_query);
256 else
257 buffer[0] = '\0';
258 tomoyo_io_printf(head, "Query lists: %10u%s\n", query,
259 buffer);
260 tomoyo_io_printf(head, "Total: %10u\n", policy + query);
261 head->r.eof = true;
262 }
263}
264
265/**
266 * tomoyo_write_memory_quota - Set memory quota.
267 *
268 * @head: Pointer to "struct tomoyo_io_buffer".
269 *
270 * Returns 0.
271 */
272int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
273{
274 char *data = head->write_buf;
275 unsigned int size;
276
277 if (sscanf(data, "Policy: %u", &size) == 1)
278 tomoyo_quota_for_policy = size;
279 else if (sscanf(data, "Query lists: %u", &size) == 1)
280 tomoyo_quota_for_query = size;
281 return 0;
282}
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
new file mode 100644
index 00000000000..82bf8c2390b
--- /dev/null
+++ b/security/tomoyo/mount.c
@@ -0,0 +1,284 @@
1/*
2 * security/tomoyo/mount.c
3 *
4 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 */
6
7#include <linux/slab.h>
8#include "common.h"
9
10/* Keywords for mount restrictions. */
11
12/* Allow to call 'mount --bind /source_dir /dest_dir' */
13#define TOMOYO_MOUNT_BIND_KEYWORD "--bind"
14/* Allow to call 'mount --move /old_dir /new_dir ' */
15#define TOMOYO_MOUNT_MOVE_KEYWORD "--move"
16/* Allow to call 'mount -o remount /dir ' */
17#define TOMOYO_MOUNT_REMOUNT_KEYWORD "--remount"
18/* Allow to call 'mount --make-unbindable /dir' */
19#define TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD "--make-unbindable"
20/* Allow to call 'mount --make-private /dir' */
21#define TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD "--make-private"
22/* Allow to call 'mount --make-slave /dir' */
23#define TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD "--make-slave"
24/* Allow to call 'mount --make-shared /dir' */
25#define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD "--make-shared"
26
27/**
28 * tomoyo_audit_mount_log - Audit mount log.
29 *
30 * @r: Pointer to "struct tomoyo_request_info".
31 *
32 * Returns 0 on success, negative value otherwise.
33 */
34static int tomoyo_audit_mount_log(struct tomoyo_request_info *r)
35{
36 const char *dev = r->param.mount.dev->name;
37 const char *dir = r->param.mount.dir->name;
38 const char *type = r->param.mount.type->name;
39 const unsigned long flags = r->param.mount.flags;
40 if (r->granted)
41 return 0;
42 if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD))
43 tomoyo_warn_log(r, "mount -o remount %s 0x%lX", dir, flags);
44 else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD)
45 || !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD))
46 tomoyo_warn_log(r, "mount %s %s %s 0x%lX", type, dev, dir,
47 flags);
48 else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) ||
49 !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) ||
50 !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) ||
51 !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD))
52 tomoyo_warn_log(r, "mount %s %s 0x%lX", type, dir, flags);
53 else
54 tomoyo_warn_log(r, "mount -t %s %s %s 0x%lX", type, dev, dir,
55 flags);
56 return tomoyo_supervisor(r,
57 TOMOYO_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",
58 tomoyo_pattern(r->param.mount.dev),
59 tomoyo_pattern(r->param.mount.dir), type,
60 flags);
61}
62
63static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,
64 const struct tomoyo_acl_info *ptr)
65{
66 const struct tomoyo_mount_acl *acl =
67 container_of(ptr, typeof(*acl), head);
68 return tomoyo_compare_number_union(r->param.mount.flags, &acl->flags) &&
69 tomoyo_compare_name_union(r->param.mount.type, &acl->fs_type) &&
70 tomoyo_compare_name_union(r->param.mount.dir, &acl->dir_name) &&
71 (!r->param.mount.need_dev ||
72 tomoyo_compare_name_union(r->param.mount.dev, &acl->dev_name));
73}
74
75/**
76 * tomoyo_mount_acl - Check permission for mount() operation.
77 *
78 * @r: Pointer to "struct tomoyo_request_info".
79 * @dev_name: Name of device file.
80 * @dir: Pointer to "struct path".
81 * @type: Name of filesystem type.
82 * @flags: Mount options.
83 *
84 * Returns 0 on success, negative value otherwise.
85 *
86 * Caller holds tomoyo_read_lock().
87 */
88static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
89 struct path *dir, char *type, unsigned long flags)
90{
91 struct path path;
92 struct file_system_type *fstype = NULL;
93 const char *requested_type = NULL;
94 const char *requested_dir_name = NULL;
95 const char *requested_dev_name = NULL;
96 struct tomoyo_path_info rtype;
97 struct tomoyo_path_info rdev;
98 struct tomoyo_path_info rdir;
99 int need_dev = 0;
100 int error = -ENOMEM;
101
102 /* Get fstype. */
103 requested_type = tomoyo_encode(type);
104 if (!requested_type)
105 goto out;
106 rtype.name = requested_type;
107 tomoyo_fill_path_info(&rtype);
108
109 /* Get mount point. */
110 requested_dir_name = tomoyo_realpath_from_path(dir);
111 if (!requested_dir_name) {
112 error = -ENOMEM;
113 goto out;
114 }
115 rdir.name = requested_dir_name;
116 tomoyo_fill_path_info(&rdir);
117
118 /* Compare fs name. */
119 if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD)) {
120 /* dev_name is ignored. */
121 } else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) ||
122 !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) ||
123 !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) ||
124 !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD)) {
125 /* dev_name is ignored. */
126 } else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD) ||
127 !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD)) {
128 need_dev = -1; /* dev_name is a directory */
129 } else {
130 fstype = get_fs_type(type);
131 if (!fstype) {
132 error = -ENODEV;
133 goto out;
134 }
135 if (fstype->fs_flags & FS_REQUIRES_DEV)
136 /* dev_name is a block device file. */
137 need_dev = 1;
138 }
139 if (need_dev) {
140 /* Get mount point or device file. */
141 if (kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
142 error = -ENOENT;
143 goto out;
144 }
145 requested_dev_name = tomoyo_realpath_from_path(&path);
146 if (!requested_dev_name) {
147 error = -ENOENT;
148 goto out;
149 }
150 } else {
151 /* Map dev_name to "<NULL>" if no dev_name given. */
152 if (!dev_name)
153 dev_name = "<NULL>";
154 requested_dev_name = tomoyo_encode(dev_name);
155 if (!requested_dev_name) {
156 error = -ENOMEM;
157 goto out;
158 }
159 }
160 rdev.name = requested_dev_name;
161 tomoyo_fill_path_info(&rdev);
162 r->param_type = TOMOYO_TYPE_MOUNT_ACL;
163 r->param.mount.need_dev = need_dev;
164 r->param.mount.dev = &rdev;
165 r->param.mount.dir = &rdir;
166 r->param.mount.type = &rtype;
167 r->param.mount.flags = flags;
168 do {
169 tomoyo_check_acl(r, tomoyo_check_mount_acl);
170 error = tomoyo_audit_mount_log(r);
171 } while (error == TOMOYO_RETRY_REQUEST);
172 out:
173 kfree(requested_dev_name);
174 kfree(requested_dir_name);
175 if (fstype)
176 put_filesystem(fstype);
177 kfree(requested_type);
178 return error;
179}
180
181/**
182 * tomoyo_mount_permission - Check permission for mount() operation.
183 *
184 * @dev_name: Name of device file.
185 * @path: Pointer to "struct path".
186 * @type: Name of filesystem type. May be NULL.
187 * @flags: Mount options.
188 * @data_page: Optional data. May be NULL.
189 *
190 * Returns 0 on success, negative value otherwise.
191 */
192int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,
193 unsigned long flags, void *data_page)
194{
195 struct tomoyo_request_info r;
196 int error;
197 int idx;
198
199 if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_MOUNT)
200 == TOMOYO_CONFIG_DISABLED)
201 return 0;
202 if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
203 flags &= ~MS_MGC_MSK;
204 if (flags & MS_REMOUNT) {
205 type = TOMOYO_MOUNT_REMOUNT_KEYWORD;
206 flags &= ~MS_REMOUNT;
207 }
208 if (flags & MS_MOVE) {
209 type = TOMOYO_MOUNT_MOVE_KEYWORD;
210 flags &= ~MS_MOVE;
211 }
212 if (flags & MS_BIND) {
213 type = TOMOYO_MOUNT_BIND_KEYWORD;
214 flags &= ~MS_BIND;
215 }
216 if (flags & MS_UNBINDABLE) {
217 type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD;
218 flags &= ~MS_UNBINDABLE;
219 }
220 if (flags & MS_PRIVATE) {
221 type = TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD;
222 flags &= ~MS_PRIVATE;
223 }
224 if (flags & MS_SLAVE) {
225 type = TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD;
226 flags &= ~MS_SLAVE;
227 }
228 if (flags & MS_SHARED) {
229 type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD;
230 flags &= ~MS_SHARED;
231 }
232 if (!type)
233 type = "<NULL>";
234 idx = tomoyo_read_lock();
235 error = tomoyo_mount_acl(&r, dev_name, path, type, flags);
236 tomoyo_read_unlock(idx);
237 return error;
238}
239
240static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
241 const struct tomoyo_acl_info *b)
242{
243 const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
244 const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
245 return tomoyo_same_acl_head(&p1->head, &p2->head) &&
246 tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
247 tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
248 tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
249 tomoyo_same_number_union(&p1->flags, &p2->flags);
250}
251
252/**
253 * tomoyo_write_mount - Write "struct tomoyo_mount_acl" list.
254 *
255 * @data: String to parse.
256 * @domain: Pointer to "struct tomoyo_domain_info".
257 * @is_delete: True if it is a delete request.
258 *
259 * Returns 0 on success, negative value otherwise.
260 *
261 * Caller holds tomoyo_read_lock().
262 */
263int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain,
264 const bool is_delete)
265{
266 struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
267 int error = is_delete ? -ENOENT : -ENOMEM;
268 char *w[4];
269 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[3][0])
270 return -EINVAL;
271 if (!tomoyo_parse_name_union(w[0], &e.dev_name) ||
272 !tomoyo_parse_name_union(w[1], &e.dir_name) ||
273 !tomoyo_parse_name_union(w[2], &e.fs_type) ||
274 !tomoyo_parse_number_union(w[3], &e.flags))
275 goto out;
276 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
277 tomoyo_same_mount_acl, NULL);
278 out:
279 tomoyo_put_name_union(&e.dev_name);
280 tomoyo_put_name_union(&e.dir_name);
281 tomoyo_put_name_union(&e.fs_type);
282 tomoyo_put_number_union(&e.flags);
283 return error;
284}
diff --git a/security/tomoyo/path_group.c b/security/tomoyo/path_group.c
deleted file mode 100644
index c988041c8e1..00000000000
--- a/security/tomoyo/path_group.c
+++ /dev/null
@@ -1,172 +0,0 @@
1/*
2 * security/tomoyo/path_group.c
3 *
4 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 */
6
7#include <linux/slab.h>
8#include "common.h"
9/* The list for "struct ccs_path_group". */
10LIST_HEAD(tomoyo_path_group_list);
11
12/**
13 * tomoyo_get_path_group - Allocate memory for "struct tomoyo_path_group".
14 *
15 * @group_name: The name of pathname group.
16 *
17 * Returns pointer to "struct tomoyo_path_group" on success, NULL otherwise.
18 */
19struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name)
20{
21 struct tomoyo_path_group *entry = NULL;
22 struct tomoyo_path_group *group = NULL;
23 const struct tomoyo_path_info *saved_group_name;
24 int error = -ENOMEM;
25 if (!tomoyo_is_correct_path(group_name, 0, 0, 0) ||
26 !group_name[0])
27 return NULL;
28 saved_group_name = tomoyo_get_name(group_name);
29 if (!saved_group_name)
30 return NULL;
31 entry = kzalloc(sizeof(*entry), GFP_NOFS);
32 if (mutex_lock_interruptible(&tomoyo_policy_lock))
33 goto out;
34 list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) {
35 if (saved_group_name != group->group_name)
36 continue;
37 atomic_inc(&group->users);
38 error = 0;
39 break;
40 }
41 if (error && tomoyo_memory_ok(entry)) {
42 INIT_LIST_HEAD(&entry->member_list);
43 entry->group_name = saved_group_name;
44 saved_group_name = NULL;
45 atomic_set(&entry->users, 1);
46 list_add_tail_rcu(&entry->list, &tomoyo_path_group_list);
47 group = entry;
48 entry = NULL;
49 error = 0;
50 }
51 mutex_unlock(&tomoyo_policy_lock);
52 out:
53 tomoyo_put_name(saved_group_name);
54 kfree(entry);
55 return !error ? group : NULL;
56}
57
58/**
59 * tomoyo_write_path_group_policy - Write "struct tomoyo_path_group" list.
60 *
61 * @data: String to parse.
62 * @is_delete: True if it is a delete request.
63 *
64 * Returns 0 on success, nagative value otherwise.
65 */
66int tomoyo_write_path_group_policy(char *data, const bool is_delete)
67{
68 struct tomoyo_path_group *group;
69 struct tomoyo_path_group_member *member;
70 struct tomoyo_path_group_member e = { };
71 int error = is_delete ? -ENOENT : -ENOMEM;
72 char *w[2];
73 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
74 return -EINVAL;
75 group = tomoyo_get_path_group(w[0]);
76 if (!group)
77 return -ENOMEM;
78 e.member_name = tomoyo_get_name(w[1]);
79 if (!e.member_name)
80 goto out;
81 if (mutex_lock_interruptible(&tomoyo_policy_lock))
82 goto out;
83 list_for_each_entry_rcu(member, &group->member_list, list) {
84 if (member->member_name != e.member_name)
85 continue;
86 member->is_deleted = is_delete;
87 error = 0;
88 break;
89 }
90 if (!is_delete && error) {
91 struct tomoyo_path_group_member *entry =
92 tomoyo_commit_ok(&e, sizeof(e));
93 if (entry) {
94 list_add_tail_rcu(&entry->list, &group->member_list);
95 error = 0;
96 }
97 }
98 mutex_unlock(&tomoyo_policy_lock);
99 out:
100 tomoyo_put_name(e.member_name);
101 tomoyo_put_path_group(group);
102 return error;
103}
104
105/**
106 * tomoyo_read_path_group_policy - Read "struct tomoyo_path_group" list.
107 *
108 * @head: Pointer to "struct tomoyo_io_buffer".
109 *
110 * Returns true on success, false otherwise.
111 *
112 * Caller holds tomoyo_read_lock().
113 */
114bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head)
115{
116 struct list_head *gpos;
117 struct list_head *mpos;
118 list_for_each_cookie(gpos, head->read_var1, &tomoyo_path_group_list) {
119 struct tomoyo_path_group *group;
120 group = list_entry(gpos, struct tomoyo_path_group, list);
121 list_for_each_cookie(mpos, head->read_var2,
122 &group->member_list) {
123 struct tomoyo_path_group_member *member;
124 member = list_entry(mpos,
125 struct tomoyo_path_group_member,
126 list);
127 if (member->is_deleted)
128 continue;
129 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_PATH_GROUP
130 "%s %s\n",
131 group->group_name->name,
132 member->member_name->name))
133 return false;
134 }
135 }
136 return true;
137}
138
139/**
140 * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group.
141 *
142 * @pathname: The name of pathname.
143 * @group: Pointer to "struct tomoyo_path_group".
144 * @may_use_pattern: True if wild card is permitted.
145 *
146 * Returns true if @pathname matches pathnames in @group, false otherwise.
147 *
148 * Caller holds tomoyo_read_lock().
149 */
150bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
151 const struct tomoyo_path_group *group,
152 const bool may_use_pattern)
153{
154 struct tomoyo_path_group_member *member;
155 bool matched = false;
156 list_for_each_entry_rcu(member, &group->member_list, list) {
157 if (member->is_deleted)
158 continue;
159 if (!member->member_name->is_patterned) {
160 if (tomoyo_pathcmp(pathname, member->member_name))
161 continue;
162 } else if (may_use_pattern) {
163 if (!tomoyo_path_matches_pattern(pathname,
164 member->member_name))
165 continue;
166 } else
167 continue;
168 matched = true;
169 break;
170 }
171 return matched;
172}
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index d1b96f01962..ed8ccd68010 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -1,174 +1,164 @@
1/* 1/*
2 * security/tomoyo/realpath.c 2 * security/tomoyo/realpath.c
3 * 3 *
4 * Get the canonicalized absolute pathnames. The basis for TOMOYO. 4 * Pathname calculation functions for TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0 2009/04/01
9 * 5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
10 */ 7 */
11 8
12#include <linux/types.h> 9#include <linux/types.h>
13#include <linux/mount.h> 10#include <linux/mount.h>
14#include <linux/mnt_namespace.h> 11#include <linux/mnt_namespace.h>
15#include <linux/fs_struct.h> 12#include <linux/fs_struct.h>
16#include <linux/hash.h>
17#include <linux/magic.h> 13#include <linux/magic.h>
18#include <linux/slab.h> 14#include <linux/slab.h>
15#include <net/sock.h>
19#include "common.h" 16#include "common.h"
20 17
21/** 18/**
22 * tomoyo_encode: Convert binary string to ascii string. 19 * tomoyo_encode: Convert binary string to ascii string.
23 * 20 *
24 * @buffer: Buffer for ASCII string. 21 * @str: String in binary format.
25 * @buflen: Size of @buffer. 22 *
26 * @str: Binary string. 23 * Returns pointer to @str in ascii format on success, NULL otherwise.
27 * 24 *
28 * Returns 0 on success, -ENOMEM otherwise. 25 * This function uses kzalloc(), so caller must kfree() if this function
26 * didn't return NULL.
29 */ 27 */
30int tomoyo_encode(char *buffer, int buflen, const char *str) 28char *tomoyo_encode(const char *str)
31{ 29{
32 while (1) { 30 int len = 0;
33 const unsigned char c = *(unsigned char *) str++; 31 const char *p = str;
32 char *cp;
33 char *cp0;
34 34
35 if (tomoyo_is_valid(c)) { 35 if (!p)
36 if (--buflen <= 0) 36 return NULL;
37 break; 37 while (*p) {
38 *buffer++ = (char) c; 38 const unsigned char c = *p++;
39 if (c != '\\') 39 if (c == '\\')
40 continue; 40 len += 2;
41 if (--buflen <= 0) 41 else if (c > ' ' && c < 127)
42 break; 42 len++;
43 *buffer++ = (char) c; 43 else
44 continue; 44 len += 4;
45 } 45 }
46 if (!c) { 46 len++;
47 if (--buflen <= 0) 47 /* Reserve space for appending "/". */
48 break; 48 cp = kzalloc(len + 10, GFP_NOFS);
49 *buffer = '\0'; 49 if (!cp)
50 return 0; 50 return NULL;
51 cp0 = cp;
52 p = str;
53 while (*p) {
54 const unsigned char c = *p++;
55
56 if (c == '\\') {
57 *cp++ = '\\';
58 *cp++ = '\\';
59 } else if (c > ' ' && c < 127) {
60 *cp++ = c;
61 } else {
62 *cp++ = '\\';
63 *cp++ = (c >> 6) + '0';
64 *cp++ = ((c >> 3) & 7) + '0';
65 *cp++ = (c & 7) + '0';
51 } 66 }
52 buflen -= 4;
53 if (buflen <= 0)
54 break;
55 *buffer++ = '\\';
56 *buffer++ = (c >> 6) + '0';
57 *buffer++ = ((c >> 3) & 7) + '0';
58 *buffer++ = (c & 7) + '0';
59 } 67 }
60 return -ENOMEM; 68 return cp0;
61} 69}
62 70
63/** 71/**
64 * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root. 72 * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
65 * 73 *
66 * @path: Pointer to "struct path". 74 * @path: Pointer to "struct path".
67 * @newname: Pointer to buffer to return value in.
68 * @newname_len: Size of @newname.
69 * 75 *
70 * Returns 0 on success, negative value otherwise. 76 * Returns the realpath of the given @path on success, NULL otherwise.
71 * 77 *
72 * If dentry is a directory, trailing '/' is appended. 78 * If dentry is a directory, trailing '/' is appended.
73 * Characters out of 0x20 < c < 0x7F range are converted to 79 * Characters out of 0x20 < c < 0x7F range are converted to
74 * \ooo style octal string. 80 * \ooo style octal string.
75 * Character \ is converted to \\ string. 81 * Character \ is converted to \\ string.
82 *
83 * These functions use kzalloc(), so the caller must call kfree()
84 * if these functions didn't return NULL.
76 */ 85 */
77int tomoyo_realpath_from_path2(struct path *path, char *newname, 86char *tomoyo_realpath_from_path(struct path *path)
78 int newname_len)
79{ 87{
80 int error = -ENOMEM; 88 char *buf = NULL;
89 char *name = NULL;
90 unsigned int buf_len = PAGE_SIZE / 2;
81 struct dentry *dentry = path->dentry; 91 struct dentry *dentry = path->dentry;
82 char *sp; 92 bool is_dir;
83 93 if (!dentry)
84 if (!dentry || !path->mnt || !newname || newname_len <= 2048) 94 return NULL;
85 return -EINVAL; 95 is_dir = dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode);
86 if (dentry->d_op && dentry->d_op->d_dname) { 96 while (1) {
97 struct path ns_root = { .mnt = NULL, .dentry = NULL };
98 char *pos;
99 buf_len <<= 1;
100 kfree(buf);
101 buf = kmalloc(buf_len, GFP_NOFS);
102 if (!buf)
103 break;
104 /* Get better name for socket. */
105 if (dentry->d_sb && dentry->d_sb->s_magic == SOCKFS_MAGIC) {
106 struct inode *inode = dentry->d_inode;
107 struct socket *sock = inode ? SOCKET_I(inode) : NULL;
108 struct sock *sk = sock ? sock->sk : NULL;
109 if (sk) {
110 snprintf(buf, buf_len - 1, "socket:[family=%u:"
111 "type=%u:protocol=%u]", sk->sk_family,
112 sk->sk_type, sk->sk_protocol);
113 } else {
114 snprintf(buf, buf_len - 1, "socket:[unknown]");
115 }
116 name = tomoyo_encode(buf);
117 break;
118 }
87 /* For "socket:[\$]" and "pipe:[\$]". */ 119 /* For "socket:[\$]" and "pipe:[\$]". */
88 static const int offset = 1536; 120 if (dentry->d_op && dentry->d_op->d_dname) {
89 sp = dentry->d_op->d_dname(dentry, newname + offset, 121 pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
90 newname_len - offset); 122 if (IS_ERR(pos))
91 } else { 123 continue;
92 struct path ns_root = {.mnt = NULL, .dentry = NULL}; 124 name = tomoyo_encode(pos);
93 125 break;
126 }
127 /* If we don't have a vfsmount, we can't calculate. */
128 if (!path->mnt)
129 break;
94 spin_lock(&dcache_lock); 130 spin_lock(&dcache_lock);
95 /* go to whatever namespace root we are under */ 131 /* go to whatever namespace root we are under */
96 sp = __d_path(path, &ns_root, newname, newname_len); 132 pos = __d_path(path, &ns_root, buf, buf_len);
97 spin_unlock(&dcache_lock); 133 spin_unlock(&dcache_lock);
98 /* Prepend "/proc" prefix if using internal proc vfs mount. */ 134 /* Prepend "/proc" prefix if using internal proc vfs mount. */
99 if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) && 135 if (!IS_ERR(pos) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
100 (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) { 136 (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
101 sp -= 5; 137 pos -= 5;
102 if (sp >= newname) 138 if (pos >= buf)
103 memcpy(sp, "/proc", 5); 139 memcpy(pos, "/proc", 5);
104 else 140 else
105 sp = ERR_PTR(-ENOMEM); 141 pos = ERR_PTR(-ENOMEM);
106 }
107 }
108 if (IS_ERR(sp))
109 error = PTR_ERR(sp);
110 else
111 error = tomoyo_encode(newname, sp - newname, sp);
112 /* Append trailing '/' if dentry is a directory. */
113 if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
114 && *newname) {
115 sp = newname + strlen(newname);
116 if (*(sp - 1) != '/') {
117 if (sp < newname + newname_len - 4) {
118 *sp++ = '/';
119 *sp = '\0';
120 } else {
121 error = -ENOMEM;
122 }
123 } 142 }
143 if (IS_ERR(pos))
144 continue;
145 name = tomoyo_encode(pos);
146 break;
124 } 147 }
125 if (error)
126 printk(KERN_WARNING "tomoyo_realpath: Pathname too long.\n");
127 return error;
128}
129
130/**
131 * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
132 *
133 * @path: Pointer to "struct path".
134 *
135 * Returns the realpath of the given @path on success, NULL otherwise.
136 *
137 * These functions use kzalloc(), so the caller must call kfree()
138 * if these functions didn't return NULL.
139 */
140char *tomoyo_realpath_from_path(struct path *path)
141{
142 char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS);
143
144 BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
145 <= TOMOYO_MAX_PATHNAME_LEN - 1);
146 if (!buf)
147 return NULL;
148 if (tomoyo_realpath_from_path2(path, buf,
149 TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
150 return buf;
151 kfree(buf); 148 kfree(buf);
152 return NULL; 149 if (!name)
153} 150 tomoyo_warn_oom(__func__);
154 151 else if (is_dir && *name) {
155/** 152 /* Append trailing '/' if dentry is a directory. */
156 * tomoyo_realpath - Get realpath of a pathname. 153 char *pos = name + strlen(name) - 1;
157 * 154 if (*pos != '/')
158 * @pathname: The pathname to solve. 155 /*
159 * 156 * This is OK because tomoyo_encode() reserves space
160 * Returns the realpath of @pathname on success, NULL otherwise. 157 * for appending "/".
161 */ 158 */
162char *tomoyo_realpath(const char *pathname) 159 *++pos = '/';
163{
164 struct path path;
165
166 if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) {
167 char *buf = tomoyo_realpath_from_path(&path);
168 path_put(&path);
169 return buf;
170 } 160 }
171 return NULL; 161 return name;
172} 162}
173 163
174/** 164/**
@@ -189,191 +179,3 @@ char *tomoyo_realpath_nofollow(const char *pathname)
189 } 179 }
190 return NULL; 180 return NULL;
191} 181}
192
193/* Memory allocated for non-string data. */
194static atomic_t tomoyo_policy_memory_size;
195/* Quota for holding policy. */
196static unsigned int tomoyo_quota_for_policy;
197
198/**
199 * tomoyo_memory_ok - Check memory quota.
200 *
201 * @ptr: Pointer to allocated memory.
202 *
203 * Returns true on success, false otherwise.
204 *
205 * Caller holds tomoyo_policy_lock.
206 * Memory pointed by @ptr will be zeroed on success.
207 */
208bool tomoyo_memory_ok(void *ptr)
209{
210 int allocated_len = ptr ? ksize(ptr) : 0;
211 atomic_add(allocated_len, &tomoyo_policy_memory_size);
212 if (ptr && (!tomoyo_quota_for_policy ||
213 atomic_read(&tomoyo_policy_memory_size)
214 <= tomoyo_quota_for_policy)) {
215 memset(ptr, 0, allocated_len);
216 return true;
217 }
218 printk(KERN_WARNING "ERROR: Out of memory "
219 "for tomoyo_alloc_element().\n");
220 if (!tomoyo_policy_loaded)
221 panic("MAC Initialization failed.\n");
222 return false;
223}
224
225/**
226 * tomoyo_commit_ok - Check memory quota.
227 *
228 * @data: Data to copy from.
229 * @size: Size in byte.
230 *
231 * Returns pointer to allocated memory on success, NULL otherwise.
232 */
233void *tomoyo_commit_ok(void *data, const unsigned int size)
234{
235 void *ptr = kzalloc(size, GFP_NOFS);
236 if (tomoyo_memory_ok(ptr)) {
237 memmove(ptr, data, size);
238 memset(data, 0, size);
239 return ptr;
240 }
241 return NULL;
242}
243
244/**
245 * tomoyo_memory_free - Free memory for elements.
246 *
247 * @ptr: Pointer to allocated memory.
248 */
249void tomoyo_memory_free(void *ptr)
250{
251 atomic_sub(ksize(ptr), &tomoyo_policy_memory_size);
252 kfree(ptr);
253}
254
255/*
256 * tomoyo_name_list is used for holding string data used by TOMOYO.
257 * Since same string data is likely used for multiple times (e.g.
258 * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
259 * "const struct tomoyo_path_info *".
260 */
261struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
262
263/**
264 * tomoyo_get_name - Allocate permanent memory for string data.
265 *
266 * @name: The string to store into the permernent memory.
267 *
268 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
269 */
270const struct tomoyo_path_info *tomoyo_get_name(const char *name)
271{
272 struct tomoyo_name_entry *ptr;
273 unsigned int hash;
274 int len;
275 int allocated_len;
276 struct list_head *head;
277
278 if (!name)
279 return NULL;
280 len = strlen(name) + 1;
281 hash = full_name_hash((const unsigned char *) name, len - 1);
282 head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
283 if (mutex_lock_interruptible(&tomoyo_policy_lock))
284 return NULL;
285 list_for_each_entry(ptr, head, list) {
286 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
287 continue;
288 atomic_inc(&ptr->users);
289 goto out;
290 }
291 ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
292 allocated_len = ptr ? ksize(ptr) : 0;
293 if (!ptr || (tomoyo_quota_for_policy &&
294 atomic_read(&tomoyo_policy_memory_size) + allocated_len
295 > tomoyo_quota_for_policy)) {
296 kfree(ptr);
297 printk(KERN_WARNING "ERROR: Out of memory "
298 "for tomoyo_get_name().\n");
299 if (!tomoyo_policy_loaded)
300 panic("MAC Initialization failed.\n");
301 ptr = NULL;
302 goto out;
303 }
304 atomic_add(allocated_len, &tomoyo_policy_memory_size);
305 ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
306 memmove((char *) ptr->entry.name, name, len);
307 atomic_set(&ptr->users, 1);
308 tomoyo_fill_path_info(&ptr->entry);
309 list_add_tail(&ptr->list, head);
310 out:
311 mutex_unlock(&tomoyo_policy_lock);
312 return ptr ? &ptr->entry : NULL;
313}
314
315/**
316 * tomoyo_realpath_init - Initialize realpath related code.
317 */
318void __init tomoyo_realpath_init(void)
319{
320 int i;
321
322 BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
323 for (i = 0; i < TOMOYO_MAX_HASH; i++)
324 INIT_LIST_HEAD(&tomoyo_name_list[i]);
325 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
326 tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME);
327 /*
328 * tomoyo_read_lock() is not needed because this function is
329 * called before the first "delete" request.
330 */
331 list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
332 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
333 panic("Can't register tomoyo_kernel_domain");
334}
335
336/**
337 * tomoyo_read_memory_counter - Check for memory usage in bytes.
338 *
339 * @head: Pointer to "struct tomoyo_io_buffer".
340 *
341 * Returns memory usage.
342 */
343int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
344{
345 if (!head->read_eof) {
346 const unsigned int policy
347 = atomic_read(&tomoyo_policy_memory_size);
348 char buffer[64];
349
350 memset(buffer, 0, sizeof(buffer));
351 if (tomoyo_quota_for_policy)
352 snprintf(buffer, sizeof(buffer) - 1,
353 " (Quota: %10u)",
354 tomoyo_quota_for_policy);
355 else
356 buffer[0] = '\0';
357 tomoyo_io_printf(head, "Policy: %10u%s\n", policy, buffer);
358 tomoyo_io_printf(head, "Total: %10u\n", policy);
359 head->read_eof = true;
360 }
361 return 0;
362}
363
364/**
365 * tomoyo_write_memory_quota - Set memory quota.
366 *
367 * @head: Pointer to "struct tomoyo_io_buffer".
368 *
369 * Returns 0.
370 */
371int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
372{
373 char *data = head->write_buf;
374 unsigned int size;
375
376 if (sscanf(data, "Policy: %u", &size) == 1)
377 tomoyo_quota_for_policy = size;
378 return 0;
379}
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c
new file mode 100644
index 00000000000..e43d5554b50
--- /dev/null
+++ b/security/tomoyo/securityfs_if.c
@@ -0,0 +1,155 @@
1/*
2 * security/tomoyo/common.c
3 *
4 * Securityfs interface for TOMOYO.
5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 */
8
9#include <linux/security.h>
10#include "common.h"
11
12/**
13 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
14 *
15 * @inode: Pointer to "struct inode".
16 * @file: Pointer to "struct file".
17 *
18 * Returns 0 on success, negative value otherwise.
19 */
20static int tomoyo_open(struct inode *inode, struct file *file)
21{
22 const int key = ((u8 *) file->f_path.dentry->d_inode->i_private)
23 - ((u8 *) NULL);
24 return tomoyo_open_control(key, file);
25}
26
27/**
28 * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface.
29 *
30 * @inode: Pointer to "struct inode".
31 * @file: Pointer to "struct file".
32 *
33 * Returns 0 on success, negative value otherwise.
34 */
35static int tomoyo_release(struct inode *inode, struct file *file)
36{
37 return tomoyo_close_control(file);
38}
39
40/**
41 * tomoyo_poll - poll() for /proc/ccs/ interface.
42 *
43 * @file: Pointer to "struct file".
44 * @wait: Pointer to "poll_table".
45 *
46 * Returns 0 on success, negative value otherwise.
47 */
48static unsigned int tomoyo_poll(struct file *file, poll_table *wait)
49{
50 return tomoyo_poll_control(file, wait);
51}
52
53/**
54 * tomoyo_read - read() for /sys/kernel/security/tomoyo/ interface.
55 *
56 * @file: Pointer to "struct file".
57 * @buf: Pointer to buffer.
58 * @count: Size of @buf.
59 * @ppos: Unused.
60 *
61 * Returns bytes read on success, negative value otherwise.
62 */
63static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
64 loff_t *ppos)
65{
66 return tomoyo_read_control(file, buf, count);
67}
68
69/**
70 * tomoyo_write - write() for /sys/kernel/security/tomoyo/ interface.
71 *
72 * @file: Pointer to "struct file".
73 * @buf: Pointer to buffer.
74 * @count: Size of @buf.
75 * @ppos: Unused.
76 *
77 * Returns @count on success, negative value otherwise.
78 */
79static ssize_t tomoyo_write(struct file *file, const char __user *buf,
80 size_t count, loff_t *ppos)
81{
82 return tomoyo_write_control(file, buf, count);
83}
84
85/*
86 * tomoyo_operations is a "struct file_operations" which is used for handling
87 * /sys/kernel/security/tomoyo/ interface.
88 *
89 * Some files under /sys/kernel/security/tomoyo/ directory accept open(O_RDWR).
90 * See tomoyo_io_buffer for internals.
91 */
92static const struct file_operations tomoyo_operations = {
93 .open = tomoyo_open,
94 .release = tomoyo_release,
95 .poll = tomoyo_poll,
96 .read = tomoyo_read,
97 .write = tomoyo_write,
98 .llseek = noop_llseek,
99};
100
101/**
102 * tomoyo_create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory.
103 *
104 * @name: The name of the interface file.
105 * @mode: The permission of the interface file.
106 * @parent: The parent directory.
107 * @key: Type of interface.
108 *
109 * Returns nothing.
110 */
111static void __init tomoyo_create_entry(const char *name, const mode_t mode,
112 struct dentry *parent, const u8 key)
113{
114 securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key,
115 &tomoyo_operations);
116}
117
118/**
119 * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface.
120 *
121 * Returns 0.
122 */
123static int __init tomoyo_initerface_init(void)
124{
125 struct dentry *tomoyo_dir;
126
127 /* Don't create securityfs entries unless registered. */
128 if (current_cred()->security != &tomoyo_kernel_domain)
129 return 0;
130
131 tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
132 tomoyo_create_entry("query", 0600, tomoyo_dir,
133 TOMOYO_QUERY);
134 tomoyo_create_entry("domain_policy", 0600, tomoyo_dir,
135 TOMOYO_DOMAINPOLICY);
136 tomoyo_create_entry("exception_policy", 0600, tomoyo_dir,
137 TOMOYO_EXCEPTIONPOLICY);
138 tomoyo_create_entry("self_domain", 0400, tomoyo_dir,
139 TOMOYO_SELFDOMAIN);
140 tomoyo_create_entry(".domain_status", 0600, tomoyo_dir,
141 TOMOYO_DOMAIN_STATUS);
142 tomoyo_create_entry(".process_status", 0600, tomoyo_dir,
143 TOMOYO_PROCESS_STATUS);
144 tomoyo_create_entry("meminfo", 0600, tomoyo_dir,
145 TOMOYO_MEMINFO);
146 tomoyo_create_entry("profile", 0600, tomoyo_dir,
147 TOMOYO_PROFILE);
148 tomoyo_create_entry("manager", 0600, tomoyo_dir,
149 TOMOYO_MANAGER);
150 tomoyo_create_entry("version", 0400, tomoyo_dir,
151 TOMOYO_VERSION);
152 return 0;
153}
154
155fs_initcall(tomoyo_initerface_init);
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index dedd97d0c16..95d3f957223 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -3,10 +3,7 @@
3 * 3 *
4 * LSM hooks for TOMOYO Linux. 4 * LSM hooks for TOMOYO Linux.
5 * 5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION 6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0 2009/04/01
9 *
10 */ 7 */
11 8
12#include <linux/security.h> 9#include <linux/security.h>
@@ -96,8 +93,7 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
96 return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY); 93 return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY);
97} 94}
98 95
99static int tomoyo_path_truncate(struct path *path, loff_t length, 96static int tomoyo_path_truncate(struct path *path)
100 unsigned int time_attrs)
101{ 97{
102 return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); 98 return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path);
103} 99}
@@ -112,7 +108,8 @@ static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
112 int mode) 108 int mode)
113{ 109{
114 struct path path = { parent->mnt, dentry }; 110 struct path path = { parent->mnt, dentry };
115 return tomoyo_path_perm(TOMOYO_TYPE_MKDIR, &path); 111 return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path,
112 mode & S_IALLUGO);
116} 113}
117 114
118static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) 115static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
@@ -133,6 +130,7 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
133{ 130{
134 struct path path = { parent->mnt, dentry }; 131 struct path path = { parent->mnt, dentry };
135 int type = TOMOYO_TYPE_CREATE; 132 int type = TOMOYO_TYPE_CREATE;
133 const unsigned int perm = mode & S_IALLUGO;
136 134
137 switch (mode & S_IFMT) { 135 switch (mode & S_IFMT) {
138 case S_IFCHR: 136 case S_IFCHR:
@@ -141,6 +139,12 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
141 case S_IFBLK: 139 case S_IFBLK:
142 type = TOMOYO_TYPE_MKBLOCK; 140 type = TOMOYO_TYPE_MKBLOCK;
143 break; 141 break;
142 default:
143 goto no_dev;
144 }
145 return tomoyo_mkdev_perm(type, &path, perm, dev);
146 no_dev:
147 switch (mode & S_IFMT) {
144 case S_IFIFO: 148 case S_IFIFO:
145 type = TOMOYO_TYPE_MKFIFO; 149 type = TOMOYO_TYPE_MKFIFO;
146 break; 150 break;
@@ -148,7 +152,7 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
148 type = TOMOYO_TYPE_MKSOCK; 152 type = TOMOYO_TYPE_MKSOCK;
149 break; 153 break;
150 } 154 }
151 return tomoyo_path_perm(type, &path); 155 return tomoyo_path_number_perm(type, &path, perm);
152} 156}
153 157
154static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, 158static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,
@@ -173,7 +177,7 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
173 unsigned long arg) 177 unsigned long arg)
174{ 178{
175 if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) 179 if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))
176 return tomoyo_check_rewrite_permission(file); 180 return tomoyo_path_perm(TOMOYO_TYPE_REWRITE, &file->f_path);
177 return 0; 181 return 0;
178} 182}
179 183
@@ -189,23 +193,24 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred)
189static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, 193static int tomoyo_file_ioctl(struct file *file, unsigned int cmd,
190 unsigned long arg) 194 unsigned long arg)
191{ 195{
192 return tomoyo_path_perm(TOMOYO_TYPE_IOCTL, &file->f_path); 196 return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd);
193} 197}
194 198
195static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, 199static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
196 mode_t mode) 200 mode_t mode)
197{ 201{
198 struct path path = { mnt, dentry }; 202 struct path path = { mnt, dentry };
199 return tomoyo_path_perm(TOMOYO_TYPE_CHMOD, &path); 203 return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, &path,
204 mode & S_IALLUGO);
200} 205}
201 206
202static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) 207static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid)
203{ 208{
204 int error = 0; 209 int error = 0;
205 if (uid != (uid_t) -1) 210 if (uid != (uid_t) -1)
206 error = tomoyo_path_perm(TOMOYO_TYPE_CHOWN, path); 211 error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, uid);
207 if (!error && gid != (gid_t) -1) 212 if (!error && gid != (gid_t) -1)
208 error = tomoyo_path_perm(TOMOYO_TYPE_CHGRP, path); 213 error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, gid);
209 return error; 214 return error;
210} 215}
211 216
@@ -217,7 +222,7 @@ static int tomoyo_path_chroot(struct path *path)
217static int tomoyo_sb_mount(char *dev_name, struct path *path, 222static int tomoyo_sb_mount(char *dev_name, struct path *path,
218 char *type, unsigned long flags, void *data) 223 char *type, unsigned long flags, void *data)
219{ 224{
220 return tomoyo_path_perm(TOMOYO_TYPE_MOUNT, path); 225 return tomoyo_mount_permission(dev_name, path, type, flags, data);
221} 226}
222 227
223static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) 228static int tomoyo_sb_umount(struct vfsmount *mnt, int flags)
@@ -277,7 +282,7 @@ static int __init tomoyo_init(void)
277 panic("Failure registering TOMOYO Linux"); 282 panic("Failure registering TOMOYO Linux");
278 printk(KERN_INFO "TOMOYO Linux initialized\n"); 283 printk(KERN_INFO "TOMOYO Linux initialized\n");
279 cred->security = &tomoyo_kernel_domain; 284 cred->security = &tomoyo_kernel_domain;
280 tomoyo_realpath_init(); 285 tomoyo_mm_init();
281 return 0; 286 return 0;
282} 287}
283 288
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
new file mode 100644
index 00000000000..9bfc1ee8222
--- /dev/null
+++ b/security/tomoyo/util.c
@@ -0,0 +1,963 @@
1/*
2 * security/tomoyo/util.c
3 *
4 * Utility functions for TOMOYO.
5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 */
8
9#include <linux/slab.h>
10#include "common.h"
11
12/* Lock for protecting policy. */
13DEFINE_MUTEX(tomoyo_policy_lock);
14
15/* Has /sbin/init started? */
16bool tomoyo_policy_loaded;
17
18/**
19 * tomoyo_parse_ulong - Parse an "unsigned long" value.
20 *
21 * @result: Pointer to "unsigned long".
22 * @str: Pointer to string to parse.
23 *
24 * Returns value type on success, 0 otherwise.
25 *
26 * The @src is updated to point the first character after the value
27 * on success.
28 */
29static u8 tomoyo_parse_ulong(unsigned long *result, char **str)
30{
31 const char *cp = *str;
32 char *ep;
33 int base = 10;
34 if (*cp == '0') {
35 char c = *(cp + 1);
36 if (c == 'x' || c == 'X') {
37 base = 16;
38 cp += 2;
39 } else if (c >= '0' && c <= '7') {
40 base = 8;
41 cp++;
42 }
43 }
44 *result = simple_strtoul(cp, &ep, base);
45 if (cp == ep)
46 return 0;
47 *str = ep;
48 switch (base) {
49 case 16:
50 return TOMOYO_VALUE_TYPE_HEXADECIMAL;
51 case 8:
52 return TOMOYO_VALUE_TYPE_OCTAL;
53 default:
54 return TOMOYO_VALUE_TYPE_DECIMAL;
55 }
56}
57
58/**
59 * tomoyo_print_ulong - Print an "unsigned long" value.
60 *
61 * @buffer: Pointer to buffer.
62 * @buffer_len: Size of @buffer.
63 * @value: An "unsigned long" value.
64 * @type: Type of @value.
65 *
66 * Returns nothing.
67 */
68void tomoyo_print_ulong(char *buffer, const int buffer_len,
69 const unsigned long value, const u8 type)
70{
71 if (type == TOMOYO_VALUE_TYPE_DECIMAL)
72 snprintf(buffer, buffer_len, "%lu", value);
73 else if (type == TOMOYO_VALUE_TYPE_OCTAL)
74 snprintf(buffer, buffer_len, "0%lo", value);
75 else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL)
76 snprintf(buffer, buffer_len, "0x%lX", value);
77 else
78 snprintf(buffer, buffer_len, "type(%u)", type);
79}
80
81/**
82 * tomoyo_parse_name_union - Parse a tomoyo_name_union.
83 *
84 * @filename: Name or name group.
85 * @ptr: Pointer to "struct tomoyo_name_union".
86 *
87 * Returns true on success, false otherwise.
88 */
89bool tomoyo_parse_name_union(const char *filename,
90 struct tomoyo_name_union *ptr)
91{
92 if (!tomoyo_correct_word(filename))
93 return false;
94 if (filename[0] == '@') {
95 ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP);
96 ptr->is_group = true;
97 return ptr->group != NULL;
98 }
99 ptr->filename = tomoyo_get_name(filename);
100 ptr->is_group = false;
101 return ptr->filename != NULL;
102}
103
104/**
105 * tomoyo_parse_number_union - Parse a tomoyo_number_union.
106 *
107 * @data: Number or number range or number group.
108 * @ptr: Pointer to "struct tomoyo_number_union".
109 *
110 * Returns true on success, false otherwise.
111 */
112bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
113{
114 u8 type;
115 unsigned long v;
116 memset(num, 0, sizeof(*num));
117 if (data[0] == '@') {
118 if (!tomoyo_correct_word(data))
119 return false;
120 num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP);
121 num->is_group = true;
122 return num->group != NULL;
123 }
124 type = tomoyo_parse_ulong(&v, &data);
125 if (!type)
126 return false;
127 num->values[0] = v;
128 num->min_type = type;
129 if (!*data) {
130 num->values[1] = v;
131 num->max_type = type;
132 return true;
133 }
134 if (*data++ != '-')
135 return false;
136 type = tomoyo_parse_ulong(&v, &data);
137 if (!type || *data)
138 return false;
139 num->values[1] = v;
140 num->max_type = type;
141 return true;
142}
143
144/**
145 * tomoyo_byte_range - Check whether the string is a \ooo style octal value.
146 *
147 * @str: Pointer to the string.
148 *
149 * Returns true if @str is a \ooo style octal value, false otherwise.
150 *
151 * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
152 * This function verifies that \ooo is in valid range.
153 */
154static inline bool tomoyo_byte_range(const char *str)
155{
156 return *str >= '0' && *str++ <= '3' &&
157 *str >= '0' && *str++ <= '7' &&
158 *str >= '0' && *str <= '7';
159}
160
161/**
162 * tomoyo_alphabet_char - Check whether the character is an alphabet.
163 *
164 * @c: The character to check.
165 *
166 * Returns true if @c is an alphabet character, false otherwise.
167 */
168static inline bool tomoyo_alphabet_char(const char c)
169{
170 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
171}
172
173/**
174 * tomoyo_make_byte - Make byte value from three octal characters.
175 *
176 * @c1: The first character.
177 * @c2: The second character.
178 * @c3: The third character.
179 *
180 * Returns byte value.
181 */
182static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
183{
184 return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
185}
186
187/**
188 * tomoyo_str_starts - Check whether the given string starts with the given keyword.
189 *
190 * @src: Pointer to pointer to the string.
191 * @find: Pointer to the keyword.
192 *
193 * Returns true if @src starts with @find, false otherwise.
194 *
195 * The @src is updated to point the first character after the @find
196 * if @src starts with @find.
197 */
198bool tomoyo_str_starts(char **src, const char *find)
199{
200 const int len = strlen(find);
201 char *tmp = *src;
202
203 if (strncmp(tmp, find, len))
204 return false;
205 tmp += len;
206 *src = tmp;
207 return true;
208}
209
210/**
211 * tomoyo_normalize_line - Format string.
212 *
213 * @buffer: The line to normalize.
214 *
215 * Leading and trailing whitespaces are removed.
216 * Multiple whitespaces are packed into single space.
217 *
218 * Returns nothing.
219 */
220void tomoyo_normalize_line(unsigned char *buffer)
221{
222 unsigned char *sp = buffer;
223 unsigned char *dp = buffer;
224 bool first = true;
225
226 while (tomoyo_invalid(*sp))
227 sp++;
228 while (*sp) {
229 if (!first)
230 *dp++ = ' ';
231 first = false;
232 while (tomoyo_valid(*sp))
233 *dp++ = *sp++;
234 while (tomoyo_invalid(*sp))
235 sp++;
236 }
237 *dp = '\0';
238}
239
240/**
241 * tomoyo_tokenize - Tokenize string.
242 *
243 * @buffer: The line to tokenize.
244 * @w: Pointer to "char *".
245 * @size: Sizeof @w .
246 *
247 * Returns true on success, false otherwise.
248 */
249bool tomoyo_tokenize(char *buffer, char *w[], size_t size)
250{
251 int count = size / sizeof(char *);
252 int i;
253 for (i = 0; i < count; i++)
254 w[i] = "";
255 for (i = 0; i < count; i++) {
256 char *cp = strchr(buffer, ' ');
257 if (cp)
258 *cp = '\0';
259 w[i] = buffer;
260 if (!cp)
261 break;
262 buffer = cp + 1;
263 }
264 return i < count || !*buffer;
265}
266
267/**
268 * tomoyo_correct_word2 - Validate a string.
269 *
270 * @string: The string to check. May be non-'\0'-terminated.
271 * @len: Length of @string.
272 *
273 * Check whether the given string follows the naming rules.
274 * Returns true if @string follows the naming rules, false otherwise.
275 */
276static bool tomoyo_correct_word2(const char *string, size_t len)
277{
278 const char *const start = string;
279 bool in_repetition = false;
280 unsigned char c;
281 unsigned char d;
282 unsigned char e;
283 if (!len)
284 goto out;
285 while (len--) {
286 c = *string++;
287 if (c == '\\') {
288 if (!len--)
289 goto out;
290 c = *string++;
291 switch (c) {
292 case '\\': /* "\\" */
293 continue;
294 case '$': /* "\$" */
295 case '+': /* "\+" */
296 case '?': /* "\?" */
297 case '*': /* "\*" */
298 case '@': /* "\@" */
299 case 'x': /* "\x" */
300 case 'X': /* "\X" */
301 case 'a': /* "\a" */
302 case 'A': /* "\A" */
303 case '-': /* "\-" */
304 continue;
305 case '{': /* "/\{" */
306 if (string - 3 < start || *(string - 3) != '/')
307 break;
308 in_repetition = true;
309 continue;
310 case '}': /* "\}/" */
311 if (*string != '/')
312 break;
313 if (!in_repetition)
314 break;
315 in_repetition = false;
316 continue;
317 case '0': /* "\ooo" */
318 case '1':
319 case '2':
320 case '3':
321 if (!len-- || !len--)
322 break;
323 d = *string++;
324 e = *string++;
325 if (d < '0' || d > '7' || e < '0' || e > '7')
326 break;
327 c = tomoyo_make_byte(c, d, e);
328 if (tomoyo_invalid(c))
329 continue; /* pattern is not \000 */
330 }
331 goto out;
332 } else if (in_repetition && c == '/') {
333 goto out;
334 } else if (tomoyo_invalid(c)) {
335 goto out;
336 }
337 }
338 if (in_repetition)
339 goto out;
340 return true;
341 out:
342 return false;
343}
344
345/**
346 * tomoyo_correct_word - Validate a string.
347 *
348 * @string: The string to check.
349 *
350 * Check whether the given string follows the naming rules.
351 * Returns true if @string follows the naming rules, false otherwise.
352 */
353bool tomoyo_correct_word(const char *string)
354{
355 return tomoyo_correct_word2(string, strlen(string));
356}
357
358/**
359 * tomoyo_correct_path - Validate a pathname.
360 *
361 * @filename: The pathname to check.
362 *
363 * Check whether the given pathname follows the naming rules.
364 * Returns true if @filename follows the naming rules, false otherwise.
365 */
366bool tomoyo_correct_path(const char *filename)
367{
368 return *filename == '/' && tomoyo_correct_word(filename);
369}
370
371/**
372 * tomoyo_correct_domain - Check whether the given domainname follows the naming rules.
373 *
374 * @domainname: The domainname to check.
375 *
376 * Returns true if @domainname follows the naming rules, false otherwise.
377 */
378bool tomoyo_correct_domain(const unsigned char *domainname)
379{
380 if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
381 TOMOYO_ROOT_NAME_LEN))
382 goto out;
383 domainname += TOMOYO_ROOT_NAME_LEN;
384 if (!*domainname)
385 return true;
386 if (*domainname++ != ' ')
387 goto out;
388 while (1) {
389 const unsigned char *cp = strchr(domainname, ' ');
390 if (!cp)
391 break;
392 if (*domainname != '/' ||
393 !tomoyo_correct_word2(domainname, cp - domainname - 1))
394 goto out;
395 domainname = cp + 1;
396 }
397 return tomoyo_correct_path(domainname);
398 out:
399 return false;
400}
401
402/**
403 * tomoyo_domain_def - Check whether the given token can be a domainname.
404 *
405 * @buffer: The token to check.
406 *
407 * Returns true if @buffer possibly be a domainname, false otherwise.
408 */
409bool tomoyo_domain_def(const unsigned char *buffer)
410{
411 return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN);
412}
413
414/**
415 * tomoyo_find_domain - Find a domain by the given name.
416 *
417 * @domainname: The domainname to find.
418 *
419 * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
420 *
421 * Caller holds tomoyo_read_lock().
422 */
423struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
424{
425 struct tomoyo_domain_info *domain;
426 struct tomoyo_path_info name;
427
428 name.name = domainname;
429 tomoyo_fill_path_info(&name);
430 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
431 if (!domain->is_deleted &&
432 !tomoyo_pathcmp(&name, domain->domainname))
433 return domain;
434 }
435 return NULL;
436}
437
438/**
439 * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
440 *
441 * @filename: The string to evaluate.
442 *
443 * Returns the initial length without a pattern in @filename.
444 */
445static int tomoyo_const_part_length(const char *filename)
446{
447 char c;
448 int len = 0;
449
450 if (!filename)
451 return 0;
452 while ((c = *filename++) != '\0') {
453 if (c != '\\') {
454 len++;
455 continue;
456 }
457 c = *filename++;
458 switch (c) {
459 case '\\': /* "\\" */
460 len += 2;
461 continue;
462 case '0': /* "\ooo" */
463 case '1':
464 case '2':
465 case '3':
466 c = *filename++;
467 if (c < '0' || c > '7')
468 break;
469 c = *filename++;
470 if (c < '0' || c > '7')
471 break;
472 len += 4;
473 continue;
474 }
475 break;
476 }
477 return len;
478}
479
480/**
481 * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members.
482 *
483 * @ptr: Pointer to "struct tomoyo_path_info" to fill in.
484 *
485 * The caller sets "struct tomoyo_path_info"->name.
486 */
487void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
488{
489 const char *name = ptr->name;
490 const int len = strlen(name);
491
492 ptr->const_len = tomoyo_const_part_length(name);
493 ptr->is_dir = len && (name[len - 1] == '/');
494 ptr->is_patterned = (ptr->const_len < len);
495 ptr->hash = full_name_hash(name, len);
496}
497
498/**
499 * tomoyo_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern.
500 *
501 * @filename: The start of string to check.
502 * @filename_end: The end of string to check.
503 * @pattern: The start of pattern to compare.
504 * @pattern_end: The end of pattern to compare.
505 *
506 * Returns true if @filename matches @pattern, false otherwise.
507 */
508static bool tomoyo_file_matches_pattern2(const char *filename,
509 const char *filename_end,
510 const char *pattern,
511 const char *pattern_end)
512{
513 while (filename < filename_end && pattern < pattern_end) {
514 char c;
515 if (*pattern != '\\') {
516 if (*filename++ != *pattern++)
517 return false;
518 continue;
519 }
520 c = *filename;
521 pattern++;
522 switch (*pattern) {
523 int i;
524 int j;
525 case '?':
526 if (c == '/') {
527 return false;
528 } else if (c == '\\') {
529 if (filename[1] == '\\')
530 filename++;
531 else if (tomoyo_byte_range(filename + 1))
532 filename += 3;
533 else
534 return false;
535 }
536 break;
537 case '\\':
538 if (c != '\\')
539 return false;
540 if (*++filename != '\\')
541 return false;
542 break;
543 case '+':
544 if (!isdigit(c))
545 return false;
546 break;
547 case 'x':
548 if (!isxdigit(c))
549 return false;
550 break;
551 case 'a':
552 if (!tomoyo_alphabet_char(c))
553 return false;
554 break;
555 case '0':
556 case '1':
557 case '2':
558 case '3':
559 if (c == '\\' && tomoyo_byte_range(filename + 1)
560 && strncmp(filename + 1, pattern, 3) == 0) {
561 filename += 3;
562 pattern += 2;
563 break;
564 }
565 return false; /* Not matched. */
566 case '*':
567 case '@':
568 for (i = 0; i <= filename_end - filename; i++) {
569 if (tomoyo_file_matches_pattern2(
570 filename + i, filename_end,
571 pattern + 1, pattern_end))
572 return true;
573 c = filename[i];
574 if (c == '.' && *pattern == '@')
575 break;
576 if (c != '\\')
577 continue;
578 if (filename[i + 1] == '\\')
579 i++;
580 else if (tomoyo_byte_range(filename + i + 1))
581 i += 3;
582 else
583 break; /* Bad pattern. */
584 }
585 return false; /* Not matched. */
586 default:
587 j = 0;
588 c = *pattern;
589 if (c == '$') {
590 while (isdigit(filename[j]))
591 j++;
592 } else if (c == 'X') {
593 while (isxdigit(filename[j]))
594 j++;
595 } else if (c == 'A') {
596 while (tomoyo_alphabet_char(filename[j]))
597 j++;
598 }
599 for (i = 1; i <= j; i++) {
600 if (tomoyo_file_matches_pattern2(
601 filename + i, filename_end,
602 pattern + 1, pattern_end))
603 return true;
604 }
605 return false; /* Not matched or bad pattern. */
606 }
607 filename++;
608 pattern++;
609 }
610 while (*pattern == '\\' &&
611 (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
612 pattern += 2;
613 return filename == filename_end && pattern == pattern_end;
614}
615
616/**
617 * tomoyo_file_matches_pattern - Pattern matching without '/' character.
618 *
619 * @filename: The start of string to check.
620 * @filename_end: The end of string to check.
621 * @pattern: The start of pattern to compare.
622 * @pattern_end: The end of pattern to compare.
623 *
624 * Returns true if @filename matches @pattern, false otherwise.
625 */
626static bool tomoyo_file_matches_pattern(const char *filename,
627 const char *filename_end,
628 const char *pattern,
629 const char *pattern_end)
630{
631 const char *pattern_start = pattern;
632 bool first = true;
633 bool result;
634
635 while (pattern < pattern_end - 1) {
636 /* Split at "\-" pattern. */
637 if (*pattern++ != '\\' || *pattern++ != '-')
638 continue;
639 result = tomoyo_file_matches_pattern2(filename,
640 filename_end,
641 pattern_start,
642 pattern - 2);
643 if (first)
644 result = !result;
645 if (result)
646 return false;
647 first = false;
648 pattern_start = pattern;
649 }
650 result = tomoyo_file_matches_pattern2(filename, filename_end,
651 pattern_start, pattern_end);
652 return first ? result : !result;
653}
654
655/**
656 * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
657 *
658 * @f: The start of string to check.
659 * @p: The start of pattern to compare.
660 *
661 * Returns true if @f matches @p, false otherwise.
662 */
663static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
664{
665 const char *f_delimiter;
666 const char *p_delimiter;
667
668 while (*f && *p) {
669 f_delimiter = strchr(f, '/');
670 if (!f_delimiter)
671 f_delimiter = f + strlen(f);
672 p_delimiter = strchr(p, '/');
673 if (!p_delimiter)
674 p_delimiter = p + strlen(p);
675 if (*p == '\\' && *(p + 1) == '{')
676 goto recursive;
677 if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
678 p_delimiter))
679 return false;
680 f = f_delimiter;
681 if (*f)
682 f++;
683 p = p_delimiter;
684 if (*p)
685 p++;
686 }
687 /* Ignore trailing "\*" and "\@" in @pattern. */
688 while (*p == '\\' &&
689 (*(p + 1) == '*' || *(p + 1) == '@'))
690 p += 2;
691 return !*f && !*p;
692 recursive:
693 /*
694 * The "\{" pattern is permitted only after '/' character.
695 * This guarantees that below "*(p - 1)" is safe.
696 * Also, the "\}" pattern is permitted only before '/' character
697 * so that "\{" + "\}" pair will not break the "\-" operator.
698 */
699 if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
700 *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
701 return false; /* Bad pattern. */
702 do {
703 /* Compare current component with pattern. */
704 if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
705 p_delimiter - 2))
706 break;
707 /* Proceed to next component. */
708 f = f_delimiter;
709 if (!*f)
710 break;
711 f++;
712 /* Continue comparison. */
713 if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
714 return true;
715 f_delimiter = strchr(f, '/');
716 } while (f_delimiter);
717 return false; /* Not matched. */
718}
719
720/**
721 * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
722 *
723 * @filename: The filename to check.
724 * @pattern: The pattern to compare.
725 *
726 * Returns true if matches, false otherwise.
727 *
728 * The following patterns are available.
729 * \\ \ itself.
730 * \ooo Octal representation of a byte.
731 * \* Zero or more repetitions of characters other than '/'.
732 * \@ Zero or more repetitions of characters other than '/' or '.'.
733 * \? 1 byte character other than '/'.
734 * \$ One or more repetitions of decimal digits.
735 * \+ 1 decimal digit.
736 * \X One or more repetitions of hexadecimal digits.
737 * \x 1 hexadecimal digit.
738 * \A One or more repetitions of alphabet characters.
739 * \a 1 alphabet character.
740 *
741 * \- Subtraction operator.
742 *
743 * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
744 * /dir/dir/dir/ ).
745 */
746bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
747 const struct tomoyo_path_info *pattern)
748{
749 const char *f = filename->name;
750 const char *p = pattern->name;
751 const int len = pattern->const_len;
752
753 /* If @pattern doesn't contain pattern, I can use strcmp(). */
754 if (!pattern->is_patterned)
755 return !tomoyo_pathcmp(filename, pattern);
756 /* Don't compare directory and non-directory. */
757 if (filename->is_dir != pattern->is_dir)
758 return false;
759 /* Compare the initial length without patterns. */
760 if (strncmp(f, p, len))
761 return false;
762 f += len;
763 p += len;
764 return tomoyo_path_matches_pattern2(f, p);
765}
766
767/**
768 * tomoyo_get_exe - Get tomoyo_realpath() of current process.
769 *
770 * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
771 *
772 * This function uses kzalloc(), so the caller must call kfree()
773 * if this function didn't return NULL.
774 */
775const char *tomoyo_get_exe(void)
776{
777 struct mm_struct *mm = current->mm;
778 struct vm_area_struct *vma;
779 const char *cp = NULL;
780
781 if (!mm)
782 return NULL;
783 down_read(&mm->mmap_sem);
784 for (vma = mm->mmap; vma; vma = vma->vm_next) {
785 if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
786 cp = tomoyo_realpath_from_path(&vma->vm_file->f_path);
787 break;
788 }
789 }
790 up_read(&mm->mmap_sem);
791 return cp;
792}
793
794/**
795 * tomoyo_get_mode - Get MAC mode.
796 *
797 * @profile: Profile number.
798 * @index: Index number of functionality.
799 *
800 * Returns mode.
801 */
802int tomoyo_get_mode(const u8 profile, const u8 index)
803{
804 u8 mode;
805 const u8 category = TOMOYO_MAC_CATEGORY_FILE;
806 if (!tomoyo_policy_loaded)
807 return TOMOYO_CONFIG_DISABLED;
808 mode = tomoyo_profile(profile)->config[index];
809 if (mode == TOMOYO_CONFIG_USE_DEFAULT)
810 mode = tomoyo_profile(profile)->config[category];
811 if (mode == TOMOYO_CONFIG_USE_DEFAULT)
812 mode = tomoyo_profile(profile)->default_config;
813 return mode & 3;
814}
815
816/**
817 * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members.
818 *
819 * @r: Pointer to "struct tomoyo_request_info" to initialize.
820 * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain().
821 * @index: Index number of functionality.
822 *
823 * Returns mode.
824 */
825int tomoyo_init_request_info(struct tomoyo_request_info *r,
826 struct tomoyo_domain_info *domain, const u8 index)
827{
828 u8 profile;
829 memset(r, 0, sizeof(*r));
830 if (!domain)
831 domain = tomoyo_domain();
832 r->domain = domain;
833 profile = domain->profile;
834 r->profile = profile;
835 r->type = index;
836 r->mode = tomoyo_get_mode(profile, index);
837 return r->mode;
838}
839
840/**
841 * tomoyo_last_word - Get last component of a line.
842 *
843 * @line: A line.
844 *
845 * Returns the last word of a line.
846 */
847const char *tomoyo_last_word(const char *name)
848{
849 const char *cp = strrchr(name, ' ');
850 if (cp)
851 return cp + 1;
852 return name;
853}
854
855/**
856 * tomoyo_warn_log - Print warning or error message on console.
857 *
858 * @r: Pointer to "struct tomoyo_request_info".
859 * @fmt: The printf()'s format string, followed by parameters.
860 */
861void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
862{
863 va_list args;
864 char *buffer;
865 const struct tomoyo_domain_info * const domain = r->domain;
866 const struct tomoyo_profile *profile = tomoyo_profile(domain->profile);
867 switch (r->mode) {
868 case TOMOYO_CONFIG_ENFORCING:
869 if (!profile->enforcing->enforcing_verbose)
870 return;
871 break;
872 case TOMOYO_CONFIG_PERMISSIVE:
873 if (!profile->permissive->permissive_verbose)
874 return;
875 break;
876 case TOMOYO_CONFIG_LEARNING:
877 if (!profile->learning->learning_verbose)
878 return;
879 break;
880 }
881 buffer = kmalloc(4096, GFP_NOFS);
882 if (!buffer)
883 return;
884 va_start(args, fmt);
885 vsnprintf(buffer, 4095, fmt, args);
886 va_end(args);
887 buffer[4095] = '\0';
888 printk(KERN_WARNING "%s: Access %s denied for %s\n",
889 r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING", buffer,
890 tomoyo_last_word(domain->domainname->name));
891 kfree(buffer);
892}
893
894/**
895 * tomoyo_domain_quota_is_ok - Check for domain's quota.
896 *
897 * @r: Pointer to "struct tomoyo_request_info".
898 *
899 * Returns true if the domain is not exceeded quota, false otherwise.
900 *
901 * Caller holds tomoyo_read_lock().
902 */
903bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
904{
905 unsigned int count = 0;
906 struct tomoyo_domain_info *domain = r->domain;
907 struct tomoyo_acl_info *ptr;
908
909 if (r->mode != TOMOYO_CONFIG_LEARNING)
910 return false;
911 if (!domain)
912 return true;
913 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
914 if (ptr->is_deleted)
915 continue;
916 switch (ptr->type) {
917 u16 perm;
918 u8 i;
919 case TOMOYO_TYPE_PATH_ACL:
920 perm = container_of(ptr, struct tomoyo_path_acl, head)
921 ->perm;
922 for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++)
923 if (perm & (1 << i))
924 count++;
925 if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
926 count -= 2;
927 break;
928 case TOMOYO_TYPE_PATH2_ACL:
929 perm = container_of(ptr, struct tomoyo_path2_acl, head)
930 ->perm;
931 for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++)
932 if (perm & (1 << i))
933 count++;
934 break;
935 case TOMOYO_TYPE_PATH_NUMBER_ACL:
936 perm = container_of(ptr, struct tomoyo_path_number_acl,
937 head)->perm;
938 for (i = 0; i < TOMOYO_MAX_PATH_NUMBER_OPERATION; i++)
939 if (perm & (1 << i))
940 count++;
941 break;
942 case TOMOYO_TYPE_MKDEV_ACL:
943 perm = container_of(ptr, struct tomoyo_mkdev_acl,
944 head)->perm;
945 for (i = 0; i < TOMOYO_MAX_MKDEV_OPERATION; i++)
946 if (perm & (1 << i))
947 count++;
948 break;
949 default:
950 count++;
951 }
952 }
953 if (count < tomoyo_profile(domain->profile)->learning->
954 learning_max_entry)
955 return true;
956 if (!domain->quota_warned) {
957 domain->quota_warned = true;
958 printk(KERN_WARNING "TOMOYO-WARNING: "
959 "Domain '%s' has so many ACLs to hold. "
960 "Stopped learning mode.\n", domain->domainname->name);
961 }
962 return false;
963}