aboutsummaryrefslogtreecommitdiffstats
path: root/security/commoncap.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/commoncap.c')
-rw-r--r--security/commoncap.c265
1 files changed, 125 insertions, 140 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 0384bf95db68..b5419273f92d 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -72,8 +72,8 @@ int cap_ptrace_may_access(struct task_struct *child, unsigned int mode)
72 int ret = 0; 72 int ret = 0;
73 73
74 rcu_read_lock(); 74 rcu_read_lock();
75 if (!cap_issubset(child->cred->cap_permitted, 75 if (!cap_issubset(__task_cred(child)->cap_permitted,
76 current->cred->cap_permitted) && 76 current_cred()->cap_permitted) &&
77 !capable(CAP_SYS_PTRACE)) 77 !capable(CAP_SYS_PTRACE))
78 ret = -EPERM; 78 ret = -EPERM;
79 rcu_read_unlock(); 79 rcu_read_unlock();
@@ -85,8 +85,8 @@ int cap_ptrace_traceme(struct task_struct *parent)
85 int ret = 0; 85 int ret = 0;
86 86
87 rcu_read_lock(); 87 rcu_read_lock();
88 if (!cap_issubset(current->cred->cap_permitted, 88 if (!cap_issubset(current_cred()->cap_permitted,
89 parent->cred->cap_permitted) && 89 __task_cred(parent)->cap_permitted) &&
90 !has_capability(parent, CAP_SYS_PTRACE)) 90 !has_capability(parent, CAP_SYS_PTRACE))
91 ret = -EPERM; 91 ret = -EPERM;
92 rcu_read_unlock(); 92 rcu_read_unlock();
@@ -117,7 +117,7 @@ static inline int cap_inh_is_capped(void)
117 * to the old permitted set. That is, if the current task 117 * to the old permitted set. That is, if the current task
118 * does *not* possess the CAP_SETPCAP capability. 118 * does *not* possess the CAP_SETPCAP capability.
119 */ 119 */
120 return (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0); 120 return cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0;
121} 121}
122 122
123static inline int cap_limit_ptraced_target(void) { return 1; } 123static inline int cap_limit_ptraced_target(void) { return 1; }
@@ -132,52 +132,39 @@ static inline int cap_limit_ptraced_target(void)
132 132
133#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ 133#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
134 134
135int cap_capset_check(const kernel_cap_t *effective, 135int cap_capset(struct cred *new,
136 const kernel_cap_t *inheritable, 136 const struct cred *old,
137 const kernel_cap_t *permitted) 137 const kernel_cap_t *effective,
138 const kernel_cap_t *inheritable,
139 const kernel_cap_t *permitted)
138{ 140{
139 const struct cred *cred = current->cred; 141 if (cap_inh_is_capped() &&
140 142 !cap_issubset(*inheritable,
141 if (cap_inh_is_capped() 143 cap_combine(old->cap_inheritable,
142 && !cap_issubset(*inheritable, 144 old->cap_permitted)))
143 cap_combine(cred->cap_inheritable,
144 cred->cap_permitted))) {
145 /* incapable of using this inheritable set */ 145 /* incapable of using this inheritable set */
146 return -EPERM; 146 return -EPERM;
147 } 147
148 if (!cap_issubset(*inheritable, 148 if (!cap_issubset(*inheritable,
149 cap_combine(cred->cap_inheritable, 149 cap_combine(old->cap_inheritable,
150 cred->cap_bset))) { 150 old->cap_bset)))
151 /* no new pI capabilities outside bounding set */ 151 /* no new pI capabilities outside bounding set */
152 return -EPERM; 152 return -EPERM;
153 }
154 153
155 /* verify restrictions on target's new Permitted set */ 154 /* verify restrictions on target's new Permitted set */
156 if (!cap_issubset (*permitted, 155 if (!cap_issubset(*permitted, old->cap_permitted))
157 cap_combine (cred->cap_permitted,
158 cred->cap_permitted))) {
159 return -EPERM; 156 return -EPERM;
160 }
161 157
162 /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ 158 /* verify the _new_Effective_ is a subset of the _new_Permitted_ */
163 if (!cap_issubset (*effective, *permitted)) { 159 if (!cap_issubset(*effective, *permitted))
164 return -EPERM; 160 return -EPERM;
165 }
166 161
162 new->cap_effective = *effective;
163 new->cap_inheritable = *inheritable;
164 new->cap_permitted = *permitted;
167 return 0; 165 return 0;
168} 166}
169 167
170void cap_capset_set(const kernel_cap_t *effective,
171 const kernel_cap_t *inheritable,
172 const kernel_cap_t *permitted)
173{
174 struct cred *cred = current->cred;
175
176 cred->cap_effective = *effective;
177 cred->cap_inheritable = *inheritable;
178 cred->cap_permitted = *permitted;
179}
180
181static inline void bprm_clear_caps(struct linux_binprm *bprm) 168static inline void bprm_clear_caps(struct linux_binprm *bprm)
182{ 169{
183 cap_clear(bprm->cap_post_exec_permitted); 170 cap_clear(bprm->cap_post_exec_permitted);
@@ -382,41 +369,46 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
382 return ret; 369 return ret;
383} 370}
384 371
385void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) 372int cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
386{ 373{
387 struct cred *cred = current->cred; 374 const struct cred *old = current_cred();
375 struct cred *new;
376
377 new = prepare_creds();
378 if (!new)
379 return -ENOMEM;
388 380
389 if (bprm->e_uid != cred->uid || bprm->e_gid != cred->gid || 381 if (bprm->e_uid != old->uid || bprm->e_gid != old->gid ||
390 !cap_issubset(bprm->cap_post_exec_permitted, 382 !cap_issubset(bprm->cap_post_exec_permitted,
391 cred->cap_permitted)) { 383 old->cap_permitted)) {
392 set_dumpable(current->mm, suid_dumpable); 384 set_dumpable(current->mm, suid_dumpable);
393 current->pdeath_signal = 0; 385 current->pdeath_signal = 0;
394 386
395 if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) { 387 if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
396 if (!capable(CAP_SETUID)) { 388 if (!capable(CAP_SETUID)) {
397 bprm->e_uid = cred->uid; 389 bprm->e_uid = old->uid;
398 bprm->e_gid = cred->gid; 390 bprm->e_gid = old->gid;
399 } 391 }
400 if (cap_limit_ptraced_target()) { 392 if (cap_limit_ptraced_target()) {
401 bprm->cap_post_exec_permitted = cap_intersect( 393 bprm->cap_post_exec_permitted = cap_intersect(
402 bprm->cap_post_exec_permitted, 394 bprm->cap_post_exec_permitted,
403 cred->cap_permitted); 395 new->cap_permitted);
404 } 396 }
405 } 397 }
406 } 398 }
407 399
408 cred->suid = cred->euid = cred->fsuid = bprm->e_uid; 400 new->suid = new->euid = new->fsuid = bprm->e_uid;
409 cred->sgid = cred->egid = cred->fsgid = bprm->e_gid; 401 new->sgid = new->egid = new->fsgid = bprm->e_gid;
410 402
411 /* For init, we want to retain the capabilities set 403 /* For init, we want to retain the capabilities set
412 * in the init_task struct. Thus we skip the usual 404 * in the init_task struct. Thus we skip the usual
413 * capability rules */ 405 * capability rules */
414 if (!is_global_init(current)) { 406 if (!is_global_init(current)) {
415 cred->cap_permitted = bprm->cap_post_exec_permitted; 407 new->cap_permitted = bprm->cap_post_exec_permitted;
416 if (bprm->cap_effective) 408 if (bprm->cap_effective)
417 cred->cap_effective = bprm->cap_post_exec_permitted; 409 new->cap_effective = bprm->cap_post_exec_permitted;
418 else 410 else
419 cap_clear(cred->cap_effective); 411 cap_clear(new->cap_effective);
420 } 412 }
421 413
422 /* 414 /*
@@ -431,15 +423,15 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
431 * Number 1 above might fail if you don't have a full bset, but I think 423 * Number 1 above might fail if you don't have a full bset, but I think
432 * that is interesting information to audit. 424 * that is interesting information to audit.
433 */ 425 */
434 if (!cap_isclear(cred->cap_effective)) { 426 if (!cap_isclear(new->cap_effective)) {
435 if (!cap_issubset(CAP_FULL_SET, cred->cap_effective) || 427 if (!cap_issubset(CAP_FULL_SET, new->cap_effective) ||
436 (bprm->e_uid != 0) || (cred->uid != 0) || 428 bprm->e_uid != 0 || new->uid != 0 ||
437 issecure(SECURE_NOROOT)) 429 issecure(SECURE_NOROOT))
438 audit_log_bprm_fcaps(bprm, &cred->cap_permitted, 430 audit_log_bprm_fcaps(bprm, new, old);
439 &cred->cap_effective);
440 } 431 }
441 432
442 cred->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); 433 new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
434 return commit_creds(new);
443} 435}
444 436
445int cap_bprm_secureexec (struct linux_binprm *bprm) 437int cap_bprm_secureexec (struct linux_binprm *bprm)
@@ -514,65 +506,49 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name)
514 * files.. 506 * files..
515 * Thanks to Olaf Kirch and Peter Benie for spotting this. 507 * Thanks to Olaf Kirch and Peter Benie for spotting this.
516 */ 508 */
517static inline void cap_emulate_setxuid (int old_ruid, int old_euid, 509static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old)
518 int old_suid)
519{ 510{
520 struct cred *cred = current->cred; 511 if ((old->uid == 0 || old->euid == 0 || old->suid == 0) &&
521 512 (new->uid != 0 && new->euid != 0 && new->suid != 0) &&
522 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
523 (cred->uid != 0 && cred->euid != 0 && cred->suid != 0) &&
524 !issecure(SECURE_KEEP_CAPS)) { 513 !issecure(SECURE_KEEP_CAPS)) {
525 cap_clear(cred->cap_permitted); 514 cap_clear(new->cap_permitted);
526 cap_clear(cred->cap_effective); 515 cap_clear(new->cap_effective);
527 }
528 if (old_euid == 0 && cred->euid != 0) {
529 cap_clear(cred->cap_effective);
530 }
531 if (old_euid != 0 && cred->euid == 0) {
532 cred->cap_effective = cred->cap_permitted;
533 } 516 }
517 if (old->euid == 0 && new->euid != 0)
518 cap_clear(new->cap_effective);
519 if (old->euid != 0 && new->euid == 0)
520 new->cap_effective = new->cap_permitted;
534} 521}
535 522
536int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, 523int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags)
537 int flags)
538{ 524{
539 struct cred *cred = current->cred;
540
541 switch (flags) { 525 switch (flags) {
542 case LSM_SETID_RE: 526 case LSM_SETID_RE:
543 case LSM_SETID_ID: 527 case LSM_SETID_ID:
544 case LSM_SETID_RES: 528 case LSM_SETID_RES:
545 /* Copied from kernel/sys.c:setreuid/setuid/setresuid. */ 529 /* Copied from kernel/sys.c:setreuid/setuid/setresuid. */
546 if (!issecure (SECURE_NO_SETUID_FIXUP)) { 530 if (!issecure(SECURE_NO_SETUID_FIXUP))
547 cap_emulate_setxuid (old_ruid, old_euid, old_suid); 531 cap_emulate_setxuid(new, old);
548 }
549 break; 532 break;
550 case LSM_SETID_FS: 533 case LSM_SETID_FS:
551 { 534 /* Copied from kernel/sys.c:setfsuid. */
552 uid_t old_fsuid = old_ruid;
553
554 /* Copied from kernel/sys.c:setfsuid. */
555 535
556 /* 536 /*
557 * FIXME - is fsuser used for all CAP_FS_MASK capabilities? 537 * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
558 * if not, we might be a bit too harsh here. 538 * if not, we might be a bit too harsh here.
559 */ 539 */
560 540 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
561 if (!issecure (SECURE_NO_SETUID_FIXUP)) { 541 if (old->fsuid == 0 && new->fsuid != 0) {
562 if (old_fsuid == 0 && cred->fsuid != 0) { 542 new->cap_effective =
563 cred->cap_effective = 543 cap_drop_fs_set(new->cap_effective);
564 cap_drop_fs_set( 544 }
565 cred->cap_effective); 545 if (old->fsuid != 0 && new->fsuid == 0) {
566 } 546 new->cap_effective =
567 if (old_fsuid != 0 && cred->fsuid == 0) { 547 cap_raise_fs_set(new->cap_effective,
568 cred->cap_effective = 548 new->cap_permitted);
569 cap_raise_fs_set(
570 cred->cap_effective,
571 cred->cap_permitted);
572 }
573 } 549 }
574 break;
575 } 550 }
551 break;
576 default: 552 default:
577 return -EINVAL; 553 return -EINVAL;
578 } 554 }
@@ -628,13 +604,14 @@ int cap_task_setnice (struct task_struct *p, int nice)
628 * this task could get inconsistent info. There can be no 604 * this task could get inconsistent info. There can be no
629 * racing writer bc a task can only change its own caps. 605 * racing writer bc a task can only change its own caps.
630 */ 606 */
631static long cap_prctl_drop(unsigned long cap) 607static long cap_prctl_drop(struct cred *new, unsigned long cap)
632{ 608{
633 if (!capable(CAP_SETPCAP)) 609 if (!capable(CAP_SETPCAP))
634 return -EPERM; 610 return -EPERM;
635 if (!cap_valid(cap)) 611 if (!cap_valid(cap))
636 return -EINVAL; 612 return -EINVAL;
637 cap_lower(current->cred->cap_bset, cap); 613
614 cap_lower(new->cap_bset, cap);
638 return 0; 615 return 0;
639} 616}
640 617
@@ -655,22 +632,29 @@ int cap_task_setnice (struct task_struct *p, int nice)
655#endif 632#endif
656 633
657int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, 634int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
658 unsigned long arg4, unsigned long arg5, long *rc_p) 635 unsigned long arg4, unsigned long arg5)
659{ 636{
660 struct cred *cred = current_cred(); 637 struct cred *new;
661 long error = 0; 638 long error = 0;
662 639
640 new = prepare_creds();
641 if (!new)
642 return -ENOMEM;
643
663 switch (option) { 644 switch (option) {
664 case PR_CAPBSET_READ: 645 case PR_CAPBSET_READ:
646 error = -EINVAL;
665 if (!cap_valid(arg2)) 647 if (!cap_valid(arg2))
666 error = -EINVAL; 648 goto error;
667 else 649 error = !!cap_raised(new->cap_bset, arg2);
668 error = !!cap_raised(cred->cap_bset, arg2); 650 goto no_change;
669 break; 651
670#ifdef CONFIG_SECURITY_FILE_CAPABILITIES 652#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
671 case PR_CAPBSET_DROP: 653 case PR_CAPBSET_DROP:
672 error = cap_prctl_drop(arg2); 654 error = cap_prctl_drop(new, arg2);
673 break; 655 if (error < 0)
656 goto error;
657 goto changed;
674 658
675 /* 659 /*
676 * The next four prctl's remain to assist with transitioning a 660 * The next four prctl's remain to assist with transitioning a
@@ -692,12 +676,12 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
692 * capability-based-privilege environment. 676 * capability-based-privilege environment.
693 */ 677 */
694 case PR_SET_SECUREBITS: 678 case PR_SET_SECUREBITS:
695 if ((((cred->securebits & SECURE_ALL_LOCKS) >> 1) 679 error = -EPERM;
696 & (cred->securebits ^ arg2)) /*[1]*/ 680 if ((((new->securebits & SECURE_ALL_LOCKS) >> 1)
697 || ((cred->securebits & SECURE_ALL_LOCKS 681 & (new->securebits ^ arg2)) /*[1]*/
698 & ~arg2)) /*[2]*/ 682 || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/
699 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ 683 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
700 || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0)) { /*[4]*/ 684 || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0) /*[4]*/
701 /* 685 /*
702 * [1] no changing of bits that are locked 686 * [1] no changing of bits that are locked
703 * [2] no unlocking of locks 687 * [2] no unlocking of locks
@@ -705,50 +689,51 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
705 * [4] doing anything requires privilege (go read about 689 * [4] doing anything requires privilege (go read about
706 * the "sendmail capabilities bug") 690 * the "sendmail capabilities bug")
707 */ 691 */
708 error = -EPERM; /* cannot change a locked bit */ 692 )
709 } else { 693 /* cannot change a locked bit */
710 cred->securebits = arg2; 694 goto error;
711 } 695 new->securebits = arg2;
712 break; 696 goto changed;
697
713 case PR_GET_SECUREBITS: 698 case PR_GET_SECUREBITS:
714 error = cred->securebits; 699 error = new->securebits;
715 break; 700 goto no_change;
716 701
717#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ 702#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
718 703
719 case PR_GET_KEEPCAPS: 704 case PR_GET_KEEPCAPS:
720 if (issecure(SECURE_KEEP_CAPS)) 705 if (issecure(SECURE_KEEP_CAPS))
721 error = 1; 706 error = 1;
722 break; 707 goto no_change;
708
723 case PR_SET_KEEPCAPS: 709 case PR_SET_KEEPCAPS:
710 error = -EINVAL;
724 if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */ 711 if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */
725 error = -EINVAL; 712 goto error;
726 else if (issecure(SECURE_KEEP_CAPS_LOCKED)) 713 error = -EPERM;
727 error = -EPERM; 714 if (issecure(SECURE_KEEP_CAPS_LOCKED))
728 else if (arg2) 715 goto error;
729 cred->securebits |= issecure_mask(SECURE_KEEP_CAPS); 716 if (arg2)
717 new->securebits |= issecure_mask(SECURE_KEEP_CAPS);
730 else 718 else
731 cred->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); 719 new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
732 break; 720 goto changed;
733 721
734 default: 722 default:
735 /* No functionality available - continue with default */ 723 /* No functionality available - continue with default */
736 return 0; 724 error = -ENOSYS;
725 goto error;
737 } 726 }
738 727
739 /* Functionality provided */ 728 /* Functionality provided */
740 *rc_p = error; 729changed:
741 return 1; 730 return commit_creds(new);
742} 731
743 732no_change:
744void cap_task_reparent_to_init (struct task_struct *p) 733 error = 0;
745{ 734error:
746 struct cred *cred = p->cred; 735 abort_creds(new);
747 736 return error;
748 cap_set_init_eff(cred->cap_effective);
749 cap_clear(cred->cap_inheritable);
750 cap_set_full(cred->cap_permitted);
751 p->cred->securebits = SECUREBITS_DEFAULT;
752} 737}
753 738
754int cap_syslog (int type) 739int cap_syslog (int type)