aboutsummaryrefslogtreecommitdiffstats
path: root/security/commoncap.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-02-07 19:45:47 -0500
committerEric W. Biederman <ebiederm@xmission.com>2012-05-03 06:28:40 -0400
commit18815a18085364d8514c0d0c4c986776cb74272c (patch)
treea931fb2eee31aee6f8d83ef4493071b9827b1b9f /security/commoncap.c
parent9c806aa06f8e121c6058db8e8073798aa5c4355b (diff)
userns: Convert capabilities related permsion checks
- Use uid_eq when comparing kuids Use gid_eq when comparing kgids - Use make_kuid(user_ns, 0) to talk about the user_namespace root uid Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'security/commoncap.c')
-rw-r--r--security/commoncap.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index dbd465a59286..ff9b113bb07c 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -472,19 +472,22 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
472 struct cred *new = bprm->cred; 472 struct cred *new = bprm->cred;
473 bool effective, has_cap = false; 473 bool effective, has_cap = false;
474 int ret; 474 int ret;
475 kuid_t root_uid;
475 476
476 effective = false; 477 effective = false;
477 ret = get_file_caps(bprm, &effective, &has_cap); 478 ret = get_file_caps(bprm, &effective, &has_cap);
478 if (ret < 0) 479 if (ret < 0)
479 return ret; 480 return ret;
480 481
482 root_uid = make_kuid(new->user_ns, 0);
483
481 if (!issecure(SECURE_NOROOT)) { 484 if (!issecure(SECURE_NOROOT)) {
482 /* 485 /*
483 * If the legacy file capability is set, then don't set privs 486 * If the legacy file capability is set, then don't set privs
484 * for a setuid root binary run by a non-root user. Do set it 487 * for a setuid root binary run by a non-root user. Do set it
485 * for a root user just to cause least surprise to an admin. 488 * for a root user just to cause least surprise to an admin.
486 */ 489 */
487 if (has_cap && new->uid != 0 && new->euid == 0) { 490 if (has_cap && !uid_eq(new->uid, root_uid) && uid_eq(new->euid, root_uid)) {
488 warn_setuid_and_fcaps_mixed(bprm->filename); 491 warn_setuid_and_fcaps_mixed(bprm->filename);
489 goto skip; 492 goto skip;
490 } 493 }
@@ -495,12 +498,12 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
495 * 498 *
496 * If only the real uid is 0, we do not set the effective bit. 499 * If only the real uid is 0, we do not set the effective bit.
497 */ 500 */
498 if (new->euid == 0 || new->uid == 0) { 501 if (uid_eq(new->euid, root_uid) || uid_eq(new->uid, root_uid)) {
499 /* pP' = (cap_bset & ~0) | (pI & ~0) */ 502 /* pP' = (cap_bset & ~0) | (pI & ~0) */
500 new->cap_permitted = cap_combine(old->cap_bset, 503 new->cap_permitted = cap_combine(old->cap_bset,
501 old->cap_inheritable); 504 old->cap_inheritable);
502 } 505 }
503 if (new->euid == 0) 506 if (uid_eq(new->euid, root_uid))
504 effective = true; 507 effective = true;
505 } 508 }
506skip: 509skip:
@@ -508,8 +511,8 @@ skip:
508 /* Don't let someone trace a set[ug]id/setpcap binary with the revised 511 /* Don't let someone trace a set[ug]id/setpcap binary with the revised
509 * credentials unless they have the appropriate permit 512 * credentials unless they have the appropriate permit
510 */ 513 */
511 if ((new->euid != old->uid || 514 if ((!uid_eq(new->euid, old->uid) ||
512 new->egid != old->gid || 515 !gid_eq(new->egid, old->gid) ||
513 !cap_issubset(new->cap_permitted, old->cap_permitted)) && 516 !cap_issubset(new->cap_permitted, old->cap_permitted)) &&
514 bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { 517 bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
515 /* downgrade; they get no more than they had, and maybe less */ 518 /* downgrade; they get no more than they had, and maybe less */
@@ -544,7 +547,7 @@ skip:
544 */ 547 */
545 if (!cap_isclear(new->cap_effective)) { 548 if (!cap_isclear(new->cap_effective)) {
546 if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || 549 if (!cap_issubset(CAP_FULL_SET, new->cap_effective) ||
547 new->euid != 0 || new->uid != 0 || 550 !uid_eq(new->euid, root_uid) || !uid_eq(new->uid, root_uid) ||
548 issecure(SECURE_NOROOT)) { 551 issecure(SECURE_NOROOT)) {
549 ret = audit_log_bprm_fcaps(bprm, new, old); 552 ret = audit_log_bprm_fcaps(bprm, new, old);
550 if (ret < 0) 553 if (ret < 0)
@@ -569,16 +572,17 @@ skip:
569int cap_bprm_secureexec(struct linux_binprm *bprm) 572int cap_bprm_secureexec(struct linux_binprm *bprm)
570{ 573{
571 const struct cred *cred = current_cred(); 574 const struct cred *cred = current_cred();
575 kuid_t root_uid = make_kuid(cred->user_ns, 0);
572 576
573 if (cred->uid != 0) { 577 if (!uid_eq(cred->uid, root_uid)) {
574 if (bprm->cap_effective) 578 if (bprm->cap_effective)
575 return 1; 579 return 1;
576 if (!cap_isclear(cred->cap_permitted)) 580 if (!cap_isclear(cred->cap_permitted))
577 return 1; 581 return 1;
578 } 582 }
579 583
580 return (cred->euid != cred->uid || 584 return (!uid_eq(cred->euid, cred->uid) ||
581 cred->egid != cred->gid); 585 !gid_eq(cred->egid, cred->gid));
582} 586}
583 587
584/** 588/**
@@ -668,15 +672,21 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name)
668 */ 672 */
669static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old) 673static inline void cap_emulate_setxuid(struct cred *new, const struct cred *old)
670{ 674{
671 if ((old->uid == 0 || old->euid == 0 || old->suid == 0) && 675 kuid_t root_uid = make_kuid(old->user_ns, 0);
672 (new->uid != 0 && new->euid != 0 && new->suid != 0) && 676
677 if ((uid_eq(old->uid, root_uid) ||
678 uid_eq(old->euid, root_uid) ||
679 uid_eq(old->suid, root_uid)) &&
680 (!uid_eq(new->uid, root_uid) &&
681 !uid_eq(new->euid, root_uid) &&
682 !uid_eq(new->suid, root_uid)) &&
673 !issecure(SECURE_KEEP_CAPS)) { 683 !issecure(SECURE_KEEP_CAPS)) {
674 cap_clear(new->cap_permitted); 684 cap_clear(new->cap_permitted);
675 cap_clear(new->cap_effective); 685 cap_clear(new->cap_effective);
676 } 686 }
677 if (old->euid == 0 && new->euid != 0) 687 if (uid_eq(old->euid, root_uid) && !uid_eq(new->euid, root_uid))
678 cap_clear(new->cap_effective); 688 cap_clear(new->cap_effective);
679 if (old->euid != 0 && new->euid == 0) 689 if (!uid_eq(old->euid, root_uid) && uid_eq(new->euid, root_uid))
680 new->cap_effective = new->cap_permitted; 690 new->cap_effective = new->cap_permitted;
681} 691}
682 692
@@ -709,11 +719,12 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags)
709 * if not, we might be a bit too harsh here. 719 * if not, we might be a bit too harsh here.
710 */ 720 */
711 if (!issecure(SECURE_NO_SETUID_FIXUP)) { 721 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
712 if (old->fsuid == 0 && new->fsuid != 0) 722 kuid_t root_uid = make_kuid(old->user_ns, 0);
723 if (uid_eq(old->fsuid, root_uid) && !uid_eq(new->fsuid, root_uid))
713 new->cap_effective = 724 new->cap_effective =
714 cap_drop_fs_set(new->cap_effective); 725 cap_drop_fs_set(new->cap_effective);
715 726
716 if (old->fsuid != 0 && new->fsuid == 0) 727 if (!uid_eq(old->fsuid, root_uid) && uid_eq(new->fsuid, root_uid))
717 new->cap_effective = 728 new->cap_effective =
718 cap_raise_fs_set(new->cap_effective, 729 cap_raise_fs_set(new->cap_effective,
719 new->cap_permitted); 730 new->cap_permitted);