aboutsummaryrefslogtreecommitdiffstats
path: root/security/commoncap.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:16 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:16 -0500
commitb6dff3ec5e116e3af6f537d4caedcad6b9e5082a (patch)
tree9e76f972eb7ce9b84e0146c8e4126a3f86acb428 /security/commoncap.c
parent15a2460ed0af7538ca8e6c610fe607a2cd9da142 (diff)
CRED: Separate task security context from task_struct
Separate the task security context from task_struct. At this point, the security data is temporarily embedded in the task_struct with two pointers pointing to it. Note that the Alpha arch is altered as it refers to (E)UID and (E)GID in entry.S via asm-offsets. With comment fixes Signed-off-by: Marc Dionne <marc.c.dionne@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: James Morris <jmorris@namei.org> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/commoncap.c')
-rw-r--r--security/commoncap.c161
1 files changed, 85 insertions, 76 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index fb4e240720d8..fa61679f8c73 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -30,7 +30,7 @@
30 30
31int cap_netlink_send(struct sock *sk, struct sk_buff *skb) 31int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
32{ 32{
33 NETLINK_CB(skb).eff_cap = current->cap_effective; 33 NETLINK_CB(skb).eff_cap = current_cap();
34 return 0; 34 return 0;
35} 35}
36 36
@@ -52,7 +52,7 @@ EXPORT_SYMBOL(cap_netlink_recv);
52int cap_capable(struct task_struct *tsk, int cap, int audit) 52int cap_capable(struct task_struct *tsk, int cap, int audit)
53{ 53{
54 /* Derived from include/linux/sched.h:capable. */ 54 /* Derived from include/linux/sched.h:capable. */
55 if (cap_raised(tsk->cap_effective, cap)) 55 if (cap_raised(tsk->cred->cap_effective, cap))
56 return 0; 56 return 0;
57 return -EPERM; 57 return -EPERM;
58} 58}
@@ -67,7 +67,8 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
67int cap_ptrace_may_access(struct task_struct *child, unsigned int mode) 67int cap_ptrace_may_access(struct task_struct *child, unsigned int mode)
68{ 68{
69 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ 69 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
70 if (cap_issubset(child->cap_permitted, current->cap_permitted)) 70 if (cap_issubset(child->cred->cap_permitted,
71 current->cred->cap_permitted))
71 return 0; 72 return 0;
72 if (capable(CAP_SYS_PTRACE)) 73 if (capable(CAP_SYS_PTRACE))
73 return 0; 74 return 0;
@@ -76,8 +77,8 @@ int cap_ptrace_may_access(struct task_struct *child, unsigned int mode)
76 77
77int cap_ptrace_traceme(struct task_struct *parent) 78int cap_ptrace_traceme(struct task_struct *parent)
78{ 79{
79 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ 80 if (cap_issubset(current->cred->cap_permitted,
80 if (cap_issubset(current->cap_permitted, parent->cap_permitted)) 81 parent->cred->cap_permitted))
81 return 0; 82 return 0;
82 if (has_capability(parent, CAP_SYS_PTRACE)) 83 if (has_capability(parent, CAP_SYS_PTRACE))
83 return 0; 84 return 0;
@@ -87,10 +88,12 @@ int cap_ptrace_traceme(struct task_struct *parent)
87int cap_capget (struct task_struct *target, kernel_cap_t *effective, 88int cap_capget (struct task_struct *target, kernel_cap_t *effective,
88 kernel_cap_t *inheritable, kernel_cap_t *permitted) 89 kernel_cap_t *inheritable, kernel_cap_t *permitted)
89{ 90{
91 struct cred *cred = target->cred;
92
90 /* Derived from kernel/capability.c:sys_capget. */ 93 /* Derived from kernel/capability.c:sys_capget. */
91 *effective = target->cap_effective; 94 *effective = cred->cap_effective;
92 *inheritable = target->cap_inheritable; 95 *inheritable = cred->cap_inheritable;
93 *permitted = target->cap_permitted; 96 *permitted = cred->cap_permitted;
94 return 0; 97 return 0;
95} 98}
96 99
@@ -122,24 +125,26 @@ int cap_capset_check(const kernel_cap_t *effective,
122 const kernel_cap_t *inheritable, 125 const kernel_cap_t *inheritable,
123 const kernel_cap_t *permitted) 126 const kernel_cap_t *permitted)
124{ 127{
128 const struct cred *cred = current->cred;
129
125 if (cap_inh_is_capped() 130 if (cap_inh_is_capped()
126 && !cap_issubset(*inheritable, 131 && !cap_issubset(*inheritable,
127 cap_combine(current->cap_inheritable, 132 cap_combine(cred->cap_inheritable,
128 current->cap_permitted))) { 133 cred->cap_permitted))) {
129 /* incapable of using this inheritable set */ 134 /* incapable of using this inheritable set */
130 return -EPERM; 135 return -EPERM;
131 } 136 }
132 if (!cap_issubset(*inheritable, 137 if (!cap_issubset(*inheritable,
133 cap_combine(current->cap_inheritable, 138 cap_combine(cred->cap_inheritable,
134 current->cap_bset))) { 139 cred->cap_bset))) {
135 /* no new pI capabilities outside bounding set */ 140 /* no new pI capabilities outside bounding set */
136 return -EPERM; 141 return -EPERM;
137 } 142 }
138 143
139 /* verify restrictions on target's new Permitted set */ 144 /* verify restrictions on target's new Permitted set */
140 if (!cap_issubset (*permitted, 145 if (!cap_issubset (*permitted,
141 cap_combine (current->cap_permitted, 146 cap_combine (cred->cap_permitted,
142 current->cap_permitted))) { 147 cred->cap_permitted))) {
143 return -EPERM; 148 return -EPERM;
144 } 149 }
145 150
@@ -155,9 +160,11 @@ void cap_capset_set(const kernel_cap_t *effective,
155 const kernel_cap_t *inheritable, 160 const kernel_cap_t *inheritable,
156 const kernel_cap_t *permitted) 161 const kernel_cap_t *permitted)
157{ 162{
158 current->cap_effective = *effective; 163 struct cred *cred = current->cred;
159 current->cap_inheritable = *inheritable; 164
160 current->cap_permitted = *permitted; 165 cred->cap_effective = *effective;
166 cred->cap_inheritable = *inheritable;
167 cred->cap_permitted = *permitted;
161} 168}
162 169
163static inline void bprm_clear_caps(struct linux_binprm *bprm) 170static inline void bprm_clear_caps(struct linux_binprm *bprm)
@@ -211,8 +218,8 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
211 * pP' = (X & fP) | (pI & fI) 218 * pP' = (X & fP) | (pI & fI)
212 */ 219 */
213 bprm->cap_post_exec_permitted.cap[i] = 220 bprm->cap_post_exec_permitted.cap[i] =
214 (current->cap_bset.cap[i] & permitted) | 221 (current->cred->cap_bset.cap[i] & permitted) |
215 (current->cap_inheritable.cap[i] & inheritable); 222 (current->cred->cap_inheritable.cap[i] & inheritable);
216 223
217 if (permitted & ~bprm->cap_post_exec_permitted.cap[i]) { 224 if (permitted & ~bprm->cap_post_exec_permitted.cap[i]) {
218 /* 225 /*
@@ -354,8 +361,8 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
354 if (bprm->e_uid == 0 || current_uid() == 0) { 361 if (bprm->e_uid == 0 || current_uid() == 0) {
355 /* pP' = (cap_bset & ~0) | (pI & ~0) */ 362 /* pP' = (cap_bset & ~0) | (pI & ~0) */
356 bprm->cap_post_exec_permitted = cap_combine( 363 bprm->cap_post_exec_permitted = cap_combine(
357 current->cap_bset, current->cap_inheritable 364 current->cred->cap_bset,
358 ); 365 current->cred->cap_inheritable);
359 bprm->cap_effective = (bprm->e_uid == 0); 366 bprm->cap_effective = (bprm->e_uid == 0);
360 ret = 0; 367 ret = 0;
361 } 368 }
@@ -366,44 +373,39 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
366 373
367void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) 374void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
368{ 375{
369 kernel_cap_t pP = current->cap_permitted; 376 struct cred *cred = current->cred;
370 kernel_cap_t pE = current->cap_effective;
371 uid_t uid;
372 gid_t gid;
373 377
374 current_uid_gid(&uid, &gid); 378 if (bprm->e_uid != cred->uid || bprm->e_gid != cred->gid ||
375
376 if (bprm->e_uid != uid || bprm->e_gid != gid ||
377 !cap_issubset(bprm->cap_post_exec_permitted, 379 !cap_issubset(bprm->cap_post_exec_permitted,
378 current->cap_permitted)) { 380 cred->cap_permitted)) {
379 set_dumpable(current->mm, suid_dumpable); 381 set_dumpable(current->mm, suid_dumpable);
380 current->pdeath_signal = 0; 382 current->pdeath_signal = 0;
381 383
382 if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) { 384 if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
383 if (!capable(CAP_SETUID)) { 385 if (!capable(CAP_SETUID)) {
384 bprm->e_uid = uid; 386 bprm->e_uid = cred->uid;
385 bprm->e_gid = gid; 387 bprm->e_gid = cred->gid;
386 } 388 }
387 if (cap_limit_ptraced_target()) { 389 if (cap_limit_ptraced_target()) {
388 bprm->cap_post_exec_permitted = cap_intersect( 390 bprm->cap_post_exec_permitted = cap_intersect(
389 bprm->cap_post_exec_permitted, 391 bprm->cap_post_exec_permitted,
390 current->cap_permitted); 392 cred->cap_permitted);
391 } 393 }
392 } 394 }
393 } 395 }
394 396
395 current->suid = current->euid = current->fsuid = bprm->e_uid; 397 cred->suid = cred->euid = cred->fsuid = bprm->e_uid;
396 current->sgid = current->egid = current->fsgid = bprm->e_gid; 398 cred->sgid = cred->egid = cred->fsgid = bprm->e_gid;
397 399
398 /* For init, we want to retain the capabilities set 400 /* For init, we want to retain the capabilities set
399 * in the init_task struct. Thus we skip the usual 401 * in the init_task struct. Thus we skip the usual
400 * capability rules */ 402 * capability rules */
401 if (!is_global_init(current)) { 403 if (!is_global_init(current)) {
402 current->cap_permitted = bprm->cap_post_exec_permitted; 404 cred->cap_permitted = bprm->cap_post_exec_permitted;
403 if (bprm->cap_effective) 405 if (bprm->cap_effective)
404 current->cap_effective = bprm->cap_post_exec_permitted; 406 cred->cap_effective = bprm->cap_post_exec_permitted;
405 else 407 else
406 cap_clear(current->cap_effective); 408 cap_clear(cred->cap_effective);
407 } 409 }
408 410
409 /* 411 /*
@@ -418,27 +420,30 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
418 * Number 1 above might fail if you don't have a full bset, but I think 420 * Number 1 above might fail if you don't have a full bset, but I think
419 * that is interesting information to audit. 421 * that is interesting information to audit.
420 */ 422 */
421 if (!cap_isclear(current->cap_effective)) { 423 if (!cap_isclear(cred->cap_effective)) {
422 if (!cap_issubset(CAP_FULL_SET, current->cap_effective) || 424 if (!cap_issubset(CAP_FULL_SET, cred->cap_effective) ||
423 (bprm->e_uid != 0) || (current->uid != 0) || 425 (bprm->e_uid != 0) || (cred->uid != 0) ||
424 issecure(SECURE_NOROOT)) 426 issecure(SECURE_NOROOT))
425 audit_log_bprm_fcaps(bprm, &pP, &pE); 427 audit_log_bprm_fcaps(bprm, &cred->cap_permitted,
428 &cred->cap_effective);
426 } 429 }
427 430
428 current->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); 431 cred->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
429} 432}
430 433
431int cap_bprm_secureexec (struct linux_binprm *bprm) 434int cap_bprm_secureexec (struct linux_binprm *bprm)
432{ 435{
433 if (current_uid() != 0) { 436 const struct cred *cred = current->cred;
437
438 if (cred->uid != 0) {
434 if (bprm->cap_effective) 439 if (bprm->cap_effective)
435 return 1; 440 return 1;
436 if (!cap_isclear(bprm->cap_post_exec_permitted)) 441 if (!cap_isclear(bprm->cap_post_exec_permitted))
437 return 1; 442 return 1;
438 } 443 }
439 444
440 return (current_euid() != current_uid() || 445 return (cred->euid != cred->uid ||
441 current_egid() != current_gid()); 446 cred->egid != cred->gid);
442} 447}
443 448
444int cap_inode_setxattr(struct dentry *dentry, const char *name, 449int cap_inode_setxattr(struct dentry *dentry, const char *name,
@@ -501,25 +506,27 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name)
501static inline void cap_emulate_setxuid (int old_ruid, int old_euid, 506static inline void cap_emulate_setxuid (int old_ruid, int old_euid,
502 int old_suid) 507 int old_suid)
503{ 508{
504 uid_t euid = current_euid(); 509 struct cred *cred = current->cred;
505 510
506 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) && 511 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
507 (current_uid() != 0 && euid != 0 && current_suid() != 0) && 512 (cred->uid != 0 && cred->euid != 0 && cred->suid != 0) &&
508 !issecure(SECURE_KEEP_CAPS)) { 513 !issecure(SECURE_KEEP_CAPS)) {
509 cap_clear (current->cap_permitted); 514 cap_clear (cred->cap_permitted);
510 cap_clear (current->cap_effective); 515 cap_clear (cred->cap_effective);
511 } 516 }
512 if (old_euid == 0 && euid != 0) { 517 if (old_euid == 0 && cred->euid != 0) {
513 cap_clear (current->cap_effective); 518 cap_clear (cred->cap_effective);
514 } 519 }
515 if (old_euid != 0 && euid == 0) { 520 if (old_euid != 0 && cred->euid == 0) {
516 current->cap_effective = current->cap_permitted; 521 cred->cap_effective = cred->cap_permitted;
517 } 522 }
518} 523}
519 524
520int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, 525int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
521 int flags) 526 int flags)
522{ 527{
528 struct cred *cred = current->cred;
529
523 switch (flags) { 530 switch (flags) {
524 case LSM_SETID_RE: 531 case LSM_SETID_RE:
525 case LSM_SETID_ID: 532 case LSM_SETID_ID:
@@ -541,16 +548,16 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
541 */ 548 */
542 549
543 if (!issecure (SECURE_NO_SETUID_FIXUP)) { 550 if (!issecure (SECURE_NO_SETUID_FIXUP)) {
544 if (old_fsuid == 0 && current_fsuid() != 0) { 551 if (old_fsuid == 0 && cred->fsuid != 0) {
545 current->cap_effective = 552 cred->cap_effective =
546 cap_drop_fs_set( 553 cap_drop_fs_set(
547 current->cap_effective); 554 cred->cap_effective);
548 } 555 }
549 if (old_fsuid != 0 && current_fsuid() == 0) { 556 if (old_fsuid != 0 && cred->fsuid == 0) {
550 current->cap_effective = 557 cred->cap_effective =
551 cap_raise_fs_set( 558 cap_raise_fs_set(
552 current->cap_effective, 559 cred->cap_effective,
553 current->cap_permitted); 560 cred->cap_permitted);
554 } 561 }
555 } 562 }
556 break; 563 break;
@@ -575,7 +582,8 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
575 */ 582 */
576static int cap_safe_nice(struct task_struct *p) 583static int cap_safe_nice(struct task_struct *p)
577{ 584{
578 if (!cap_issubset(p->cap_permitted, current->cap_permitted) && 585 if (!cap_issubset(p->cred->cap_permitted,
586 current->cred->cap_permitted) &&
579 !capable(CAP_SYS_NICE)) 587 !capable(CAP_SYS_NICE))
580 return -EPERM; 588 return -EPERM;
581 return 0; 589 return 0;
@@ -610,7 +618,7 @@ static long cap_prctl_drop(unsigned long cap)
610 return -EPERM; 618 return -EPERM;
611 if (!cap_valid(cap)) 619 if (!cap_valid(cap))
612 return -EINVAL; 620 return -EINVAL;
613 cap_lower(current->cap_bset, cap); 621 cap_lower(current->cred->cap_bset, cap);
614 return 0; 622 return 0;
615} 623}
616 624
@@ -633,6 +641,7 @@ int cap_task_setnice (struct task_struct *p, int nice)
633int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, 641int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
634 unsigned long arg4, unsigned long arg5, long *rc_p) 642 unsigned long arg4, unsigned long arg5, long *rc_p)
635{ 643{
644 struct cred *cred = current->cred;
636 long error = 0; 645 long error = 0;
637 646
638 switch (option) { 647 switch (option) {
@@ -640,7 +649,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
640 if (!cap_valid(arg2)) 649 if (!cap_valid(arg2))
641 error = -EINVAL; 650 error = -EINVAL;
642 else 651 else
643 error = !!cap_raised(current->cap_bset, arg2); 652 error = !!cap_raised(cred->cap_bset, arg2);
644 break; 653 break;
645#ifdef CONFIG_SECURITY_FILE_CAPABILITIES 654#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
646 case PR_CAPBSET_DROP: 655 case PR_CAPBSET_DROP:
@@ -667,9 +676,9 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
667 * capability-based-privilege environment. 676 * capability-based-privilege environment.
668 */ 677 */
669 case PR_SET_SECUREBITS: 678 case PR_SET_SECUREBITS:
670 if ((((current->securebits & SECURE_ALL_LOCKS) >> 1) 679 if ((((cred->securebits & SECURE_ALL_LOCKS) >> 1)
671 & (current->securebits ^ arg2)) /*[1]*/ 680 & (cred->securebits ^ arg2)) /*[1]*/
672 || ((current->securebits & SECURE_ALL_LOCKS 681 || ((cred->securebits & SECURE_ALL_LOCKS
673 & ~arg2)) /*[2]*/ 682 & ~arg2)) /*[2]*/
674 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ 683 || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/
675 || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0)) { /*[4]*/ 684 || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0)) { /*[4]*/
@@ -682,11 +691,11 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
682 */ 691 */
683 error = -EPERM; /* cannot change a locked bit */ 692 error = -EPERM; /* cannot change a locked bit */
684 } else { 693 } else {
685 current->securebits = arg2; 694 cred->securebits = arg2;
686 } 695 }
687 break; 696 break;
688 case PR_GET_SECUREBITS: 697 case PR_GET_SECUREBITS:
689 error = current->securebits; 698 error = cred->securebits;
690 break; 699 break;
691 700
692#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ 701#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
@@ -701,10 +710,9 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
701 else if (issecure(SECURE_KEEP_CAPS_LOCKED)) 710 else if (issecure(SECURE_KEEP_CAPS_LOCKED))
702 error = -EPERM; 711 error = -EPERM;
703 else if (arg2) 712 else if (arg2)
704 current->securebits |= issecure_mask(SECURE_KEEP_CAPS); 713 cred->securebits |= issecure_mask(SECURE_KEEP_CAPS);
705 else 714 else
706 current->securebits &= 715 cred->securebits &= ~issecure_mask(SECURE_KEEP_CAPS);
707 ~issecure_mask(SECURE_KEEP_CAPS);
708 break; 716 break;
709 717
710 default: 718 default:
@@ -719,11 +727,12 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
719 727
720void cap_task_reparent_to_init (struct task_struct *p) 728void cap_task_reparent_to_init (struct task_struct *p)
721{ 729{
722 cap_set_init_eff(p->cap_effective); 730 struct cred *cred = p->cred;
723 cap_clear(p->cap_inheritable); 731
724 cap_set_full(p->cap_permitted); 732 cap_set_init_eff(cred->cap_effective);
725 p->securebits = SECUREBITS_DEFAULT; 733 cap_clear(cred->cap_inheritable);
726 return; 734 cap_set_full(cred->cap_permitted);
735 p->cred->securebits = SECUREBITS_DEFAULT;
727} 736}
728 737
729int cap_syslog (int type) 738int cap_syslog (int type)