aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-28 11:26:12 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-28 11:26:12 -0400
commit7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch)
treee730a4565e0318140d2fbd2f0415d18a339d7336 /security
parent41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff)
parent0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff)
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig11
-rw-r--r--security/Makefile3
-rw-r--r--security/capability.c6
-rw-r--r--security/commoncap.c134
-rw-r--r--security/device_cgroup.c216
-rw-r--r--security/inode.c36
-rw-r--r--security/root_plug.c3
-rw-r--r--security/security.c23
-rw-r--r--security/selinux/Kconfig3
-rw-r--r--security/selinux/avc.c2
-rw-r--r--security/selinux/hooks.c390
-rw-r--r--security/selinux/include/avc.h4
-rw-r--r--security/selinux/include/netlabel.h44
-rw-r--r--security/selinux/include/objsec.h9
-rw-r--r--security/selinux/include/security.h15
-rw-r--r--security/selinux/netlabel.c280
-rw-r--r--security/selinux/ss/avtab.c8
-rw-r--r--security/selinux/ss/conditional.c18
-rw-r--r--security/selinux/ss/conditional.h2
-rw-r--r--security/selinux/ss/ebitmap.c4
-rw-r--r--security/selinux/ss/hashtab.c6
-rw-r--r--security/selinux/ss/mls.c14
-rw-r--r--security/selinux/ss/policydb.c225
-rw-r--r--security/selinux/ss/policydb.h5
-rw-r--r--security/selinux/ss/services.c210
-rw-r--r--security/selinux/ss/sidtab.c12
-rw-r--r--security/smack/smack.h1
-rw-r--r--security/smack/smack_access.c10
-rw-r--r--security/smack/smack_lsm.c57
-rw-r--r--security/smack/smackfs.c96
30 files changed, 1332 insertions, 515 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 62ed4717d334..d9f47ce7e207 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -51,6 +51,14 @@ config SECURITY
51 51
52 If you are unsure how to answer this question, answer N. 52 If you are unsure how to answer this question, answer N.
53 53
54config SECURITYFS
55 bool "Enable the securityfs filesystem"
56 help
57 This will build the securityfs filesystem. It is currently used by
58 the TPM bios character driver. It is not used by SELinux or SMACK.
59
60 If you are unsure how to answer this question, answer N.
61
54config SECURITY_NETWORK 62config SECURITY_NETWORK
55 bool "Socket and Networking Security Hooks" 63 bool "Socket and Networking Security Hooks"
56 depends on SECURITY 64 depends on SECURITY
@@ -74,8 +82,7 @@ config SECURITY_NETWORK_XFRM
74 If you are unsure how to answer this question, answer N. 82 If you are unsure how to answer this question, answer N.
75 83
76config SECURITY_FILE_CAPABILITIES 84config SECURITY_FILE_CAPABILITIES
77 bool "File POSIX Capabilities (EXPERIMENTAL)" 85 bool "File POSIX Capabilities"
78 depends on EXPERIMENTAL
79 default n 86 default n
80 help 87 help
81 This enables filesystem capabilities, allowing you to give 88 This enables filesystem capabilities, allowing you to give
diff --git a/security/Makefile b/security/Makefile
index f65426099aa6..c05c127fff9a 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -10,7 +10,8 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack
10obj-y += commoncap.o 10obj-y += commoncap.o
11 11
12# Object file lists 12# Object file lists
13obj-$(CONFIG_SECURITY) += security.o capability.o inode.o 13obj-$(CONFIG_SECURITY) += security.o capability.o
14obj-$(CONFIG_SECURITYFS) += inode.o
14# Must precede capability.o in order to stack properly. 15# Must precede capability.o in order to stack properly.
15obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o 16obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
16obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o 17obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
diff --git a/security/capability.c b/security/capability.c
index 5b01c0b02422..245874819036 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -211,8 +211,7 @@ static int cap_inode_follow_link(struct dentry *dentry,
211 return 0; 211 return 0;
212} 212}
213 213
214static int cap_inode_permission(struct inode *inode, int mask, 214static int cap_inode_permission(struct inode *inode, int mask)
215 struct nameidata *nd)
216{ 215{
217 return 0; 216 return 0;
218} 217}
@@ -812,7 +811,8 @@ struct security_operations default_security_ops = {
812 811
813void security_fixup_ops(struct security_operations *ops) 812void security_fixup_ops(struct security_operations *ops)
814{ 813{
815 set_to_cap_if_null(ops, ptrace); 814 set_to_cap_if_null(ops, ptrace_may_access);
815 set_to_cap_if_null(ops, ptrace_traceme);
816 set_to_cap_if_null(ops, capget); 816 set_to_cap_if_null(ops, capget);
817 set_to_cap_if_null(ops, capset_check); 817 set_to_cap_if_null(ops, capset_check);
818 set_to_cap_if_null(ops, capset_set); 818 set_to_cap_if_null(ops, capset_set);
diff --git a/security/commoncap.c b/security/commoncap.c
index 0b6537a3672d..399bfdb9e2da 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -63,14 +63,24 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
63 return 0; 63 return 0;
64} 64}
65 65
66int cap_ptrace (struct task_struct *parent, struct task_struct *child, 66int cap_ptrace_may_access(struct task_struct *child, unsigned int mode)
67 unsigned int mode)
68{ 67{
69 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ 68 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
70 if (!cap_issubset(child->cap_permitted, parent->cap_permitted) && 69 if (cap_issubset(child->cap_permitted, current->cap_permitted))
71 !__capable(parent, CAP_SYS_PTRACE)) 70 return 0;
72 return -EPERM; 71 if (capable(CAP_SYS_PTRACE))
73 return 0; 72 return 0;
73 return -EPERM;
74}
75
76int cap_ptrace_traceme(struct task_struct *parent)
77{
78 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
79 if (cap_issubset(current->cap_permitted, parent->cap_permitted))
80 return 0;
81 if (has_capability(parent, CAP_SYS_PTRACE))
82 return 0;
83 return -EPERM;
74} 84}
75 85
76int cap_capget (struct task_struct *target, kernel_cap_t *effective, 86int cap_capget (struct task_struct *target, kernel_cap_t *effective,
@@ -162,8 +172,7 @@ void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
162 172
163static inline void bprm_clear_caps(struct linux_binprm *bprm) 173static inline void bprm_clear_caps(struct linux_binprm *bprm)
164{ 174{
165 cap_clear(bprm->cap_inheritable); 175 cap_clear(bprm->cap_post_exec_permitted);
166 cap_clear(bprm->cap_permitted);
167 bprm->cap_effective = false; 176 bprm->cap_effective = false;
168} 177}
169 178
@@ -198,6 +207,7 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
198{ 207{
199 __u32 magic_etc; 208 __u32 magic_etc;
200 unsigned tocopy, i; 209 unsigned tocopy, i;
210 int ret;
201 211
202 if (size < sizeof(magic_etc)) 212 if (size < sizeof(magic_etc))
203 return -EINVAL; 213 return -EINVAL;
@@ -225,19 +235,40 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
225 bprm->cap_effective = false; 235 bprm->cap_effective = false;
226 } 236 }
227 237
228 for (i = 0; i < tocopy; ++i) { 238 ret = 0;
229 bprm->cap_permitted.cap[i] = 239
230 le32_to_cpu(caps->data[i].permitted); 240 CAP_FOR_EACH_U32(i) {
231 bprm->cap_inheritable.cap[i] = 241 __u32 value_cpu;
232 le32_to_cpu(caps->data[i].inheritable); 242
233 } 243 if (i >= tocopy) {
234 while (i < VFS_CAP_U32) { 244 /*
235 bprm->cap_permitted.cap[i] = 0; 245 * Legacy capability sets have no upper bits
236 bprm->cap_inheritable.cap[i] = 0; 246 */
237 i++; 247 bprm->cap_post_exec_permitted.cap[i] = 0;
248 continue;
249 }
250 /*
251 * pP' = (X & fP) | (pI & fI)
252 */
253 value_cpu = le32_to_cpu(caps->data[i].permitted);
254 bprm->cap_post_exec_permitted.cap[i] =
255 (current->cap_bset.cap[i] & value_cpu) |
256 (current->cap_inheritable.cap[i] &
257 le32_to_cpu(caps->data[i].inheritable));
258 if (value_cpu & ~bprm->cap_post_exec_permitted.cap[i]) {
259 /*
260 * insufficient to execute correctly
261 */
262 ret = -EPERM;
263 }
238 } 264 }
239 265
240 return 0; 266 /*
267 * For legacy apps, with no internal support for recognizing they
268 * do not have enough capabilities, we return an error if they are
269 * missing some "forced" (aka file-permitted) capabilities.
270 */
271 return bprm->cap_effective ? ret : 0;
241} 272}
242 273
243/* Locate any VFS capabilities: */ 274/* Locate any VFS capabilities: */
@@ -269,9 +300,9 @@ static int get_file_caps(struct linux_binprm *bprm)
269 goto out; 300 goto out;
270 301
271 rc = cap_from_disk(&vcaps, bprm, rc); 302 rc = cap_from_disk(&vcaps, bprm, rc);
272 if (rc) 303 if (rc == -EINVAL)
273 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", 304 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
274 __func__, rc, bprm->filename); 305 __func__, rc, bprm->filename);
275 306
276out: 307out:
277 dput(dentry); 308 dput(dentry);
@@ -304,25 +335,24 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
304 int ret; 335 int ret;
305 336
306 ret = get_file_caps(bprm); 337 ret = get_file_caps(bprm);
307 if (ret)
308 printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
309 __func__, ret, bprm->filename);
310
311 /* To support inheritance of root-permissions and suid-root
312 * executables under compatibility mode, we raise all three
313 * capability sets for the file.
314 *
315 * If only the real uid is 0, we only raise the inheritable
316 * and permitted sets of the executable file.
317 */
318 338
319 if (!issecure (SECURE_NOROOT)) { 339 if (!issecure(SECURE_NOROOT)) {
340 /*
341 * To support inheritance of root-permissions and suid-root
342 * executables under compatibility mode, we override the
343 * capability sets for the file.
344 *
345 * If only the real uid is 0, we do not set the effective
346 * bit.
347 */
320 if (bprm->e_uid == 0 || current->uid == 0) { 348 if (bprm->e_uid == 0 || current->uid == 0) {
321 cap_set_full (bprm->cap_inheritable); 349 /* pP' = (cap_bset & ~0) | (pI & ~0) */
322 cap_set_full (bprm->cap_permitted); 350 bprm->cap_post_exec_permitted = cap_combine(
351 current->cap_bset, current->cap_inheritable
352 );
353 bprm->cap_effective = (bprm->e_uid == 0);
354 ret = 0;
323 } 355 }
324 if (bprm->e_uid == 0)
325 bprm->cap_effective = true;
326 } 356 }
327 357
328 return ret; 358 return ret;
@@ -330,17 +360,9 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
330 360
331void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) 361void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
332{ 362{
333 /* Derived from fs/exec.c:compute_creds. */
334 kernel_cap_t new_permitted, working;
335
336 new_permitted = cap_intersect(bprm->cap_permitted,
337 current->cap_bset);
338 working = cap_intersect(bprm->cap_inheritable,
339 current->cap_inheritable);
340 new_permitted = cap_combine(new_permitted, working);
341
342 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid || 363 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
343 !cap_issubset (new_permitted, current->cap_permitted)) { 364 !cap_issubset(bprm->cap_post_exec_permitted,
365 current->cap_permitted)) {
344 set_dumpable(current->mm, suid_dumpable); 366 set_dumpable(current->mm, suid_dumpable);
345 current->pdeath_signal = 0; 367 current->pdeath_signal = 0;
346 368
@@ -350,9 +372,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
350 bprm->e_gid = current->gid; 372 bprm->e_gid = current->gid;
351 } 373 }
352 if (cap_limit_ptraced_target()) { 374 if (cap_limit_ptraced_target()) {
353 new_permitted = 375 bprm->cap_post_exec_permitted = cap_intersect(
354 cap_intersect(new_permitted, 376 bprm->cap_post_exec_permitted,
355 current->cap_permitted); 377 current->cap_permitted);
356 } 378 }
357 } 379 }
358 } 380 }
@@ -364,9 +386,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
364 * in the init_task struct. Thus we skip the usual 386 * in the init_task struct. Thus we skip the usual
365 * capability rules */ 387 * capability rules */
366 if (!is_global_init(current)) { 388 if (!is_global_init(current)) {
367 current->cap_permitted = new_permitted; 389 current->cap_permitted = bprm->cap_post_exec_permitted;
368 if (bprm->cap_effective) 390 if (bprm->cap_effective)
369 current->cap_effective = new_permitted; 391 current->cap_effective = bprm->cap_post_exec_permitted;
370 else 392 else
371 cap_clear(current->cap_effective); 393 cap_clear(current->cap_effective);
372 } 394 }
@@ -381,9 +403,7 @@ int cap_bprm_secureexec (struct linux_binprm *bprm)
381 if (current->uid != 0) { 403 if (current->uid != 0) {
382 if (bprm->cap_effective) 404 if (bprm->cap_effective)
383 return 1; 405 return 1;
384 if (!cap_isclear(bprm->cap_permitted)) 406 if (!cap_isclear(bprm->cap_post_exec_permitted))
385 return 1;
386 if (!cap_isclear(bprm->cap_inheritable))
387 return 1; 407 return 1;
388 } 408 }
389 409
@@ -521,10 +541,10 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
521 * yet with increased caps. 541 * yet with increased caps.
522 * So we check for increased caps on the target process. 542 * So we check for increased caps on the target process.
523 */ 543 */
524static inline int cap_safe_nice(struct task_struct *p) 544static int cap_safe_nice(struct task_struct *p)
525{ 545{
526 if (!cap_issubset(p->cap_permitted, current->cap_permitted) && 546 if (!cap_issubset(p->cap_permitted, current->cap_permitted) &&
527 !__capable(current, CAP_SYS_NICE)) 547 !capable(CAP_SYS_NICE))
528 return -EPERM; 548 return -EPERM;
529 return 0; 549 return 0;
530} 550}
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index ddd92cec78ed..5ba78701adc3 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * dev_cgroup.c - device cgroup subsystem 2 * device_cgroup.c - device cgroup subsystem
3 * 3 *
4 * Copyright 2007 IBM Corp 4 * Copyright 2007 IBM Corp
5 */ 5 */
@@ -10,6 +10,7 @@
10#include <linux/list.h> 10#include <linux/list.h>
11#include <linux/uaccess.h> 11#include <linux/uaccess.h>
12#include <linux/seq_file.h> 12#include <linux/seq_file.h>
13#include <linux/rcupdate.h>
13 14
14#define ACC_MKNOD 1 15#define ACC_MKNOD 1
15#define ACC_READ 2 16#define ACC_READ 2
@@ -22,18 +23,8 @@
22 23
23/* 24/*
24 * whitelist locking rules: 25 * whitelist locking rules:
25 * cgroup_lock() cannot be taken under dev_cgroup->lock. 26 * hold cgroup_lock() for update/read.
26 * dev_cgroup->lock can be taken with or without cgroup_lock(). 27 * hold rcu_read_lock() for read.
27 *
28 * modifications always require cgroup_lock
29 * modifications to a list which is visible require the
30 * dev_cgroup->lock *and* cgroup_lock()
31 * walking the list requires dev_cgroup->lock or cgroup_lock().
32 *
33 * reasoning: dev_whitelist_copy() needs to kmalloc, so needs
34 * a mutex, which the cgroup_lock() is. Since modifying
35 * a visible list requires both locks, either lock can be
36 * taken for walking the list.
37 */ 28 */
38 29
39struct dev_whitelist_item { 30struct dev_whitelist_item {
@@ -41,12 +32,12 @@ struct dev_whitelist_item {
41 short type; 32 short type;
42 short access; 33 short access;
43 struct list_head list; 34 struct list_head list;
35 struct rcu_head rcu;
44}; 36};
45 37
46struct dev_cgroup { 38struct dev_cgroup {
47 struct cgroup_subsys_state css; 39 struct cgroup_subsys_state css;
48 struct list_head whitelist; 40 struct list_head whitelist;
49 spinlock_t lock;
50}; 41};
51 42
52static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) 43static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
@@ -59,6 +50,11 @@ static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup)
59 return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id)); 50 return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id));
60} 51}
61 52
53static inline struct dev_cgroup *task_devcgroup(struct task_struct *task)
54{
55 return css_to_devcgroup(task_subsys_state(task, devices_subsys_id));
56}
57
62struct cgroup_subsys devices_subsys; 58struct cgroup_subsys devices_subsys;
63 59
64static int devcgroup_can_attach(struct cgroup_subsys *ss, 60static int devcgroup_can_attach(struct cgroup_subsys *ss,
@@ -78,13 +74,9 @@ static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig)
78 struct dev_whitelist_item *wh, *tmp, *new; 74 struct dev_whitelist_item *wh, *tmp, *new;
79 75
80 list_for_each_entry(wh, orig, list) { 76 list_for_each_entry(wh, orig, list) {
81 new = kmalloc(sizeof(*wh), GFP_KERNEL); 77 new = kmemdup(wh, sizeof(*wh), GFP_KERNEL);
82 if (!new) 78 if (!new)
83 goto free_and_exit; 79 goto free_and_exit;
84 new->major = wh->major;
85 new->minor = wh->minor;
86 new->type = wh->type;
87 new->access = wh->access;
88 list_add_tail(&new->list, dest); 80 list_add_tail(&new->list, dest);
89 } 81 }
90 82
@@ -101,19 +93,16 @@ free_and_exit:
101/* Stupid prototype - don't bother combining existing entries */ 93/* Stupid prototype - don't bother combining existing entries */
102/* 94/*
103 * called under cgroup_lock() 95 * called under cgroup_lock()
104 * since the list is visible to other tasks, we need the spinlock also
105 */ 96 */
106static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, 97static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
107 struct dev_whitelist_item *wh) 98 struct dev_whitelist_item *wh)
108{ 99{
109 struct dev_whitelist_item *whcopy, *walk; 100 struct dev_whitelist_item *whcopy, *walk;
110 101
111 whcopy = kmalloc(sizeof(*whcopy), GFP_KERNEL); 102 whcopy = kmemdup(wh, sizeof(*wh), GFP_KERNEL);
112 if (!whcopy) 103 if (!whcopy)
113 return -ENOMEM; 104 return -ENOMEM;
114 105
115 memcpy(whcopy, wh, sizeof(*whcopy));
116 spin_lock(&dev_cgroup->lock);
117 list_for_each_entry(walk, &dev_cgroup->whitelist, list) { 106 list_for_each_entry(walk, &dev_cgroup->whitelist, list) {
118 if (walk->type != wh->type) 107 if (walk->type != wh->type)
119 continue; 108 continue;
@@ -128,21 +117,26 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
128 } 117 }
129 118
130 if (whcopy != NULL) 119 if (whcopy != NULL)
131 list_add_tail(&whcopy->list, &dev_cgroup->whitelist); 120 list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist);
132 spin_unlock(&dev_cgroup->lock);
133 return 0; 121 return 0;
134} 122}
135 123
124static void whitelist_item_free(struct rcu_head *rcu)
125{
126 struct dev_whitelist_item *item;
127
128 item = container_of(rcu, struct dev_whitelist_item, rcu);
129 kfree(item);
130}
131
136/* 132/*
137 * called under cgroup_lock() 133 * called under cgroup_lock()
138 * since the list is visible to other tasks, we need the spinlock also
139 */ 134 */
140static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup, 135static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
141 struct dev_whitelist_item *wh) 136 struct dev_whitelist_item *wh)
142{ 137{
143 struct dev_whitelist_item *walk, *tmp; 138 struct dev_whitelist_item *walk, *tmp;
144 139
145 spin_lock(&dev_cgroup->lock);
146 list_for_each_entry_safe(walk, tmp, &dev_cgroup->whitelist, list) { 140 list_for_each_entry_safe(walk, tmp, &dev_cgroup->whitelist, list) {
147 if (walk->type == DEV_ALL) 141 if (walk->type == DEV_ALL)
148 goto remove; 142 goto remove;
@@ -156,11 +150,10 @@ static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
156remove: 150remove:
157 walk->access &= ~wh->access; 151 walk->access &= ~wh->access;
158 if (!walk->access) { 152 if (!walk->access) {
159 list_del(&walk->list); 153 list_del_rcu(&walk->list);
160 kfree(walk); 154 call_rcu(&walk->rcu, whitelist_item_free);
161 } 155 }
162 } 156 }
163 spin_unlock(&dev_cgroup->lock);
164} 157}
165 158
166/* 159/*
@@ -188,7 +181,7 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss,
188 } 181 }
189 wh->minor = wh->major = ~0; 182 wh->minor = wh->major = ~0;
190 wh->type = DEV_ALL; 183 wh->type = DEV_ALL;
191 wh->access = ACC_MKNOD | ACC_READ | ACC_WRITE; 184 wh->access = ACC_MASK;
192 list_add(&wh->list, &dev_cgroup->whitelist); 185 list_add(&wh->list, &dev_cgroup->whitelist);
193 } else { 186 } else {
194 parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup); 187 parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
@@ -200,7 +193,6 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss,
200 } 193 }
201 } 194 }
202 195
203 spin_lock_init(&dev_cgroup->lock);
204 return &dev_cgroup->css; 196 return &dev_cgroup->css;
205} 197}
206 198
@@ -250,11 +242,10 @@ static char type_to_char(short type)
250 242
251static void set_majmin(char *str, unsigned m) 243static void set_majmin(char *str, unsigned m)
252{ 244{
253 memset(str, 0, MAJMINLEN);
254 if (m == ~0) 245 if (m == ~0)
255 sprintf(str, "*"); 246 strcpy(str, "*");
256 else 247 else
257 snprintf(str, MAJMINLEN, "%u", m); 248 sprintf(str, "%u", m);
258} 249}
259 250
260static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, 251static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
@@ -264,15 +255,15 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
264 struct dev_whitelist_item *wh; 255 struct dev_whitelist_item *wh;
265 char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN]; 256 char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
266 257
267 spin_lock(&devcgroup->lock); 258 rcu_read_lock();
268 list_for_each_entry(wh, &devcgroup->whitelist, list) { 259 list_for_each_entry_rcu(wh, &devcgroup->whitelist, list) {
269 set_access(acc, wh->access); 260 set_access(acc, wh->access);
270 set_majmin(maj, wh->major); 261 set_majmin(maj, wh->major);
271 set_majmin(min, wh->minor); 262 set_majmin(min, wh->minor);
272 seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type), 263 seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type),
273 maj, min, acc); 264 maj, min, acc);
274 } 265 }
275 spin_unlock(&devcgroup->lock); 266 rcu_read_unlock();
276 267
277 return 0; 268 return 0;
278} 269}
@@ -312,20 +303,16 @@ static int may_access_whitelist(struct dev_cgroup *c,
312 * when adding a new allow rule to a device whitelist, the rule 303 * when adding a new allow rule to a device whitelist, the rule
313 * must be allowed in the parent device 304 * must be allowed in the parent device
314 */ 305 */
315static int parent_has_perm(struct cgroup *childcg, 306static int parent_has_perm(struct dev_cgroup *childcg,
316 struct dev_whitelist_item *wh) 307 struct dev_whitelist_item *wh)
317{ 308{
318 struct cgroup *pcg = childcg->parent; 309 struct cgroup *pcg = childcg->css.cgroup->parent;
319 struct dev_cgroup *parent; 310 struct dev_cgroup *parent;
320 int ret;
321 311
322 if (!pcg) 312 if (!pcg)
323 return 1; 313 return 1;
324 parent = cgroup_to_devcgroup(pcg); 314 parent = cgroup_to_devcgroup(pcg);
325 spin_lock(&parent->lock); 315 return may_access_whitelist(parent, wh);
326 ret = may_access_whitelist(parent, wh);
327 spin_unlock(&parent->lock);
328 return ret;
329} 316}
330 317
331/* 318/*
@@ -341,40 +328,17 @@ static int parent_has_perm(struct cgroup *childcg,
341 * new access is only allowed if you're in the top-level cgroup, or your 328 * new access is only allowed if you're in the top-level cgroup, or your
342 * parent cgroup has the access you're asking for. 329 * parent cgroup has the access you're asking for.
343 */ 330 */
344static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft, 331static int devcgroup_update_access(struct dev_cgroup *devcgroup,
345 struct file *file, const char __user *userbuf, 332 int filetype, const char *buffer)
346 size_t nbytes, loff_t *ppos)
347{ 333{
348 struct cgroup *cur_cgroup; 334 const char *b;
349 struct dev_cgroup *devcgroup, *cur_devcgroup; 335 char *endp;
350 int filetype = cft->private; 336 int count;
351 char *buffer, *b;
352 int retval = 0, count;
353 struct dev_whitelist_item wh; 337 struct dev_whitelist_item wh;
354 338
355 if (!capable(CAP_SYS_ADMIN)) 339 if (!capable(CAP_SYS_ADMIN))
356 return -EPERM; 340 return -EPERM;
357 341
358 devcgroup = cgroup_to_devcgroup(cgroup);
359 cur_cgroup = task_cgroup(current, devices_subsys.subsys_id);
360 cur_devcgroup = cgroup_to_devcgroup(cur_cgroup);
361
362 buffer = kmalloc(nbytes+1, GFP_KERNEL);
363 if (!buffer)
364 return -ENOMEM;
365
366 if (copy_from_user(buffer, userbuf, nbytes)) {
367 retval = -EFAULT;
368 goto out1;
369 }
370 buffer[nbytes] = 0; /* nul-terminate */
371
372 cgroup_lock();
373 if (cgroup_is_removed(cgroup)) {
374 retval = -ENODEV;
375 goto out2;
376 }
377
378 memset(&wh, 0, sizeof(wh)); 342 memset(&wh, 0, sizeof(wh));
379 b = buffer; 343 b = buffer;
380 344
@@ -392,32 +356,23 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
392 wh.type = DEV_CHAR; 356 wh.type = DEV_CHAR;
393 break; 357 break;
394 default: 358 default:
395 retval = -EINVAL; 359 return -EINVAL;
396 goto out2;
397 } 360 }
398 b++; 361 b++;
399 if (!isspace(*b)) { 362 if (!isspace(*b))
400 retval = -EINVAL; 363 return -EINVAL;
401 goto out2;
402 }
403 b++; 364 b++;
404 if (*b == '*') { 365 if (*b == '*') {
405 wh.major = ~0; 366 wh.major = ~0;
406 b++; 367 b++;
407 } else if (isdigit(*b)) { 368 } else if (isdigit(*b)) {
408 wh.major = 0; 369 wh.major = simple_strtoul(b, &endp, 10);
409 while (isdigit(*b)) { 370 b = endp;
410 wh.major = wh.major*10+(*b-'0');
411 b++;
412 }
413 } else { 371 } else {
414 retval = -EINVAL; 372 return -EINVAL;
415 goto out2;
416 }
417 if (*b != ':') {
418 retval = -EINVAL;
419 goto out2;
420 } 373 }
374 if (*b != ':')
375 return -EINVAL;
421 b++; 376 b++;
422 377
423 /* read minor */ 378 /* read minor */
@@ -425,19 +380,13 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
425 wh.minor = ~0; 380 wh.minor = ~0;
426 b++; 381 b++;
427 } else if (isdigit(*b)) { 382 } else if (isdigit(*b)) {
428 wh.minor = 0; 383 wh.minor = simple_strtoul(b, &endp, 10);
429 while (isdigit(*b)) { 384 b = endp;
430 wh.minor = wh.minor*10+(*b-'0');
431 b++;
432 }
433 } else { 385 } else {
434 retval = -EINVAL; 386 return -EINVAL;
435 goto out2;
436 }
437 if (!isspace(*b)) {
438 retval = -EINVAL;
439 goto out2;
440 } 387 }
388 if (!isspace(*b))
389 return -EINVAL;
441 for (b++, count = 0; count < 3; count++, b++) { 390 for (b++, count = 0; count < 3; count++, b++) {
442 switch (*b) { 391 switch (*b) {
443 case 'r': 392 case 'r':
@@ -454,47 +403,46 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
454 count = 3; 403 count = 3;
455 break; 404 break;
456 default: 405 default:
457 retval = -EINVAL; 406 return -EINVAL;
458 goto out2;
459 } 407 }
460 } 408 }
461 409
462handle: 410handle:
463 retval = 0;
464 switch (filetype) { 411 switch (filetype) {
465 case DEVCG_ALLOW: 412 case DEVCG_ALLOW:
466 if (!parent_has_perm(cgroup, &wh)) 413 if (!parent_has_perm(devcgroup, &wh))
467 retval = -EPERM; 414 return -EPERM;
468 else 415 return dev_whitelist_add(devcgroup, &wh);
469 retval = dev_whitelist_add(devcgroup, &wh);
470 break;
471 case DEVCG_DENY: 416 case DEVCG_DENY:
472 dev_whitelist_rm(devcgroup, &wh); 417 dev_whitelist_rm(devcgroup, &wh);
473 break; 418 break;
474 default: 419 default:
475 retval = -EINVAL; 420 return -EINVAL;
476 goto out2;
477 } 421 }
422 return 0;
423}
478 424
479 if (retval == 0) 425static int devcgroup_access_write(struct cgroup *cgrp, struct cftype *cft,
480 retval = nbytes; 426 const char *buffer)
481 427{
482out2: 428 int retval;
429 if (!cgroup_lock_live_group(cgrp))
430 return -ENODEV;
431 retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp),
432 cft->private, buffer);
483 cgroup_unlock(); 433 cgroup_unlock();
484out1:
485 kfree(buffer);
486 return retval; 434 return retval;
487} 435}
488 436
489static struct cftype dev_cgroup_files[] = { 437static struct cftype dev_cgroup_files[] = {
490 { 438 {
491 .name = "allow", 439 .name = "allow",
492 .write = devcgroup_access_write, 440 .write_string = devcgroup_access_write,
493 .private = DEVCG_ALLOW, 441 .private = DEVCG_ALLOW,
494 }, 442 },
495 { 443 {
496 .name = "deny", 444 .name = "deny",
497 .write = devcgroup_access_write, 445 .write_string = devcgroup_access_write,
498 .private = DEVCG_DENY, 446 .private = DEVCG_DENY,
499 }, 447 },
500 { 448 {
@@ -530,13 +478,12 @@ int devcgroup_inode_permission(struct inode *inode, int mask)
530 return 0; 478 return 0;
531 if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode)) 479 if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode))
532 return 0; 480 return 0;
533 dev_cgroup = css_to_devcgroup(task_subsys_state(current,
534 devices_subsys_id));
535 if (!dev_cgroup)
536 return 0;
537 481
538 spin_lock(&dev_cgroup->lock); 482 rcu_read_lock();
539 list_for_each_entry(wh, &dev_cgroup->whitelist, list) { 483
484 dev_cgroup = task_devcgroup(current);
485
486 list_for_each_entry_rcu(wh, &dev_cgroup->whitelist, list) {
540 if (wh->type & DEV_ALL) 487 if (wh->type & DEV_ALL)
541 goto acc_check; 488 goto acc_check;
542 if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode)) 489 if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode))
@@ -552,10 +499,11 @@ acc_check:
552 continue; 499 continue;
553 if ((mask & MAY_READ) && !(wh->access & ACC_READ)) 500 if ((mask & MAY_READ) && !(wh->access & ACC_READ))
554 continue; 501 continue;
555 spin_unlock(&dev_cgroup->lock); 502 rcu_read_unlock();
556 return 0; 503 return 0;
557 } 504 }
558 spin_unlock(&dev_cgroup->lock); 505
506 rcu_read_unlock();
559 507
560 return -EPERM; 508 return -EPERM;
561} 509}
@@ -565,12 +513,10 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
565 struct dev_cgroup *dev_cgroup; 513 struct dev_cgroup *dev_cgroup;
566 struct dev_whitelist_item *wh; 514 struct dev_whitelist_item *wh;
567 515
568 dev_cgroup = css_to_devcgroup(task_subsys_state(current, 516 rcu_read_lock();
569 devices_subsys_id)); 517
570 if (!dev_cgroup) 518 dev_cgroup = task_devcgroup(current);
571 return 0;
572 519
573 spin_lock(&dev_cgroup->lock);
574 list_for_each_entry(wh, &dev_cgroup->whitelist, list) { 520 list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
575 if (wh->type & DEV_ALL) 521 if (wh->type & DEV_ALL)
576 goto acc_check; 522 goto acc_check;
@@ -585,9 +531,11 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
585acc_check: 531acc_check:
586 if (!(wh->access & ACC_MKNOD)) 532 if (!(wh->access & ACC_MKNOD))
587 continue; 533 continue;
588 spin_unlock(&dev_cgroup->lock); 534 rcu_read_unlock();
589 return 0; 535 return 0;
590 } 536 }
591 spin_unlock(&dev_cgroup->lock); 537
538 rcu_read_unlock();
539
592 return -EPERM; 540 return -EPERM;
593} 541}
diff --git a/security/inode.c b/security/inode.c
index acc6cf0d7900..efea5a605466 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -20,8 +20,7 @@
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/namei.h> 21#include <linux/namei.h>
22#include <linux/security.h> 22#include <linux/security.h>
23 23#include <linux/magic.h>
24#define SECURITYFS_MAGIC 0x73636673
25 24
26static struct vfsmount *mount; 25static struct vfsmount *mount;
27static int mount_count; 26static int mount_count;
@@ -190,7 +189,7 @@ static int create_by_name(const char *name, mode_t mode,
190 * @name: a pointer to a string containing the name of the file to create. 189 * @name: a pointer to a string containing the name of the file to create.
191 * @mode: the permission that the file should have 190 * @mode: the permission that the file should have
192 * @parent: a pointer to the parent dentry for this file. This should be a 191 * @parent: a pointer to the parent dentry for this file. This should be a
193 * directory dentry if set. If this paramater is NULL, then the 192 * directory dentry if set. If this parameter is %NULL, then the
194 * file will be created in the root of the securityfs filesystem. 193 * file will be created in the root of the securityfs filesystem.
195 * @data: a pointer to something that the caller will want to get to later 194 * @data: a pointer to something that the caller will want to get to later
196 * on. The inode.i_private pointer will point to this value on 195 * on. The inode.i_private pointer will point to this value on
@@ -199,18 +198,18 @@ static int create_by_name(const char *name, mode_t mode,
199 * this file. 198 * this file.
200 * 199 *
201 * This is the basic "create a file" function for securityfs. It allows for a 200 * This is the basic "create a file" function for securityfs. It allows for a
202 * wide range of flexibility in createing a file, or a directory (if you 201 * wide range of flexibility in creating a file, or a directory (if you
203 * want to create a directory, the securityfs_create_dir() function is 202 * want to create a directory, the securityfs_create_dir() function is
204 * recommended to be used instead.) 203 * recommended to be used instead).
205 * 204 *
206 * This function will return a pointer to a dentry if it succeeds. This 205 * This function returns a pointer to a dentry if it succeeds. This
207 * pointer must be passed to the securityfs_remove() function when the file is 206 * pointer must be passed to the securityfs_remove() function when the file is
208 * to be removed (no automatic cleanup happens if your module is unloaded, 207 * to be removed (no automatic cleanup happens if your module is unloaded,
209 * you are responsible here.) If an error occurs, NULL will be returned. 208 * you are responsible here). If an error occurs, %NULL is returned.
210 * 209 *
211 * If securityfs is not enabled in the kernel, the value -ENODEV will be 210 * If securityfs is not enabled in the kernel, the value %-ENODEV is
212 * returned. It is not wise to check for this value, but rather, check for 211 * returned. It is not wise to check for this value, but rather, check for
213 * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 212 * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
214 * code. 213 * code.
215 */ 214 */
216struct dentry *securityfs_create_file(const char *name, mode_t mode, 215struct dentry *securityfs_create_file(const char *name, mode_t mode,
@@ -252,19 +251,19 @@ EXPORT_SYMBOL_GPL(securityfs_create_file);
252 * @name: a pointer to a string containing the name of the directory to 251 * @name: a pointer to a string containing the name of the directory to
253 * create. 252 * create.
254 * @parent: a pointer to the parent dentry for this file. This should be a 253 * @parent: a pointer to the parent dentry for this file. This should be a
255 * directory dentry if set. If this paramater is NULL, then the 254 * directory dentry if set. If this parameter is %NULL, then the
256 * directory will be created in the root of the securityfs filesystem. 255 * directory will be created in the root of the securityfs filesystem.
257 * 256 *
258 * This function creates a directory in securityfs with the given name. 257 * This function creates a directory in securityfs with the given @name.
259 * 258 *
260 * This function will return a pointer to a dentry if it succeeds. This 259 * This function returns a pointer to a dentry if it succeeds. This
261 * pointer must be passed to the securityfs_remove() function when the file is 260 * pointer must be passed to the securityfs_remove() function when the file is
262 * to be removed (no automatic cleanup happens if your module is unloaded, 261 * to be removed (no automatic cleanup happens if your module is unloaded,
263 * you are responsible here.) If an error occurs, NULL will be returned. 262 * you are responsible here). If an error occurs, %NULL will be returned.
264 * 263 *
265 * If securityfs is not enabled in the kernel, the value -ENODEV will be 264 * If securityfs is not enabled in the kernel, the value %-ENODEV is
266 * returned. It is not wise to check for this value, but rather, check for 265 * returned. It is not wise to check for this value, but rather, check for
267 * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 266 * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
268 * code. 267 * code.
269 */ 268 */
270struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) 269struct dentry *securityfs_create_dir(const char *name, struct dentry *parent)
@@ -278,16 +277,15 @@ EXPORT_SYMBOL_GPL(securityfs_create_dir);
278/** 277/**
279 * securityfs_remove - removes a file or directory from the securityfs filesystem 278 * securityfs_remove - removes a file or directory from the securityfs filesystem
280 * 279 *
281 * @dentry: a pointer to a the dentry of the file or directory to be 280 * @dentry: a pointer to a the dentry of the file or directory to be removed.
282 * removed.
283 * 281 *
284 * This function removes a file or directory in securityfs that was previously 282 * This function removes a file or directory in securityfs that was previously
285 * created with a call to another securityfs function (like 283 * created with a call to another securityfs function (like
286 * securityfs_create_file() or variants thereof.) 284 * securityfs_create_file() or variants thereof.)
287 * 285 *
288 * This function is required to be called in order for the file to be 286 * This function is required to be called in order for the file to be
289 * removed, no automatic cleanup of files will happen when a module is 287 * removed. No automatic cleanup of files will happen when a module is
290 * removed, you are responsible here. 288 * removed; you are responsible here.
291 */ 289 */
292void securityfs_remove(struct dentry *dentry) 290void securityfs_remove(struct dentry *dentry)
293{ 291{
diff --git a/security/root_plug.c b/security/root_plug.c
index be0ebec2580b..c3f68b5b372d 100644
--- a/security/root_plug.c
+++ b/security/root_plug.c
@@ -72,7 +72,8 @@ static int rootplug_bprm_check_security (struct linux_binprm *bprm)
72 72
73static struct security_operations rootplug_security_ops = { 73static struct security_operations rootplug_security_ops = {
74 /* Use the capability functions for some of the hooks */ 74 /* Use the capability functions for some of the hooks */
75 .ptrace = cap_ptrace, 75 .ptrace_may_access = cap_ptrace_may_access,
76 .ptrace_traceme = cap_ptrace_traceme,
76 .capget = cap_capget, 77 .capget = cap_capget,
77 .capset_check = cap_capset_check, 78 .capset_check = cap_capset_check,
78 .capset_set = cap_capset_set, 79 .capset_set = cap_capset_set,
diff --git a/security/security.c b/security/security.c
index 59f23b5918b3..255b08559b2b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -82,8 +82,8 @@ __setup("security=", choose_lsm);
82 * 82 *
83 * Return true if: 83 * Return true if:
84 * -The passed LSM is the one chosen by user at boot time, 84 * -The passed LSM is the one chosen by user at boot time,
85 * -or user didsn't specify a specific LSM and we're the first to ask 85 * -or user didn't specify a specific LSM and we're the first to ask
86 * for registeration permissoin, 86 * for registration permission,
87 * -or the passed LSM is currently loaded. 87 * -or the passed LSM is currently loaded.
88 * Otherwise, return false. 88 * Otherwise, return false.
89 */ 89 */
@@ -101,13 +101,13 @@ int __init security_module_enable(struct security_operations *ops)
101 * register_security - registers a security framework with the kernel 101 * register_security - registers a security framework with the kernel
102 * @ops: a pointer to the struct security_options that is to be registered 102 * @ops: a pointer to the struct security_options that is to be registered
103 * 103 *
104 * This function is to allow a security module to register itself with the 104 * This function allows a security module to register itself with the
105 * kernel security subsystem. Some rudimentary checking is done on the @ops 105 * kernel security subsystem. Some rudimentary checking is done on the @ops
106 * value passed to this function. You'll need to check first if your LSM 106 * value passed to this function. You'll need to check first if your LSM
107 * is allowed to register its @ops by calling security_module_enable(@ops). 107 * is allowed to register its @ops by calling security_module_enable(@ops).
108 * 108 *
109 * If there is already a security module registered with the kernel, 109 * If there is already a security module registered with the kernel,
110 * an error will be returned. Otherwise 0 is returned on success. 110 * an error will be returned. Otherwise %0 is returned on success.
111 */ 111 */
112int register_security(struct security_operations *ops) 112int register_security(struct security_operations *ops)
113{ 113{
@@ -127,10 +127,14 @@ int register_security(struct security_operations *ops)
127 127
128/* Security operations */ 128/* Security operations */
129 129
130int security_ptrace(struct task_struct *parent, struct task_struct *child, 130int security_ptrace_may_access(struct task_struct *child, unsigned int mode)
131 unsigned int mode)
132{ 131{
133 return security_ops->ptrace(parent, child, mode); 132 return security_ops->ptrace_may_access(child, mode);
133}
134
135int security_ptrace_traceme(struct task_struct *parent)
136{
137 return security_ops->ptrace_traceme(parent);
134} 138}
135 139
136int security_capget(struct task_struct *target, 140int security_capget(struct task_struct *target,
@@ -429,11 +433,11 @@ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
429 return security_ops->inode_follow_link(dentry, nd); 433 return security_ops->inode_follow_link(dentry, nd);
430} 434}
431 435
432int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd) 436int security_inode_permission(struct inode *inode, int mask)
433{ 437{
434 if (unlikely(IS_PRIVATE(inode))) 438 if (unlikely(IS_PRIVATE(inode)))
435 return 0; 439 return 0;
436 return security_ops->inode_permission(inode, mask, nd); 440 return security_ops->inode_permission(inode, mask);
437} 441}
438 442
439int security_inode_setattr(struct dentry *dentry, struct iattr *attr) 443int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
@@ -442,6 +446,7 @@ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
442 return 0; 446 return 0;
443 return security_ops->inode_setattr(dentry, attr); 447 return security_ops->inode_setattr(dentry, attr);
444} 448}
449EXPORT_SYMBOL_GPL(security_inode_setattr);
445 450
446int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) 451int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
447{ 452{
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index a436d1cfa88b..26301dd651d3 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -6,9 +6,6 @@ config SECURITY_SELINUX
6 help 6 help
7 This selects NSA Security-Enhanced Linux (SELinux). 7 This selects NSA Security-Enhanced Linux (SELinux).
8 You will also need a policy configuration and a labeled filesystem. 8 You will also need a policy configuration and a labeled filesystem.
9 You can obtain the policy compiler (checkpolicy), the utility for
10 labeling filesystems (setfiles), and an example policy configuration
11 from <http://www.nsa.gov/selinux/>.
12 If you are unsure how to answer this question, answer N. 9 If you are unsure how to answer this question, answer N.
13 10
14config SECURITY_SELINUX_BOOTPARAM 11config SECURITY_SELINUX_BOOTPARAM
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 114b4b4c97b2..cb30c7e350b3 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -136,7 +136,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
136 * @tclass: target security class 136 * @tclass: target security class
137 * @av: access vector 137 * @av: access vector
138 */ 138 */
139static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) 139void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
140{ 140{
141 const char **common_pts = NULL; 141 const char **common_pts = NULL;
142 u32 common_base = 0; 142 u32 common_base = 0;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 63f131fc42e4..3e3fde7c1d2b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -25,7 +25,7 @@
25 25
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/kernel.h> 27#include <linux/kernel.h>
28#include <linux/ptrace.h> 28#include <linux/tracehook.h>
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/sched.h> 30#include <linux/sched.h>
31#include <linux/security.h> 31#include <linux/security.h>
@@ -75,6 +75,7 @@
75#include <linux/string.h> 75#include <linux/string.h>
76#include <linux/selinux.h> 76#include <linux/selinux.h>
77#include <linux/mutex.h> 77#include <linux/mutex.h>
78#include <linux/posix-timers.h>
78 79
79#include "avc.h" 80#include "avc.h"
80#include "objsec.h" 81#include "objsec.h"
@@ -291,6 +292,7 @@ static void sk_free_security(struct sock *sk)
291 struct sk_security_struct *ssec = sk->sk_security; 292 struct sk_security_struct *ssec = sk->sk_security;
292 293
293 sk->sk_security = NULL; 294 sk->sk_security = NULL;
295 selinux_netlbl_sk_security_free(ssec);
294 kfree(ssec); 296 kfree(ssec);
295} 297}
296 298
@@ -324,7 +326,7 @@ enum {
324 Opt_rootcontext = 4, 326 Opt_rootcontext = 4,
325}; 327};
326 328
327static match_table_t tokens = { 329static const match_table_t tokens = {
328 {Opt_context, CONTEXT_STR "%s"}, 330 {Opt_context, CONTEXT_STR "%s"},
329 {Opt_fscontext, FSCONTEXT_STR "%s"}, 331 {Opt_fscontext, FSCONTEXT_STR "%s"},
330 {Opt_defcontext, DEFCONTEXT_STR "%s"}, 332 {Opt_defcontext, DEFCONTEXT_STR "%s"},
@@ -957,7 +959,8 @@ out_err:
957 return rc; 959 return rc;
958} 960}
959 961
960void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts) 962static void selinux_write_opts(struct seq_file *m,
963 struct security_mnt_opts *opts)
961{ 964{
962 int i; 965 int i;
963 char *prefix; 966 char *prefix;
@@ -998,8 +1001,12 @@ static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
998 int rc; 1001 int rc;
999 1002
1000 rc = selinux_get_mnt_opts(sb, &opts); 1003 rc = selinux_get_mnt_opts(sb, &opts);
1001 if (rc) 1004 if (rc) {
1005 /* before policy load we may get EINVAL, don't show anything */
1006 if (rc == -EINVAL)
1007 rc = 0;
1002 return rc; 1008 return rc;
1009 }
1003 1010
1004 selinux_write_opts(m, &opts); 1011 selinux_write_opts(m, &opts);
1005 1012
@@ -1286,7 +1293,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1286 /* Default to the fs superblock SID. */ 1293 /* Default to the fs superblock SID. */
1287 isec->sid = sbsec->sid; 1294 isec->sid = sbsec->sid;
1288 1295
1289 if (sbsec->proc) { 1296 if (sbsec->proc && !S_ISLNK(inode->i_mode)) {
1290 struct proc_inode *proci = PROC_I(inode); 1297 struct proc_inode *proci = PROC_I(inode);
1291 if (proci->pde) { 1298 if (proci->pde) {
1292 isec->sclass = inode_mode_to_security_class(inode->i_mode); 1299 isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -1734,24 +1741,34 @@ static inline u32 file_to_av(struct file *file)
1734 1741
1735/* Hook functions begin here. */ 1742/* Hook functions begin here. */
1736 1743
1737static int selinux_ptrace(struct task_struct *parent, 1744static int selinux_ptrace_may_access(struct task_struct *child,
1738 struct task_struct *child, 1745 unsigned int mode)
1739 unsigned int mode)
1740{ 1746{
1741 int rc; 1747 int rc;
1742 1748
1743 rc = secondary_ops->ptrace(parent, child, mode); 1749 rc = secondary_ops->ptrace_may_access(child, mode);
1744 if (rc) 1750 if (rc)
1745 return rc; 1751 return rc;
1746 1752
1747 if (mode == PTRACE_MODE_READ) { 1753 if (mode == PTRACE_MODE_READ) {
1748 struct task_security_struct *tsec = parent->security; 1754 struct task_security_struct *tsec = current->security;
1749 struct task_security_struct *csec = child->security; 1755 struct task_security_struct *csec = child->security;
1750 return avc_has_perm(tsec->sid, csec->sid, 1756 return avc_has_perm(tsec->sid, csec->sid,
1751 SECCLASS_FILE, FILE__READ, NULL); 1757 SECCLASS_FILE, FILE__READ, NULL);
1752 } 1758 }
1753 1759
1754 return task_has_perm(parent, child, PROCESS__PTRACE); 1760 return task_has_perm(current, child, PROCESS__PTRACE);
1761}
1762
1763static int selinux_ptrace_traceme(struct task_struct *parent)
1764{
1765 int rc;
1766
1767 rc = secondary_ops->ptrace_traceme(parent);
1768 if (rc)
1769 return rc;
1770
1771 return task_has_perm(parent, current, PROCESS__PTRACE);
1755} 1772}
1756 1773
1757static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, 1774static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
@@ -1971,22 +1988,6 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
1971 return __vm_enough_memory(mm, pages, cap_sys_admin); 1988 return __vm_enough_memory(mm, pages, cap_sys_admin);
1972} 1989}
1973 1990
1974/**
1975 * task_tracer_task - return the task that is tracing the given task
1976 * @task: task to consider
1977 *
1978 * Returns NULL if noone is tracing @task, or the &struct task_struct
1979 * pointer to its tracer.
1980 *
1981 * Must be called under rcu_read_lock().
1982 */
1983static struct task_struct *task_tracer_task(struct task_struct *task)
1984{
1985 if (task->ptrace & PT_PTRACED)
1986 return rcu_dereference(task->parent);
1987 return NULL;
1988}
1989
1990/* binprm security operations */ 1991/* binprm security operations */
1991 1992
1992static int selinux_bprm_alloc_security(struct linux_binprm *bprm) 1993static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
@@ -2122,7 +2123,6 @@ static inline void flush_unauthorized_files(struct files_struct *files)
2122 long j = -1; 2123 long j = -1;
2123 int drop_tty = 0; 2124 int drop_tty = 0;
2124 2125
2125 mutex_lock(&tty_mutex);
2126 tty = get_current_tty(); 2126 tty = get_current_tty();
2127 if (tty) { 2127 if (tty) {
2128 file_list_lock(); 2128 file_list_lock();
@@ -2140,8 +2140,8 @@ static inline void flush_unauthorized_files(struct files_struct *files)
2140 } 2140 }
2141 } 2141 }
2142 file_list_unlock(); 2142 file_list_unlock();
2143 tty_kref_put(tty);
2143 } 2144 }
2144 mutex_unlock(&tty_mutex);
2145 /* Reset controlling tty. */ 2145 /* Reset controlling tty. */
2146 if (drop_tty) 2146 if (drop_tty)
2147 no_tty(); 2147 no_tty();
@@ -2238,7 +2238,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2238 u32 ptsid = 0; 2238 u32 ptsid = 0;
2239 2239
2240 rcu_read_lock(); 2240 rcu_read_lock();
2241 tracer = task_tracer_task(current); 2241 tracer = tracehook_tracer_task(current);
2242 if (likely(tracer != NULL)) { 2242 if (likely(tracer != NULL)) {
2243 sec = tracer->security; 2243 sec = tracer->security;
2244 ptsid = sec->sid; 2244 ptsid = sec->sid;
@@ -2323,13 +2323,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
2323 initrlim = init_task.signal->rlim+i; 2323 initrlim = init_task.signal->rlim+i;
2324 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); 2324 rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
2325 } 2325 }
2326 if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) { 2326 update_rlimit_cpu(rlim->rlim_cur);
2327 /*
2328 * This will cause RLIMIT_CPU calculations
2329 * to be refigured.
2330 */
2331 current->it_prof_expires = jiffies_to_cputime(1);
2332 }
2333 } 2327 }
2334 2328
2335 /* Wake up the parent if it is waiting so that it can 2329 /* Wake up the parent if it is waiting so that it can
@@ -2640,12 +2634,11 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
2640 return dentry_has_perm(current, NULL, dentry, FILE__READ); 2634 return dentry_has_perm(current, NULL, dentry, FILE__READ);
2641} 2635}
2642 2636
2643static int selinux_inode_permission(struct inode *inode, int mask, 2637static int selinux_inode_permission(struct inode *inode, int mask)
2644 struct nameidata *nd)
2645{ 2638{
2646 int rc; 2639 int rc;
2647 2640
2648 rc = secondary_ops->inode_permission(inode, mask, nd); 2641 rc = secondary_ops->inode_permission(inode, mask);
2649 if (rc) 2642 if (rc)
2650 return rc; 2643 return rc;
2651 2644
@@ -3551,38 +3544,44 @@ out:
3551#endif /* IPV6 */ 3544#endif /* IPV6 */
3552 3545
3553static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, 3546static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3554 char **addrp, int src, u8 *proto) 3547 char **_addrp, int src, u8 *proto)
3555{ 3548{
3556 int ret = 0; 3549 char *addrp;
3550 int ret;
3557 3551
3558 switch (ad->u.net.family) { 3552 switch (ad->u.net.family) {
3559 case PF_INET: 3553 case PF_INET:
3560 ret = selinux_parse_skb_ipv4(skb, ad, proto); 3554 ret = selinux_parse_skb_ipv4(skb, ad, proto);
3561 if (ret || !addrp) 3555 if (ret)
3562 break; 3556 goto parse_error;
3563 *addrp = (char *)(src ? &ad->u.net.v4info.saddr : 3557 addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3564 &ad->u.net.v4info.daddr); 3558 &ad->u.net.v4info.daddr);
3565 break; 3559 goto okay;
3566 3560
3567#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 3561#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3568 case PF_INET6: 3562 case PF_INET6:
3569 ret = selinux_parse_skb_ipv6(skb, ad, proto); 3563 ret = selinux_parse_skb_ipv6(skb, ad, proto);
3570 if (ret || !addrp) 3564 if (ret)
3571 break; 3565 goto parse_error;
3572 *addrp = (char *)(src ? &ad->u.net.v6info.saddr : 3566 addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3573 &ad->u.net.v6info.daddr); 3567 &ad->u.net.v6info.daddr);
3574 break; 3568 goto okay;
3575#endif /* IPV6 */ 3569#endif /* IPV6 */
3576 default: 3570 default:
3577 break; 3571 addrp = NULL;
3572 goto okay;
3578 } 3573 }
3579 3574
3580 if (unlikely(ret)) 3575parse_error:
3581 printk(KERN_WARNING 3576 printk(KERN_WARNING
3582 "SELinux: failure in selinux_parse_skb()," 3577 "SELinux: failure in selinux_parse_skb(),"
3583 " unable to parse packet\n"); 3578 " unable to parse packet\n");
3584
3585 return ret; 3579 return ret;
3580
3581okay:
3582 if (_addrp)
3583 *_addrp = addrp;
3584 return 0;
3586} 3585}
3587 3586
3588/** 3587/**
@@ -3797,6 +3796,7 @@ out:
3797 3796
3798static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) 3797static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
3799{ 3798{
3799 struct sock *sk = sock->sk;
3800 struct inode_security_struct *isec; 3800 struct inode_security_struct *isec;
3801 int err; 3801 int err;
3802 3802
@@ -3810,7 +3810,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
3810 isec = SOCK_INODE(sock)->i_security; 3810 isec = SOCK_INODE(sock)->i_security;
3811 if (isec->sclass == SECCLASS_TCP_SOCKET || 3811 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3812 isec->sclass == SECCLASS_DCCP_SOCKET) { 3812 isec->sclass == SECCLASS_DCCP_SOCKET) {
3813 struct sock *sk = sock->sk;
3814 struct avc_audit_data ad; 3813 struct avc_audit_data ad;
3815 struct sockaddr_in *addr4 = NULL; 3814 struct sockaddr_in *addr4 = NULL;
3816 struct sockaddr_in6 *addr6 = NULL; 3815 struct sockaddr_in6 *addr6 = NULL;
@@ -3844,6 +3843,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
3844 goto out; 3843 goto out;
3845 } 3844 }
3846 3845
3846 err = selinux_netlbl_socket_connect(sk, address);
3847
3847out: 3848out:
3848 return err; 3849 return err;
3849} 3850}
@@ -4073,20 +4074,28 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
4073} 4074}
4074 4075
4075static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 4076static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4076 struct avc_audit_data *ad, 4077 u16 family)
4077 u16 family, char *addrp)
4078{ 4078{
4079 int err; 4079 int err;
4080 struct sk_security_struct *sksec = sk->sk_security; 4080 struct sk_security_struct *sksec = sk->sk_security;
4081 u32 peer_sid; 4081 u32 peer_sid;
4082 u32 sk_sid = sksec->sid; 4082 u32 sk_sid = sksec->sid;
4083 struct avc_audit_data ad;
4084 char *addrp;
4085
4086 AVC_AUDIT_DATA_INIT(&ad, NET);
4087 ad.u.net.netif = skb->iif;
4088 ad.u.net.family = family;
4089 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
4090 if (err)
4091 return err;
4083 4092
4084 if (selinux_compat_net) 4093 if (selinux_compat_net)
4085 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad, 4094 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, &ad,
4086 family, addrp); 4095 family, addrp);
4087 else 4096 else
4088 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, 4097 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4089 PACKET__RECV, ad); 4098 PACKET__RECV, &ad);
4090 if (err) 4099 if (err)
4091 return err; 4100 return err;
4092 4101
@@ -4095,12 +4104,14 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
4095 if (err) 4104 if (err)
4096 return err; 4105 return err;
4097 err = avc_has_perm(sk_sid, peer_sid, 4106 err = avc_has_perm(sk_sid, peer_sid,
4098 SECCLASS_PEER, PEER__RECV, ad); 4107 SECCLASS_PEER, PEER__RECV, &ad);
4108 if (err)
4109 selinux_netlbl_err(skb, err, 0);
4099 } else { 4110 } else {
4100 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad); 4111 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
4101 if (err) 4112 if (err)
4102 return err; 4113 return err;
4103 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad); 4114 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
4104 } 4115 }
4105 4116
4106 return err; 4117 return err;
@@ -4114,6 +4125,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4114 u32 sk_sid = sksec->sid; 4125 u32 sk_sid = sksec->sid;
4115 struct avc_audit_data ad; 4126 struct avc_audit_data ad;
4116 char *addrp; 4127 char *addrp;
4128 u8 secmark_active;
4129 u8 peerlbl_active;
4117 4130
4118 if (family != PF_INET && family != PF_INET6) 4131 if (family != PF_INET && family != PF_INET6)
4119 return 0; 4132 return 0;
@@ -4122,6 +4135,18 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4122 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) 4135 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4123 family = PF_INET; 4136 family = PF_INET;
4124 4137
4138 /* If any sort of compatibility mode is enabled then handoff processing
4139 * to the selinux_sock_rcv_skb_compat() function to deal with the
4140 * special handling. We do this in an attempt to keep this function
4141 * as fast and as clean as possible. */
4142 if (selinux_compat_net || !selinux_policycap_netpeer)
4143 return selinux_sock_rcv_skb_compat(sk, skb, family);
4144
4145 secmark_active = selinux_secmark_enabled();
4146 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4147 if (!secmark_active && !peerlbl_active)
4148 return 0;
4149
4125 AVC_AUDIT_DATA_INIT(&ad, NET); 4150 AVC_AUDIT_DATA_INIT(&ad, NET);
4126 ad.u.net.netif = skb->iif; 4151 ad.u.net.netif = skb->iif;
4127 ad.u.net.family = family; 4152 ad.u.net.family = family;
@@ -4129,15 +4154,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4129 if (err) 4154 if (err)
4130 return err; 4155 return err;
4131 4156
4132 /* If any sort of compatibility mode is enabled then handoff processing 4157 if (peerlbl_active) {
4133 * to the selinux_sock_rcv_skb_compat() function to deal with the
4134 * special handling. We do this in an attempt to keep this function
4135 * as fast and as clean as possible. */
4136 if (selinux_compat_net || !selinux_policycap_netpeer)
4137 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
4138 family, addrp);
4139
4140 if (netlbl_enabled() || selinux_xfrm_enabled()) {
4141 u32 peer_sid; 4158 u32 peer_sid;
4142 4159
4143 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); 4160 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
@@ -4145,13 +4162,17 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
4145 return err; 4162 return err;
4146 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, 4163 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4147 peer_sid, &ad); 4164 peer_sid, &ad);
4148 if (err) 4165 if (err) {
4166 selinux_netlbl_err(skb, err, 0);
4149 return err; 4167 return err;
4168 }
4150 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, 4169 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4151 PEER__RECV, &ad); 4170 PEER__RECV, &ad);
4171 if (err)
4172 selinux_netlbl_err(skb, err, 0);
4152 } 4173 }
4153 4174
4154 if (selinux_secmark_enabled()) { 4175 if (secmark_active) {
4155 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, 4176 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4156 PACKET__RECV, &ad); 4177 PACKET__RECV, &ad);
4157 if (err) 4178 if (err)
@@ -4210,10 +4231,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
4210 u32 peer_secid = SECSID_NULL; 4231 u32 peer_secid = SECSID_NULL;
4211 u16 family; 4232 u16 family;
4212 4233
4213 if (sock) 4234 if (skb && skb->protocol == htons(ETH_P_IP))
4235 family = PF_INET;
4236 else if (skb && skb->protocol == htons(ETH_P_IPV6))
4237 family = PF_INET6;
4238 else if (sock)
4214 family = sock->sk->sk_family; 4239 family = sock->sk->sk_family;
4215 else if (skb && skb->sk)
4216 family = skb->sk->sk_family;
4217 else 4240 else
4218 goto out; 4241 goto out;
4219 4242
@@ -4271,8 +4294,6 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
4271 sk->sk_family == PF_UNIX) 4294 sk->sk_family == PF_UNIX)
4272 isec->sid = sksec->sid; 4295 isec->sid = sksec->sid;
4273 sksec->sclass = isec->sclass; 4296 sksec->sclass = isec->sclass;
4274
4275 selinux_netlbl_sock_graft(sk, parent);
4276} 4297}
4277 4298
4278static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, 4299static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
@@ -4280,10 +4301,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4280{ 4301{
4281 struct sk_security_struct *sksec = sk->sk_security; 4302 struct sk_security_struct *sksec = sk->sk_security;
4282 int err; 4303 int err;
4304 u16 family = sk->sk_family;
4283 u32 newsid; 4305 u32 newsid;
4284 u32 peersid; 4306 u32 peersid;
4285 4307
4286 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid); 4308 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4309 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4310 family = PF_INET;
4311
4312 err = selinux_skb_peerlbl_sid(skb, family, &peersid);
4287 if (err) 4313 if (err)
4288 return err; 4314 return err;
4289 if (peersid == SECSID_NULL) { 4315 if (peersid == SECSID_NULL) {
@@ -4318,12 +4344,18 @@ static void selinux_inet_csk_clone(struct sock *newsk,
4318 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); 4344 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
4319} 4345}
4320 4346
4321static void selinux_inet_conn_established(struct sock *sk, 4347static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
4322 struct sk_buff *skb)
4323{ 4348{
4349 u16 family = sk->sk_family;
4324 struct sk_security_struct *sksec = sk->sk_security; 4350 struct sk_security_struct *sksec = sk->sk_security;
4325 4351
4326 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid); 4352 /* handle mapped IPv4 packets arriving via IPv6 sockets */
4353 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
4354 family = PF_INET;
4355
4356 selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
4357
4358 selinux_netlbl_inet_conn_established(sk, family);
4327} 4359}
4328 4360
4329static void selinux_req_classify_flow(const struct request_sock *req, 4361static void selinux_req_classify_flow(const struct request_sock *req,
@@ -4373,39 +4405,54 @@ out:
4373static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, 4405static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4374 u16 family) 4406 u16 family)
4375{ 4407{
4408 int err;
4376 char *addrp; 4409 char *addrp;
4377 u32 peer_sid; 4410 u32 peer_sid;
4378 struct avc_audit_data ad; 4411 struct avc_audit_data ad;
4379 u8 secmark_active; 4412 u8 secmark_active;
4413 u8 netlbl_active;
4380 u8 peerlbl_active; 4414 u8 peerlbl_active;
4381 4415
4382 if (!selinux_policycap_netpeer) 4416 if (!selinux_policycap_netpeer)
4383 return NF_ACCEPT; 4417 return NF_ACCEPT;
4384 4418
4385 secmark_active = selinux_secmark_enabled(); 4419 secmark_active = selinux_secmark_enabled();
4386 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); 4420 netlbl_active = netlbl_enabled();
4421 peerlbl_active = netlbl_active || selinux_xfrm_enabled();
4387 if (!secmark_active && !peerlbl_active) 4422 if (!secmark_active && !peerlbl_active)
4388 return NF_ACCEPT; 4423 return NF_ACCEPT;
4389 4424
4425 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4426 return NF_DROP;
4427
4390 AVC_AUDIT_DATA_INIT(&ad, NET); 4428 AVC_AUDIT_DATA_INIT(&ad, NET);
4391 ad.u.net.netif = ifindex; 4429 ad.u.net.netif = ifindex;
4392 ad.u.net.family = family; 4430 ad.u.net.family = family;
4393 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) 4431 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4394 return NF_DROP; 4432 return NF_DROP;
4395 4433
4396 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) 4434 if (peerlbl_active) {
4397 return NF_DROP; 4435 err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4398 4436 peer_sid, &ad);
4399 if (peerlbl_active) 4437 if (err) {
4400 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family, 4438 selinux_netlbl_err(skb, err, 1);
4401 peer_sid, &ad) != 0)
4402 return NF_DROP; 4439 return NF_DROP;
4440 }
4441 }
4403 4442
4404 if (secmark_active) 4443 if (secmark_active)
4405 if (avc_has_perm(peer_sid, skb->secmark, 4444 if (avc_has_perm(peer_sid, skb->secmark,
4406 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) 4445 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4407 return NF_DROP; 4446 return NF_DROP;
4408 4447
4448 if (netlbl_active)
4449 /* we do this in the FORWARD path and not the POST_ROUTING
4450 * path because we want to make sure we apply the necessary
4451 * labeling before IPsec is applied so we can leverage AH
4452 * protection */
4453 if (selinux_netlbl_skbuff_setsid(skb, family, peer_sid) != 0)
4454 return NF_DROP;
4455
4409 return NF_ACCEPT; 4456 return NF_ACCEPT;
4410} 4457}
4411 4458
@@ -4429,6 +4476,37 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4429} 4476}
4430#endif /* IPV6 */ 4477#endif /* IPV6 */
4431 4478
4479static unsigned int selinux_ip_output(struct sk_buff *skb,
4480 u16 family)
4481{
4482 u32 sid;
4483
4484 if (!netlbl_enabled())
4485 return NF_ACCEPT;
4486
4487 /* we do this in the LOCAL_OUT path and not the POST_ROUTING path
4488 * because we want to make sure we apply the necessary labeling
4489 * before IPsec is applied so we can leverage AH protection */
4490 if (skb->sk) {
4491 struct sk_security_struct *sksec = skb->sk->sk_security;
4492 sid = sksec->sid;
4493 } else
4494 sid = SECINITSID_KERNEL;
4495 if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
4496 return NF_DROP;
4497
4498 return NF_ACCEPT;
4499}
4500
4501static unsigned int selinux_ipv4_output(unsigned int hooknum,
4502 struct sk_buff *skb,
4503 const struct net_device *in,
4504 const struct net_device *out,
4505 int (*okfn)(struct sk_buff *))
4506{
4507 return selinux_ip_output(skb, PF_INET);
4508}
4509
4432static int selinux_ip_postroute_iptables_compat(struct sock *sk, 4510static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4433 int ifindex, 4511 int ifindex,
4434 struct avc_audit_data *ad, 4512 struct avc_audit_data *ad,
@@ -4496,30 +4574,36 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4496 4574
4497static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, 4575static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4498 int ifindex, 4576 int ifindex,
4499 struct avc_audit_data *ad, 4577 u16 family)
4500 u16 family,
4501 char *addrp,
4502 u8 proto)
4503{ 4578{
4504 struct sock *sk = skb->sk; 4579 struct sock *sk = skb->sk;
4505 struct sk_security_struct *sksec; 4580 struct sk_security_struct *sksec;
4581 struct avc_audit_data ad;
4582 char *addrp;
4583 u8 proto;
4506 4584
4507 if (sk == NULL) 4585 if (sk == NULL)
4508 return NF_ACCEPT; 4586 return NF_ACCEPT;
4509 sksec = sk->sk_security; 4587 sksec = sk->sk_security;
4510 4588
4589 AVC_AUDIT_DATA_INIT(&ad, NET);
4590 ad.u.net.netif = ifindex;
4591 ad.u.net.family = family;
4592 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4593 return NF_DROP;
4594
4511 if (selinux_compat_net) { 4595 if (selinux_compat_net) {
4512 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex, 4596 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4513 ad, family, addrp)) 4597 &ad, family, addrp))
4514 return NF_DROP; 4598 return NF_DROP;
4515 } else { 4599 } else {
4516 if (avc_has_perm(sksec->sid, skb->secmark, 4600 if (avc_has_perm(sksec->sid, skb->secmark,
4517 SECCLASS_PACKET, PACKET__SEND, ad)) 4601 SECCLASS_PACKET, PACKET__SEND, &ad))
4518 return NF_DROP; 4602 return NF_DROP;
4519 } 4603 }
4520 4604
4521 if (selinux_policycap_netpeer) 4605 if (selinux_policycap_netpeer)
4522 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto)) 4606 if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
4523 return NF_DROP; 4607 return NF_DROP;
4524 4608
4525 return NF_ACCEPT; 4609 return NF_ACCEPT;
@@ -4533,23 +4617,15 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4533 struct sock *sk; 4617 struct sock *sk;
4534 struct avc_audit_data ad; 4618 struct avc_audit_data ad;
4535 char *addrp; 4619 char *addrp;
4536 u8 proto;
4537 u8 secmark_active; 4620 u8 secmark_active;
4538 u8 peerlbl_active; 4621 u8 peerlbl_active;
4539 4622
4540 AVC_AUDIT_DATA_INIT(&ad, NET);
4541 ad.u.net.netif = ifindex;
4542 ad.u.net.family = family;
4543 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4544 return NF_DROP;
4545
4546 /* If any sort of compatibility mode is enabled then handoff processing 4623 /* If any sort of compatibility mode is enabled then handoff processing
4547 * to the selinux_ip_postroute_compat() function to deal with the 4624 * to the selinux_ip_postroute_compat() function to deal with the
4548 * special handling. We do this in an attempt to keep this function 4625 * special handling. We do this in an attempt to keep this function
4549 * as fast and as clean as possible. */ 4626 * as fast and as clean as possible. */
4550 if (selinux_compat_net || !selinux_policycap_netpeer) 4627 if (selinux_compat_net || !selinux_policycap_netpeer)
4551 return selinux_ip_postroute_compat(skb, ifindex, &ad, 4628 return selinux_ip_postroute_compat(skb, ifindex, family);
4552 family, addrp, proto);
4553 4629
4554 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec 4630 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4555 * packet transformation so allow the packet to pass without any checks 4631 * packet transformation so allow the packet to pass without any checks
@@ -4565,21 +4641,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4565 if (!secmark_active && !peerlbl_active) 4641 if (!secmark_active && !peerlbl_active)
4566 return NF_ACCEPT; 4642 return NF_ACCEPT;
4567 4643
4568 /* if the packet is locally generated (skb->sk != NULL) then use the 4644 /* if the packet is being forwarded then get the peer label from the
4569 * socket's label as the peer label, otherwise the packet is being 4645 * packet itself; otherwise check to see if it is from a local
4570 * forwarded through this system and we need to fetch the peer label 4646 * application or the kernel, if from an application get the peer label
4571 * directly from the packet */ 4647 * from the sending socket, otherwise use the kernel's sid */
4572 sk = skb->sk; 4648 sk = skb->sk;
4573 if (sk) { 4649 if (sk == NULL) {
4650 switch (family) {
4651 case PF_INET:
4652 if (IPCB(skb)->flags & IPSKB_FORWARDED)
4653 secmark_perm = PACKET__FORWARD_OUT;
4654 else
4655 secmark_perm = PACKET__SEND;
4656 break;
4657 case PF_INET6:
4658 if (IP6CB(skb)->flags & IP6SKB_FORWARDED)
4659 secmark_perm = PACKET__FORWARD_OUT;
4660 else
4661 secmark_perm = PACKET__SEND;
4662 break;
4663 default:
4664 return NF_DROP;
4665 }
4666 if (secmark_perm == PACKET__FORWARD_OUT) {
4667 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4668 return NF_DROP;
4669 } else
4670 peer_sid = SECINITSID_KERNEL;
4671 } else {
4574 struct sk_security_struct *sksec = sk->sk_security; 4672 struct sk_security_struct *sksec = sk->sk_security;
4575 peer_sid = sksec->sid; 4673 peer_sid = sksec->sid;
4576 secmark_perm = PACKET__SEND; 4674 secmark_perm = PACKET__SEND;
4577 } else {
4578 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4579 return NF_DROP;
4580 secmark_perm = PACKET__FORWARD_OUT;
4581 } 4675 }
4582 4676
4677 AVC_AUDIT_DATA_INIT(&ad, NET);
4678 ad.u.net.netif = ifindex;
4679 ad.u.net.family = family;
4680 if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
4681 return NF_DROP;
4682
4583 if (secmark_active) 4683 if (secmark_active)
4584 if (avc_has_perm(peer_sid, skb->secmark, 4684 if (avc_has_perm(peer_sid, skb->secmark,
4585 SECCLASS_PACKET, secmark_perm, &ad)) 4685 SECCLASS_PACKET, secmark_perm, &ad))
@@ -5222,8 +5322,12 @@ static int selinux_setprocattr(struct task_struct *p,
5222 5322
5223 if (sid == 0) 5323 if (sid == 0)
5224 return -EINVAL; 5324 return -EINVAL;
5225 5325 /*
5226 /* Only allow single threaded processes to change context */ 5326 * SELinux allows to change context in the following case only.
5327 * - Single threaded processes.
5328 * - Multi threaded processes intend to change its context into
5329 * more restricted domain (defined by TYPEBOUNDS statement).
5330 */
5227 if (atomic_read(&p->mm->mm_users) != 1) { 5331 if (atomic_read(&p->mm->mm_users) != 1) {
5228 struct task_struct *g, *t; 5332 struct task_struct *g, *t;
5229 struct mm_struct *mm = p->mm; 5333 struct mm_struct *mm = p->mm;
@@ -5231,11 +5335,16 @@ static int selinux_setprocattr(struct task_struct *p,
5231 do_each_thread(g, t) { 5335 do_each_thread(g, t) {
5232 if (t->mm == mm && t != p) { 5336 if (t->mm == mm && t != p) {
5233 read_unlock(&tasklist_lock); 5337 read_unlock(&tasklist_lock);
5234 return -EPERM; 5338 error = security_bounded_transition(tsec->sid, sid);
5339 if (!error)
5340 goto boundary_ok;
5341
5342 return error;
5235 } 5343 }
5236 } while_each_thread(g, t); 5344 } while_each_thread(g, t);
5237 read_unlock(&tasklist_lock); 5345 read_unlock(&tasklist_lock);
5238 } 5346 }
5347boundary_ok:
5239 5348
5240 /* Check permissions for the transition. */ 5349 /* Check permissions for the transition. */
5241 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, 5350 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
@@ -5247,7 +5356,7 @@ static int selinux_setprocattr(struct task_struct *p,
5247 Otherwise, leave SID unchanged and fail. */ 5356 Otherwise, leave SID unchanged and fail. */
5248 task_lock(p); 5357 task_lock(p);
5249 rcu_read_lock(); 5358 rcu_read_lock();
5250 tracer = task_tracer_task(p); 5359 tracer = tracehook_tracer_task(p);
5251 if (tracer != NULL) { 5360 if (tracer != NULL) {
5252 struct task_security_struct *ptsec = tracer->security; 5361 struct task_security_struct *ptsec = tracer->security;
5253 u32 ptsid = ptsec->sid; 5362 u32 ptsid = ptsec->sid;
@@ -5359,7 +5468,8 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
5359static struct security_operations selinux_ops = { 5468static struct security_operations selinux_ops = {
5360 .name = "selinux", 5469 .name = "selinux",
5361 5470
5362 .ptrace = selinux_ptrace, 5471 .ptrace_may_access = selinux_ptrace_may_access,
5472 .ptrace_traceme = selinux_ptrace_traceme,
5363 .capget = selinux_capget, 5473 .capget = selinux_capget,
5364 .capset_check = selinux_capset_check, 5474 .capset_check = selinux_capset_check,
5365 .capset_set = selinux_capset_set, 5475 .capset_set = selinux_capset_set,
@@ -5643,6 +5753,13 @@ static struct nf_hook_ops selinux_ipv4_ops[] = {
5643 .pf = PF_INET, 5753 .pf = PF_INET,
5644 .hooknum = NF_INET_FORWARD, 5754 .hooknum = NF_INET_FORWARD,
5645 .priority = NF_IP_PRI_SELINUX_FIRST, 5755 .priority = NF_IP_PRI_SELINUX_FIRST,
5756 },
5757 {
5758 .hook = selinux_ipv4_output,
5759 .owner = THIS_MODULE,
5760 .pf = PF_INET,
5761 .hooknum = NF_INET_LOCAL_OUT,
5762 .priority = NF_IP_PRI_SELINUX_FIRST,
5646 } 5763 }
5647}; 5764};
5648 5765
@@ -5670,27 +5787,20 @@ static struct nf_hook_ops selinux_ipv6_ops[] = {
5670static int __init selinux_nf_ip_init(void) 5787static int __init selinux_nf_ip_init(void)
5671{ 5788{
5672 int err = 0; 5789 int err = 0;
5673 u32 iter;
5674 5790
5675 if (!selinux_enabled) 5791 if (!selinux_enabled)
5676 goto out; 5792 goto out;
5677 5793
5678 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); 5794 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5679 5795
5680 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) { 5796 err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5681 err = nf_register_hook(&selinux_ipv4_ops[iter]); 5797 if (err)
5682 if (err) 5798 panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
5683 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5684 err);
5685 }
5686 5799
5687#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5800#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5688 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) { 5801 err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5689 err = nf_register_hook(&selinux_ipv6_ops[iter]); 5802 if (err)
5690 if (err) 5803 panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
5691 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5692 err);
5693 }
5694#endif /* IPV6 */ 5804#endif /* IPV6 */
5695 5805
5696out: 5806out:
@@ -5702,15 +5812,11 @@ __initcall(selinux_nf_ip_init);
5702#ifdef CONFIG_SECURITY_SELINUX_DISABLE 5812#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5703static void selinux_nf_ip_exit(void) 5813static void selinux_nf_ip_exit(void)
5704{ 5814{
5705 u32 iter;
5706
5707 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); 5815 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
5708 5816
5709 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) 5817 nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
5710 nf_unregister_hook(&selinux_ipv4_ops[iter]);
5711#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5818#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5712 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) 5819 nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
5713 nf_unregister_hook(&selinux_ipv6_ops[iter]);
5714#endif /* IPV6 */ 5820#endif /* IPV6 */
5715} 5821}
5716#endif 5822#endif
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 7b9769f5e775..d12ff1a9c0aa 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -12,6 +12,7 @@
12#include <linux/kdev_t.h> 12#include <linux/kdev_t.h>
13#include <linux/spinlock.h> 13#include <linux/spinlock.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/audit.h>
15#include <linux/in6.h> 16#include <linux/in6.h>
16#include <linux/path.h> 17#include <linux/path.h>
17#include <asm/system.h> 18#include <asm/system.h>
@@ -126,6 +127,9 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
126 u32 events, u32 ssid, u32 tsid, 127 u32 events, u32 ssid, u32 tsid,
127 u16 tclass, u32 perms); 128 u16 tclass, u32 perms);
128 129
130/* Shows permission in human readable form */
131void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
132
129/* Exported to selinuxfs */ 133/* Exported to selinuxfs */
130int avc_get_hash_stats(char *page); 134int avc_get_hash_stats(char *page);
131extern unsigned int avc_cache_threshold; 135extern unsigned int avc_cache_threshold;
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index 487a7d81fe20..b913c8d06038 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -39,6 +39,9 @@
39#ifdef CONFIG_NETLABEL 39#ifdef CONFIG_NETLABEL
40void selinux_netlbl_cache_invalidate(void); 40void selinux_netlbl_cache_invalidate(void);
41 41
42void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
43
44void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec);
42void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, 45void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
43 int family); 46 int family);
44 47
@@ -46,8 +49,11 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
46 u16 family, 49 u16 family,
47 u32 *type, 50 u32 *type,
48 u32 *sid); 51 u32 *sid);
52int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
53 u16 family,
54 u32 sid);
49 55
50void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); 56void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family);
51int selinux_netlbl_socket_post_create(struct socket *sock); 57int selinux_netlbl_socket_post_create(struct socket *sock);
52int selinux_netlbl_inode_permission(struct inode *inode, int mask); 58int selinux_netlbl_inode_permission(struct inode *inode, int mask);
53int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 59int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
@@ -57,12 +63,27 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
57int selinux_netlbl_socket_setsockopt(struct socket *sock, 63int selinux_netlbl_socket_setsockopt(struct socket *sock,
58 int level, 64 int level,
59 int optname); 65 int optname);
66int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr);
67
60#else 68#else
61static inline void selinux_netlbl_cache_invalidate(void) 69static inline void selinux_netlbl_cache_invalidate(void)
62{ 70{
63 return; 71 return;
64} 72}
65 73
74static inline void selinux_netlbl_err(struct sk_buff *skb,
75 int error,
76 int gateway)
77{
78 return;
79}
80
81static inline void selinux_netlbl_sk_security_free(
82 struct sk_security_struct *ssec)
83{
84 return;
85}
86
66static inline void selinux_netlbl_sk_security_reset( 87static inline void selinux_netlbl_sk_security_reset(
67 struct sk_security_struct *ssec, 88 struct sk_security_struct *ssec,
68 int family) 89 int family)
@@ -79,9 +100,21 @@ static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
79 *sid = SECSID_NULL; 100 *sid = SECSID_NULL;
80 return 0; 101 return 0;
81} 102}
103static inline int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
104 u16 family,
105 u32 sid)
106{
107 return 0;
108}
82 109
83static inline void selinux_netlbl_sock_graft(struct sock *sk, 110static inline int selinux_netlbl_conn_setsid(struct sock *sk,
84 struct socket *sock) 111 struct sockaddr *addr)
112{
113 return 0;
114}
115
116static inline void selinux_netlbl_inet_conn_established(struct sock *sk,
117 u16 family)
85{ 118{
86 return; 119 return;
87} 120}
@@ -107,6 +140,11 @@ static inline int selinux_netlbl_socket_setsockopt(struct socket *sock,
107{ 140{
108 return 0; 141 return 0;
109} 142}
143static inline int selinux_netlbl_socket_connect(struct sock *sk,
144 struct sockaddr *addr)
145{
146 return 0;
147}
110#endif /* CONFIG_NETLABEL */ 148#endif /* CONFIG_NETLABEL */
111 149
112#endif 150#endif
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 91070ab874ce..f8be8d7fa26d 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -109,16 +109,19 @@ struct netport_security_struct {
109}; 109};
110 110
111struct sk_security_struct { 111struct sk_security_struct {
112 u32 sid; /* SID of this object */
113 u32 peer_sid; /* SID of peer */
114 u16 sclass; /* sock security class */
115#ifdef CONFIG_NETLABEL 112#ifdef CONFIG_NETLABEL
116 enum { /* NetLabel state */ 113 enum { /* NetLabel state */
117 NLBL_UNSET = 0, 114 NLBL_UNSET = 0,
118 NLBL_REQUIRE, 115 NLBL_REQUIRE,
119 NLBL_LABELED, 116 NLBL_LABELED,
117 NLBL_REQSKB,
118 NLBL_CONNLABELED,
120 } nlbl_state; 119 } nlbl_state;
120 struct netlbl_lsm_secattr *nlbl_secattr; /* NetLabel sec attributes */
121#endif 121#endif
122 u32 sid; /* SID of this object */
123 u32 peer_sid; /* SID of peer */
124 u16 sclass; /* sock security class */
122}; 125};
123 126
124struct key_security_struct { 127struct key_security_struct {
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 7c543003d653..72447370bc95 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -27,13 +27,14 @@
27#define POLICYDB_VERSION_RANGETRANS 21 27#define POLICYDB_VERSION_RANGETRANS 21
28#define POLICYDB_VERSION_POLCAP 22 28#define POLICYDB_VERSION_POLCAP 22
29#define POLICYDB_VERSION_PERMISSIVE 23 29#define POLICYDB_VERSION_PERMISSIVE 23
30#define POLICYDB_VERSION_BOUNDARY 24
30 31
31/* Range of policy versions we understand*/ 32/* Range of policy versions we understand*/
32#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE 33#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
33#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX 34#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
34#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE 35#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
35#else 36#else
36#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE 37#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY
37#endif 38#endif
38 39
39#define CONTEXT_MNT 0x01 40#define CONTEXT_MNT 0x01
@@ -62,6 +63,16 @@ enum {
62extern int selinux_policycap_netpeer; 63extern int selinux_policycap_netpeer;
63extern int selinux_policycap_openperm; 64extern int selinux_policycap_openperm;
64 65
66/*
67 * type_datum properties
68 * available at the kernel policy version >= POLICYDB_VERSION_BOUNDARY
69 */
70#define TYPEDATUM_PROPERTY_PRIMARY 0x0001
71#define TYPEDATUM_PROPERTY_ATTRIBUTE 0x0002
72
73/* limitation of boundary depth */
74#define POLICYDB_BOUNDS_MAXDEPTH 4
75
65int security_load_policy(void *data, size_t len); 76int security_load_policy(void *data, size_t len);
66 77
67int security_policycap_supported(unsigned int req_cap); 78int security_policycap_supported(unsigned int req_cap);
@@ -117,6 +128,8 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen,
117int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, 128int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
118 u16 tclass); 129 u16 tclass);
119 130
131int security_bounded_transition(u32 oldsid, u32 newsid);
132
120int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); 133int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
121 134
122int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, 135int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 89b418392f11..f58701a7b728 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -9,7 +9,7 @@
9 */ 9 */
10 10
11/* 11/*
12 * (c) Copyright Hewlett-Packard Development Company, L.P., 2007 12 * (c) Copyright Hewlett-Packard Development Company, L.P., 2007, 2008
13 * 13 *
14 * This program is free software; you can redistribute it and/or modify 14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by 15 * it under the terms of the GNU General Public License as published by
@@ -29,8 +29,12 @@
29 29
30#include <linux/spinlock.h> 30#include <linux/spinlock.h>
31#include <linux/rcupdate.h> 31#include <linux/rcupdate.h>
32#include <linux/ip.h>
33#include <linux/ipv6.h>
32#include <net/sock.h> 34#include <net/sock.h>
33#include <net/netlabel.h> 35#include <net/netlabel.h>
36#include <net/ip.h>
37#include <net/ipv6.h>
34 38
35#include "objsec.h" 39#include "objsec.h"
36#include "security.h" 40#include "security.h"
@@ -64,32 +68,69 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
64} 68}
65 69
66/** 70/**
71 * selinux_netlbl_sock_genattr - Generate the NetLabel socket secattr
72 * @sk: the socket
73 *
74 * Description:
75 * Generate the NetLabel security attributes for a socket, making full use of
76 * the socket's attribute cache. Returns a pointer to the security attributes
77 * on success, NULL on failure.
78 *
79 */
80static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
81{
82 int rc;
83 struct sk_security_struct *sksec = sk->sk_security;
84 struct netlbl_lsm_secattr *secattr;
85
86 if (sksec->nlbl_secattr != NULL)
87 return sksec->nlbl_secattr;
88
89 secattr = netlbl_secattr_alloc(GFP_ATOMIC);
90 if (secattr == NULL)
91 return NULL;
92 rc = security_netlbl_sid_to_secattr(sksec->sid, secattr);
93 if (rc != 0) {
94 netlbl_secattr_free(secattr);
95 return NULL;
96 }
97 sksec->nlbl_secattr = secattr;
98
99 return secattr;
100}
101
102/**
67 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism 103 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
68 * @sk: the socket to label 104 * @sk: the socket to label
69 * @sid: the SID to use
70 * 105 *
71 * Description: 106 * Description:
72 * Attempt to label a socket using the NetLabel mechanism using the given 107 * Attempt to label a socket using the NetLabel mechanism. Returns zero values
73 * SID. Returns zero values on success, negative values on failure. 108 * on success, negative values on failure.
74 * 109 *
75 */ 110 */
76static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) 111static int selinux_netlbl_sock_setsid(struct sock *sk)
77{ 112{
78 int rc; 113 int rc;
79 struct sk_security_struct *sksec = sk->sk_security; 114 struct sk_security_struct *sksec = sk->sk_security;
80 struct netlbl_lsm_secattr secattr; 115 struct netlbl_lsm_secattr *secattr;
81 116
82 netlbl_secattr_init(&secattr); 117 if (sksec->nlbl_state != NLBL_REQUIRE)
118 return 0;
83 119
84 rc = security_netlbl_sid_to_secattr(sid, &secattr); 120 secattr = selinux_netlbl_sock_genattr(sk);
85 if (rc != 0) 121 if (secattr == NULL)
86 goto sock_setsid_return; 122 return -ENOMEM;
87 rc = netlbl_sock_setattr(sk, &secattr); 123 rc = netlbl_sock_setattr(sk, secattr);
88 if (rc == 0) 124 switch (rc) {
125 case 0:
89 sksec->nlbl_state = NLBL_LABELED; 126 sksec->nlbl_state = NLBL_LABELED;
127 break;
128 case -EDESTADDRREQ:
129 sksec->nlbl_state = NLBL_REQSKB;
130 rc = 0;
131 break;
132 }
90 133
91sock_setsid_return:
92 netlbl_secattr_destroy(&secattr);
93 return rc; 134 return rc;
94} 135}
95 136
@@ -106,6 +147,38 @@ void selinux_netlbl_cache_invalidate(void)
106} 147}
107 148
108/** 149/**
150 * selinux_netlbl_err - Handle a NetLabel packet error
151 * @skb: the packet
152 * @error: the error code
153 * @gateway: true if host is acting as a gateway, false otherwise
154 *
155 * Description:
156 * When a packet is dropped due to a call to avc_has_perm() pass the error
157 * code to the NetLabel subsystem so any protocol specific processing can be
158 * done. This is safe to call even if you are unsure if NetLabel labeling is
159 * present on the packet, NetLabel is smart enough to only act when it should.
160 *
161 */
162void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
163{
164 netlbl_skbuff_err(skb, error, gateway);
165}
166
167/**
168 * selinux_netlbl_sk_security_free - Free the NetLabel fields
169 * @sssec: the sk_security_struct
170 *
171 * Description:
172 * Free all of the memory in the NetLabel fields of a sk_security_struct.
173 *
174 */
175void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec)
176{
177 if (ssec->nlbl_secattr != NULL)
178 netlbl_secattr_free(ssec->nlbl_secattr);
179}
180
181/**
109 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields 182 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
110 * @ssec: the sk_security_struct 183 * @ssec: the sk_security_struct
111 * @family: the socket family 184 * @family: the socket family
@@ -163,35 +236,118 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
163} 236}
164 237
165/** 238/**
166 * selinux_netlbl_sock_graft - Netlabel the new socket 239 * selinux_netlbl_skbuff_setsid - Set the NetLabel on a packet given a sid
240 * @skb: the packet
241 * @family: protocol family
242 * @sid: the SID
243 *
244 * Description
245 * Call the NetLabel mechanism to set the label of a packet using @sid.
246 * Returns zero on auccess, negative values on failure.
247 *
248 */
249int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
250 u16 family,
251 u32 sid)
252{
253 int rc;
254 struct netlbl_lsm_secattr secattr_storage;
255 struct netlbl_lsm_secattr *secattr = NULL;
256 struct sock *sk;
257
258 /* if this is a locally generated packet check to see if it is already
259 * being labeled by it's parent socket, if it is just exit */
260 sk = skb->sk;
261 if (sk != NULL) {
262 struct sk_security_struct *sksec = sk->sk_security;
263 if (sksec->nlbl_state != NLBL_REQSKB)
264 return 0;
265 secattr = sksec->nlbl_secattr;
266 }
267 if (secattr == NULL) {
268 secattr = &secattr_storage;
269 netlbl_secattr_init(secattr);
270 rc = security_netlbl_sid_to_secattr(sid, secattr);
271 if (rc != 0)
272 goto skbuff_setsid_return;
273 }
274
275 rc = netlbl_skbuff_setattr(skb, family, secattr);
276
277skbuff_setsid_return:
278 if (secattr == &secattr_storage)
279 netlbl_secattr_destroy(secattr);
280 return rc;
281}
282
283/**
284 * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection
167 * @sk: the new connection 285 * @sk: the new connection
168 * @sock: the new socket
169 * 286 *
170 * Description: 287 * Description:
171 * The connection represented by @sk is being grafted onto @sock so set the 288 * A new connection has been established on @sk so make sure it is labeled
172 * socket's NetLabel to match the SID of @sk. 289 * correctly with the NetLabel susbsystem.
173 * 290 *
174 */ 291 */
175void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) 292void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family)
176{ 293{
294 int rc;
177 struct sk_security_struct *sksec = sk->sk_security; 295 struct sk_security_struct *sksec = sk->sk_security;
178 struct netlbl_lsm_secattr secattr; 296 struct netlbl_lsm_secattr *secattr;
179 u32 nlbl_peer_sid; 297 struct inet_sock *sk_inet = inet_sk(sk);
298 struct sockaddr_in addr;
180 299
181 if (sksec->nlbl_state != NLBL_REQUIRE) 300 if (sksec->nlbl_state != NLBL_REQUIRE)
182 return; 301 return;
183 302
184 netlbl_secattr_init(&secattr); 303 secattr = selinux_netlbl_sock_genattr(sk);
185 if (netlbl_sock_getattr(sk, &secattr) == 0 && 304 if (secattr == NULL)
186 secattr.flags != NETLBL_SECATTR_NONE && 305 return;
187 security_netlbl_secattr_to_sid(&secattr, &nlbl_peer_sid) == 0)
188 sksec->peer_sid = nlbl_peer_sid;
189 netlbl_secattr_destroy(&secattr);
190 306
191 /* Try to set the NetLabel on the socket to save time later, if we fail 307 rc = netlbl_sock_setattr(sk, secattr);
192 * here we will pick up the pieces in later calls to 308 switch (rc) {
193 * selinux_netlbl_inode_permission(). */ 309 case 0:
194 selinux_netlbl_sock_setsid(sk, sksec->sid); 310 sksec->nlbl_state = NLBL_LABELED;
311 break;
312 case -EDESTADDRREQ:
313 /* no PF_INET6 support yet because we don't support any IPv6
314 * labeling protocols */
315 if (family != PF_INET) {
316 sksec->nlbl_state = NLBL_UNSET;
317 return;
318 }
319
320 addr.sin_family = family;
321 addr.sin_addr.s_addr = sk_inet->daddr;
322 if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr,
323 secattr) != 0) {
324 /* we failed to label the connected socket (could be
325 * for a variety of reasons, the actual "why" isn't
326 * important here) so we have to go to our backup plan,
327 * labeling the packets individually in the netfilter
328 * local output hook. this is okay but we need to
329 * adjust the MSS of the connection to take into
330 * account any labeling overhead, since we don't know
331 * the exact overhead at this point we'll use the worst
332 * case value which is 40 bytes for IPv4 */
333 struct inet_connection_sock *sk_conn = inet_csk(sk);
334 sk_conn->icsk_ext_hdr_len += 40 -
335 (sk_inet->opt ? sk_inet->opt->optlen : 0);
336 sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
337
338 sksec->nlbl_state = NLBL_REQSKB;
339 } else
340 sksec->nlbl_state = NLBL_CONNLABELED;
341 break;
342 default:
343 /* note that we are failing to label the socket which could be
344 * a bad thing since it means traffic could leave the system
345 * without the desired labeling, however, all is not lost as
346 * we have a check in selinux_netlbl_inode_permission() to
347 * pick up the pieces that we might drop here because we can't
348 * return an error code */
349 break;
350 }
195} 351}
196 352
197/** 353/**
@@ -205,13 +361,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
205 */ 361 */
206int selinux_netlbl_socket_post_create(struct socket *sock) 362int selinux_netlbl_socket_post_create(struct socket *sock)
207{ 363{
208 struct sock *sk = sock->sk; 364 return selinux_netlbl_sock_setsid(sock->sk);
209 struct sk_security_struct *sksec = sk->sk_security;
210
211 if (sksec->nlbl_state != NLBL_REQUIRE)
212 return 0;
213
214 return selinux_netlbl_sock_setsid(sk, sksec->sid);
215} 365}
216 366
217/** 367/**
@@ -246,7 +396,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
246 local_bh_disable(); 396 local_bh_disable();
247 bh_lock_sock_nested(sk); 397 bh_lock_sock_nested(sk);
248 if (likely(sksec->nlbl_state == NLBL_REQUIRE)) 398 if (likely(sksec->nlbl_state == NLBL_REQUIRE))
249 rc = selinux_netlbl_sock_setsid(sk, sksec->sid); 399 rc = selinux_netlbl_sock_setsid(sk);
250 else 400 else
251 rc = 0; 401 rc = 0;
252 bh_unlock_sock(sk); 402 bh_unlock_sock(sk);
@@ -307,7 +457,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
307 return 0; 457 return 0;
308 458
309 if (nlbl_sid != SECINITSID_UNLABELED) 459 if (nlbl_sid != SECINITSID_UNLABELED)
310 netlbl_skbuff_err(skb, rc); 460 netlbl_skbuff_err(skb, rc, 0);
311 return rc; 461 return rc;
312} 462}
313 463
@@ -334,7 +484,8 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
334 struct netlbl_lsm_secattr secattr; 484 struct netlbl_lsm_secattr secattr;
335 485
336 if (level == IPPROTO_IP && optname == IP_OPTIONS && 486 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
337 sksec->nlbl_state == NLBL_LABELED) { 487 (sksec->nlbl_state == NLBL_LABELED ||
488 sksec->nlbl_state == NLBL_CONNLABELED)) {
338 netlbl_secattr_init(&secattr); 489 netlbl_secattr_init(&secattr);
339 lock_sock(sk); 490 lock_sock(sk);
340 rc = netlbl_sock_getattr(sk, &secattr); 491 rc = netlbl_sock_getattr(sk, &secattr);
@@ -346,3 +497,50 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
346 497
347 return rc; 498 return rc;
348} 499}
500
501/**
502 * selinux_netlbl_socket_connect - Label a client-side socket on connect
503 * @sk: the socket to label
504 * @addr: the destination address
505 *
506 * Description:
507 * Attempt to label a connected socket with NetLabel using the given address.
508 * Returns zero values on success, negative values on failure.
509 *
510 */
511int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr)
512{
513 int rc;
514 struct sk_security_struct *sksec = sk->sk_security;
515 struct netlbl_lsm_secattr *secattr;
516
517 if (sksec->nlbl_state != NLBL_REQSKB &&
518 sksec->nlbl_state != NLBL_CONNLABELED)
519 return 0;
520
521 local_bh_disable();
522 bh_lock_sock_nested(sk);
523
524 /* connected sockets are allowed to disconnect when the address family
525 * is set to AF_UNSPEC, if that is what is happening we want to reset
526 * the socket */
527 if (addr->sa_family == AF_UNSPEC) {
528 netlbl_sock_delattr(sk);
529 sksec->nlbl_state = NLBL_REQSKB;
530 rc = 0;
531 goto socket_connect_return;
532 }
533 secattr = selinux_netlbl_sock_genattr(sk);
534 if (secattr == NULL) {
535 rc = -ENOMEM;
536 goto socket_connect_return;
537 }
538 rc = netlbl_conn_setattr(sk, addr, secattr);
539 if (rc == 0)
540 sksec->nlbl_state = NLBL_CONNLABELED;
541
542socket_connect_return:
543 bh_unlock_sock(sk);
544 local_bh_enable();
545 return rc;
546}
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index a1be97f8beea..1215b8e47dba 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -98,7 +98,7 @@ struct avtab_node *
98avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) 98avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
99{ 99{
100 int hvalue; 100 int hvalue;
101 struct avtab_node *prev, *cur, *newnode; 101 struct avtab_node *prev, *cur;
102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
103 103
104 if (!h || !h->htable) 104 if (!h || !h->htable)
@@ -122,9 +122,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
122 key->target_class < cur->key.target_class) 122 key->target_class < cur->key.target_class)
123 break; 123 break;
124 } 124 }
125 newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum); 125 return avtab_insert_node(h, hvalue, prev, cur, key, datum);
126
127 return newnode;
128} 126}
129 127
130struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) 128struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
@@ -231,7 +229,7 @@ void avtab_destroy(struct avtab *h)
231 229
232 for (i = 0; i < h->nslot; i++) { 230 for (i = 0; i < h->nslot; i++) {
233 cur = h->htable[i]; 231 cur = h->htable[i];
234 while (cur != NULL) { 232 while (cur) {
235 temp = cur; 233 temp = cur;
236 cur = cur->next; 234 cur = cur->next;
237 kmem_cache_free(avtab_node_cachep, temp); 235 kmem_cache_free(avtab_node_cachep, temp);
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index fb4efe4f4bc8..4a4e35cac22b 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -29,7 +29,7 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
29 int s[COND_EXPR_MAXDEPTH]; 29 int s[COND_EXPR_MAXDEPTH];
30 int sp = -1; 30 int sp = -1;
31 31
32 for (cur = expr; cur != NULL; cur = cur->next) { 32 for (cur = expr; cur; cur = cur->next) {
33 switch (cur->expr_type) { 33 switch (cur->expr_type) {
34 case COND_BOOL: 34 case COND_BOOL:
35 if (sp == (COND_EXPR_MAXDEPTH - 1)) 35 if (sp == (COND_EXPR_MAXDEPTH - 1))
@@ -97,14 +97,14 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
97 if (new_state == -1) 97 if (new_state == -1)
98 printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); 98 printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
99 /* turn the rules on or off */ 99 /* turn the rules on or off */
100 for (cur = node->true_list; cur != NULL; cur = cur->next) { 100 for (cur = node->true_list; cur; cur = cur->next) {
101 if (new_state <= 0) 101 if (new_state <= 0)
102 cur->node->key.specified &= ~AVTAB_ENABLED; 102 cur->node->key.specified &= ~AVTAB_ENABLED;
103 else 103 else
104 cur->node->key.specified |= AVTAB_ENABLED; 104 cur->node->key.specified |= AVTAB_ENABLED;
105 } 105 }
106 106
107 for (cur = node->false_list; cur != NULL; cur = cur->next) { 107 for (cur = node->false_list; cur; cur = cur->next) {
108 /* -1 or 1 */ 108 /* -1 or 1 */
109 if (new_state) 109 if (new_state)
110 cur->node->key.specified &= ~AVTAB_ENABLED; 110 cur->node->key.specified &= ~AVTAB_ENABLED;
@@ -128,7 +128,7 @@ int cond_policydb_init(struct policydb *p)
128static void cond_av_list_destroy(struct cond_av_list *list) 128static void cond_av_list_destroy(struct cond_av_list *list)
129{ 129{
130 struct cond_av_list *cur, *next; 130 struct cond_av_list *cur, *next;
131 for (cur = list; cur != NULL; cur = next) { 131 for (cur = list; cur; cur = next) {
132 next = cur->next; 132 next = cur->next;
133 /* the avtab_ptr_t node is destroy by the avtab */ 133 /* the avtab_ptr_t node is destroy by the avtab */
134 kfree(cur); 134 kfree(cur);
@@ -139,7 +139,7 @@ static void cond_node_destroy(struct cond_node *node)
139{ 139{
140 struct cond_expr *cur_expr, *next_expr; 140 struct cond_expr *cur_expr, *next_expr;
141 141
142 for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) { 142 for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) {
143 next_expr = cur_expr->next; 143 next_expr = cur_expr->next;
144 kfree(cur_expr); 144 kfree(cur_expr);
145 } 145 }
@@ -155,7 +155,7 @@ static void cond_list_destroy(struct cond_node *list)
155 if (list == NULL) 155 if (list == NULL)
156 return; 156 return;
157 157
158 for (cur = list; cur != NULL; cur = next) { 158 for (cur = list; cur; cur = next) {
159 next = cur->next; 159 next = cur->next;
160 cond_node_destroy(cur); 160 cond_node_destroy(cur);
161 } 161 }
@@ -239,7 +239,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
239 rc = next_entry(key, fp, len); 239 rc = next_entry(key, fp, len);
240 if (rc < 0) 240 if (rc < 0)
241 goto err; 241 goto err;
242 key[len] = 0; 242 key[len] = '\0';
243 if (hashtab_insert(h, key, booldatum)) 243 if (hashtab_insert(h, key, booldatum))
244 goto err; 244 goto err;
245 245
@@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
291 goto err; 291 goto err;
292 } 292 }
293 found = 0; 293 found = 0;
294 for (cur = other; cur != NULL; cur = cur->next) { 294 for (cur = other; cur; cur = cur->next) {
295 if (cur->node == node_ptr) { 295 if (cur->node == node_ptr) {
296 found = 1; 296 found = 1;
297 break; 297 break;
@@ -485,7 +485,7 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi
485 if (!ctab || !key || !avd) 485 if (!ctab || !key || !avd)
486 return; 486 return;
487 487
488 for (node = avtab_search_node(ctab, key); node != NULL; 488 for (node = avtab_search_node(ctab, key); node;
489 node = avtab_search_node_next(node, key->specified)) { 489 node = avtab_search_node_next(node, key->specified)) {
490 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == 490 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) ==
491 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) 491 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h
index 65b9f8366e9c..53ddb013ae57 100644
--- a/security/selinux/ss/conditional.h
+++ b/security/selinux/ss/conditional.h
@@ -28,7 +28,7 @@ struct cond_expr {
28#define COND_XOR 5 /* bool ^ bool */ 28#define COND_XOR 5 /* bool ^ bool */
29#define COND_EQ 6 /* bool == bool */ 29#define COND_EQ 6 /* bool == bool */
30#define COND_NEQ 7 /* bool != bool */ 30#define COND_NEQ 7 /* bool != bool */
31#define COND_LAST 8 31#define COND_LAST COND_NEQ
32 __u32 expr_type; 32 __u32 expr_type;
33 __u32 bool; 33 __u32 bool;
34 struct cond_expr *next; 34 struct cond_expr *next;
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index ddc275490af8..68c7348d1acc 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -109,7 +109,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
109 *catmap = c_iter; 109 *catmap = c_iter;
110 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); 110 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
111 111
112 while (e_iter != NULL) { 112 while (e_iter) {
113 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) { 113 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
114 unsigned int delta, e_startbit, c_endbit; 114 unsigned int delta, e_startbit, c_endbit;
115 115
@@ -197,7 +197,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
197 } 197 }
198 } 198 }
199 c_iter = c_iter->next; 199 c_iter = c_iter->next;
200 } while (c_iter != NULL); 200 } while (c_iter);
201 if (e_iter != NULL) 201 if (e_iter != NULL)
202 ebmap->highbit = e_iter->startbit + EBITMAP_SIZE; 202 ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
203 else 203 else
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 2e7788e13213..933e735bb185 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -81,7 +81,7 @@ void *hashtab_search(struct hashtab *h, const void *key)
81 81
82 hvalue = h->hash_value(h, key); 82 hvalue = h->hash_value(h, key);
83 cur = h->htable[hvalue]; 83 cur = h->htable[hvalue];
84 while (cur != NULL && h->keycmp(h, key, cur->key) > 0) 84 while (cur && h->keycmp(h, key, cur->key) > 0)
85 cur = cur->next; 85 cur = cur->next;
86 86
87 if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) 87 if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
@@ -100,7 +100,7 @@ void hashtab_destroy(struct hashtab *h)
100 100
101 for (i = 0; i < h->size; i++) { 101 for (i = 0; i < h->size; i++) {
102 cur = h->htable[i]; 102 cur = h->htable[i];
103 while (cur != NULL) { 103 while (cur) {
104 temp = cur; 104 temp = cur;
105 cur = cur->next; 105 cur = cur->next;
106 kfree(temp); 106 kfree(temp);
@@ -127,7 +127,7 @@ int hashtab_map(struct hashtab *h,
127 127
128 for (i = 0; i < h->size; i++) { 128 for (i = 0; i < h->size; i++) {
129 cur = h->htable[i]; 129 cur = h->htable[i];
130 while (cur != NULL) { 130 while (cur) {
131 ret = apply(cur->key, cur->datum, args); 131 ret = apply(cur->key, cur->datum, args);
132 if (ret) 132 if (ret)
133 return ret; 133 return ret;
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 77d745da48bb..b5407f16c2a4 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -283,8 +283,8 @@ int mls_context_to_sid(struct policydb *pol,
283 p++; 283 p++;
284 284
285 delim = *p; 285 delim = *p;
286 if (delim != 0) 286 if (delim != '\0')
287 *p++ = 0; 287 *p++ = '\0';
288 288
289 for (l = 0; l < 2; l++) { 289 for (l = 0; l < 2; l++) {
290 levdatum = hashtab_search(pol->p_levels.table, scontextp); 290 levdatum = hashtab_search(pol->p_levels.table, scontextp);
@@ -302,14 +302,14 @@ int mls_context_to_sid(struct policydb *pol,
302 while (*p && *p != ',' && *p != '-') 302 while (*p && *p != ',' && *p != '-')
303 p++; 303 p++;
304 delim = *p; 304 delim = *p;
305 if (delim != 0) 305 if (delim != '\0')
306 *p++ = 0; 306 *p++ = '\0';
307 307
308 /* Separate into range if exists */ 308 /* Separate into range if exists */
309 rngptr = strchr(scontextp, '.'); 309 rngptr = strchr(scontextp, '.');
310 if (rngptr != NULL) { 310 if (rngptr != NULL) {
311 /* Remove '.' */ 311 /* Remove '.' */
312 *rngptr++ = 0; 312 *rngptr++ = '\0';
313 } 313 }
314 314
315 catdatum = hashtab_search(pol->p_cats.table, 315 catdatum = hashtab_search(pol->p_cats.table,
@@ -357,8 +357,8 @@ int mls_context_to_sid(struct policydb *pol,
357 p++; 357 p++;
358 358
359 delim = *p; 359 delim = *p;
360 if (delim != 0) 360 if (delim != '\0')
361 *p++ = 0; 361 *p++ = '\0';
362 } else 362 } else
363 break; 363 break;
364 } 364 }
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 2391761ae422..72e4a54973aa 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -30,6 +30,7 @@
30#include <linux/slab.h> 30#include <linux/slab.h>
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 "security.h" 34#include "security.h"
34 35
35#include "policydb.h" 36#include "policydb.h"
@@ -116,7 +117,12 @@ static struct policydb_compat_info policydb_compat[] = {
116 .version = POLICYDB_VERSION_PERMISSIVE, 117 .version = POLICYDB_VERSION_PERMISSIVE,
117 .sym_num = SYM_NUM, 118 .sym_num = SYM_NUM,
118 .ocon_num = OCON_NUM, 119 .ocon_num = OCON_NUM,
119 } 120 },
121 {
122 .version = POLICYDB_VERSION_BOUNDARY,
123 .sym_num = SYM_NUM,
124 .ocon_num = OCON_NUM,
125 },
120}; 126};
121 127
122static struct policydb_compat_info *policydb_lookup_compat(int version) 128static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -254,7 +260,9 @@ static int role_index(void *key, void *datum, void *datap)
254 260
255 role = datum; 261 role = datum;
256 p = datap; 262 p = datap;
257 if (!role->value || role->value > p->p_roles.nprim) 263 if (!role->value
264 || role->value > p->p_roles.nprim
265 || role->bounds > p->p_roles.nprim)
258 return -EINVAL; 266 return -EINVAL;
259 p->p_role_val_to_name[role->value - 1] = key; 267 p->p_role_val_to_name[role->value - 1] = key;
260 p->role_val_to_struct[role->value - 1] = role; 268 p->role_val_to_struct[role->value - 1] = role;
@@ -270,9 +278,12 @@ static int type_index(void *key, void *datum, void *datap)
270 p = datap; 278 p = datap;
271 279
272 if (typdatum->primary) { 280 if (typdatum->primary) {
273 if (!typdatum->value || typdatum->value > p->p_types.nprim) 281 if (!typdatum->value
282 || typdatum->value > p->p_types.nprim
283 || typdatum->bounds > p->p_types.nprim)
274 return -EINVAL; 284 return -EINVAL;
275 p->p_type_val_to_name[typdatum->value - 1] = key; 285 p->p_type_val_to_name[typdatum->value - 1] = key;
286 p->type_val_to_struct[typdatum->value - 1] = typdatum;
276 } 287 }
277 288
278 return 0; 289 return 0;
@@ -285,7 +296,9 @@ static int user_index(void *key, void *datum, void *datap)
285 296
286 usrdatum = datum; 297 usrdatum = datum;
287 p = datap; 298 p = datap;
288 if (!usrdatum->value || usrdatum->value > p->p_users.nprim) 299 if (!usrdatum->value
300 || usrdatum->value > p->p_users.nprim
301 || usrdatum->bounds > p->p_users.nprim)
289 return -EINVAL; 302 return -EINVAL;
290 p->p_user_val_to_name[usrdatum->value - 1] = key; 303 p->p_user_val_to_name[usrdatum->value - 1] = key;
291 p->user_val_to_struct[usrdatum->value - 1] = usrdatum; 304 p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
@@ -438,6 +451,14 @@ static int policydb_index_others(struct policydb *p)
438 goto out; 451 goto out;
439 } 452 }
440 453
454 p->type_val_to_struct =
455 kmalloc(p->p_types.nprim * sizeof(*(p->type_val_to_struct)),
456 GFP_KERNEL);
457 if (!p->type_val_to_struct) {
458 rc = -ENOMEM;
459 goto out;
460 }
461
441 if (cond_init_bool_indexes(p)) { 462 if (cond_init_bool_indexes(p)) {
442 rc = -ENOMEM; 463 rc = -ENOMEM;
443 goto out; 464 goto out;
@@ -625,6 +646,7 @@ void policydb_destroy(struct policydb *p)
625 kfree(p->class_val_to_struct); 646 kfree(p->class_val_to_struct);
626 kfree(p->role_val_to_struct); 647 kfree(p->role_val_to_struct);
627 kfree(p->user_val_to_struct); 648 kfree(p->user_val_to_struct);
649 kfree(p->type_val_to_struct);
628 650
629 avtab_destroy(&p->te_avtab); 651 avtab_destroy(&p->te_avtab);
630 652
@@ -932,7 +954,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
932 rc = next_entry(key, fp, len); 954 rc = next_entry(key, fp, len);
933 if (rc < 0) 955 if (rc < 0)
934 goto bad; 956 goto bad;
935 key[len] = 0; 957 key[len] = '\0';
936 958
937 rc = hashtab_insert(h, key, perdatum); 959 rc = hashtab_insert(h, key, perdatum);
938 if (rc) 960 if (rc)
@@ -979,7 +1001,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
979 rc = next_entry(key, fp, len); 1001 rc = next_entry(key, fp, len);
980 if (rc < 0) 1002 if (rc < 0)
981 goto bad; 1003 goto bad;
982 key[len] = 0; 1004 key[len] = '\0';
983 1005
984 for (i = 0; i < nel; i++) { 1006 for (i = 0; i < nel; i++) {
985 rc = perm_read(p, comdatum->permissions.table, fp); 1007 rc = perm_read(p, comdatum->permissions.table, fp);
@@ -1117,7 +1139,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1117 rc = next_entry(key, fp, len); 1139 rc = next_entry(key, fp, len);
1118 if (rc < 0) 1140 if (rc < 0)
1119 goto bad; 1141 goto bad;
1120 key[len] = 0; 1142 key[len] = '\0';
1121 1143
1122 if (len2) { 1144 if (len2) {
1123 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL); 1145 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL);
@@ -1128,7 +1150,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1128 rc = next_entry(cladatum->comkey, fp, len2); 1150 rc = next_entry(cladatum->comkey, fp, len2);
1129 if (rc < 0) 1151 if (rc < 0)
1130 goto bad; 1152 goto bad;
1131 cladatum->comkey[len2] = 0; 1153 cladatum->comkey[len2] = '\0';
1132 1154
1133 cladatum->comdatum = hashtab_search(p->p_commons.table, 1155 cladatum->comdatum = hashtab_search(p->p_commons.table,
1134 cladatum->comkey); 1156 cladatum->comkey);
@@ -1176,8 +1198,8 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1176{ 1198{
1177 char *key = NULL; 1199 char *key = NULL;
1178 struct role_datum *role; 1200 struct role_datum *role;
1179 int rc; 1201 int rc, to_read = 2;
1180 __le32 buf[2]; 1202 __le32 buf[3];
1181 u32 len; 1203 u32 len;
1182 1204
1183 role = kzalloc(sizeof(*role), GFP_KERNEL); 1205 role = kzalloc(sizeof(*role), GFP_KERNEL);
@@ -1186,12 +1208,17 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1186 goto out; 1208 goto out;
1187 } 1209 }
1188 1210
1189 rc = next_entry(buf, fp, sizeof buf); 1211 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1212 to_read = 3;
1213
1214 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1190 if (rc < 0) 1215 if (rc < 0)
1191 goto bad; 1216 goto bad;
1192 1217
1193 len = le32_to_cpu(buf[0]); 1218 len = le32_to_cpu(buf[0]);
1194 role->value = le32_to_cpu(buf[1]); 1219 role->value = le32_to_cpu(buf[1]);
1220 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1221 role->bounds = le32_to_cpu(buf[2]);
1195 1222
1196 key = kmalloc(len + 1, GFP_KERNEL); 1223 key = kmalloc(len + 1, GFP_KERNEL);
1197 if (!key) { 1224 if (!key) {
@@ -1201,7 +1228,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1201 rc = next_entry(key, fp, len); 1228 rc = next_entry(key, fp, len);
1202 if (rc < 0) 1229 if (rc < 0)
1203 goto bad; 1230 goto bad;
1204 key[len] = 0; 1231 key[len] = '\0';
1205 1232
1206 rc = ebitmap_read(&role->dominates, fp); 1233 rc = ebitmap_read(&role->dominates, fp);
1207 if (rc) 1234 if (rc)
@@ -1236,8 +1263,8 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1236{ 1263{
1237 char *key = NULL; 1264 char *key = NULL;
1238 struct type_datum *typdatum; 1265 struct type_datum *typdatum;
1239 int rc; 1266 int rc, to_read = 3;
1240 __le32 buf[3]; 1267 __le32 buf[4];
1241 u32 len; 1268 u32 len;
1242 1269
1243 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); 1270 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
@@ -1246,13 +1273,27 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1246 return rc; 1273 return rc;
1247 } 1274 }
1248 1275
1249 rc = next_entry(buf, fp, sizeof buf); 1276 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1277 to_read = 4;
1278
1279 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1250 if (rc < 0) 1280 if (rc < 0)
1251 goto bad; 1281 goto bad;
1252 1282
1253 len = le32_to_cpu(buf[0]); 1283 len = le32_to_cpu(buf[0]);
1254 typdatum->value = le32_to_cpu(buf[1]); 1284 typdatum->value = le32_to_cpu(buf[1]);
1255 typdatum->primary = le32_to_cpu(buf[2]); 1285 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
1286 u32 prop = le32_to_cpu(buf[2]);
1287
1288 if (prop & TYPEDATUM_PROPERTY_PRIMARY)
1289 typdatum->primary = 1;
1290 if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE)
1291 typdatum->attribute = 1;
1292
1293 typdatum->bounds = le32_to_cpu(buf[3]);
1294 } else {
1295 typdatum->primary = le32_to_cpu(buf[2]);
1296 }
1256 1297
1257 key = kmalloc(len + 1, GFP_KERNEL); 1298 key = kmalloc(len + 1, GFP_KERNEL);
1258 if (!key) { 1299 if (!key) {
@@ -1262,7 +1303,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1262 rc = next_entry(key, fp, len); 1303 rc = next_entry(key, fp, len);
1263 if (rc < 0) 1304 if (rc < 0)
1264 goto bad; 1305 goto bad;
1265 key[len] = 0; 1306 key[len] = '\0';
1266 1307
1267 rc = hashtab_insert(h, key, typdatum); 1308 rc = hashtab_insert(h, key, typdatum);
1268 if (rc) 1309 if (rc)
@@ -1309,8 +1350,8 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1309{ 1350{
1310 char *key = NULL; 1351 char *key = NULL;
1311 struct user_datum *usrdatum; 1352 struct user_datum *usrdatum;
1312 int rc; 1353 int rc, to_read = 2;
1313 __le32 buf[2]; 1354 __le32 buf[3];
1314 u32 len; 1355 u32 len;
1315 1356
1316 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); 1357 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
@@ -1319,12 +1360,17 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1319 goto out; 1360 goto out;
1320 } 1361 }
1321 1362
1322 rc = next_entry(buf, fp, sizeof buf); 1363 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1364 to_read = 3;
1365
1366 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1323 if (rc < 0) 1367 if (rc < 0)
1324 goto bad; 1368 goto bad;
1325 1369
1326 len = le32_to_cpu(buf[0]); 1370 len = le32_to_cpu(buf[0]);
1327 usrdatum->value = le32_to_cpu(buf[1]); 1371 usrdatum->value = le32_to_cpu(buf[1]);
1372 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1373 usrdatum->bounds = le32_to_cpu(buf[2]);
1328 1374
1329 key = kmalloc(len + 1, GFP_KERNEL); 1375 key = kmalloc(len + 1, GFP_KERNEL);
1330 if (!key) { 1376 if (!key) {
@@ -1334,7 +1380,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1334 rc = next_entry(key, fp, len); 1380 rc = next_entry(key, fp, len);
1335 if (rc < 0) 1381 if (rc < 0)
1336 goto bad; 1382 goto bad;
1337 key[len] = 0; 1383 key[len] = '\0';
1338 1384
1339 rc = ebitmap_read(&usrdatum->roles, fp); 1385 rc = ebitmap_read(&usrdatum->roles, fp);
1340 if (rc) 1386 if (rc)
@@ -1388,7 +1434,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
1388 rc = next_entry(key, fp, len); 1434 rc = next_entry(key, fp, len);
1389 if (rc < 0) 1435 if (rc < 0)
1390 goto bad; 1436 goto bad;
1391 key[len] = 0; 1437 key[len] = '\0';
1392 1438
1393 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); 1439 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
1394 if (!levdatum->level) { 1440 if (!levdatum->level) {
@@ -1440,7 +1486,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
1440 rc = next_entry(key, fp, len); 1486 rc = next_entry(key, fp, len);
1441 if (rc < 0) 1487 if (rc < 0)
1442 goto bad; 1488 goto bad;
1443 key[len] = 0; 1489 key[len] = '\0';
1444 1490
1445 rc = hashtab_insert(h, key, catdatum); 1491 rc = hashtab_insert(h, key, catdatum);
1446 if (rc) 1492 if (rc)
@@ -1465,6 +1511,133 @@ static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp)
1465 cat_read, 1511 cat_read,
1466}; 1512};
1467 1513
1514static int user_bounds_sanity_check(void *key, void *datum, void *datap)
1515{
1516 struct user_datum *upper, *user;
1517 struct policydb *p = datap;
1518 int depth = 0;
1519
1520 upper = user = datum;
1521 while (upper->bounds) {
1522 struct ebitmap_node *node;
1523 unsigned long bit;
1524
1525 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1526 printk(KERN_ERR "SELinux: user %s: "
1527 "too deep or looped boundary",
1528 (char *) key);
1529 return -EINVAL;
1530 }
1531
1532 upper = p->user_val_to_struct[upper->bounds - 1];
1533 ebitmap_for_each_positive_bit(&user->roles, node, bit) {
1534 if (ebitmap_get_bit(&upper->roles, bit))
1535 continue;
1536
1537 printk(KERN_ERR
1538 "SELinux: boundary violated policy: "
1539 "user=%s role=%s bounds=%s\n",
1540 p->p_user_val_to_name[user->value - 1],
1541 p->p_role_val_to_name[bit],
1542 p->p_user_val_to_name[upper->value - 1]);
1543
1544 return -EINVAL;
1545 }
1546 }
1547
1548 return 0;
1549}
1550
1551static int role_bounds_sanity_check(void *key, void *datum, void *datap)
1552{
1553 struct role_datum *upper, *role;
1554 struct policydb *p = datap;
1555 int depth = 0;
1556
1557 upper = role = datum;
1558 while (upper->bounds) {
1559 struct ebitmap_node *node;
1560 unsigned long bit;
1561
1562 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1563 printk(KERN_ERR "SELinux: role %s: "
1564 "too deep or looped bounds\n",
1565 (char *) key);
1566 return -EINVAL;
1567 }
1568
1569 upper = p->role_val_to_struct[upper->bounds - 1];
1570 ebitmap_for_each_positive_bit(&role->types, node, bit) {
1571 if (ebitmap_get_bit(&upper->types, bit))
1572 continue;
1573
1574 printk(KERN_ERR
1575 "SELinux: boundary violated policy: "
1576 "role=%s type=%s bounds=%s\n",
1577 p->p_role_val_to_name[role->value - 1],
1578 p->p_type_val_to_name[bit],
1579 p->p_role_val_to_name[upper->value - 1]);
1580
1581 return -EINVAL;
1582 }
1583 }
1584
1585 return 0;
1586}
1587
1588static int type_bounds_sanity_check(void *key, void *datum, void *datap)
1589{
1590 struct type_datum *upper, *type;
1591 struct policydb *p = datap;
1592 int depth = 0;
1593
1594 upper = type = datum;
1595 while (upper->bounds) {
1596 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1597 printk(KERN_ERR "SELinux: type %s: "
1598 "too deep or looped boundary\n",
1599 (char *) key);
1600 return -EINVAL;
1601 }
1602
1603 upper = p->type_val_to_struct[upper->bounds - 1];
1604 if (upper->attribute) {
1605 printk(KERN_ERR "SELinux: type %s: "
1606 "bounded by attribute %s",
1607 (char *) key,
1608 p->p_type_val_to_name[upper->value - 1]);
1609 return -EINVAL;
1610 }
1611 }
1612
1613 return 0;
1614}
1615
1616static int policydb_bounds_sanity_check(struct policydb *p)
1617{
1618 int rc;
1619
1620 if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
1621 return 0;
1622
1623 rc = hashtab_map(p->p_users.table,
1624 user_bounds_sanity_check, p);
1625 if (rc)
1626 return rc;
1627
1628 rc = hashtab_map(p->p_roles.table,
1629 role_bounds_sanity_check, p);
1630 if (rc)
1631 return rc;
1632
1633 rc = hashtab_map(p->p_types.table,
1634 type_bounds_sanity_check, p);
1635 if (rc)
1636 return rc;
1637
1638 return 0;
1639}
1640
1468extern int ss_initialized; 1641extern int ss_initialized;
1469 1642
1470/* 1643/*
@@ -1523,7 +1696,7 @@ int policydb_read(struct policydb *p, void *fp)
1523 kfree(policydb_str); 1696 kfree(policydb_str);
1524 goto bad; 1697 goto bad;
1525 } 1698 }
1526 policydb_str[len] = 0; 1699 policydb_str[len] = '\0';
1527 if (strcmp(policydb_str, POLICYDB_STRING)) { 1700 if (strcmp(policydb_str, POLICYDB_STRING)) {
1528 printk(KERN_ERR "SELinux: policydb string %s does not match " 1701 printk(KERN_ERR "SELinux: policydb string %s does not match "
1529 "my string %s\n", policydb_str, POLICYDB_STRING); 1702 "my string %s\n", policydb_str, POLICYDB_STRING);
@@ -1961,6 +2134,10 @@ int policydb_read(struct policydb *p, void *fp)
1961 goto bad; 2134 goto bad;
1962 } 2135 }
1963 2136
2137 rc = policydb_bounds_sanity_check(p);
2138 if (rc)
2139 goto bad;
2140
1964 rc = 0; 2141 rc = 0;
1965out: 2142out:
1966 return rc; 2143 return rc;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 4253370fda6a..55152d498b53 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -61,6 +61,7 @@ struct class_datum {
61/* Role attributes */ 61/* Role attributes */
62struct role_datum { 62struct role_datum {
63 u32 value; /* internal role value */ 63 u32 value; /* internal role value */
64 u32 bounds; /* boundary of role */
64 struct ebitmap dominates; /* set of roles dominated by this role */ 65 struct ebitmap dominates; /* set of roles dominated by this role */
65 struct ebitmap types; /* set of authorized types for role */ 66 struct ebitmap types; /* set of authorized types for role */
66}; 67};
@@ -81,12 +82,15 @@ struct role_allow {
81/* Type attributes */ 82/* Type attributes */
82struct type_datum { 83struct type_datum {
83 u32 value; /* internal type value */ 84 u32 value; /* internal type value */
85 u32 bounds; /* boundary of type */
84 unsigned char primary; /* primary name? */ 86 unsigned char primary; /* primary name? */
87 unsigned char attribute;/* attribute ?*/
85}; 88};
86 89
87/* User attributes */ 90/* User attributes */
88struct user_datum { 91struct user_datum {
89 u32 value; /* internal user value */ 92 u32 value; /* internal user value */
93 u32 bounds; /* bounds of user */
90 struct ebitmap roles; /* set of authorized roles for user */ 94 struct ebitmap roles; /* set of authorized roles for user */
91 struct mls_range range; /* MLS range (min - max) for user */ 95 struct mls_range range; /* MLS range (min - max) for user */
92 struct mls_level dfltlevel; /* default login MLS level for user */ 96 struct mls_level dfltlevel; /* default login MLS level for user */
@@ -209,6 +213,7 @@ struct policydb {
209 struct class_datum **class_val_to_struct; 213 struct class_datum **class_val_to_struct;
210 struct role_datum **role_val_to_struct; 214 struct role_datum **role_val_to_struct;
211 struct user_datum **user_val_to_struct; 215 struct user_datum **user_val_to_struct;
216 struct type_datum **type_val_to_struct;
212 217
213 /* type enforcement access vectors and transitions */ 218 /* type enforcement access vectors and transitions */
214 struct avtab te_avtab; 219 struct avtab te_avtab;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b52f923ce680..343c8ab14af0 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -88,6 +88,11 @@ static u32 latest_granting;
88static int context_struct_to_string(struct context *context, char **scontext, 88static int context_struct_to_string(struct context *context, char **scontext,
89 u32 *scontext_len); 89 u32 *scontext_len);
90 90
91static int context_struct_compute_av(struct context *scontext,
92 struct context *tcontext,
93 u16 tclass,
94 u32 requested,
95 struct av_decision *avd);
91/* 96/*
92 * Return the boolean value of a constraint expression 97 * Return the boolean value of a constraint expression
93 * when it is applied to the specified source and target 98 * when it is applied to the specified source and target
@@ -274,6 +279,100 @@ mls_ops:
274} 279}
275 280
276/* 281/*
282 * security_boundary_permission - drops violated permissions
283 * on boundary constraint.
284 */
285static void type_attribute_bounds_av(struct context *scontext,
286 struct context *tcontext,
287 u16 tclass,
288 u32 requested,
289 struct av_decision *avd)
290{
291 struct context lo_scontext;
292 struct context lo_tcontext;
293 struct av_decision lo_avd;
294 struct type_datum *source
295 = policydb.type_val_to_struct[scontext->type - 1];
296 struct type_datum *target
297 = policydb.type_val_to_struct[tcontext->type - 1];
298 u32 masked = 0;
299
300 if (source->bounds) {
301 memset(&lo_avd, 0, sizeof(lo_avd));
302
303 memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
304 lo_scontext.type = source->bounds;
305
306 context_struct_compute_av(&lo_scontext,
307 tcontext,
308 tclass,
309 requested,
310 &lo_avd);
311 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
312 return; /* no masked permission */
313 masked = ~lo_avd.allowed & avd->allowed;
314 }
315
316 if (target->bounds) {
317 memset(&lo_avd, 0, sizeof(lo_avd));
318
319 memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
320 lo_tcontext.type = target->bounds;
321
322 context_struct_compute_av(scontext,
323 &lo_tcontext,
324 tclass,
325 requested,
326 &lo_avd);
327 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
328 return; /* no masked permission */
329 masked = ~lo_avd.allowed & avd->allowed;
330 }
331
332 if (source->bounds && target->bounds) {
333 memset(&lo_avd, 0, sizeof(lo_avd));
334 /*
335 * lo_scontext and lo_tcontext are already
336 * set up.
337 */
338
339 context_struct_compute_av(&lo_scontext,
340 &lo_tcontext,
341 tclass,
342 requested,
343 &lo_avd);
344 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
345 return; /* no masked permission */
346 masked = ~lo_avd.allowed & avd->allowed;
347 }
348
349 if (masked) {
350 struct audit_buffer *ab;
351 char *stype_name
352 = policydb.p_type_val_to_name[source->value - 1];
353 char *ttype_name
354 = policydb.p_type_val_to_name[target->value - 1];
355 char *tclass_name
356 = policydb.p_class_val_to_name[tclass - 1];
357
358 /* mask violated permissions */
359 avd->allowed &= ~masked;
360
361 /* notice to userspace via audit message */
362 ab = audit_log_start(current->audit_context,
363 GFP_ATOMIC, AUDIT_SELINUX_ERR);
364 if (!ab)
365 return;
366
367 audit_log_format(ab, "av boundary violation: "
368 "source=%s target=%s tclass=%s",
369 stype_name, ttype_name, tclass_name);
370 avc_dump_av(ab, tclass, masked);
371 audit_log_end(ab);
372 }
373}
374
375/*
277 * Compute access vectors based on a context structure pair for 376 * Compute access vectors based on a context structure pair for
278 * the permissions in a particular class. 377 * the permissions in a particular class.
279 */ 378 */
@@ -356,7 +455,7 @@ static int context_struct_compute_av(struct context *scontext,
356 avkey.source_type = i + 1; 455 avkey.source_type = i + 1;
357 avkey.target_type = j + 1; 456 avkey.target_type = j + 1;
358 for (node = avtab_search_node(&policydb.te_avtab, &avkey); 457 for (node = avtab_search_node(&policydb.te_avtab, &avkey);
359 node != NULL; 458 node;
360 node = avtab_search_node_next(node, avkey.specified)) { 459 node = avtab_search_node_next(node, avkey.specified)) {
361 if (node->key.specified == AVTAB_ALLOWED) 460 if (node->key.specified == AVTAB_ALLOWED)
362 avd->allowed |= node->datum.data; 461 avd->allowed |= node->datum.data;
@@ -404,6 +503,14 @@ static int context_struct_compute_av(struct context *scontext,
404 PROCESS__DYNTRANSITION); 503 PROCESS__DYNTRANSITION);
405 } 504 }
406 505
506 /*
507 * If the given source and target types have boundary
508 * constraint, lazy checks have to mask any violated
509 * permission and notice it to userspace via audit.
510 */
511 type_attribute_bounds_av(scontext, tcontext,
512 tclass, requested, avd);
513
407 return 0; 514 return 0;
408 515
409inval_class: 516inval_class:
@@ -549,6 +656,69 @@ out:
549 return rc; 656 return rc;
550} 657}
551 658
659/*
660 * security_bounded_transition - check whether the given
661 * transition is directed to bounded, or not.
662 * It returns 0, if @newsid is bounded by @oldsid.
663 * Otherwise, it returns error code.
664 *
665 * @oldsid : current security identifier
666 * @newsid : destinated security identifier
667 */
668int security_bounded_transition(u32 old_sid, u32 new_sid)
669{
670 struct context *old_context, *new_context;
671 struct type_datum *type;
672 int index;
673 int rc = -EINVAL;
674
675 read_lock(&policy_rwlock);
676
677 old_context = sidtab_search(&sidtab, old_sid);
678 if (!old_context) {
679 printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
680 __func__, old_sid);
681 goto out;
682 }
683
684 new_context = sidtab_search(&sidtab, new_sid);
685 if (!new_context) {
686 printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
687 __func__, new_sid);
688 goto out;
689 }
690
691 /* type/domain unchaned */
692 if (old_context->type == new_context->type) {
693 rc = 0;
694 goto out;
695 }
696
697 index = new_context->type;
698 while (true) {
699 type = policydb.type_val_to_struct[index - 1];
700 BUG_ON(!type);
701
702 /* not bounded anymore */
703 if (!type->bounds) {
704 rc = -EPERM;
705 break;
706 }
707
708 /* @newsid is bounded by @oldsid */
709 if (type->bounds == old_context->type) {
710 rc = 0;
711 break;
712 }
713 index = type->bounds;
714 }
715out:
716 read_unlock(&policy_rwlock);
717
718 return rc;
719}
720
721
552/** 722/**
553 * security_compute_av - Compute access vector decisions. 723 * security_compute_av - Compute access vector decisions.
554 * @ssid: source security identifier 724 * @ssid: source security identifier
@@ -794,7 +964,7 @@ static int string_to_context_struct(struct policydb *pol,
794 *p++ = 0; 964 *p++ = 0;
795 965
796 typdatum = hashtab_search(pol->p_types.table, scontextp); 966 typdatum = hashtab_search(pol->p_types.table, scontextp);
797 if (!typdatum) 967 if (!typdatum || typdatum->attribute)
798 goto out; 968 goto out;
799 969
800 ctx->type = typdatum->value; 970 ctx->type = typdatum->value;
@@ -811,11 +981,12 @@ static int string_to_context_struct(struct policydb *pol,
811 /* Check the validity of the new context. */ 981 /* Check the validity of the new context. */
812 if (!policydb_context_isvalid(pol, ctx)) { 982 if (!policydb_context_isvalid(pol, ctx)) {
813 rc = -EINVAL; 983 rc = -EINVAL;
814 context_destroy(ctx);
815 goto out; 984 goto out;
816 } 985 }
817 rc = 0; 986 rc = 0;
818out: 987out:
988 if (rc)
989 context_destroy(ctx);
819 return rc; 990 return rc;
820} 991}
821 992
@@ -868,8 +1039,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
868 } else if (rc) 1039 } else if (rc)
869 goto out; 1040 goto out;
870 rc = sidtab_context_to_sid(&sidtab, &context, sid); 1041 rc = sidtab_context_to_sid(&sidtab, &context, sid);
871 if (rc) 1042 context_destroy(&context);
872 context_destroy(&context);
873out: 1043out:
874 read_unlock(&policy_rwlock); 1044 read_unlock(&policy_rwlock);
875 kfree(scontext2); 1045 kfree(scontext2);
@@ -1037,7 +1207,7 @@ static int security_compute_sid(u32 ssid,
1037 /* If no permanent rule, also check for enabled conditional rules */ 1207 /* If no permanent rule, also check for enabled conditional rules */
1038 if (!avdatum) { 1208 if (!avdatum) {
1039 node = avtab_search_node(&policydb.te_cond_avtab, &avkey); 1209 node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
1040 for (; node != NULL; node = avtab_search_node_next(node, specified)) { 1210 for (; node; node = avtab_search_node_next(node, specified)) {
1041 if (node->key.specified & AVTAB_ENABLED) { 1211 if (node->key.specified & AVTAB_ENABLED) {
1042 avdatum = &node->datum; 1212 avdatum = &node->datum;
1043 break; 1213 break;
@@ -2050,7 +2220,7 @@ int security_set_bools(int len, int *values)
2050 policydb.bool_val_to_struct[i]->state = 0; 2220 policydb.bool_val_to_struct[i]->state = 0;
2051 } 2221 }
2052 2222
2053 for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { 2223 for (cur = policydb.cond_list; cur; cur = cur->next) {
2054 rc = evaluate_cond_node(&policydb, cur); 2224 rc = evaluate_cond_node(&policydb, cur);
2055 if (rc) 2225 if (rc)
2056 goto out; 2226 goto out;
@@ -2102,7 +2272,7 @@ static int security_preserve_bools(struct policydb *p)
2102 if (booldatum) 2272 if (booldatum)
2103 booldatum->state = bvalues[i]; 2273 booldatum->state = bvalues[i];
2104 } 2274 }
2105 for (cur = p->cond_list; cur != NULL; cur = cur->next) { 2275 for (cur = p->cond_list; cur; cur = cur->next) {
2106 rc = evaluate_cond_node(p, cur); 2276 rc = evaluate_cond_node(p, cur);
2107 if (rc) 2277 if (rc)
2108 goto out; 2278 goto out;
@@ -2737,6 +2907,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2737 if (ctx == NULL) 2907 if (ctx == NULL)
2738 goto netlbl_secattr_to_sid_return; 2908 goto netlbl_secattr_to_sid_return;
2739 2909
2910 context_init(&ctx_new);
2740 ctx_new.user = ctx->user; 2911 ctx_new.user = ctx->user;
2741 ctx_new.role = ctx->role; 2912 ctx_new.role = ctx->role;
2742 ctx_new.type = ctx->type; 2913 ctx_new.type = ctx->type;
@@ -2745,13 +2916,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2745 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat, 2916 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
2746 secattr->attr.mls.cat) != 0) 2917 secattr->attr.mls.cat) != 0)
2747 goto netlbl_secattr_to_sid_return; 2918 goto netlbl_secattr_to_sid_return;
2748 ctx_new.range.level[1].cat.highbit = 2919 memcpy(&ctx_new.range.level[1].cat,
2749 ctx_new.range.level[0].cat.highbit; 2920 &ctx_new.range.level[0].cat,
2750 ctx_new.range.level[1].cat.node = 2921 sizeof(ctx_new.range.level[0].cat));
2751 ctx_new.range.level[0].cat.node;
2752 } else {
2753 ebitmap_init(&ctx_new.range.level[0].cat);
2754 ebitmap_init(&ctx_new.range.level[1].cat);
2755 } 2922 }
2756 if (mls_context_isvalid(&policydb, &ctx_new) != 1) 2923 if (mls_context_isvalid(&policydb, &ctx_new) != 1)
2757 goto netlbl_secattr_to_sid_return_cleanup; 2924 goto netlbl_secattr_to_sid_return_cleanup;
@@ -2788,7 +2955,7 @@ netlbl_secattr_to_sid_return_cleanup:
2788 */ 2955 */
2789int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) 2956int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2790{ 2957{
2791 int rc = -ENOENT; 2958 int rc;
2792 struct context *ctx; 2959 struct context *ctx;
2793 2960
2794 if (!ss_initialized) 2961 if (!ss_initialized)
@@ -2796,11 +2963,18 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2796 2963
2797 read_lock(&policy_rwlock); 2964 read_lock(&policy_rwlock);
2798 ctx = sidtab_search(&sidtab, sid); 2965 ctx = sidtab_search(&sidtab, sid);
2799 if (ctx == NULL) 2966 if (ctx == NULL) {
2967 rc = -ENOENT;
2800 goto netlbl_sid_to_secattr_failure; 2968 goto netlbl_sid_to_secattr_failure;
2969 }
2801 secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], 2970 secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
2802 GFP_ATOMIC); 2971 GFP_ATOMIC);
2803 secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY; 2972 if (secattr->domain == NULL) {
2973 rc = -ENOMEM;
2974 goto netlbl_sid_to_secattr_failure;
2975 }
2976 secattr->attr.secid = sid;
2977 secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
2804 mls_export_netlbl_lvl(ctx, secattr); 2978 mls_export_netlbl_lvl(ctx, secattr);
2805 rc = mls_export_netlbl_cat(ctx, secattr); 2979 rc = mls_export_netlbl_cat(ctx, secattr);
2806 if (rc != 0) 2980 if (rc != 0)
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index a81ded104129..e817989764cd 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -43,7 +43,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
43 hvalue = SIDTAB_HASH(sid); 43 hvalue = SIDTAB_HASH(sid);
44 prev = NULL; 44 prev = NULL;
45 cur = s->htable[hvalue]; 45 cur = s->htable[hvalue];
46 while (cur != NULL && sid > cur->sid) { 46 while (cur && sid > cur->sid) {
47 prev = cur; 47 prev = cur;
48 cur = cur->next; 48 cur = cur->next;
49 } 49 }
@@ -92,7 +92,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
92 92
93 hvalue = SIDTAB_HASH(sid); 93 hvalue = SIDTAB_HASH(sid);
94 cur = s->htable[hvalue]; 94 cur = s->htable[hvalue];
95 while (cur != NULL && sid > cur->sid) 95 while (cur && sid > cur->sid)
96 cur = cur->next; 96 cur = cur->next;
97 97
98 if (force && cur && sid == cur->sid && cur->context.len) 98 if (force && cur && sid == cur->sid && cur->context.len)
@@ -103,7 +103,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
103 sid = SECINITSID_UNLABELED; 103 sid = SECINITSID_UNLABELED;
104 hvalue = SIDTAB_HASH(sid); 104 hvalue = SIDTAB_HASH(sid);
105 cur = s->htable[hvalue]; 105 cur = s->htable[hvalue];
106 while (cur != NULL && sid > cur->sid) 106 while (cur && sid > cur->sid)
107 cur = cur->next; 107 cur = cur->next;
108 if (!cur || sid != cur->sid) 108 if (!cur || sid != cur->sid)
109 return NULL; 109 return NULL;
@@ -136,7 +136,7 @@ int sidtab_map(struct sidtab *s,
136 136
137 for (i = 0; i < SIDTAB_SIZE; i++) { 137 for (i = 0; i < SIDTAB_SIZE; i++) {
138 cur = s->htable[i]; 138 cur = s->htable[i];
139 while (cur != NULL) { 139 while (cur) {
140 rc = apply(cur->sid, &cur->context, args); 140 rc = apply(cur->sid, &cur->context, args);
141 if (rc) 141 if (rc)
142 goto out; 142 goto out;
@@ -155,7 +155,7 @@ static inline u32 sidtab_search_context(struct sidtab *s,
155 155
156 for (i = 0; i < SIDTAB_SIZE; i++) { 156 for (i = 0; i < SIDTAB_SIZE; i++) {
157 cur = s->htable[i]; 157 cur = s->htable[i];
158 while (cur != NULL) { 158 while (cur) {
159 if (context_cmp(&cur->context, context)) 159 if (context_cmp(&cur->context, context))
160 return cur->sid; 160 return cur->sid;
161 cur = cur->next; 161 cur = cur->next;
@@ -242,7 +242,7 @@ void sidtab_destroy(struct sidtab *s)
242 242
243 for (i = 0; i < SIDTAB_SIZE; i++) { 243 for (i = 0; i < SIDTAB_SIZE; i++) {
244 cur = s->htable[i]; 244 cur = s->htable[i];
245 while (cur != NULL) { 245 while (cur) {
246 temp = cur; 246 temp = cur;
247 cur = cur->next; 247 cur = cur->next;
248 context_destroy(&temp->context); 248 context_destroy(&temp->context);
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 4a4477f5afdc..31dce559595a 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -178,6 +178,7 @@ u32 smack_to_secid(const char *);
178extern int smack_cipso_direct; 178extern int smack_cipso_direct;
179extern int smack_net_nltype; 179extern int smack_net_nltype;
180extern char *smack_net_ambient; 180extern char *smack_net_ambient;
181extern char *smack_onlycap;
181 182
182extern struct smack_known *smack_known; 183extern struct smack_known *smack_known;
183extern struct smack_known smack_known_floor; 184extern struct smack_known smack_known_floor;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index f6b5f6eed6dd..79ff21ed4c3b 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -157,7 +157,7 @@ int smk_access(char *subject_label, char *object_label, int request)
157 * 157 *
158 * This function checks the current subject label/object label pair 158 * This function checks the current subject label/object label pair
159 * in the access rule list and returns 0 if the access is permitted, 159 * in the access rule list and returns 0 if the access is permitted,
160 * non zero otherwise. It allows that current my have the capability 160 * non zero otherwise. It allows that current may have the capability
161 * to override the rules. 161 * to override the rules.
162 */ 162 */
163int smk_curacc(char *obj_label, u32 mode) 163int smk_curacc(char *obj_label, u32 mode)
@@ -168,6 +168,14 @@ int smk_curacc(char *obj_label, u32 mode)
168 if (rc == 0) 168 if (rc == 0)
169 return 0; 169 return 0;
170 170
171 /*
172 * Return if a specific label has been designated as the
173 * only one that gets privilege and current does not
174 * have that label.
175 */
176 if (smack_onlycap != NULL && smack_onlycap != current->security)
177 return rc;
178
171 if (capable(CAP_MAC_OVERRIDE)) 179 if (capable(CAP_MAC_OVERRIDE))
172 return 0; 180 return 0;
173 181
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index ee5a51cbc5eb..6e2dc0bab70d 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -87,27 +87,46 @@ struct inode_smack *new_inode_smack(char *smack)
87 */ 87 */
88 88
89/** 89/**
90 * smack_ptrace - Smack approval on ptrace 90 * smack_ptrace_may_access - Smack approval on PTRACE_ATTACH
91 * @ptp: parent task pointer
92 * @ctp: child task pointer 91 * @ctp: child task pointer
93 * 92 *
94 * Returns 0 if access is OK, an error code otherwise 93 * Returns 0 if access is OK, an error code otherwise
95 * 94 *
96 * Do the capability checks, and require read and write. 95 * Do the capability checks, and require read and write.
97 */ 96 */
98static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp, 97static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode)
99 unsigned int mode)
100{ 98{
101 int rc; 99 int rc;
102 100
103 rc = cap_ptrace(ptp, ctp, mode); 101 rc = cap_ptrace_may_access(ctp, mode);
104 if (rc != 0) 102 if (rc != 0)
105 return rc; 103 return rc;
106 104
107 rc = smk_access(ptp->security, ctp->security, MAY_READWRITE); 105 rc = smk_access(current->security, ctp->security, MAY_READWRITE);
108 if (rc != 0 && __capable(ptp, CAP_MAC_OVERRIDE)) 106 if (rc != 0 && capable(CAP_MAC_OVERRIDE))
109 return 0; 107 return 0;
108 return rc;
109}
110
111/**
112 * smack_ptrace_traceme - Smack approval on PTRACE_TRACEME
113 * @ptp: parent task pointer
114 *
115 * Returns 0 if access is OK, an error code otherwise
116 *
117 * Do the capability checks, and require read and write.
118 */
119static int smack_ptrace_traceme(struct task_struct *ptp)
120{
121 int rc;
110 122
123 rc = cap_ptrace_traceme(ptp);
124 if (rc != 0)
125 return rc;
126
127 rc = smk_access(ptp->security, current->security, MAY_READWRITE);
128 if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE))
129 return 0;
111 return rc; 130 return rc;
112} 131}
113 132
@@ -522,8 +541,7 @@ static int smack_inode_rename(struct inode *old_inode,
522 * 541 *
523 * Returns 0 if access is permitted, -EACCES otherwise 542 * Returns 0 if access is permitted, -EACCES otherwise
524 */ 543 */
525static int smack_inode_permission(struct inode *inode, int mask, 544static int smack_inode_permission(struct inode *inode, int mask)
526 struct nameidata *nd)
527{ 545{
528 /* 546 /*
529 * No permission to check. Existence test. Yup, it's there. 547 * No permission to check. Existence test. Yup, it's there.
@@ -924,7 +942,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
924 */ 942 */
925 file = container_of(fown, struct file, f_owner); 943 file = container_of(fown, struct file, f_owner);
926 rc = smk_access(file->f_security, tsk->security, MAY_WRITE); 944 rc = smk_access(file->f_security, tsk->security, MAY_WRITE);
927 if (rc != 0 && __capable(tsk, CAP_MAC_OVERRIDE)) 945 if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
928 return 0; 946 return 0;
929 return rc; 947 return rc;
930} 948}
@@ -1165,12 +1183,12 @@ static int smack_task_wait(struct task_struct *p)
1165 * account for the smack labels having gotten to 1183 * account for the smack labels having gotten to
1166 * be different in the first place. 1184 * be different in the first place.
1167 * 1185 *
1168 * This breaks the strict subjet/object access 1186 * This breaks the strict subject/object access
1169 * control ideal, taking the object's privilege 1187 * control ideal, taking the object's privilege
1170 * state into account in the decision as well as 1188 * state into account in the decision as well as
1171 * the smack value. 1189 * the smack value.
1172 */ 1190 */
1173 if (capable(CAP_MAC_OVERRIDE) || __capable(p, CAP_MAC_OVERRIDE)) 1191 if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE))
1174 return 0; 1192 return 0;
1175 1193
1176 return rc; 1194 return rc;
@@ -2017,9 +2035,6 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2017{ 2035{
2018 char *newsmack; 2036 char *newsmack;
2019 2037
2020 if (!__capable(p, CAP_MAC_ADMIN))
2021 return -EPERM;
2022
2023 /* 2038 /*
2024 * Changing another process' Smack value is too dangerous 2039 * Changing another process' Smack value is too dangerous
2025 * and supports no sane use case. 2040 * and supports no sane use case.
@@ -2027,6 +2042,9 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2027 if (p != current) 2042 if (p != current)
2028 return -EPERM; 2043 return -EPERM;
2029 2044
2045 if (!capable(CAP_MAC_ADMIN))
2046 return -EPERM;
2047
2030 if (value == NULL || size == 0 || size >= SMK_LABELLEN) 2048 if (value == NULL || size == 0 || size >= SMK_LABELLEN)
2031 return -EINVAL; 2049 return -EINVAL;
2032 2050
@@ -2161,7 +2179,10 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
2161 * This is the simplist possible security model 2179 * This is the simplist possible security model
2162 * for networking. 2180 * for networking.
2163 */ 2181 */
2164 return smk_access(smack, ssp->smk_in, MAY_WRITE); 2182 rc = smk_access(smack, ssp->smk_in, MAY_WRITE);
2183 if (rc != 0)
2184 netlbl_skbuff_err(skb, rc, 0);
2185 return rc;
2165} 2186}
2166 2187
2167/** 2188/**
@@ -2553,7 +2574,8 @@ static void smack_release_secctx(char *secdata, u32 seclen)
2553struct security_operations smack_ops = { 2574struct security_operations smack_ops = {
2554 .name = "smack", 2575 .name = "smack",
2555 2576
2556 .ptrace = smack_ptrace, 2577 .ptrace_may_access = smack_ptrace_may_access,
2578 .ptrace_traceme = smack_ptrace_traceme,
2557 .capget = cap_capget, 2579 .capget = cap_capget,
2558 .capset_check = cap_capset_check, 2580 .capset_check = cap_capset_check,
2559 .capset_set = cap_capset_set, 2581 .capset_set = cap_capset_set,
@@ -2730,4 +2752,3 @@ static __init int smack_init(void)
2730 * all processes and objects when they are created. 2752 * all processes and objects when they are created.
2731 */ 2753 */
2732security_initcall(smack_init); 2754security_initcall(smack_init);
2733
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 271a835fbbe3..c21d8c8bf0c7 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -39,6 +39,7 @@ enum smk_inos {
39 SMK_DIRECT = 6, /* CIPSO level indicating direct label */ 39 SMK_DIRECT = 6, /* CIPSO level indicating direct label */
40 SMK_AMBIENT = 7, /* internet ambient label */ 40 SMK_AMBIENT = 7, /* internet ambient label */
41 SMK_NLTYPE = 8, /* label scheme to use by default */ 41 SMK_NLTYPE = 8, /* label scheme to use by default */
42 SMK_ONLYCAP = 9, /* the only "capable" label */
42}; 43};
43 44
44/* 45/*
@@ -68,6 +69,16 @@ int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4;
68 */ 69 */
69int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; 70int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
70 71
72/*
73 * Unless a process is running with this label even
74 * having CAP_MAC_OVERRIDE isn't enough to grant
75 * privilege to violate MAC policy. If no label is
76 * designated (the NULL case) capabilities apply to
77 * everyone. It is expected that the hat (^) label
78 * will be used if any label is used.
79 */
80char *smack_onlycap;
81
71static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; 82static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
72struct smk_list_entry *smack_list; 83struct smk_list_entry *smack_list;
73 84
@@ -343,9 +354,11 @@ static void smk_cipso_doi(void)
343 doip->tags[rc] = CIPSO_V4_TAG_INVALID; 354 doip->tags[rc] = CIPSO_V4_TAG_INVALID;
344 355
345 rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info); 356 rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info);
346 if (rc != 0) 357 if (rc != 0) {
347 printk(KERN_WARNING "%s:%d add rc = %d\n", 358 printk(KERN_WARNING "%s:%d add rc = %d\n",
348 __func__, __LINE__, rc); 359 __func__, __LINE__, rc);
360 kfree(doip);
361 }
349} 362}
350 363
351/** 364/**
@@ -787,6 +800,85 @@ static const struct file_operations smk_ambient_ops = {
787 .write = smk_write_ambient, 800 .write = smk_write_ambient,
788}; 801};
789 802
803/**
804 * smk_read_onlycap - read() for /smack/onlycap
805 * @filp: file pointer, not actually used
806 * @buf: where to put the result
807 * @cn: maximum to send along
808 * @ppos: where to start
809 *
810 * Returns number of bytes read or error code, as appropriate
811 */
812static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
813 size_t cn, loff_t *ppos)
814{
815 char *smack = "";
816 ssize_t rc = -EINVAL;
817 int asize;
818
819 if (*ppos != 0)
820 return 0;
821
822 if (smack_onlycap != NULL)
823 smack = smack_onlycap;
824
825 asize = strlen(smack) + 1;
826
827 if (cn >= asize)
828 rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
829
830 return rc;
831}
832
833/**
834 * smk_write_onlycap - write() for /smack/onlycap
835 * @filp: file pointer, not actually used
836 * @buf: where to get the data from
837 * @count: bytes sent
838 * @ppos: where to start
839 *
840 * Returns number of bytes written or error code, as appropriate
841 */
842static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
843 size_t count, loff_t *ppos)
844{
845 char in[SMK_LABELLEN];
846 char *sp = current->security;
847
848 if (!capable(CAP_MAC_ADMIN))
849 return -EPERM;
850
851 /*
852 * This can be done using smk_access() but is done
853 * explicitly for clarity. The smk_access() implementation
854 * would use smk_access(smack_onlycap, MAY_WRITE)
855 */
856 if (smack_onlycap != NULL && smack_onlycap != sp)
857 return -EPERM;
858
859 if (count >= SMK_LABELLEN)
860 return -EINVAL;
861
862 if (copy_from_user(in, buf, count) != 0)
863 return -EFAULT;
864
865 /*
866 * Should the null string be passed in unset the onlycap value.
867 * This seems like something to be careful with as usually
868 * smk_import only expects to return NULL for errors. It
869 * is usually the case that a nullstring or "\n" would be
870 * bad to pass to smk_import but in fact this is useful here.
871 */
872 smack_onlycap = smk_import(in, count);
873
874 return count;
875}
876
877static const struct file_operations smk_onlycap_ops = {
878 .read = smk_read_onlycap,
879 .write = smk_write_onlycap,
880};
881
790struct option_names { 882struct option_names {
791 int o_number; 883 int o_number;
792 char *o_name; 884 char *o_name;
@@ -919,6 +1011,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
919 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, 1011 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
920 [SMK_NLTYPE] = 1012 [SMK_NLTYPE] =
921 {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR}, 1013 {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR},
1014 [SMK_ONLYCAP] =
1015 {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
922 /* last one */ {""} 1016 /* last one */ {""}
923 }; 1017 };
924 1018