aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-21 16:25:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-21 16:25:04 -0400
commit3556485f1595e3964ba539e39ea682acbb835cee (patch)
tree7f5ee254f425b1427ac0059b5f347a307f8538a1 /security
parentb8716614a7cc2fc15ea2a518edd04755fb08d922 (diff)
parent09f61cdbb32a9d812c618d3922db533542736bb0 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates for 3.4 from James Morris: "The main addition here is the new Yama security module from Kees Cook, which was discussed at the Linux Security Summit last year. Its purpose is to collect miscellaneous DAC security enhancements in one place. This also marks a departure in policy for LSM modules, which were previously limited to being standalone access control systems. Chromium OS is using Yama, and I believe there are plans for Ubuntu, at least. This patchset also includes maintenance updates for AppArmor, TOMOYO and others." Fix trivial conflict in <net/sock.h> due to the jumo_label->static_key rename. * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (38 commits) AppArmor: Fix location of const qualifier on generated string tables TOMOYO: Return error if fails to delete a domain AppArmor: add const qualifiers to string arrays AppArmor: Add ability to load extended policy TOMOYO: Return appropriate value to poll(). AppArmor: Move path failure information into aa_get_name and rename AppArmor: Update dfa matching routines. AppArmor: Minor cleanup of d_namespace_path to consolidate error handling AppArmor: Retrieve the dentry_path for error reporting when path lookup fails AppArmor: Add const qualifiers to generated string tables AppArmor: Fix oops in policy unpack auditing AppArmor: Fix error returned when a path lookup is disconnected KEYS: testing wrong bit for KEY_FLAG_REVOKED TOMOYO: Fix mount flags checking order. security: fix ima kconfig warning AppArmor: Fix the error case for chroot relative path name lookup AppArmor: fix mapping of META_READ to audit and quiet flags AppArmor: Fix underflow in xindex calculation AppArmor: Fix dropping of allowed operations that are force audited AppArmor: Add mising end of structure test to caps unpacking ...
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig6
-rw-r--r--security/Makefile2
-rw-r--r--security/apparmor/Makefile27
-rw-r--r--security/apparmor/apparmorfs.c195
-rw-r--r--security/apparmor/audit.c7
-rw-r--r--security/apparmor/domain.c5
-rw-r--r--security/apparmor/file.c21
-rw-r--r--security/apparmor/include/apparmor.h15
-rw-r--r--security/apparmor/include/apparmorfs.h44
-rw-r--r--security/apparmor/include/audit.h9
-rw-r--r--security/apparmor/include/file.h2
-rw-r--r--security/apparmor/include/match.h3
-rw-r--r--security/apparmor/include/path.h3
-rw-r--r--security/apparmor/include/policy.h15
-rw-r--r--security/apparmor/include/resource.h4
-rw-r--r--security/apparmor/match.c80
-rw-r--r--security/apparmor/path.c56
-rw-r--r--security/apparmor/policy.c3
-rw-r--r--security/apparmor/policy_unpack.c31
-rw-r--r--security/apparmor/resource.c5
-rw-r--r--security/capability.c5
-rw-r--r--security/commoncap.c1
-rw-r--r--security/integrity/ima/Kconfig4
-rw-r--r--security/integrity/ima/ima_audit.c2
-rw-r--r--security/integrity/ima/ima_policy.c3
-rw-r--r--security/keys/keyctl.c15
-rw-r--r--security/keys/process_keys.c3
-rw-r--r--security/security.c21
-rw-r--r--security/selinux/hooks.c2
-rw-r--r--security/smack/smack_lsm.c3
-rw-r--r--security/tomoyo/audit.c4
-rw-r--r--security/tomoyo/common.c63
-rw-r--r--security/tomoyo/common.h6
-rw-r--r--security/tomoyo/mount.c38
-rw-r--r--security/tomoyo/securityfs_if.c5
-rw-r--r--security/yama/Kconfig13
-rw-r--r--security/yama/Makefile3
-rw-r--r--security/yama/yama_lsm.c323
38 files changed, 856 insertions, 191 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 51bd5a0b69ae..ccc61f8006b2 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -187,6 +187,7 @@ source security/selinux/Kconfig
187source security/smack/Kconfig 187source security/smack/Kconfig
188source security/tomoyo/Kconfig 188source security/tomoyo/Kconfig
189source security/apparmor/Kconfig 189source security/apparmor/Kconfig
190source security/yama/Kconfig
190 191
191source security/integrity/Kconfig 192source security/integrity/Kconfig
192 193
@@ -196,6 +197,7 @@ choice
196 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK 197 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
197 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO 198 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
198 default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR 199 default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
200 default DEFAULT_SECURITY_YAMA if SECURITY_YAMA
199 default DEFAULT_SECURITY_DAC 201 default DEFAULT_SECURITY_DAC
200 202
201 help 203 help
@@ -214,6 +216,9 @@ choice
214 config DEFAULT_SECURITY_APPARMOR 216 config DEFAULT_SECURITY_APPARMOR
215 bool "AppArmor" if SECURITY_APPARMOR=y 217 bool "AppArmor" if SECURITY_APPARMOR=y
216 218
219 config DEFAULT_SECURITY_YAMA
220 bool "Yama" if SECURITY_YAMA=y
221
217 config DEFAULT_SECURITY_DAC 222 config DEFAULT_SECURITY_DAC
218 bool "Unix Discretionary Access Controls" 223 bool "Unix Discretionary Access Controls"
219 224
@@ -225,6 +230,7 @@ config DEFAULT_SECURITY
225 default "smack" if DEFAULT_SECURITY_SMACK 230 default "smack" if DEFAULT_SECURITY_SMACK
226 default "tomoyo" if DEFAULT_SECURITY_TOMOYO 231 default "tomoyo" if DEFAULT_SECURITY_TOMOYO
227 default "apparmor" if DEFAULT_SECURITY_APPARMOR 232 default "apparmor" if DEFAULT_SECURITY_APPARMOR
233 default "yama" if DEFAULT_SECURITY_YAMA
228 default "" if DEFAULT_SECURITY_DAC 234 default "" if DEFAULT_SECURITY_DAC
229 235
230endmenu 236endmenu
diff --git a/security/Makefile b/security/Makefile
index a5e502f8a05b..c26c81e92571 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -7,6 +7,7 @@ subdir-$(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 9subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
10subdir-$(CONFIG_SECURITY_YAMA) += yama
10 11
11# always enable default capabilities 12# always enable default capabilities
12obj-y += commoncap.o 13obj-y += commoncap.o
@@ -21,6 +22,7 @@ obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
21obj-$(CONFIG_AUDIT) += lsm_audit.o 22obj-$(CONFIG_AUDIT) += lsm_audit.o
22obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o 23obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
23obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o 24obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o
25obj-$(CONFIG_SECURITY_YAMA) += yama/built-in.o
24obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o 26obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
25 27
26# Object integrity file lists 28# Object integrity file lists
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 2dafe50a2e25..806bd19af7f2 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -15,7 +15,7 @@ clean-files := capability_names.h rlim_names.h
15# to 15# to
16# [1] = "dac_override", 16# [1] = "dac_override",
17quiet_cmd_make-caps = GEN $@ 17quiet_cmd_make-caps = GEN $@
18cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ;\ 18cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
19 sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \ 19 sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \
20 -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\ 20 -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
21 echo "};" >> $@ 21 echo "};" >> $@
@@ -28,25 +28,38 @@ cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ;\
28# [RLIMIT_STACK] = "stack", 28# [RLIMIT_STACK] = "stack",
29# 29#
30# and build a second integer table (with the second sed cmd), that maps 30# and build a second integer table (with the second sed cmd), that maps
31# RLIMIT defines to the order defined in asm-generic/resource.h Thi is 31# RLIMIT defines to the order defined in asm-generic/resource.h This is
32# required by policy load to map policy ordering of RLIMITs to internal 32# required by policy load to map policy ordering of RLIMITs to internal
33# ordering for architectures that redefine an RLIMIT. 33# ordering for architectures that redefine an RLIMIT.
34# Transforms lines from 34# Transforms lines from
35# #define RLIMIT_STACK 3 /* max stack size */ 35# #define RLIMIT_STACK 3 /* max stack size */
36# to 36# to
37# RLIMIT_STACK, 37# RLIMIT_STACK,
38#
39# and build the securityfs entries for the mapping.
40# Transforms lines from
41# #define RLIMIT_FSIZE 1 /* Maximum filesize */
42# #define RLIMIT_STACK 3 /* max stack size */
43# to
44# #define AA_FS_RLIMIT_MASK "fsize stack"
38quiet_cmd_make-rlim = GEN $@ 45quiet_cmd_make-rlim = GEN $@
39cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ;\ 46cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
47 > $@ ;\
40 sed $< >> $@ -r -n \ 48 sed $< >> $@ -r -n \
41 -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\ 49 -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\
42 echo "};" >> $@ ;\ 50 echo "};" >> $@ ;\
43 echo "static const int rlim_map[] = {" >> $@ ;\ 51 echo "static const int rlim_map[RLIM_NLIMITS] = {" >> $@ ;\
44 sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\ 52 sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
45 echo "};" >> $@ 53 echo "};" >> $@ ; \
54 echo -n '\#define AA_FS_RLIMIT_MASK "' >> $@ ;\
55 sed -r -n 's/^\# ?define[ \t]+RLIMIT_([A-Z0-9_]+).*/\L\1/p' $< | \
56 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
46 57
47$(obj)/capability.o : $(obj)/capability_names.h 58$(obj)/capability.o : $(obj)/capability_names.h
48$(obj)/resource.o : $(obj)/rlim_names.h 59$(obj)/resource.o : $(obj)/rlim_names.h
49$(obj)/capability_names.h : $(srctree)/include/linux/capability.h 60$(obj)/capability_names.h : $(srctree)/include/linux/capability.h \
61 $(src)/Makefile
50 $(call cmd,make-caps) 62 $(call cmd,make-caps)
51$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h 63$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h \
64 $(src)/Makefile
52 $(call cmd,make-rlim) 65 $(call cmd,make-rlim)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index e39df6d43779..16c15ec6f670 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -18,12 +18,14 @@
18#include <linux/seq_file.h> 18#include <linux/seq_file.h>
19#include <linux/uaccess.h> 19#include <linux/uaccess.h>
20#include <linux/namei.h> 20#include <linux/namei.h>
21#include <linux/capability.h>
21 22
22#include "include/apparmor.h" 23#include "include/apparmor.h"
23#include "include/apparmorfs.h" 24#include "include/apparmorfs.h"
24#include "include/audit.h" 25#include "include/audit.h"
25#include "include/context.h" 26#include "include/context.h"
26#include "include/policy.h" 27#include "include/policy.h"
28#include "include/resource.h"
27 29
28/** 30/**
29 * aa_simple_write_to_buffer - common routine for getting policy from user 31 * aa_simple_write_to_buffer - common routine for getting policy from user
@@ -142,38 +144,166 @@ static const struct file_operations aa_fs_profile_remove = {
142 .llseek = default_llseek, 144 .llseek = default_llseek,
143}; 145};
144 146
145/** Base file system setup **/ 147static int aa_fs_seq_show(struct seq_file *seq, void *v)
148{
149 struct aa_fs_entry *fs_file = seq->private;
150
151 if (!fs_file)
152 return 0;
146 153
147static struct dentry *aa_fs_dentry __initdata; 154 switch (fs_file->v_type) {
155 case AA_FS_TYPE_BOOLEAN:
156 seq_printf(seq, "%s\n", fs_file->v.boolean ? "yes" : "no");
157 break;
158 case AA_FS_TYPE_STRING:
159 seq_printf(seq, "%s\n", fs_file->v.string);
160 break;
161 case AA_FS_TYPE_U64:
162 seq_printf(seq, "%#08lx\n", fs_file->v.u64);
163 break;
164 default:
165 /* Ignore unpritable entry types. */
166 break;
167 }
168
169 return 0;
170}
148 171
149static void __init aafs_remove(const char *name) 172static int aa_fs_seq_open(struct inode *inode, struct file *file)
150{ 173{
151 struct dentry *dentry; 174 return single_open(file, aa_fs_seq_show, inode->i_private);
175}
176
177const struct file_operations aa_fs_seq_file_ops = {
178 .owner = THIS_MODULE,
179 .open = aa_fs_seq_open,
180 .read = seq_read,
181 .llseek = seq_lseek,
182 .release = single_release,
183};
184
185/** Base file system setup **/
186
187static struct aa_fs_entry aa_fs_entry_file[] = {
188 AA_FS_FILE_STRING("mask", "create read write exec append mmap_exec " \
189 "link lock"),
190 { }
191};
152 192
153 dentry = lookup_one_len(name, aa_fs_dentry, strlen(name)); 193static struct aa_fs_entry aa_fs_entry_domain[] = {
154 if (!IS_ERR(dentry)) { 194 AA_FS_FILE_BOOLEAN("change_hat", 1),
155 securityfs_remove(dentry); 195 AA_FS_FILE_BOOLEAN("change_hatv", 1),
156 dput(dentry); 196 AA_FS_FILE_BOOLEAN("change_onexec", 1),
197 AA_FS_FILE_BOOLEAN("change_profile", 1),
198 { }
199};
200
201static struct aa_fs_entry aa_fs_entry_features[] = {
202 AA_FS_DIR("domain", aa_fs_entry_domain),
203 AA_FS_DIR("file", aa_fs_entry_file),
204 AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
205 AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
206 { }
207};
208
209static struct aa_fs_entry aa_fs_entry_apparmor[] = {
210 AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load),
211 AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace),
212 AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove),
213 AA_FS_DIR("features", aa_fs_entry_features),
214 { }
215};
216
217static struct aa_fs_entry aa_fs_entry =
218 AA_FS_DIR("apparmor", aa_fs_entry_apparmor);
219
220/**
221 * aafs_create_file - create a file entry in the apparmor securityfs
222 * @fs_file: aa_fs_entry to build an entry for (NOT NULL)
223 * @parent: the parent dentry in the securityfs
224 *
225 * Use aafs_remove_file to remove entries created with this fn.
226 */
227static int __init aafs_create_file(struct aa_fs_entry *fs_file,
228 struct dentry *parent)
229{
230 int error = 0;
231
232 fs_file->dentry = securityfs_create_file(fs_file->name,
233 S_IFREG | fs_file->mode,
234 parent, fs_file,
235 fs_file->file_ops);
236 if (IS_ERR(fs_file->dentry)) {
237 error = PTR_ERR(fs_file->dentry);
238 fs_file->dentry = NULL;
157 } 239 }
240 return error;
158} 241}
159 242
160/** 243/**
161 * aafs_create - create an entry in the apparmor filesystem 244 * aafs_create_dir - recursively create a directory entry in the securityfs
162 * @name: name of the entry (NOT NULL) 245 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL)
163 * @mask: file permission mask of the file 246 * @parent: the parent dentry in the securityfs
164 * @fops: file operations for the file (NOT NULL)
165 * 247 *
166 * Used aafs_remove to remove entries created with this fn. 248 * Use aafs_remove_dir to remove entries created with this fn.
167 */ 249 */
168static int __init aafs_create(const char *name, umode_t mask, 250static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
169 const struct file_operations *fops) 251 struct dentry *parent)
170{ 252{
171 struct dentry *dentry; 253 int error;
254 struct aa_fs_entry *fs_file;
172 255
173 dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry, 256 fs_dir->dentry = securityfs_create_dir(fs_dir->name, parent);
174 NULL, fops); 257 if (IS_ERR(fs_dir->dentry)) {
258 error = PTR_ERR(fs_dir->dentry);
259 fs_dir->dentry = NULL;
260 goto failed;
261 }
175 262
176 return IS_ERR(dentry) ? PTR_ERR(dentry) : 0; 263 for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) {
264 if (fs_file->v_type == AA_FS_TYPE_DIR)
265 error = aafs_create_dir(fs_file, fs_dir->dentry);
266 else
267 error = aafs_create_file(fs_file, fs_dir->dentry);
268 if (error)
269 goto failed;
270 }
271
272 return 0;
273
274failed:
275 return error;
276}
277
278/**
279 * aafs_remove_file - drop a single file entry in the apparmor securityfs
280 * @fs_file: aa_fs_entry to detach from the securityfs (NOT NULL)
281 */
282static void __init aafs_remove_file(struct aa_fs_entry *fs_file)
283{
284 if (!fs_file->dentry)
285 return;
286
287 securityfs_remove(fs_file->dentry);
288 fs_file->dentry = NULL;
289}
290
291/**
292 * aafs_remove_dir - recursively drop a directory entry from the securityfs
293 * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL)
294 */
295static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir)
296{
297 struct aa_fs_entry *fs_file;
298
299 for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) {
300 if (fs_file->v_type == AA_FS_TYPE_DIR)
301 aafs_remove_dir(fs_file);
302 else
303 aafs_remove_file(fs_file);
304 }
305
306 aafs_remove_file(fs_dir);
177} 307}
178 308
179/** 309/**
@@ -183,14 +313,7 @@ static int __init aafs_create(const char *name, umode_t mask,
183 */ 313 */
184void __init aa_destroy_aafs(void) 314void __init aa_destroy_aafs(void)
185{ 315{
186 if (aa_fs_dentry) { 316 aafs_remove_dir(&aa_fs_entry);
187 aafs_remove(".remove");
188 aafs_remove(".replace");
189 aafs_remove(".load");
190
191 securityfs_remove(aa_fs_dentry);
192 aa_fs_dentry = NULL;
193 }
194} 317}
195 318
196/** 319/**
@@ -207,25 +330,13 @@ static int __init aa_create_aafs(void)
207 if (!apparmor_initialized) 330 if (!apparmor_initialized)
208 return 0; 331 return 0;
209 332
210 if (aa_fs_dentry) { 333 if (aa_fs_entry.dentry) {
211 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__); 334 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
212 return -EEXIST; 335 return -EEXIST;
213 } 336 }
214 337
215 aa_fs_dentry = securityfs_create_dir("apparmor", NULL); 338 /* Populate fs tree. */
216 if (IS_ERR(aa_fs_dentry)) { 339 error = aafs_create_dir(&aa_fs_entry, NULL);
217 error = PTR_ERR(aa_fs_dentry);
218 aa_fs_dentry = NULL;
219 goto error;
220 }
221
222 error = aafs_create(".load", 0640, &aa_fs_profile_load);
223 if (error)
224 goto error;
225 error = aafs_create(".replace", 0640, &aa_fs_profile_replace);
226 if (error)
227 goto error;
228 error = aafs_create(".remove", 0640, &aa_fs_profile_remove);
229 if (error) 340 if (error)
230 goto error; 341 goto error;
231 342
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index f3fafedd798a..5ff67776a5ad 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -19,7 +19,7 @@
19#include "include/audit.h" 19#include "include/audit.h"
20#include "include/policy.h" 20#include "include/policy.h"
21 21
22const char *op_table[] = { 22const char *const op_table[] = {
23 "null", 23 "null",
24 24
25 "sysctl", 25 "sysctl",
@@ -73,7 +73,7 @@ const char *op_table[] = {
73 "profile_remove" 73 "profile_remove"
74}; 74};
75 75
76const char *audit_mode_names[] = { 76const char *const audit_mode_names[] = {
77 "normal", 77 "normal",
78 "quiet_denied", 78 "quiet_denied",
79 "quiet", 79 "quiet",
@@ -81,7 +81,7 @@ const char *audit_mode_names[] = {
81 "all" 81 "all"
82}; 82};
83 83
84static char *aa_audit_type[] = { 84static const char *const aa_audit_type[] = {
85 "AUDIT", 85 "AUDIT",
86 "ALLOWED", 86 "ALLOWED",
87 "DENIED", 87 "DENIED",
@@ -89,6 +89,7 @@ static char *aa_audit_type[] = {
89 "STATUS", 89 "STATUS",
90 "ERROR", 90 "ERROR",
91 "KILLED" 91 "KILLED"
92 "AUTO"
92}; 93};
93 94
94/* 95/*
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index c1e18ba5bdc0..7c69599a69e1 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -372,13 +372,12 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
372 state = profile->file.start; 372 state = profile->file.start;
373 373
374 /* buffer freed below, name is pointer into buffer */ 374 /* buffer freed below, name is pointer into buffer */
375 error = aa_get_name(&bprm->file->f_path, profile->path_flags, &buffer, 375 error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer,
376 &name); 376 &name, &info);
377 if (error) { 377 if (error) {
378 if (profile->flags & 378 if (profile->flags &
379 (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED)) 379 (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED))
380 error = 0; 380 error = 0;
381 info = "Exec failed name resolution";
382 name = bprm->filename; 381 name = bprm->filename;
383 goto audit; 382 goto audit;
384 } 383 }
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index 7312db741219..3022c0f4f0db 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -173,8 +173,6 @@ static u32 map_old_perms(u32 old)
173 if (old & 0x40) /* AA_EXEC_MMAP */ 173 if (old & 0x40) /* AA_EXEC_MMAP */
174 new |= AA_EXEC_MMAP; 174 new |= AA_EXEC_MMAP;
175 175
176 new |= AA_MAY_META_READ;
177
178 return new; 176 return new;
179} 177}
180 178
@@ -212,6 +210,7 @@ static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state,
212 perms.quiet = map_old_perms(dfa_other_quiet(dfa, state)); 210 perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
213 perms.xindex = dfa_other_xindex(dfa, state); 211 perms.xindex = dfa_other_xindex(dfa, state);
214 } 212 }
213 perms.allow |= AA_MAY_META_READ;
215 214
216 /* change_profile wasn't determined by ownership in old mapping */ 215 /* change_profile wasn't determined by ownership in old mapping */
217 if (ACCEPT_TABLE(dfa)[state] & 0x80000000) 216 if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
@@ -279,22 +278,16 @@ int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
279 int error; 278 int error;
280 279
281 flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); 280 flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
282 error = aa_get_name(path, flags, &buffer, &name); 281 error = aa_path_name(path, flags, &buffer, &name, &info);
283 if (error) { 282 if (error) {
284 if (error == -ENOENT && is_deleted(path->dentry)) { 283 if (error == -ENOENT && is_deleted(path->dentry)) {
285 /* Access to open files that are deleted are 284 /* Access to open files that are deleted are
286 * give a pass (implicit delegation) 285 * give a pass (implicit delegation)
287 */ 286 */
288 error = 0; 287 error = 0;
288 info = NULL;
289 perms.allow = request; 289 perms.allow = request;
290 } else if (error == -ENOENT) 290 }
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 { 291 } else {
299 aa_str_perms(profile->file.dfa, profile->file.start, name, cond, 292 aa_str_perms(profile->file.dfa, profile->file.start, name, cond,
300 &perms); 293 &perms);
@@ -365,12 +358,14 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
365 lperms = nullperms; 358 lperms = nullperms;
366 359
367 /* buffer freed below, lname is pointer in buffer */ 360 /* buffer freed below, lname is pointer in buffer */
368 error = aa_get_name(&link, profile->path_flags, &buffer, &lname); 361 error = aa_path_name(&link, profile->path_flags, &buffer, &lname,
362 &info);
369 if (error) 363 if (error)
370 goto audit; 364 goto audit;
371 365
372 /* buffer2 freed below, tname is pointer in buffer2 */ 366 /* buffer2 freed below, tname is pointer in buffer2 */
373 error = aa_get_name(&target, profile->path_flags, &buffer2, &tname); 367 error = aa_path_name(&target, profile->path_flags, &buffer2, &tname,
368 &info);
374 if (error) 369 if (error)
375 goto audit; 370 goto audit;
376 371
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index df3649560818..40aedd9f73ea 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -19,6 +19,19 @@
19 19
20#include "match.h" 20#include "match.h"
21 21
22/*
23 * Class of mediation types in the AppArmor policy db
24 */
25#define AA_CLASS_ENTRY 0
26#define AA_CLASS_UNKNOWN 1
27#define AA_CLASS_FILE 2
28#define AA_CLASS_CAP 3
29#define AA_CLASS_NET 4
30#define AA_CLASS_RLIMITS 5
31#define AA_CLASS_DOMAIN 6
32
33#define AA_CLASS_LAST AA_CLASS_DOMAIN
34
22/* Control parameters settable through module/boot flags */ 35/* Control parameters settable through module/boot flags */
23extern enum audit_mode aa_g_audit; 36extern enum audit_mode aa_g_audit;
24extern bool aa_g_audit_header; 37extern bool aa_g_audit_header;
@@ -81,7 +94,7 @@ static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
81 unsigned int start) 94 unsigned int start)
82{ 95{
83 /* the null transition only needs the string's null terminator byte */ 96 /* the null transition only needs the string's null terminator byte */
84 return aa_dfa_match_len(dfa, start, "", 1); 97 return aa_dfa_next(dfa, start, 0);
85} 98}
86 99
87static inline bool mediated_filesystem(struct inode *inode) 100static inline bool mediated_filesystem(struct inode *inode)
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index cb1e93a114d7..7ea4769fab3f 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -15,6 +15,50 @@
15#ifndef __AA_APPARMORFS_H 15#ifndef __AA_APPARMORFS_H
16#define __AA_APPARMORFS_H 16#define __AA_APPARMORFS_H
17 17
18enum aa_fs_type {
19 AA_FS_TYPE_BOOLEAN,
20 AA_FS_TYPE_STRING,
21 AA_FS_TYPE_U64,
22 AA_FS_TYPE_FOPS,
23 AA_FS_TYPE_DIR,
24};
25
26struct aa_fs_entry;
27
28struct aa_fs_entry {
29 const char *name;
30 struct dentry *dentry;
31 umode_t mode;
32 enum aa_fs_type v_type;
33 union {
34 bool boolean;
35 char *string;
36 unsigned long u64;
37 struct aa_fs_entry *files;
38 } v;
39 const struct file_operations *file_ops;
40};
41
42extern const struct file_operations aa_fs_seq_file_ops;
43
44#define AA_FS_FILE_BOOLEAN(_name, _value) \
45 { .name = (_name), .mode = 0444, \
46 .v_type = AA_FS_TYPE_BOOLEAN, .v.boolean = (_value), \
47 .file_ops = &aa_fs_seq_file_ops }
48#define AA_FS_FILE_STRING(_name, _value) \
49 { .name = (_name), .mode = 0444, \
50 .v_type = AA_FS_TYPE_STRING, .v.string = (_value), \
51 .file_ops = &aa_fs_seq_file_ops }
52#define AA_FS_FILE_U64(_name, _value) \
53 { .name = (_name), .mode = 0444, \
54 .v_type = AA_FS_TYPE_U64, .v.u64 = (_value), \
55 .file_ops = &aa_fs_seq_file_ops }
56#define AA_FS_FILE_FOPS(_name, _mode, _fops) \
57 { .name = (_name), .v_type = AA_FS_TYPE_FOPS, \
58 .mode = (_mode), .file_ops = (_fops) }
59#define AA_FS_DIR(_name, _value) \
60 { .name = (_name), .v_type = AA_FS_TYPE_DIR, .v.files = (_value) }
61
18extern void __init aa_destroy_aafs(void); 62extern void __init aa_destroy_aafs(void);
19 63
20#endif /* __AA_APPARMORFS_H */ 64#endif /* __AA_APPARMORFS_H */
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 1951786d32e9..4ba78c203af1 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -25,11 +25,9 @@
25 25
26struct aa_profile; 26struct aa_profile;
27 27
28extern const char *audit_mode_names[]; 28extern const char *const audit_mode_names[];
29#define AUDIT_MAX_INDEX 5 29#define AUDIT_MAX_INDEX 5
30 30
31#define AUDIT_APPARMOR_AUTO 0 /* auto choose audit message type */
32
33enum audit_mode { 31enum audit_mode {
34 AUDIT_NORMAL, /* follow normal auditing of accesses */ 32 AUDIT_NORMAL, /* follow normal auditing of accesses */
35 AUDIT_QUIET_DENIED, /* quiet all denied access messages */ 33 AUDIT_QUIET_DENIED, /* quiet all denied access messages */
@@ -45,10 +43,11 @@ enum audit_type {
45 AUDIT_APPARMOR_HINT, 43 AUDIT_APPARMOR_HINT,
46 AUDIT_APPARMOR_STATUS, 44 AUDIT_APPARMOR_STATUS,
47 AUDIT_APPARMOR_ERROR, 45 AUDIT_APPARMOR_ERROR,
48 AUDIT_APPARMOR_KILL 46 AUDIT_APPARMOR_KILL,
47 AUDIT_APPARMOR_AUTO
49}; 48};
50 49
51extern const char *op_table[]; 50extern const char *const op_table[];
52enum aa_ops { 51enum aa_ops {
53 OP_NULL, 52 OP_NULL,
54 53
diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
index ab8c6d87f758..f98fd4701d80 100644
--- a/security/apparmor/include/file.h
+++ b/security/apparmor/include/file.h
@@ -117,7 +117,7 @@ static inline u16 dfa_map_xindex(u16 mask)
117 index |= AA_X_NAME; 117 index |= AA_X_NAME;
118 } else if (old_index == 3) { 118 } else if (old_index == 3) {
119 index |= AA_X_NAME | AA_X_CHILD; 119 index |= AA_X_NAME | AA_X_CHILD;
120 } else { 120 } else if (old_index) {
121 index |= AA_X_TABLE; 121 index |= AA_X_TABLE;
122 index |= old_index - 4; 122 index |= old_index - 4;
123 } 123 }
diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
index a4a863997bd5..775843e7f984 100644
--- a/security/apparmor/include/match.h
+++ b/security/apparmor/include/match.h
@@ -116,6 +116,9 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
116 const char *str, int len); 116 const char *str, int len);
117unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start, 117unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
118 const char *str); 118 const char *str);
119unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
120 const char c);
121
119void aa_dfa_free_kref(struct kref *kref); 122void aa_dfa_free_kref(struct kref *kref);
120 123
121/** 124/**
diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
index 27b327a7fae5..286ac75dc88b 100644
--- a/security/apparmor/include/path.h
+++ b/security/apparmor/include/path.h
@@ -26,6 +26,7 @@ enum path_flags {
26 PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */ 26 PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */
27}; 27};
28 28
29int aa_get_name(struct path *path, int flags, char **buffer, const char **name); 29int aa_path_name(struct path *path, int flags, char **buffer,
30 const char **name, const char **info);
30 31
31#endif /* __AA_PATH_H */ 32#endif /* __AA_PATH_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index aeda5cf56904..bda4569fdd83 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -29,7 +29,7 @@
29#include "file.h" 29#include "file.h"
30#include "resource.h" 30#include "resource.h"
31 31
32extern const char *profile_mode_names[]; 32extern const char *const profile_mode_names[];
33#define APPARMOR_NAMES_MAX_INDEX 3 33#define APPARMOR_NAMES_MAX_INDEX 3
34 34
35#define COMPLAIN_MODE(_profile) \ 35#define COMPLAIN_MODE(_profile) \
@@ -129,6 +129,17 @@ struct aa_namespace {
129 struct list_head sub_ns; 129 struct list_head sub_ns;
130}; 130};
131 131
132/* struct aa_policydb - match engine for a policy
133 * dfa: dfa pattern match
134 * start: set of start states for the different classes of data
135 */
136struct aa_policydb {
137 /* Generic policy DFA specific rule types will be subsections of it */
138 struct aa_dfa *dfa;
139 unsigned int start[AA_CLASS_LAST + 1];
140
141};
142
132/* struct aa_profile - basic confinement data 143/* struct aa_profile - basic confinement data
133 * @base - base components of the profile (name, refcount, lists, lock ...) 144 * @base - base components of the profile (name, refcount, lists, lock ...)
134 * @parent: parent of profile 145 * @parent: parent of profile
@@ -143,6 +154,7 @@ struct aa_namespace {
143 * @flags: flags controlling profile behavior 154 * @flags: flags controlling profile behavior
144 * @path_flags: flags controlling path generation behavior 155 * @path_flags: flags controlling path generation behavior
145 * @size: the memory consumed by this profiles rules 156 * @size: the memory consumed by this profiles rules
157 * @policy: general match rules governing policy
146 * @file: The set of rules governing basic file access and domain transitions 158 * @file: The set of rules governing basic file access and domain transitions
147 * @caps: capabilities for the profile 159 * @caps: capabilities for the profile
148 * @rlimits: rlimits for the profile 160 * @rlimits: rlimits for the profile
@@ -179,6 +191,7 @@ struct aa_profile {
179 u32 path_flags; 191 u32 path_flags;
180 int size; 192 int size;
181 193
194 struct aa_policydb policy;
182 struct aa_file_rules file; 195 struct aa_file_rules file;
183 struct aa_caps caps; 196 struct aa_caps caps;
184 struct aa_rlimit rlimits; 197 struct aa_rlimit rlimits;
diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
index 02baec732bb5..d3f4cf027957 100644
--- a/security/apparmor/include/resource.h
+++ b/security/apparmor/include/resource.h
@@ -18,6 +18,8 @@
18#include <linux/resource.h> 18#include <linux/resource.h>
19#include <linux/sched.h> 19#include <linux/sched.h>
20 20
21#include "apparmorfs.h"
22
21struct aa_profile; 23struct aa_profile;
22 24
23/* struct aa_rlimit - rlimit settings for the profile 25/* struct aa_rlimit - rlimit settings for the profile
@@ -32,6 +34,8 @@ struct aa_rlimit {
32 struct rlimit limits[RLIM_NLIMITS]; 34 struct rlimit limits[RLIM_NLIMITS];
33}; 35};
34 36
37extern struct aa_fs_entry aa_fs_entry_rlimit[];
38
35int aa_map_resource(int resource); 39int aa_map_resource(int resource);
36int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, 40int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *,
37 unsigned int resource, struct rlimit *new_rlim); 41 unsigned int resource, struct rlimit *new_rlim);
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 94de6b4907c8..90971a8c3789 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -335,12 +335,12 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
335} 335}
336 336
337/** 337/**
338 * aa_dfa_next_state - traverse @dfa to find state @str stops at 338 * aa_dfa_match - traverse @dfa to find state @str stops at
339 * @dfa: the dfa to match @str against (NOT NULL) 339 * @dfa: the dfa to match @str against (NOT NULL)
340 * @start: the state of the dfa to start matching in 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) 341 * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
342 * 342 *
343 * aa_dfa_next_state will match @str against the dfa and return the state it 343 * aa_dfa_match 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 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. 345 * label, or as the start state of a continuing match.
346 * 346 *
@@ -349,5 +349,79 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
349unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start, 349unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
350 const char *str) 350 const char *str)
351{ 351{
352 return aa_dfa_match_len(dfa, start, str, strlen(str)); 352 u16 *def = DEFAULT_TABLE(dfa);
353 u32 *base = BASE_TABLE(dfa);
354 u16 *next = NEXT_TABLE(dfa);
355 u16 *check = CHECK_TABLE(dfa);
356 unsigned int state = start, pos;
357
358 if (state == 0)
359 return 0;
360
361 /* current state is <state>, matching character *str */
362 if (dfa->tables[YYTD_ID_EC]) {
363 /* Equivalence class table defined */
364 u8 *equiv = EQUIV_TABLE(dfa);
365 /* default is direct to next state */
366 while (*str) {
367 pos = base[state] + equiv[(u8) *str++];
368 if (check[pos] == state)
369 state = next[pos];
370 else
371 state = def[state];
372 }
373 } else {
374 /* default is direct to next state */
375 while (*str) {
376 pos = base[state] + (u8) *str++;
377 if (check[pos] == state)
378 state = next[pos];
379 else
380 state = def[state];
381 }
382 }
383
384 return state;
385}
386
387/**
388 * aa_dfa_next - step one character to the next state in the dfa
389 * @dfa: the dfa to tranverse (NOT NULL)
390 * @state: the state to start in
391 * @c: the input character to transition on
392 *
393 * aa_dfa_match will step through the dfa by one input character @c
394 *
395 * Returns: state reach after input @c
396 */
397unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
398 const char c)
399{
400 u16 *def = DEFAULT_TABLE(dfa);
401 u32 *base = BASE_TABLE(dfa);
402 u16 *next = NEXT_TABLE(dfa);
403 u16 *check = CHECK_TABLE(dfa);
404 unsigned int pos;
405
406 /* current state is <state>, matching character *str */
407 if (dfa->tables[YYTD_ID_EC]) {
408 /* Equivalence class table defined */
409 u8 *equiv = EQUIV_TABLE(dfa);
410 /* default is direct to next state */
411
412 pos = base[state] + equiv[(u8) c];
413 if (check[pos] == state)
414 state = next[pos];
415 else
416 state = def[state];
417 } else {
418 /* default is direct to next state */
419 pos = base[state] + (u8) c;
420 if (check[pos] == state)
421 state = next[pos];
422 else
423 state = def[state];
424 }
425
426 return state;
353} 427}
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index 9d070a7c3ffc..2daeea4f9266 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -83,31 +83,29 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
83 struct path root; 83 struct path root;
84 get_fs_root(current->fs, &root); 84 get_fs_root(current->fs, &root);
85 res = __d_path(path, &root, buf, buflen); 85 res = __d_path(path, &root, buf, buflen);
86 if (res && !IS_ERR(res)) {
87 /* everything's fine */
88 *name = res;
89 path_put(&root);
90 goto ok;
91 }
92 path_put(&root); 86 path_put(&root);
93 connected = 0; 87 } else {
88 res = d_absolute_path(path, buf, buflen);
89 if (!our_mnt(path->mnt))
90 connected = 0;
94 } 91 }
95 92
96 res = d_absolute_path(path, buf, buflen);
97
98 *name = res;
99 /* handle error conditions - and still allow a partial path to 93 /* handle error conditions - and still allow a partial path to
100 * be returned. 94 * be returned.
101 */ 95 */
102 if (IS_ERR(res)) { 96 if (!res || IS_ERR(res)) {
103 error = PTR_ERR(res);
104 *name = buf;
105 goto out;
106 }
107 if (!our_mnt(path->mnt))
108 connected = 0; 97 connected = 0;
98 res = dentry_path_raw(path->dentry, buf, buflen);
99 if (IS_ERR(res)) {
100 error = PTR_ERR(res);
101 *name = buf;
102 goto out;
103 };
104 } else if (!our_mnt(path->mnt))
105 connected = 0;
106
107 *name = res;
109 108
110ok:
111 /* Handle two cases: 109 /* Handle two cases:
112 * 1. A deleted dentry && profile is not allowing mediation of deleted 110 * 1. A deleted dentry && profile is not allowing mediation of deleted
113 * 2. On some filesystems, newly allocated dentries appear to the 111 * 2. On some filesystems, newly allocated dentries appear to the
@@ -138,7 +136,7 @@ ok:
138 /* disconnected path, don't return pathname starting 136 /* disconnected path, don't return pathname starting
139 * with '/' 137 * with '/'
140 */ 138 */
141 error = -ESTALE; 139 error = -EACCES;
142 if (*res == '/') 140 if (*res == '/')
143 *name = res + 1; 141 *name = res + 1;
144 } 142 }
@@ -159,7 +157,7 @@ out:
159 * Returns: %0 else error on failure 157 * Returns: %0 else error on failure
160 */ 158 */
161static int get_name_to_buffer(struct path *path, int flags, char *buffer, 159static int get_name_to_buffer(struct path *path, int flags, char *buffer,
162 int size, char **name) 160 int size, char **name, const char **info)
163{ 161{
164 int adjust = (flags & PATH_IS_DIR) ? 1 : 0; 162 int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
165 int error = d_namespace_path(path, buffer, size - adjust, name, flags); 163 int error = d_namespace_path(path, buffer, size - adjust, name, flags);
@@ -171,15 +169,27 @@ static int get_name_to_buffer(struct path *path, int flags, char *buffer,
171 */ 169 */
172 strcpy(&buffer[size - 2], "/"); 170 strcpy(&buffer[size - 2], "/");
173 171
172 if (info && error) {
173 if (error == -ENOENT)
174 *info = "Failed name lookup - deleted entry";
175 else if (error == -ESTALE)
176 *info = "Failed name lookup - disconnected path";
177 else if (error == -ENAMETOOLONG)
178 *info = "Failed name lookup - name too long";
179 else
180 *info = "Failed name lookup";
181 }
182
174 return error; 183 return error;
175} 184}
176 185
177/** 186/**
178 * aa_get_name - compute the pathname of a file 187 * aa_path_name - compute the pathname of a file
179 * @path: path the file (NOT NULL) 188 * @path: path the file (NOT NULL)
180 * @flags: flags controlling path name generation 189 * @flags: flags controlling path name generation
181 * @buffer: buffer that aa_get_name() allocated (NOT NULL) 190 * @buffer: buffer that aa_get_name() allocated (NOT NULL)
182 * @name: Returns - the generated path name if !error (NOT NULL) 191 * @name: Returns - the generated path name if !error (NOT NULL)
192 * @info: Returns - information on why the path lookup failed (MAYBE NULL)
183 * 193 *
184 * @name is a pointer to the beginning of the pathname (which usually differs 194 * @name is a pointer to the beginning of the pathname (which usually differs
185 * from the beginning of the buffer), or NULL. If there is an error @name 195 * from the beginning of the buffer), or NULL. If there is an error @name
@@ -192,7 +202,8 @@ static int get_name_to_buffer(struct path *path, int flags, char *buffer,
192 * 202 *
193 * Returns: %0 else error code if could retrieve name 203 * Returns: %0 else error code if could retrieve name
194 */ 204 */
195int aa_get_name(struct path *path, int flags, char **buffer, const char **name) 205int aa_path_name(struct path *path, int flags, char **buffer, const char **name,
206 const char **info)
196{ 207{
197 char *buf, *str = NULL; 208 char *buf, *str = NULL;
198 int size = 256; 209 int size = 256;
@@ -206,7 +217,7 @@ int aa_get_name(struct path *path, int flags, char **buffer, const char **name)
206 if (!buf) 217 if (!buf)
207 return -ENOMEM; 218 return -ENOMEM;
208 219
209 error = get_name_to_buffer(path, flags, buf, size, &str); 220 error = get_name_to_buffer(path, flags, buf, size, &str, info);
210 if (error != -ENAMETOOLONG) 221 if (error != -ENAMETOOLONG)
211 break; 222 break;
212 223
@@ -214,6 +225,7 @@ int aa_get_name(struct path *path, int flags, char **buffer, const char **name)
214 size <<= 1; 225 size <<= 1;
215 if (size > aa_g_path_max) 226 if (size > aa_g_path_max)
216 return -ENAMETOOLONG; 227 return -ENAMETOOLONG;
228 *info = NULL;
217 } 229 }
218 *buffer = buf; 230 *buffer = buf;
219 *name = str; 231 *name = str;
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 4f0eadee78b8..906414383022 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -93,7 +93,7 @@
93/* root profile namespace */ 93/* root profile namespace */
94struct aa_namespace *root_ns; 94struct aa_namespace *root_ns;
95 95
96const char *profile_mode_names[] = { 96const char *const profile_mode_names[] = {
97 "enforce", 97 "enforce",
98 "complain", 98 "complain",
99 "kill", 99 "kill",
@@ -749,6 +749,7 @@ static void free_profile(struct aa_profile *profile)
749 749
750 aa_free_sid(profile->sid); 750 aa_free_sid(profile->sid);
751 aa_put_dfa(profile->xmatch); 751 aa_put_dfa(profile->xmatch);
752 aa_put_dfa(profile->policy.dfa);
752 753
753 aa_put_profile(profile->replacedby); 754 aa_put_profile(profile->replacedby);
754 755
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 741dd13e089b..25fd51edc8da 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -84,7 +84,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
84 * @new: profile if it has been allocated (MAYBE NULL) 84 * @new: profile if it has been allocated (MAYBE NULL)
85 * @name: name of the profile being manipulated (MAYBE NULL) 85 * @name: name of the profile being manipulated (MAYBE NULL)
86 * @info: any extra info about the failure (MAYBE NULL) 86 * @info: any extra info about the failure (MAYBE NULL)
87 * @e: buffer position info (NOT NULL) 87 * @e: buffer position info
88 * @error: error code 88 * @error: error code
89 * 89 *
90 * Returns: %0 or error 90 * Returns: %0 or error
@@ -95,7 +95,8 @@ static int audit_iface(struct aa_profile *new, const char *name,
95 struct aa_profile *profile = __aa_current_profile(); 95 struct aa_profile *profile = __aa_current_profile();
96 struct common_audit_data sa; 96 struct common_audit_data sa;
97 COMMON_AUDIT_DATA_INIT(&sa, NONE); 97 COMMON_AUDIT_DATA_INIT(&sa, NONE);
98 sa.aad.iface.pos = e->pos - e->start; 98 if (e)
99 sa.aad.iface.pos = e->pos - e->start;
99 sa.aad.iface.target = new; 100 sa.aad.iface.target = new;
100 sa.aad.name = name; 101 sa.aad.name = name;
101 sa.aad.info = info; 102 sa.aad.info = info;
@@ -468,7 +469,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
468{ 469{
469 struct aa_profile *profile = NULL; 470 struct aa_profile *profile = NULL;
470 const char *name = NULL; 471 const char *name = NULL;
471 int error = -EPROTO; 472 int i, error = -EPROTO;
472 kernel_cap_t tmpcap; 473 kernel_cap_t tmpcap;
473 u32 tmp; 474 u32 tmp;
474 475
@@ -554,11 +555,35 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
554 goto fail; 555 goto fail;
555 if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL)) 556 if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
556 goto fail; 557 goto fail;
558 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
559 goto fail;
557 } 560 }
558 561
559 if (!unpack_rlimits(e, profile)) 562 if (!unpack_rlimits(e, profile))
560 goto fail; 563 goto fail;
561 564
565 if (unpack_nameX(e, AA_STRUCT, "policydb")) {
566 /* generic policy dfa - optional and may be NULL */
567 profile->policy.dfa = unpack_dfa(e);
568 if (IS_ERR(profile->policy.dfa)) {
569 error = PTR_ERR(profile->policy.dfa);
570 profile->policy.dfa = NULL;
571 goto fail;
572 }
573 if (!unpack_u32(e, &profile->policy.start[0], "start"))
574 /* default start state */
575 profile->policy.start[0] = DFA_START;
576 /* setup class index */
577 for (i = AA_CLASS_FILE; i <= AA_CLASS_LAST; i++) {
578 profile->policy.start[i] =
579 aa_dfa_next(profile->policy.dfa,
580 profile->policy.start[0],
581 i);
582 }
583 if (!unpack_nameX(e, AA_STRUCTEND, NULL))
584 goto fail;
585 }
586
562 /* get file rules */ 587 /* get file rules */
563 profile->file.dfa = unpack_dfa(e); 588 profile->file.dfa = unpack_dfa(e);
564 if (IS_ERR(profile->file.dfa)) { 589 if (IS_ERR(profile->file.dfa)) {
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
index a4136c10b1c6..72c25a4f2cfd 100644
--- a/security/apparmor/resource.c
+++ b/security/apparmor/resource.c
@@ -23,6 +23,11 @@
23 */ 23 */
24#include "rlim_names.h" 24#include "rlim_names.h"
25 25
26struct aa_fs_entry aa_fs_entry_rlimit[] = {
27 AA_FS_FILE_STRING("mask", AA_FS_RLIMIT_MASK),
28 { }
29};
30
26/* audit callback for resource specific fields */ 31/* audit callback for resource specific fields */
27static void audit_cb(struct audit_buffer *ab, void *va) 32static void audit_cb(struct audit_buffer *ab, void *va)
28{ 33{
diff --git a/security/capability.c b/security/capability.c
index 2f680eb02b59..5bb21b1c448c 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -358,6 +358,10 @@ static int cap_task_create(unsigned long clone_flags)
358 return 0; 358 return 0;
359} 359}
360 360
361static void cap_task_free(struct task_struct *task)
362{
363}
364
361static int cap_cred_alloc_blank(struct cred *cred, gfp_t gfp) 365static int cap_cred_alloc_blank(struct cred *cred, gfp_t gfp)
362{ 366{
363 return 0; 367 return 0;
@@ -954,6 +958,7 @@ void __init security_fixup_ops(struct security_operations *ops)
954 set_to_cap_if_null(ops, file_receive); 958 set_to_cap_if_null(ops, file_receive);
955 set_to_cap_if_null(ops, dentry_open); 959 set_to_cap_if_null(ops, dentry_open);
956 set_to_cap_if_null(ops, task_create); 960 set_to_cap_if_null(ops, task_create);
961 set_to_cap_if_null(ops, task_free);
957 set_to_cap_if_null(ops, cred_alloc_blank); 962 set_to_cap_if_null(ops, cred_alloc_blank);
958 set_to_cap_if_null(ops, cred_free); 963 set_to_cap_if_null(ops, cred_free);
959 set_to_cap_if_null(ops, cred_prepare); 964 set_to_cap_if_null(ops, cred_prepare);
diff --git a/security/commoncap.c b/security/commoncap.c
index 7ce191ea29a0..0cf4b53480a7 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -28,6 +28,7 @@
28#include <linux/prctl.h> 28#include <linux/prctl.h>
29#include <linux/securebits.h> 29#include <linux/securebits.h>
30#include <linux/user_namespace.h> 30#include <linux/user_namespace.h>
31#include <linux/binfmts.h>
31 32
32/* 33/*
33 * If a non-root user executes a setuid-root binary in 34 * If a non-root user executes a setuid-root binary in
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 4f554f20dc97..35664fe6daa1 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -9,8 +9,8 @@ config IMA
9 select CRYPTO_HMAC 9 select CRYPTO_HMAC
10 select CRYPTO_MD5 10 select CRYPTO_MD5
11 select CRYPTO_SHA1 11 select CRYPTO_SHA1
12 select TCG_TPM if !S390 && !UML 12 select TCG_TPM if HAS_IOMEM && !UML
13 select TCG_TIS if TCG_TPM 13 select TCG_TIS if TCG_TPM && X86
14 help 14 help
15 The Trusted Computing Group(TCG) runtime Integrity 15 The Trusted Computing Group(TCG) runtime Integrity
16 Measurement Architecture(IMA) maintains a list of hash 16 Measurement Architecture(IMA) maintains a list of hash
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
index 2ad942fb1e23..21e96bf188df 100644
--- a/security/integrity/ima/ima_audit.c
+++ b/security/integrity/ima/ima_audit.c
@@ -61,6 +61,6 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
61 audit_log_untrustedstring(ab, inode->i_sb->s_id); 61 audit_log_untrustedstring(ab, inode->i_sb->s_id);
62 audit_log_format(ab, " ino=%lu", inode->i_ino); 62 audit_log_format(ab, " ino=%lu", inode->i_ino);
63 } 63 }
64 audit_log_format(ab, " res=%d", !result ? 0 : 1); 64 audit_log_format(ab, " res=%d", !result);
65 audit_log_end(ab); 65 audit_log_end(ab);
66} 66}
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index d45061d02fee..d8edff209bf3 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -62,6 +62,7 @@ static struct ima_measure_rule_entry default_rules[] = {
62 {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, 62 {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
63 {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, 63 {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
64 {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, 64 {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
65 {.action = DONT_MEASURE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC},
65 {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC}, 66 {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
66 {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC}, 67 {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
67 {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC, 68 {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
@@ -417,7 +418,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
417 if (!result && (entry->action == UNKNOWN)) 418 if (!result && (entry->action == UNKNOWN))
418 result = -EINVAL; 419 result = -EINVAL;
419 420
420 audit_log_format(ab, "res=%d", !!result); 421 audit_log_format(ab, "res=%d", !result);
421 audit_log_end(ab); 422 audit_log_end(ab);
422 return result; 423 return result;
423} 424}
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 0b3f5d72af1c..6523599e9ac0 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -388,11 +388,24 @@ long keyctl_keyring_clear(key_serial_t ringid)
388 keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); 388 keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
389 if (IS_ERR(keyring_ref)) { 389 if (IS_ERR(keyring_ref)) {
390 ret = PTR_ERR(keyring_ref); 390 ret = PTR_ERR(keyring_ref);
391
392 /* Root is permitted to invalidate certain special keyrings */
393 if (capable(CAP_SYS_ADMIN)) {
394 keyring_ref = lookup_user_key(ringid, 0, 0);
395 if (IS_ERR(keyring_ref))
396 goto error;
397 if (test_bit(KEY_FLAG_ROOT_CAN_CLEAR,
398 &key_ref_to_ptr(keyring_ref)->flags))
399 goto clear;
400 goto error_put;
401 }
402
391 goto error; 403 goto error;
392 } 404 }
393 405
406clear:
394 ret = keyring_clear(key_ref_to_ptr(keyring_ref)); 407 ret = keyring_clear(key_ref_to_ptr(keyring_ref));
395 408error_put:
396 key_ref_put(keyring_ref); 409 key_ref_put(keyring_ref);
397error: 410error:
398 return ret; 411 return ret;
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 1068cb1939b3..be7ecb2018dd 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -657,7 +657,8 @@ try_again:
657 goto error; 657 goto error;
658 658
659 down_read(&cred->request_key_auth->sem); 659 down_read(&cred->request_key_auth->sem);
660 if (cred->request_key_auth->flags & KEY_FLAG_REVOKED) { 660 if (test_bit(KEY_FLAG_REVOKED,
661 &cred->request_key_auth->flags)) {
661 key_ref = ERR_PTR(-EKEYREVOKED); 662 key_ref = ERR_PTR(-EKEYREVOKED);
662 key = NULL; 663 key = NULL;
663 } else { 664 } else {
diff --git a/security/security.c b/security/security.c
index d7542493454d..bf619ffc9a4d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -19,6 +19,8 @@
19#include <linux/integrity.h> 19#include <linux/integrity.h>
20#include <linux/ima.h> 20#include <linux/ima.h>
21#include <linux/evm.h> 21#include <linux/evm.h>
22#include <linux/fsnotify.h>
23#include <net/flow.h>
22 24
23#define MAX_LSM_EVM_XATTR 2 25#define MAX_LSM_EVM_XATTR 2
24 26
@@ -187,25 +189,11 @@ int security_settime(const struct timespec *ts, const struct timezone *tz)
187 return security_ops->settime(ts, tz); 189 return security_ops->settime(ts, tz);
188} 190}
189 191
190int security_vm_enough_memory(long pages)
191{
192 WARN_ON(current->mm == NULL);
193 return security_ops->vm_enough_memory(current->mm, pages);
194}
195
196int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) 192int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
197{ 193{
198 WARN_ON(mm == NULL);
199 return security_ops->vm_enough_memory(mm, pages); 194 return security_ops->vm_enough_memory(mm, pages);
200} 195}
201 196
202int security_vm_enough_memory_kern(long pages)
203{
204 /* If current->mm is a kernel thread then we will pass NULL,
205 for this specific case that is fine */
206 return security_ops->vm_enough_memory(current->mm, pages);
207}
208
209int security_bprm_set_creds(struct linux_binprm *bprm) 197int security_bprm_set_creds(struct linux_binprm *bprm)
210{ 198{
211 return security_ops->bprm_set_creds(bprm); 199 return security_ops->bprm_set_creds(bprm);
@@ -729,6 +717,11 @@ int security_task_create(unsigned long clone_flags)
729 return security_ops->task_create(clone_flags); 717 return security_ops->task_create(clone_flags);
730} 718}
731 719
720void security_task_free(struct task_struct *task)
721{
722 security_ops->task_free(task);
723}
724
732int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) 725int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
733{ 726{
734 return security_ops->cred_alloc_blank(cred, gfp); 727 return security_ops->cred_alloc_blank(cred, gfp);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6a3683e28426..304929909375 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -81,6 +81,8 @@
81#include <linux/syslog.h> 81#include <linux/syslog.h>
82#include <linux/user_namespace.h> 82#include <linux/user_namespace.h>
83#include <linux/export.h> 83#include <linux/export.h>
84#include <linux/msg.h>
85#include <linux/shm.h>
84 86
85#include "avc.h" 87#include "avc.h"
86#include "objsec.h" 88#include "objsec.h"
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index e8af5b0ba80f..cd667b4089a5 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -36,6 +36,9 @@
36#include <linux/magic.h> 36#include <linux/magic.h>
37#include <linux/dcache.h> 37#include <linux/dcache.h>
38#include <linux/personality.h> 38#include <linux/personality.h>
39#include <linux/msg.h>
40#include <linux/shm.h>
41#include <linux/binfmts.h>
39#include "smack.h" 42#include "smack.h"
40 43
41#define task_security(task) (task_cred_xxx((task), security)) 44#define task_security(task) (task_cred_xxx((task), security))
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c
index 5ca47ea3049f..7ef9fa3e37e0 100644
--- a/security/tomoyo/audit.c
+++ b/security/tomoyo/audit.c
@@ -446,11 +446,11 @@ void tomoyo_read_log(struct tomoyo_io_buffer *head)
446 * tomoyo_poll_log - Wait for an audit log. 446 * tomoyo_poll_log - Wait for an audit log.
447 * 447 *
448 * @file: Pointer to "struct file". 448 * @file: Pointer to "struct file".
449 * @wait: Pointer to "poll_table". 449 * @wait: Pointer to "poll_table". Maybe NULL.
450 * 450 *
451 * Returns POLLIN | POLLRDNORM when ready to read an audit log. 451 * Returns POLLIN | POLLRDNORM when ready to read an audit log.
452 */ 452 */
453int tomoyo_poll_log(struct file *file, poll_table *wait) 453unsigned int tomoyo_poll_log(struct file *file, poll_table *wait)
454{ 454{
455 if (tomoyo_log_count) 455 if (tomoyo_log_count)
456 return POLLIN | POLLRDNORM; 456 return POLLIN | POLLRDNORM;
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index c47d3ce6c733..8656b16eef7b 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -1069,7 +1069,7 @@ static int tomoyo_write_task(struct tomoyo_acl_param *param)
1069 * 1069 *
1070 * @domainname: The name of domain. 1070 * @domainname: The name of domain.
1071 * 1071 *
1072 * Returns 0. 1072 * Returns 0 on success, negative value otherwise.
1073 * 1073 *
1074 * Caller holds tomoyo_read_lock(). 1074 * Caller holds tomoyo_read_lock().
1075 */ 1075 */
@@ -1081,7 +1081,7 @@ static int tomoyo_delete_domain(char *domainname)
1081 name.name = domainname; 1081 name.name = domainname;
1082 tomoyo_fill_path_info(&name); 1082 tomoyo_fill_path_info(&name);
1083 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 1083 if (mutex_lock_interruptible(&tomoyo_policy_lock))
1084 return 0; 1084 return -EINTR;
1085 /* Is there an active domain? */ 1085 /* Is there an active domain? */
1086 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 1086 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
1087 /* Never delete tomoyo_kernel_domain */ 1087 /* Never delete tomoyo_kernel_domain */
@@ -1164,15 +1164,16 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
1164 bool is_select = !is_delete && tomoyo_str_starts(&data, "select "); 1164 bool is_select = !is_delete && tomoyo_str_starts(&data, "select ");
1165 unsigned int profile; 1165 unsigned int profile;
1166 if (*data == '<') { 1166 if (*data == '<') {
1167 int ret = 0;
1167 domain = NULL; 1168 domain = NULL;
1168 if (is_delete) 1169 if (is_delete)
1169 tomoyo_delete_domain(data); 1170 ret = tomoyo_delete_domain(data);
1170 else if (is_select) 1171 else if (is_select)
1171 domain = tomoyo_find_domain(data); 1172 domain = tomoyo_find_domain(data);
1172 else 1173 else
1173 domain = tomoyo_assign_domain(data, false); 1174 domain = tomoyo_assign_domain(data, false);
1174 head->w.domain = domain; 1175 head->w.domain = domain;
1175 return 0; 1176 return ret;
1176 } 1177 }
1177 if (!domain) 1178 if (!domain)
1178 return -EINVAL; 1179 return -EINVAL;
@@ -2111,7 +2112,7 @@ static struct tomoyo_domain_info *tomoyo_find_domain_by_qid
2111 struct tomoyo_domain_info *domain = NULL; 2112 struct tomoyo_domain_info *domain = NULL;
2112 spin_lock(&tomoyo_query_list_lock); 2113 spin_lock(&tomoyo_query_list_lock);
2113 list_for_each_entry(ptr, &tomoyo_query_list, list) { 2114 list_for_each_entry(ptr, &tomoyo_query_list, list) {
2114 if (ptr->serial != serial || ptr->answer) 2115 if (ptr->serial != serial)
2115 continue; 2116 continue;
2116 domain = ptr->domain; 2117 domain = ptr->domain;
2117 break; 2118 break;
@@ -2130,28 +2131,13 @@ static struct tomoyo_domain_info *tomoyo_find_domain_by_qid
2130 * 2131 *
2131 * Waits for access requests which violated policy in enforcing mode. 2132 * Waits for access requests which violated policy in enforcing mode.
2132 */ 2133 */
2133static int tomoyo_poll_query(struct file *file, poll_table *wait) 2134static unsigned int tomoyo_poll_query(struct file *file, poll_table *wait)
2134{ 2135{
2135 struct list_head *tmp; 2136 if (!list_empty(&tomoyo_query_list))
2136 bool found = false; 2137 return POLLIN | POLLRDNORM;
2137 u8 i; 2138 poll_wait(file, &tomoyo_query_wait, wait);
2138 for (i = 0; i < 2; i++) { 2139 if (!list_empty(&tomoyo_query_list))
2139 spin_lock(&tomoyo_query_list_lock); 2140 return POLLIN | POLLRDNORM;
2140 list_for_each(tmp, &tomoyo_query_list) {
2141 struct tomoyo_query *ptr =
2142 list_entry(tmp, typeof(*ptr), list);
2143 if (ptr->answer)
2144 continue;
2145 found = true;
2146 break;
2147 }
2148 spin_unlock(&tomoyo_query_list_lock);
2149 if (found)
2150 return POLLIN | POLLRDNORM;
2151 if (i)
2152 break;
2153 poll_wait(file, &tomoyo_query_wait, wait);
2154 }
2155 return 0; 2141 return 0;
2156} 2142}
2157 2143
@@ -2175,8 +2161,6 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head)
2175 spin_lock(&tomoyo_query_list_lock); 2161 spin_lock(&tomoyo_query_list_lock);
2176 list_for_each(tmp, &tomoyo_query_list) { 2162 list_for_each(tmp, &tomoyo_query_list) {
2177 struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 2163 struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
2178 if (ptr->answer)
2179 continue;
2180 if (pos++ != head->r.query_index) 2164 if (pos++ != head->r.query_index)
2181 continue; 2165 continue;
2182 len = ptr->query_len; 2166 len = ptr->query_len;
@@ -2194,8 +2178,6 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head)
2194 spin_lock(&tomoyo_query_list_lock); 2178 spin_lock(&tomoyo_query_list_lock);
2195 list_for_each(tmp, &tomoyo_query_list) { 2179 list_for_each(tmp, &tomoyo_query_list) {
2196 struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 2180 struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
2197 if (ptr->answer)
2198 continue;
2199 if (pos++ != head->r.query_index) 2181 if (pos++ != head->r.query_index)
2200 continue; 2182 continue;
2201 /* 2183 /*
@@ -2243,8 +2225,10 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
2243 struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 2225 struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
2244 if (ptr->serial != serial) 2226 if (ptr->serial != serial)
2245 continue; 2227 continue;
2246 if (!ptr->answer) 2228 ptr->answer = answer;
2247 ptr->answer = answer; 2229 /* Remove from tomoyo_query_list. */
2230 if (ptr->answer)
2231 list_del_init(&ptr->list);
2248 break; 2232 break;
2249 } 2233 }
2250 spin_unlock(&tomoyo_query_list_lock); 2234 spin_unlock(&tomoyo_query_list_lock);
@@ -2477,18 +2461,17 @@ int tomoyo_open_control(const u8 type, struct file *file)
2477 * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface. 2461 * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface.
2478 * 2462 *
2479 * @file: Pointer to "struct file". 2463 * @file: Pointer to "struct file".
2480 * @wait: Pointer to "poll_table". 2464 * @wait: Pointer to "poll_table". Maybe NULL.
2481 * 2465 *
2482 * Waits for read readiness. 2466 * Returns POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM if ready to read/write,
2483 * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd and 2467 * POLLOUT | POLLWRNORM otherwise.
2484 * /sys/kernel/security/tomoyo/audit is handled by /usr/sbin/tomoyo-auditd.
2485 */ 2468 */
2486int tomoyo_poll_control(struct file *file, poll_table *wait) 2469unsigned int tomoyo_poll_control(struct file *file, poll_table *wait)
2487{ 2470{
2488 struct tomoyo_io_buffer *head = file->private_data; 2471 struct tomoyo_io_buffer *head = file->private_data;
2489 if (!head->poll) 2472 if (head->poll)
2490 return -ENOSYS; 2473 return head->poll(file, wait) | POLLOUT | POLLWRNORM;
2491 return head->poll(file, wait); 2474 return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
2492} 2475}
2493 2476
2494/** 2477/**
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 9512222d5581..30fd98369700 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -788,7 +788,7 @@ struct tomoyo_acl_param {
788struct tomoyo_io_buffer { 788struct tomoyo_io_buffer {
789 void (*read) (struct tomoyo_io_buffer *); 789 void (*read) (struct tomoyo_io_buffer *);
790 int (*write) (struct tomoyo_io_buffer *); 790 int (*write) (struct tomoyo_io_buffer *);
791 int (*poll) (struct file *file, poll_table *wait); 791 unsigned int (*poll) (struct file *file, poll_table *wait);
792 /* Exclusive lock for this structure. */ 792 /* Exclusive lock for this structure. */
793 struct mutex io_sem; 793 struct mutex io_sem;
794 char __user *read_user_buf; 794 char __user *read_user_buf;
@@ -981,8 +981,8 @@ int tomoyo_path_number_perm(const u8 operation, struct path *path,
981 unsigned long number); 981 unsigned long number);
982int tomoyo_path_perm(const u8 operation, struct path *path, 982int tomoyo_path_perm(const u8 operation, struct path *path,
983 const char *target); 983 const char *target);
984int tomoyo_poll_control(struct file *file, poll_table *wait); 984unsigned int tomoyo_poll_control(struct file *file, poll_table *wait);
985int tomoyo_poll_log(struct file *file, poll_table *wait); 985unsigned int tomoyo_poll_log(struct file *file, poll_table *wait);
986int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr, 986int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
987 int addr_len); 987 int addr_len);
988int tomoyo_socket_connect_permission(struct socket *sock, 988int tomoyo_socket_connect_permission(struct socket *sock,
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
index bee09d062057..fe00cdfd0267 100644
--- a/security/tomoyo/mount.c
+++ b/security/tomoyo/mount.c
@@ -199,30 +199,32 @@ int tomoyo_mount_permission(char *dev_name, struct path *path,
199 if (flags & MS_REMOUNT) { 199 if (flags & MS_REMOUNT) {
200 type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]; 200 type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT];
201 flags &= ~MS_REMOUNT; 201 flags &= ~MS_REMOUNT;
202 } 202 } else if (flags & MS_BIND) {
203 if (flags & MS_MOVE) {
204 type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];
205 flags &= ~MS_MOVE;
206 }
207 if (flags & MS_BIND) {
208 type = tomoyo_mounts[TOMOYO_MOUNT_BIND]; 203 type = tomoyo_mounts[TOMOYO_MOUNT_BIND];
209 flags &= ~MS_BIND; 204 flags &= ~MS_BIND;
210 } 205 } else if (flags & MS_SHARED) {
211 if (flags & MS_UNBINDABLE) { 206 if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
212 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE]; 207 return -EINVAL;
213 flags &= ~MS_UNBINDABLE; 208 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED];
214 } 209 flags &= ~MS_SHARED;
215 if (flags & MS_PRIVATE) { 210 } else if (flags & MS_PRIVATE) {
211 if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
212 return -EINVAL;
216 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE]; 213 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE];
217 flags &= ~MS_PRIVATE; 214 flags &= ~MS_PRIVATE;
218 } 215 } else if (flags & MS_SLAVE) {
219 if (flags & MS_SLAVE) { 216 if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
217 return -EINVAL;
220 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE]; 218 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE];
221 flags &= ~MS_SLAVE; 219 flags &= ~MS_SLAVE;
222 } 220 } else if (flags & MS_UNBINDABLE) {
223 if (flags & MS_SHARED) { 221 if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
224 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]; 222 return -EINVAL;
225 flags &= ~MS_SHARED; 223 type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE];
224 flags &= ~MS_UNBINDABLE;
225 } else if (flags & MS_MOVE) {
226 type = tomoyo_mounts[TOMOYO_MOUNT_MOVE];
227 flags &= ~MS_MOVE;
226 } 228 }
227 if (!type) 229 if (!type)
228 type = "<NULL>"; 230 type = "<NULL>";
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c
index 482b2a5f48f0..8592f2fc6ebb 100644
--- a/security/tomoyo/securityfs_if.c
+++ b/security/tomoyo/securityfs_if.c
@@ -157,9 +157,10 @@ static int tomoyo_release(struct inode *inode, struct file *file)
157 * tomoyo_poll - poll() for /sys/kernel/security/tomoyo/ interface. 157 * tomoyo_poll - poll() for /sys/kernel/security/tomoyo/ interface.
158 * 158 *
159 * @file: Pointer to "struct file". 159 * @file: Pointer to "struct file".
160 * @wait: Pointer to "poll_table". 160 * @wait: Pointer to "poll_table". Maybe NULL.
161 * 161 *
162 * Returns 0 on success, negative value otherwise. 162 * Returns POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM if ready to read/write,
163 * POLLOUT | POLLWRNORM otherwise.
163 */ 164 */
164static unsigned int tomoyo_poll(struct file *file, poll_table *wait) 165static unsigned int tomoyo_poll(struct file *file, poll_table *wait)
165{ 166{
diff --git a/security/yama/Kconfig b/security/yama/Kconfig
new file mode 100644
index 000000000000..51d6709d8bbd
--- /dev/null
+++ b/security/yama/Kconfig
@@ -0,0 +1,13 @@
1config SECURITY_YAMA
2 bool "Yama support"
3 depends on SECURITY
4 select SECURITYFS
5 select SECURITY_PATH
6 default n
7 help
8 This selects Yama, which extends DAC support with additional
9 system-wide security settings beyond regular Linux discretionary
10 access controls. Currently available is ptrace scope restriction.
11 Further information can be found in Documentation/security/Yama.txt.
12
13 If you are unsure how to answer this question, answer N.
diff --git a/security/yama/Makefile b/security/yama/Makefile
new file mode 100644
index 000000000000..8b5e06588456
--- /dev/null
+++ b/security/yama/Makefile
@@ -0,0 +1,3 @@
1obj-$(CONFIG_SECURITY_YAMA) := yama.o
2
3yama-y := yama_lsm.o
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
new file mode 100644
index 000000000000..573723843a04
--- /dev/null
+++ b/security/yama/yama_lsm.c
@@ -0,0 +1,323 @@
1/*
2 * Yama Linux Security Module
3 *
4 * Author: Kees Cook <keescook@chromium.org>
5 *
6 * Copyright (C) 2010 Canonical, Ltd.
7 * Copyright (C) 2011 The Chromium OS Authors.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2, as
11 * published by the Free Software Foundation.
12 *
13 */
14
15#include <linux/security.h>
16#include <linux/sysctl.h>
17#include <linux/ptrace.h>
18#include <linux/prctl.h>
19#include <linux/ratelimit.h>
20
21static int ptrace_scope = 1;
22
23/* describe a ptrace relationship for potential exception */
24struct ptrace_relation {
25 struct task_struct *tracer;
26 struct task_struct *tracee;
27 struct list_head node;
28};
29
30static LIST_HEAD(ptracer_relations);
31static DEFINE_SPINLOCK(ptracer_relations_lock);
32
33/**
34 * yama_ptracer_add - add/replace an exception for this tracer/tracee pair
35 * @tracer: the task_struct of the process doing the ptrace
36 * @tracee: the task_struct of the process to be ptraced
37 *
38 * Each tracee can have, at most, one tracer registered. Each time this
39 * is called, the prior registered tracer will be replaced for the tracee.
40 *
41 * Returns 0 if relationship was added, -ve on error.
42 */
43static int yama_ptracer_add(struct task_struct *tracer,
44 struct task_struct *tracee)
45{
46 int rc = 0;
47 struct ptrace_relation *added;
48 struct ptrace_relation *entry, *relation = NULL;
49
50 added = kmalloc(sizeof(*added), GFP_KERNEL);
51 if (!added)
52 return -ENOMEM;
53
54 spin_lock_bh(&ptracer_relations_lock);
55 list_for_each_entry(entry, &ptracer_relations, node)
56 if (entry->tracee == tracee) {
57 relation = entry;
58 break;
59 }
60 if (!relation) {
61 relation = added;
62 relation->tracee = tracee;
63 list_add(&relation->node, &ptracer_relations);
64 }
65 relation->tracer = tracer;
66
67 spin_unlock_bh(&ptracer_relations_lock);
68 if (added != relation)
69 kfree(added);
70
71 return rc;
72}
73
74/**
75 * yama_ptracer_del - remove exceptions related to the given tasks
76 * @tracer: remove any relation where tracer task matches
77 * @tracee: remove any relation where tracee task matches
78 */
79static void yama_ptracer_del(struct task_struct *tracer,
80 struct task_struct *tracee)
81{
82 struct ptrace_relation *relation, *safe;
83
84 spin_lock_bh(&ptracer_relations_lock);
85 list_for_each_entry_safe(relation, safe, &ptracer_relations, node)
86 if (relation->tracee == tracee ||
87 (tracer && relation->tracer == tracer)) {
88 list_del(&relation->node);
89 kfree(relation);
90 }
91 spin_unlock_bh(&ptracer_relations_lock);
92}
93
94/**
95 * yama_task_free - check for task_pid to remove from exception list
96 * @task: task being removed
97 */
98static void yama_task_free(struct task_struct *task)
99{
100 yama_ptracer_del(task, task);
101}
102
103/**
104 * yama_task_prctl - check for Yama-specific prctl operations
105 * @option: operation
106 * @arg2: argument
107 * @arg3: argument
108 * @arg4: argument
109 * @arg5: argument
110 *
111 * Return 0 on success, -ve on error. -ENOSYS is returned when Yama
112 * does not handle the given option.
113 */
114static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
115 unsigned long arg4, unsigned long arg5)
116{
117 int rc;
118 struct task_struct *myself = current;
119
120 rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
121 if (rc != -ENOSYS)
122 return rc;
123
124 switch (option) {
125 case PR_SET_PTRACER:
126 /* Since a thread can call prctl(), find the group leader
127 * before calling _add() or _del() on it, since we want
128 * process-level granularity of control. The tracer group
129 * leader checking is handled later when walking the ancestry
130 * at the time of PTRACE_ATTACH check.
131 */
132 rcu_read_lock();
133 if (!thread_group_leader(myself))
134 myself = rcu_dereference(myself->group_leader);
135 get_task_struct(myself);
136 rcu_read_unlock();
137
138 if (arg2 == 0) {
139 yama_ptracer_del(NULL, myself);
140 rc = 0;
141 } else if (arg2 == PR_SET_PTRACER_ANY) {
142 rc = yama_ptracer_add(NULL, myself);
143 } else {
144 struct task_struct *tracer;
145
146 rcu_read_lock();
147 tracer = find_task_by_vpid(arg2);
148 if (tracer)
149 get_task_struct(tracer);
150 else
151 rc = -EINVAL;
152 rcu_read_unlock();
153
154 if (tracer) {
155 rc = yama_ptracer_add(tracer, myself);
156 put_task_struct(tracer);
157 }
158 }
159
160 put_task_struct(myself);
161 break;
162 }
163
164 return rc;
165}
166
167/**
168 * task_is_descendant - walk up a process family tree looking for a match
169 * @parent: the process to compare against while walking up from child
170 * @child: the process to start from while looking upwards for parent
171 *
172 * Returns 1 if child is a descendant of parent, 0 if not.
173 */
174static int task_is_descendant(struct task_struct *parent,
175 struct task_struct *child)
176{
177 int rc = 0;
178 struct task_struct *walker = child;
179
180 if (!parent || !child)
181 return 0;
182
183 rcu_read_lock();
184 if (!thread_group_leader(parent))
185 parent = rcu_dereference(parent->group_leader);
186 while (walker->pid > 0) {
187 if (!thread_group_leader(walker))
188 walker = rcu_dereference(walker->group_leader);
189 if (walker == parent) {
190 rc = 1;
191 break;
192 }
193 walker = rcu_dereference(walker->real_parent);
194 }
195 rcu_read_unlock();
196
197 return rc;
198}
199
200/**
201 * ptracer_exception_found - tracer registered as exception for this tracee
202 * @tracer: the task_struct of the process attempting ptrace
203 * @tracee: the task_struct of the process to be ptraced
204 *
205 * Returns 1 if tracer has is ptracer exception ancestor for tracee.
206 */
207static int ptracer_exception_found(struct task_struct *tracer,
208 struct task_struct *tracee)
209{
210 int rc = 0;
211 struct ptrace_relation *relation;
212 struct task_struct *parent = NULL;
213 bool found = false;
214
215 spin_lock_bh(&ptracer_relations_lock);
216 rcu_read_lock();
217 if (!thread_group_leader(tracee))
218 tracee = rcu_dereference(tracee->group_leader);
219 list_for_each_entry(relation, &ptracer_relations, node)
220 if (relation->tracee == tracee) {
221 parent = relation->tracer;
222 found = true;
223 break;
224 }
225
226 if (found && (parent == NULL || task_is_descendant(parent, tracer)))
227 rc = 1;
228 rcu_read_unlock();
229 spin_unlock_bh(&ptracer_relations_lock);
230
231 return rc;
232}
233
234/**
235 * yama_ptrace_access_check - validate PTRACE_ATTACH calls
236 * @child: task that current task is attempting to ptrace
237 * @mode: ptrace attach mode
238 *
239 * Returns 0 if following the ptrace is allowed, -ve on error.
240 */
241static int yama_ptrace_access_check(struct task_struct *child,
242 unsigned int mode)
243{
244 int rc;
245
246 /* If standard caps disallows it, so does Yama. We should
247 * only tighten restrictions further.
248 */
249 rc = cap_ptrace_access_check(child, mode);
250 if (rc)
251 return rc;
252
253 /* require ptrace target be a child of ptracer on attach */
254 if (mode == PTRACE_MODE_ATTACH &&
255 ptrace_scope &&
256 !task_is_descendant(current, child) &&
257 !ptracer_exception_found(current, child) &&
258 !capable(CAP_SYS_PTRACE))
259 rc = -EPERM;
260
261 if (rc) {
262 char name[sizeof(current->comm)];
263 printk_ratelimited(KERN_NOTICE "ptrace of non-child"
264 " pid %d was attempted by: %s (pid %d)\n",
265 child->pid,
266 get_task_comm(name, current),
267 current->pid);
268 }
269
270 return rc;
271}
272
273static struct security_operations yama_ops = {
274 .name = "yama",
275
276 .ptrace_access_check = yama_ptrace_access_check,
277 .task_prctl = yama_task_prctl,
278 .task_free = yama_task_free,
279};
280
281#ifdef CONFIG_SYSCTL
282static int zero;
283static int one = 1;
284
285struct ctl_path yama_sysctl_path[] = {
286 { .procname = "kernel", },
287 { .procname = "yama", },
288 { }
289};
290
291static struct ctl_table yama_sysctl_table[] = {
292 {
293 .procname = "ptrace_scope",
294 .data = &ptrace_scope,
295 .maxlen = sizeof(int),
296 .mode = 0644,
297 .proc_handler = proc_dointvec_minmax,
298 .extra1 = &zero,
299 .extra2 = &one,
300 },
301 { }
302};
303#endif /* CONFIG_SYSCTL */
304
305static __init int yama_init(void)
306{
307 if (!security_module_enable(&yama_ops))
308 return 0;
309
310 printk(KERN_INFO "Yama: becoming mindful.\n");
311
312 if (register_security(&yama_ops))
313 panic("Yama: kernel registration failed.\n");
314
315#ifdef CONFIG_SYSCTL
316 if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
317 panic("Yama: sysctl registration failed.\n");
318#endif
319
320 return 0;
321}
322
323security_initcall(yama_init);