aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig3
-rw-r--r--security/commoncap.c108
-rw-r--r--security/device_cgroup.c158
-rw-r--r--security/selinux/hooks.c22
4 files changed, 131 insertions, 160 deletions
diff --git a/security/Kconfig b/security/Kconfig
index 62ed4717d334..559293922a47 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -74,8 +74,7 @@ config SECURITY_NETWORK_XFRM
74 If you are unsure how to answer this question, answer N. 74 If you are unsure how to answer this question, answer N.
75 75
76config SECURITY_FILE_CAPABILITIES 76config SECURITY_FILE_CAPABILITIES
77 bool "File POSIX Capabilities (EXPERIMENTAL)" 77 bool "File POSIX Capabilities"
78 depends on EXPERIMENTAL
79 default n 78 default n
80 help 79 help
81 This enables filesystem capabilities, allowing you to give 80 This enables filesystem capabilities, allowing you to give
diff --git a/security/commoncap.c b/security/commoncap.c
index 0b6537a3672d..4afbece37a08 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -162,8 +162,7 @@ void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
162 162
163static inline void bprm_clear_caps(struct linux_binprm *bprm) 163static inline void bprm_clear_caps(struct linux_binprm *bprm)
164{ 164{
165 cap_clear(bprm->cap_inheritable); 165 cap_clear(bprm->cap_post_exec_permitted);
166 cap_clear(bprm->cap_permitted);
167 bprm->cap_effective = false; 166 bprm->cap_effective = false;
168} 167}
169 168
@@ -198,6 +197,7 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
198{ 197{
199 __u32 magic_etc; 198 __u32 magic_etc;
200 unsigned tocopy, i; 199 unsigned tocopy, i;
200 int ret;
201 201
202 if (size < sizeof(magic_etc)) 202 if (size < sizeof(magic_etc))
203 return -EINVAL; 203 return -EINVAL;
@@ -225,19 +225,40 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
225 bprm->cap_effective = false; 225 bprm->cap_effective = false;
226 } 226 }
227 227
228 for (i = 0; i < tocopy; ++i) { 228 ret = 0;
229 bprm->cap_permitted.cap[i] = 229
230 le32_to_cpu(caps->data[i].permitted); 230 CAP_FOR_EACH_U32(i) {
231 bprm->cap_inheritable.cap[i] = 231 __u32 value_cpu;
232 le32_to_cpu(caps->data[i].inheritable); 232
233 } 233 if (i >= tocopy) {
234 while (i < VFS_CAP_U32) { 234 /*
235 bprm->cap_permitted.cap[i] = 0; 235 * Legacy capability sets have no upper bits
236 bprm->cap_inheritable.cap[i] = 0; 236 */
237 i++; 237 bprm->cap_post_exec_permitted.cap[i] = 0;
238 continue;
239 }
240 /*
241 * pP' = (X & fP) | (pI & fI)
242 */
243 value_cpu = le32_to_cpu(caps->data[i].permitted);
244 bprm->cap_post_exec_permitted.cap[i] =
245 (current->cap_bset.cap[i] & value_cpu) |
246 (current->cap_inheritable.cap[i] &
247 le32_to_cpu(caps->data[i].inheritable));
248 if (value_cpu & ~bprm->cap_post_exec_permitted.cap[i]) {
249 /*
250 * insufficient to execute correctly
251 */
252 ret = -EPERM;
253 }
238 } 254 }
239 255
240 return 0; 256 /*
257 * For legacy apps, with no internal support for recognizing they
258 * do not have enough capabilities, we return an error if they are
259 * missing some "forced" (aka file-permitted) capabilities.
260 */
261 return bprm->cap_effective ? ret : 0;
241} 262}
242 263
243/* Locate any VFS capabilities: */ 264/* Locate any VFS capabilities: */
@@ -269,9 +290,9 @@ static int get_file_caps(struct linux_binprm *bprm)
269 goto out; 290 goto out;
270 291
271 rc = cap_from_disk(&vcaps, bprm, rc); 292 rc = cap_from_disk(&vcaps, bprm, rc);
272 if (rc) 293 if (rc == -EINVAL)
273 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", 294 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
274 __func__, rc, bprm->filename); 295 __func__, rc, bprm->filename);
275 296
276out: 297out:
277 dput(dentry); 298 dput(dentry);
@@ -304,25 +325,24 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
304 int ret; 325 int ret;
305 326
306 ret = get_file_caps(bprm); 327 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 328
319 if (!issecure (SECURE_NOROOT)) { 329 if (!issecure(SECURE_NOROOT)) {
330 /*
331 * To support inheritance of root-permissions and suid-root
332 * executables under compatibility mode, we override the
333 * capability sets for the file.
334 *
335 * If only the real uid is 0, we do not set the effective
336 * bit.
337 */
320 if (bprm->e_uid == 0 || current->uid == 0) { 338 if (bprm->e_uid == 0 || current->uid == 0) {
321 cap_set_full (bprm->cap_inheritable); 339 /* pP' = (cap_bset & ~0) | (pI & ~0) */
322 cap_set_full (bprm->cap_permitted); 340 bprm->cap_post_exec_permitted = cap_combine(
341 current->cap_bset, current->cap_inheritable
342 );
343 bprm->cap_effective = (bprm->e_uid == 0);
344 ret = 0;
323 } 345 }
324 if (bprm->e_uid == 0)
325 bprm->cap_effective = true;
326 } 346 }
327 347
328 return ret; 348 return ret;
@@ -330,17 +350,9 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
330 350
331void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) 351void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
332{ 352{
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 || 353 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
343 !cap_issubset (new_permitted, current->cap_permitted)) { 354 !cap_issubset(bprm->cap_post_exec_permitted,
355 current->cap_permitted)) {
344 set_dumpable(current->mm, suid_dumpable); 356 set_dumpable(current->mm, suid_dumpable);
345 current->pdeath_signal = 0; 357 current->pdeath_signal = 0;
346 358
@@ -350,9 +362,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
350 bprm->e_gid = current->gid; 362 bprm->e_gid = current->gid;
351 } 363 }
352 if (cap_limit_ptraced_target()) { 364 if (cap_limit_ptraced_target()) {
353 new_permitted = 365 bprm->cap_post_exec_permitted = cap_intersect(
354 cap_intersect(new_permitted, 366 bprm->cap_post_exec_permitted,
355 current->cap_permitted); 367 current->cap_permitted);
356 } 368 }
357 } 369 }
358 } 370 }
@@ -364,9 +376,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
364 * in the init_task struct. Thus we skip the usual 376 * in the init_task struct. Thus we skip the usual
365 * capability rules */ 377 * capability rules */
366 if (!is_global_init(current)) { 378 if (!is_global_init(current)) {
367 current->cap_permitted = new_permitted; 379 current->cap_permitted = bprm->cap_post_exec_permitted;
368 if (bprm->cap_effective) 380 if (bprm->cap_effective)
369 current->cap_effective = new_permitted; 381 current->cap_effective = bprm->cap_post_exec_permitted;
370 else 382 else
371 cap_clear(current->cap_effective); 383 cap_clear(current->cap_effective);
372 } 384 }
@@ -381,9 +393,7 @@ int cap_bprm_secureexec (struct linux_binprm *bprm)
381 if (current->uid != 0) { 393 if (current->uid != 0) {
382 if (bprm->cap_effective) 394 if (bprm->cap_effective)
383 return 1; 395 return 1;
384 if (!cap_isclear(bprm->cap_permitted)) 396 if (!cap_isclear(bprm->cap_post_exec_permitted))
385 return 1;
386 if (!cap_isclear(bprm->cap_inheritable))
387 return 1; 397 return 1;
388 } 398 }
389 399
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index ddd92cec78ed..7bd296cca041 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -41,6 +41,7 @@ struct dev_whitelist_item {
41 short type; 41 short type;
42 short access; 42 short access;
43 struct list_head list; 43 struct list_head list;
44 struct rcu_head rcu;
44}; 45};
45 46
46struct dev_cgroup { 47struct dev_cgroup {
@@ -59,6 +60,11 @@ static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup)
59 return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id)); 60 return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id));
60} 61}
61 62
63static inline struct dev_cgroup *task_devcgroup(struct task_struct *task)
64{
65 return css_to_devcgroup(task_subsys_state(task, devices_subsys_id));
66}
67
62struct cgroup_subsys devices_subsys; 68struct cgroup_subsys devices_subsys;
63 69
64static int devcgroup_can_attach(struct cgroup_subsys *ss, 70static int devcgroup_can_attach(struct cgroup_subsys *ss,
@@ -128,11 +134,19 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
128 } 134 }
129 135
130 if (whcopy != NULL) 136 if (whcopy != NULL)
131 list_add_tail(&whcopy->list, &dev_cgroup->whitelist); 137 list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist);
132 spin_unlock(&dev_cgroup->lock); 138 spin_unlock(&dev_cgroup->lock);
133 return 0; 139 return 0;
134} 140}
135 141
142static void whitelist_item_free(struct rcu_head *rcu)
143{
144 struct dev_whitelist_item *item;
145
146 item = container_of(rcu, struct dev_whitelist_item, rcu);
147 kfree(item);
148}
149
136/* 150/*
137 * called under cgroup_lock() 151 * called under cgroup_lock()
138 * since the list is visible to other tasks, we need the spinlock also 152 * since the list is visible to other tasks, we need the spinlock also
@@ -156,8 +170,8 @@ static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
156remove: 170remove:
157 walk->access &= ~wh->access; 171 walk->access &= ~wh->access;
158 if (!walk->access) { 172 if (!walk->access) {
159 list_del(&walk->list); 173 list_del_rcu(&walk->list);
160 kfree(walk); 174 call_rcu(&walk->rcu, whitelist_item_free);
161 } 175 }
162 } 176 }
163 spin_unlock(&dev_cgroup->lock); 177 spin_unlock(&dev_cgroup->lock);
@@ -188,7 +202,7 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss,
188 } 202 }
189 wh->minor = wh->major = ~0; 203 wh->minor = wh->major = ~0;
190 wh->type = DEV_ALL; 204 wh->type = DEV_ALL;
191 wh->access = ACC_MKNOD | ACC_READ | ACC_WRITE; 205 wh->access = ACC_MASK;
192 list_add(&wh->list, &dev_cgroup->whitelist); 206 list_add(&wh->list, &dev_cgroup->whitelist);
193 } else { 207 } else {
194 parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup); 208 parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
@@ -250,11 +264,10 @@ static char type_to_char(short type)
250 264
251static void set_majmin(char *str, unsigned m) 265static void set_majmin(char *str, unsigned m)
252{ 266{
253 memset(str, 0, MAJMINLEN);
254 if (m == ~0) 267 if (m == ~0)
255 sprintf(str, "*"); 268 strcpy(str, "*");
256 else 269 else
257 snprintf(str, MAJMINLEN, "%u", m); 270 sprintf(str, "%u", m);
258} 271}
259 272
260static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, 273static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
@@ -264,15 +277,15 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
264 struct dev_whitelist_item *wh; 277 struct dev_whitelist_item *wh;
265 char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN]; 278 char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
266 279
267 spin_lock(&devcgroup->lock); 280 rcu_read_lock();
268 list_for_each_entry(wh, &devcgroup->whitelist, list) { 281 list_for_each_entry_rcu(wh, &devcgroup->whitelist, list) {
269 set_access(acc, wh->access); 282 set_access(acc, wh->access);
270 set_majmin(maj, wh->major); 283 set_majmin(maj, wh->major);
271 set_majmin(min, wh->minor); 284 set_majmin(min, wh->minor);
272 seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type), 285 seq_printf(m, "%c %s:%s %s\n", type_to_char(wh->type),
273 maj, min, acc); 286 maj, min, acc);
274 } 287 }
275 spin_unlock(&devcgroup->lock); 288 rcu_read_unlock();
276 289
277 return 0; 290 return 0;
278} 291}
@@ -312,10 +325,10 @@ static int may_access_whitelist(struct dev_cgroup *c,
312 * when adding a new allow rule to a device whitelist, the rule 325 * when adding a new allow rule to a device whitelist, the rule
313 * must be allowed in the parent device 326 * must be allowed in the parent device
314 */ 327 */
315static int parent_has_perm(struct cgroup *childcg, 328static int parent_has_perm(struct dev_cgroup *childcg,
316 struct dev_whitelist_item *wh) 329 struct dev_whitelist_item *wh)
317{ 330{
318 struct cgroup *pcg = childcg->parent; 331 struct cgroup *pcg = childcg->css.cgroup->parent;
319 struct dev_cgroup *parent; 332 struct dev_cgroup *parent;
320 int ret; 333 int ret;
321 334
@@ -341,39 +354,19 @@ static int parent_has_perm(struct cgroup *childcg,
341 * new access is only allowed if you're in the top-level cgroup, or your 354 * 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. 355 * parent cgroup has the access you're asking for.
343 */ 356 */
344static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft, 357static int devcgroup_update_access(struct dev_cgroup *devcgroup,
345 struct file *file, const char __user *userbuf, 358 int filetype, const char *buffer)
346 size_t nbytes, loff_t *ppos)
347{ 359{
348 struct cgroup *cur_cgroup; 360 struct dev_cgroup *cur_devcgroup;
349 struct dev_cgroup *devcgroup, *cur_devcgroup; 361 const char *b;
350 int filetype = cft->private; 362 char *endp;
351 char *buffer, *b;
352 int retval = 0, count; 363 int retval = 0, count;
353 struct dev_whitelist_item wh; 364 struct dev_whitelist_item wh;
354 365
355 if (!capable(CAP_SYS_ADMIN)) 366 if (!capable(CAP_SYS_ADMIN))
356 return -EPERM; 367 return -EPERM;
357 368
358 devcgroup = cgroup_to_devcgroup(cgroup); 369 cur_devcgroup = task_devcgroup(current);
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 370
378 memset(&wh, 0, sizeof(wh)); 371 memset(&wh, 0, sizeof(wh));
379 b = buffer; 372 b = buffer;
@@ -392,32 +385,23 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
392 wh.type = DEV_CHAR; 385 wh.type = DEV_CHAR;
393 break; 386 break;
394 default: 387 default:
395 retval = -EINVAL; 388 return -EINVAL;
396 goto out2;
397 } 389 }
398 b++; 390 b++;
399 if (!isspace(*b)) { 391 if (!isspace(*b))
400 retval = -EINVAL; 392 return -EINVAL;
401 goto out2;
402 }
403 b++; 393 b++;
404 if (*b == '*') { 394 if (*b == '*') {
405 wh.major = ~0; 395 wh.major = ~0;
406 b++; 396 b++;
407 } else if (isdigit(*b)) { 397 } else if (isdigit(*b)) {
408 wh.major = 0; 398 wh.major = simple_strtoul(b, &endp, 10);
409 while (isdigit(*b)) { 399 b = endp;
410 wh.major = wh.major*10+(*b-'0');
411 b++;
412 }
413 } else { 400 } else {
414 retval = -EINVAL; 401 return -EINVAL;
415 goto out2;
416 }
417 if (*b != ':') {
418 retval = -EINVAL;
419 goto out2;
420 } 402 }
403 if (*b != ':')
404 return -EINVAL;
421 b++; 405 b++;
422 406
423 /* read minor */ 407 /* read minor */
@@ -425,19 +409,13 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
425 wh.minor = ~0; 409 wh.minor = ~0;
426 b++; 410 b++;
427 } else if (isdigit(*b)) { 411 } else if (isdigit(*b)) {
428 wh.minor = 0; 412 wh.minor = simple_strtoul(b, &endp, 10);
429 while (isdigit(*b)) { 413 b = endp;
430 wh.minor = wh.minor*10+(*b-'0');
431 b++;
432 }
433 } else { 414 } else {
434 retval = -EINVAL; 415 return -EINVAL;
435 goto out2;
436 }
437 if (!isspace(*b)) {
438 retval = -EINVAL;
439 goto out2;
440 } 416 }
417 if (!isspace(*b))
418 return -EINVAL;
441 for (b++, count = 0; count < 3; count++, b++) { 419 for (b++, count = 0; count < 3; count++, b++) {
442 switch (*b) { 420 switch (*b) {
443 case 'r': 421 case 'r':
@@ -454,8 +432,7 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft,
454 count = 3; 432 count = 3;
455 break; 433 break;
456 default: 434 default:
457 retval = -EINVAL; 435 return -EINVAL;
458 goto out2;
459 } 436 }
460 } 437 }
461 438
@@ -463,38 +440,39 @@ handle:
463 retval = 0; 440 retval = 0;
464 switch (filetype) { 441 switch (filetype) {
465 case DEVCG_ALLOW: 442 case DEVCG_ALLOW:
466 if (!parent_has_perm(cgroup, &wh)) 443 if (!parent_has_perm(devcgroup, &wh))
467 retval = -EPERM; 444 return -EPERM;
468 else 445 return dev_whitelist_add(devcgroup, &wh);
469 retval = dev_whitelist_add(devcgroup, &wh);
470 break;
471 case DEVCG_DENY: 446 case DEVCG_DENY:
472 dev_whitelist_rm(devcgroup, &wh); 447 dev_whitelist_rm(devcgroup, &wh);
473 break; 448 break;
474 default: 449 default:
475 retval = -EINVAL; 450 return -EINVAL;
476 goto out2;
477 } 451 }
452 return 0;
453}
478 454
479 if (retval == 0) 455static int devcgroup_access_write(struct cgroup *cgrp, struct cftype *cft,
480 retval = nbytes; 456 const char *buffer)
481 457{
482out2: 458 int retval;
459 if (!cgroup_lock_live_group(cgrp))
460 return -ENODEV;
461 retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp),
462 cft->private, buffer);
483 cgroup_unlock(); 463 cgroup_unlock();
484out1:
485 kfree(buffer);
486 return retval; 464 return retval;
487} 465}
488 466
489static struct cftype dev_cgroup_files[] = { 467static struct cftype dev_cgroup_files[] = {
490 { 468 {
491 .name = "allow", 469 .name = "allow",
492 .write = devcgroup_access_write, 470 .write_string = devcgroup_access_write,
493 .private = DEVCG_ALLOW, 471 .private = DEVCG_ALLOW,
494 }, 472 },
495 { 473 {
496 .name = "deny", 474 .name = "deny",
497 .write = devcgroup_access_write, 475 .write_string = devcgroup_access_write,
498 .private = DEVCG_DENY, 476 .private = DEVCG_DENY,
499 }, 477 },
500 { 478 {
@@ -535,8 +513,8 @@ int devcgroup_inode_permission(struct inode *inode, int mask)
535 if (!dev_cgroup) 513 if (!dev_cgroup)
536 return 0; 514 return 0;
537 515
538 spin_lock(&dev_cgroup->lock); 516 rcu_read_lock();
539 list_for_each_entry(wh, &dev_cgroup->whitelist, list) { 517 list_for_each_entry_rcu(wh, &dev_cgroup->whitelist, list) {
540 if (wh->type & DEV_ALL) 518 if (wh->type & DEV_ALL)
541 goto acc_check; 519 goto acc_check;
542 if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode)) 520 if ((wh->type & DEV_BLOCK) && !S_ISBLK(inode->i_mode))
@@ -552,10 +530,10 @@ acc_check:
552 continue; 530 continue;
553 if ((mask & MAY_READ) && !(wh->access & ACC_READ)) 531 if ((mask & MAY_READ) && !(wh->access & ACC_READ))
554 continue; 532 continue;
555 spin_unlock(&dev_cgroup->lock); 533 rcu_read_unlock();
556 return 0; 534 return 0;
557 } 535 }
558 spin_unlock(&dev_cgroup->lock); 536 rcu_read_unlock();
559 537
560 return -EPERM; 538 return -EPERM;
561} 539}
@@ -570,7 +548,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
570 if (!dev_cgroup) 548 if (!dev_cgroup)
571 return 0; 549 return 0;
572 550
573 spin_lock(&dev_cgroup->lock); 551 rcu_read_lock();
574 list_for_each_entry(wh, &dev_cgroup->whitelist, list) { 552 list_for_each_entry(wh, &dev_cgroup->whitelist, list) {
575 if (wh->type & DEV_ALL) 553 if (wh->type & DEV_ALL)
576 goto acc_check; 554 goto acc_check;
@@ -585,9 +563,9 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
585acc_check: 563acc_check:
586 if (!(wh->access & ACC_MKNOD)) 564 if (!(wh->access & ACC_MKNOD))
587 continue; 565 continue;
588 spin_unlock(&dev_cgroup->lock); 566 rcu_read_unlock();
589 return 0; 567 return 0;
590 } 568 }
591 spin_unlock(&dev_cgroup->lock); 569 rcu_read_unlock();
592 return -EPERM; 570 return -EPERM;
593} 571}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index df0515dd4d12..da36dac6535f 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>
@@ -1971,22 +1971,6 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
1971 return __vm_enough_memory(mm, pages, cap_sys_admin); 1971 return __vm_enough_memory(mm, pages, cap_sys_admin);
1972} 1972}
1973 1973
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 */ 1974/* binprm security operations */
1991 1975
1992static int selinux_bprm_alloc_security(struct linux_binprm *bprm) 1976static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
@@ -2238,7 +2222,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
2238 u32 ptsid = 0; 2222 u32 ptsid = 0;
2239 2223
2240 rcu_read_lock(); 2224 rcu_read_lock();
2241 tracer = task_tracer_task(current); 2225 tracer = tracehook_tracer_task(current);
2242 if (likely(tracer != NULL)) { 2226 if (likely(tracer != NULL)) {
2243 sec = tracer->security; 2227 sec = tracer->security;
2244 ptsid = sec->sid; 2228 ptsid = sec->sid;
@@ -5247,7 +5231,7 @@ static int selinux_setprocattr(struct task_struct *p,
5247 Otherwise, leave SID unchanged and fail. */ 5231 Otherwise, leave SID unchanged and fail. */
5248 task_lock(p); 5232 task_lock(p);
5249 rcu_read_lock(); 5233 rcu_read_lock();
5250 tracer = task_tracer_task(p); 5234 tracer = tracehook_tracer_task(p);
5251 if (tracer != NULL) { 5235 if (tracer != NULL) {
5252 struct task_security_struct *ptsec = tracer->security; 5236 struct task_security_struct *ptsec = tracer->security;
5253 u32 ptsid = ptsec->sid; 5237 u32 ptsid = ptsec->sid;