aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 20:42:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 20:42:39 -0400
commit644473e9c60c1ff4f6351fed637a6e5551e3dce7 (patch)
tree10316518bedc735a2c6552886658d69dfd9f1eb0 /kernel/sys.c
parentfb827ec68446c83e9e8754fa9b55aed27ecc4661 (diff)
parent4b06a81f1daee668fbd6de85557bfb36dd36078f (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull user namespace enhancements from Eric Biederman: "This is a course correction for the user namespace, so that we can reach an inexpensive, maintainable, and reasonably complete implementation. Highlights: - Config guards make it impossible to enable the user namespace and code that has not been converted to be user namespace safe. - Use of the new kuid_t type ensures the if you somehow get past the config guards the kernel will encounter type errors if you enable user namespaces and attempt to compile in code whose permission checks have not been updated to be user namespace safe. - All uids from child user namespaces are mapped into the initial user namespace before they are processed. Removing the need to add an additional check to see if the user namespace of the compared uids remains the same. - With the user namespaces compiled out the performance is as good or better than it is today. - For most operations absolutely nothing changes performance or operationally with the user namespace enabled. - The worst case performance I could come up with was timing 1 billion cache cold stat operations with the user namespace code enabled. This went from 156s to 164s on my laptop (or 156ns to 164ns per stat operation). - (uid_t)-1 and (gid_t)-1 are reserved as an internal error value. Most uid/gid setting system calls treat these value specially anyway so attempting to use -1 as a uid would likely cause entertaining failures in userspace. - If setuid is called with a uid that can not be mapped setuid fails. I have looked at sendmail, login, ssh and every other program I could think of that would call setuid and they all check for and handle the case where setuid fails. - If stat or a similar system call is called from a context in which we can not map a uid we lie and return overflowuid. The LFS experience suggests not lying and returning an error code might be better, but the historical precedent with uids is different and I can not think of anything that would break by lying about a uid we can't map. - Capabilities are localized to the current user namespace making it safe to give the initial user in a user namespace all capabilities. My git tree covers all of the modifications needed to convert the core kernel and enough changes to make a system bootable to runlevel 1." Fix up trivial conflicts due to nearby independent changes in fs/stat.c * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (46 commits) userns: Silence silly gcc warning. cred: use correct cred accessor with regards to rcu read lock userns: Convert the move_pages, and migrate_pages permission checks to use uid_eq userns: Convert cgroup permission checks to use uid_eq userns: Convert tmpfs to use kuid and kgid where appropriate userns: Convert sysfs to use kgid/kuid where appropriate userns: Convert sysctl permission checks to use kuid and kgids. userns: Convert proc to use kuid/kgid where appropriate userns: Convert ext4 to user kuid/kgid where appropriate userns: Convert ext3 to use kuid/kgid where appropriate userns: Convert ext2 to use kuid/kgid where appropriate. userns: Convert devpts to use kuid/kgid where appropriate userns: Convert binary formats to use kuid/kgid where appropriate userns: Add negative depends on entries to avoid building code that is userns unsafe userns: signal remove unnecessary map_cred_ns userns: Teach inode_capable to understand inodes whose uids map to other namespaces. userns: Fail exec for suid and sgid binaries with ids outside our user namespace. userns: Convert stat to return values mapped from kuids and kgids userns: Convert user specfied uids and gids in chown into kuids and kgid userns: Use uid_eq gid_eq helpers when comparing kuids and kgids in the vfs ...
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c266
1 files changed, 174 insertions, 92 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index ba0ae8eea6fb..6df42624e454 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -93,10 +93,8 @@
93int overflowuid = DEFAULT_OVERFLOWUID; 93int overflowuid = DEFAULT_OVERFLOWUID;
94int overflowgid = DEFAULT_OVERFLOWGID; 94int overflowgid = DEFAULT_OVERFLOWGID;
95 95
96#ifdef CONFIG_UID16
97EXPORT_SYMBOL(overflowuid); 96EXPORT_SYMBOL(overflowuid);
98EXPORT_SYMBOL(overflowgid); 97EXPORT_SYMBOL(overflowgid);
99#endif
100 98
101/* 99/*
102 * the same as above, but for filesystems which can only store a 16-bit 100 * the same as above, but for filesystems which can only store a 16-bit
@@ -133,11 +131,10 @@ static bool set_one_prio_perm(struct task_struct *p)
133{ 131{
134 const struct cred *cred = current_cred(), *pcred = __task_cred(p); 132 const struct cred *cred = current_cred(), *pcred = __task_cred(p);
135 133
136 if (pcred->user->user_ns == cred->user->user_ns && 134 if (uid_eq(pcred->uid, cred->euid) ||
137 (pcred->uid == cred->euid || 135 uid_eq(pcred->euid, cred->euid))
138 pcred->euid == cred->euid))
139 return true; 136 return true;
140 if (ns_capable(pcred->user->user_ns, CAP_SYS_NICE)) 137 if (ns_capable(pcred->user_ns, CAP_SYS_NICE))
141 return true; 138 return true;
142 return false; 139 return false;
143} 140}
@@ -177,6 +174,7 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
177 const struct cred *cred = current_cred(); 174 const struct cred *cred = current_cred();
178 int error = -EINVAL; 175 int error = -EINVAL;
179 struct pid *pgrp; 176 struct pid *pgrp;
177 kuid_t uid;
180 178
181 if (which > PRIO_USER || which < PRIO_PROCESS) 179 if (which > PRIO_USER || which < PRIO_PROCESS)
182 goto out; 180 goto out;
@@ -209,18 +207,19 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
209 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 207 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
210 break; 208 break;
211 case PRIO_USER: 209 case PRIO_USER:
212 user = (struct user_struct *) cred->user; 210 uid = make_kuid(cred->user_ns, who);
211 user = cred->user;
213 if (!who) 212 if (!who)
214 who = cred->uid; 213 uid = cred->uid;
215 else if ((who != cred->uid) && 214 else if (!uid_eq(uid, cred->uid) &&
216 !(user = find_user(who))) 215 !(user = find_user(uid)))
217 goto out_unlock; /* No processes for this user */ 216 goto out_unlock; /* No processes for this user */
218 217
219 do_each_thread(g, p) { 218 do_each_thread(g, p) {
220 if (__task_cred(p)->uid == who) 219 if (uid_eq(task_uid(p), uid))
221 error = set_one_prio(p, niceval, error); 220 error = set_one_prio(p, niceval, error);
222 } while_each_thread(g, p); 221 } while_each_thread(g, p);
223 if (who != cred->uid) 222 if (!uid_eq(uid, cred->uid))
224 free_uid(user); /* For find_user() */ 223 free_uid(user); /* For find_user() */
225 break; 224 break;
226 } 225 }
@@ -244,6 +243,7 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
244 const struct cred *cred = current_cred(); 243 const struct cred *cred = current_cred();
245 long niceval, retval = -ESRCH; 244 long niceval, retval = -ESRCH;
246 struct pid *pgrp; 245 struct pid *pgrp;
246 kuid_t uid;
247 247
248 if (which > PRIO_USER || which < PRIO_PROCESS) 248 if (which > PRIO_USER || which < PRIO_PROCESS)
249 return -EINVAL; 249 return -EINVAL;
@@ -274,21 +274,22 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who)
274 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); 274 } while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
275 break; 275 break;
276 case PRIO_USER: 276 case PRIO_USER:
277 user = (struct user_struct *) cred->user; 277 uid = make_kuid(cred->user_ns, who);
278 user = cred->user;
278 if (!who) 279 if (!who)
279 who = cred->uid; 280 uid = cred->uid;
280 else if ((who != cred->uid) && 281 else if (!uid_eq(uid, cred->uid) &&
281 !(user = find_user(who))) 282 !(user = find_user(uid)))
282 goto out_unlock; /* No processes for this user */ 283 goto out_unlock; /* No processes for this user */
283 284
284 do_each_thread(g, p) { 285 do_each_thread(g, p) {
285 if (__task_cred(p)->uid == who) { 286 if (uid_eq(task_uid(p), uid)) {
286 niceval = 20 - task_nice(p); 287 niceval = 20 - task_nice(p);
287 if (niceval > retval) 288 if (niceval > retval)
288 retval = niceval; 289 retval = niceval;
289 } 290 }
290 } while_each_thread(g, p); 291 } while_each_thread(g, p);
291 if (who != cred->uid) 292 if (!uid_eq(uid, cred->uid))
292 free_uid(user); /* for find_user() */ 293 free_uid(user); /* for find_user() */
293 break; 294 break;
294 } 295 }
@@ -553,9 +554,19 @@ void ctrl_alt_del(void)
553 */ 554 */
554SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid) 555SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
555{ 556{
557 struct user_namespace *ns = current_user_ns();
556 const struct cred *old; 558 const struct cred *old;
557 struct cred *new; 559 struct cred *new;
558 int retval; 560 int retval;
561 kgid_t krgid, kegid;
562
563 krgid = make_kgid(ns, rgid);
564 kegid = make_kgid(ns, egid);
565
566 if ((rgid != (gid_t) -1) && !gid_valid(krgid))
567 return -EINVAL;
568 if ((egid != (gid_t) -1) && !gid_valid(kegid))
569 return -EINVAL;
559 570
560 new = prepare_creds(); 571 new = prepare_creds();
561 if (!new) 572 if (!new)
@@ -564,25 +575,25 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
564 575
565 retval = -EPERM; 576 retval = -EPERM;
566 if (rgid != (gid_t) -1) { 577 if (rgid != (gid_t) -1) {
567 if (old->gid == rgid || 578 if (gid_eq(old->gid, krgid) ||
568 old->egid == rgid || 579 gid_eq(old->egid, krgid) ||
569 nsown_capable(CAP_SETGID)) 580 nsown_capable(CAP_SETGID))
570 new->gid = rgid; 581 new->gid = krgid;
571 else 582 else
572 goto error; 583 goto error;
573 } 584 }
574 if (egid != (gid_t) -1) { 585 if (egid != (gid_t) -1) {
575 if (old->gid == egid || 586 if (gid_eq(old->gid, kegid) ||
576 old->egid == egid || 587 gid_eq(old->egid, kegid) ||
577 old->sgid == egid || 588 gid_eq(old->sgid, kegid) ||
578 nsown_capable(CAP_SETGID)) 589 nsown_capable(CAP_SETGID))
579 new->egid = egid; 590 new->egid = kegid;
580 else 591 else
581 goto error; 592 goto error;
582 } 593 }
583 594
584 if (rgid != (gid_t) -1 || 595 if (rgid != (gid_t) -1 ||
585 (egid != (gid_t) -1 && egid != old->gid)) 596 (egid != (gid_t) -1 && !gid_eq(kegid, old->gid)))
586 new->sgid = new->egid; 597 new->sgid = new->egid;
587 new->fsgid = new->egid; 598 new->fsgid = new->egid;
588 599
@@ -600,9 +611,15 @@ error:
600 */ 611 */
601SYSCALL_DEFINE1(setgid, gid_t, gid) 612SYSCALL_DEFINE1(setgid, gid_t, gid)
602{ 613{
614 struct user_namespace *ns = current_user_ns();
603 const struct cred *old; 615 const struct cred *old;
604 struct cred *new; 616 struct cred *new;
605 int retval; 617 int retval;
618 kgid_t kgid;
619
620 kgid = make_kgid(ns, gid);
621 if (!gid_valid(kgid))
622 return -EINVAL;
606 623
607 new = prepare_creds(); 624 new = prepare_creds();
608 if (!new) 625 if (!new)
@@ -611,9 +628,9 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
611 628
612 retval = -EPERM; 629 retval = -EPERM;
613 if (nsown_capable(CAP_SETGID)) 630 if (nsown_capable(CAP_SETGID))
614 new->gid = new->egid = new->sgid = new->fsgid = gid; 631 new->gid = new->egid = new->sgid = new->fsgid = kgid;
615 else if (gid == old->gid || gid == old->sgid) 632 else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid))
616 new->egid = new->fsgid = gid; 633 new->egid = new->fsgid = kgid;
617 else 634 else
618 goto error; 635 goto error;
619 636
@@ -631,7 +648,7 @@ static int set_user(struct cred *new)
631{ 648{
632 struct user_struct *new_user; 649 struct user_struct *new_user;
633 650
634 new_user = alloc_uid(current_user_ns(), new->uid); 651 new_user = alloc_uid(new->uid);
635 if (!new_user) 652 if (!new_user)
636 return -EAGAIN; 653 return -EAGAIN;
637 654
@@ -670,9 +687,19 @@ static int set_user(struct cred *new)
670 */ 687 */
671SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) 688SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
672{ 689{
690 struct user_namespace *ns = current_user_ns();
673 const struct cred *old; 691 const struct cred *old;
674 struct cred *new; 692 struct cred *new;
675 int retval; 693 int retval;
694 kuid_t kruid, keuid;
695
696 kruid = make_kuid(ns, ruid);
697 keuid = make_kuid(ns, euid);
698
699 if ((ruid != (uid_t) -1) && !uid_valid(kruid))
700 return -EINVAL;
701 if ((euid != (uid_t) -1) && !uid_valid(keuid))
702 return -EINVAL;
676 703
677 new = prepare_creds(); 704 new = prepare_creds();
678 if (!new) 705 if (!new)
@@ -681,29 +708,29 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
681 708
682 retval = -EPERM; 709 retval = -EPERM;
683 if (ruid != (uid_t) -1) { 710 if (ruid != (uid_t) -1) {
684 new->uid = ruid; 711 new->uid = kruid;
685 if (old->uid != ruid && 712 if (!uid_eq(old->uid, kruid) &&
686 old->euid != ruid && 713 !uid_eq(old->euid, kruid) &&
687 !nsown_capable(CAP_SETUID)) 714 !nsown_capable(CAP_SETUID))
688 goto error; 715 goto error;
689 } 716 }
690 717
691 if (euid != (uid_t) -1) { 718 if (euid != (uid_t) -1) {
692 new->euid = euid; 719 new->euid = keuid;
693 if (old->uid != euid && 720 if (!uid_eq(old->uid, keuid) &&
694 old->euid != euid && 721 !uid_eq(old->euid, keuid) &&
695 old->suid != euid && 722 !uid_eq(old->suid, keuid) &&
696 !nsown_capable(CAP_SETUID)) 723 !nsown_capable(CAP_SETUID))
697 goto error; 724 goto error;
698 } 725 }
699 726
700 if (new->uid != old->uid) { 727 if (!uid_eq(new->uid, old->uid)) {
701 retval = set_user(new); 728 retval = set_user(new);
702 if (retval < 0) 729 if (retval < 0)
703 goto error; 730 goto error;
704 } 731 }
705 if (ruid != (uid_t) -1 || 732 if (ruid != (uid_t) -1 ||
706 (euid != (uid_t) -1 && euid != old->uid)) 733 (euid != (uid_t) -1 && !uid_eq(keuid, old->uid)))
707 new->suid = new->euid; 734 new->suid = new->euid;
708 new->fsuid = new->euid; 735 new->fsuid = new->euid;
709 736
@@ -731,9 +758,15 @@ error:
731 */ 758 */
732SYSCALL_DEFINE1(setuid, uid_t, uid) 759SYSCALL_DEFINE1(setuid, uid_t, uid)
733{ 760{
761 struct user_namespace *ns = current_user_ns();
734 const struct cred *old; 762 const struct cred *old;
735 struct cred *new; 763 struct cred *new;
736 int retval; 764 int retval;
765 kuid_t kuid;
766
767 kuid = make_kuid(ns, uid);
768 if (!uid_valid(kuid))
769 return -EINVAL;
737 770
738 new = prepare_creds(); 771 new = prepare_creds();
739 if (!new) 772 if (!new)
@@ -742,17 +775,17 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
742 775
743 retval = -EPERM; 776 retval = -EPERM;
744 if (nsown_capable(CAP_SETUID)) { 777 if (nsown_capable(CAP_SETUID)) {
745 new->suid = new->uid = uid; 778 new->suid = new->uid = kuid;
746 if (uid != old->uid) { 779 if (!uid_eq(kuid, old->uid)) {
747 retval = set_user(new); 780 retval = set_user(new);
748 if (retval < 0) 781 if (retval < 0)
749 goto error; 782 goto error;
750 } 783 }
751 } else if (uid != old->uid && uid != new->suid) { 784 } else if (!uid_eq(kuid, old->uid) && !uid_eq(kuid, new->suid)) {
752 goto error; 785 goto error;
753 } 786 }
754 787
755 new->fsuid = new->euid = uid; 788 new->fsuid = new->euid = kuid;
756 789
757 retval = security_task_fix_setuid(new, old, LSM_SETID_ID); 790 retval = security_task_fix_setuid(new, old, LSM_SETID_ID);
758 if (retval < 0) 791 if (retval < 0)
@@ -772,9 +805,24 @@ error:
772 */ 805 */
773SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) 806SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
774{ 807{
808 struct user_namespace *ns = current_user_ns();
775 const struct cred *old; 809 const struct cred *old;
776 struct cred *new; 810 struct cred *new;
777 int retval; 811 int retval;
812 kuid_t kruid, keuid, ksuid;
813
814 kruid = make_kuid(ns, ruid);
815 keuid = make_kuid(ns, euid);
816 ksuid = make_kuid(ns, suid);
817
818 if ((ruid != (uid_t) -1) && !uid_valid(kruid))
819 return -EINVAL;
820
821 if ((euid != (uid_t) -1) && !uid_valid(keuid))
822 return -EINVAL;
823
824 if ((suid != (uid_t) -1) && !uid_valid(ksuid))
825 return -EINVAL;
778 826
779 new = prepare_creds(); 827 new = prepare_creds();
780 if (!new) 828 if (!new)
@@ -784,29 +832,29 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
784 832
785 retval = -EPERM; 833 retval = -EPERM;
786 if (!nsown_capable(CAP_SETUID)) { 834 if (!nsown_capable(CAP_SETUID)) {
787 if (ruid != (uid_t) -1 && ruid != old->uid && 835 if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) &&
788 ruid != old->euid && ruid != old->suid) 836 !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid))
789 goto error; 837 goto error;
790 if (euid != (uid_t) -1 && euid != old->uid && 838 if (euid != (uid_t) -1 && !uid_eq(keuid, old->uid) &&
791 euid != old->euid && euid != old->suid) 839 !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid))
792 goto error; 840 goto error;
793 if (suid != (uid_t) -1 && suid != old->uid && 841 if (suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) &&
794 suid != old->euid && suid != old->suid) 842 !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid))
795 goto error; 843 goto error;
796 } 844 }
797 845
798 if (ruid != (uid_t) -1) { 846 if (ruid != (uid_t) -1) {
799 new->uid = ruid; 847 new->uid = kruid;
800 if (ruid != old->uid) { 848 if (!uid_eq(kruid, old->uid)) {
801 retval = set_user(new); 849 retval = set_user(new);
802 if (retval < 0) 850 if (retval < 0)
803 goto error; 851 goto error;
804 } 852 }
805 } 853 }
806 if (euid != (uid_t) -1) 854 if (euid != (uid_t) -1)
807 new->euid = euid; 855 new->euid = keuid;
808 if (suid != (uid_t) -1) 856 if (suid != (uid_t) -1)
809 new->suid = suid; 857 new->suid = ksuid;
810 new->fsuid = new->euid; 858 new->fsuid = new->euid;
811 859
812 retval = security_task_fix_setuid(new, old, LSM_SETID_RES); 860 retval = security_task_fix_setuid(new, old, LSM_SETID_RES);
@@ -820,14 +868,19 @@ error:
820 return retval; 868 return retval;
821} 869}
822 870
823SYSCALL_DEFINE3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid) 871SYSCALL_DEFINE3(getresuid, uid_t __user *, ruidp, uid_t __user *, euidp, uid_t __user *, suidp)
824{ 872{
825 const struct cred *cred = current_cred(); 873 const struct cred *cred = current_cred();
826 int retval; 874 int retval;
875 uid_t ruid, euid, suid;
876
877 ruid = from_kuid_munged(cred->user_ns, cred->uid);
878 euid = from_kuid_munged(cred->user_ns, cred->euid);
879 suid = from_kuid_munged(cred->user_ns, cred->suid);
827 880
828 if (!(retval = put_user(cred->uid, ruid)) && 881 if (!(retval = put_user(ruid, ruidp)) &&
829 !(retval = put_user(cred->euid, euid))) 882 !(retval = put_user(euid, euidp)))
830 retval = put_user(cred->suid, suid); 883 retval = put_user(suid, suidp);
831 884
832 return retval; 885 return retval;
833} 886}
@@ -837,9 +890,22 @@ SYSCALL_DEFINE3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __u
837 */ 890 */
838SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) 891SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
839{ 892{
893 struct user_namespace *ns = current_user_ns();
840 const struct cred *old; 894 const struct cred *old;
841 struct cred *new; 895 struct cred *new;
842 int retval; 896 int retval;
897 kgid_t krgid, kegid, ksgid;
898
899 krgid = make_kgid(ns, rgid);
900 kegid = make_kgid(ns, egid);
901 ksgid = make_kgid(ns, sgid);
902
903 if ((rgid != (gid_t) -1) && !gid_valid(krgid))
904 return -EINVAL;
905 if ((egid != (gid_t) -1) && !gid_valid(kegid))
906 return -EINVAL;
907 if ((sgid != (gid_t) -1) && !gid_valid(ksgid))
908 return -EINVAL;
843 909
844 new = prepare_creds(); 910 new = prepare_creds();
845 if (!new) 911 if (!new)
@@ -848,23 +914,23 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
848 914
849 retval = -EPERM; 915 retval = -EPERM;
850 if (!nsown_capable(CAP_SETGID)) { 916 if (!nsown_capable(CAP_SETGID)) {
851 if (rgid != (gid_t) -1 && rgid != old->gid && 917 if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) &&
852 rgid != old->egid && rgid != old->sgid) 918 !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid))
853 goto error; 919 goto error;
854 if (egid != (gid_t) -1 && egid != old->gid && 920 if (egid != (gid_t) -1 && !gid_eq(kegid, old->gid) &&
855 egid != old->egid && egid != old->sgid) 921 !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid))
856 goto error; 922 goto error;
857 if (sgid != (gid_t) -1 && sgid != old->gid && 923 if (sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) &&
858 sgid != old->egid && sgid != old->sgid) 924 !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid))
859 goto error; 925 goto error;
860 } 926 }
861 927
862 if (rgid != (gid_t) -1) 928 if (rgid != (gid_t) -1)
863 new->gid = rgid; 929 new->gid = krgid;
864 if (egid != (gid_t) -1) 930 if (egid != (gid_t) -1)
865 new->egid = egid; 931 new->egid = kegid;
866 if (sgid != (gid_t) -1) 932 if (sgid != (gid_t) -1)
867 new->sgid = sgid; 933 new->sgid = ksgid;
868 new->fsgid = new->egid; 934 new->fsgid = new->egid;
869 935
870 return commit_creds(new); 936 return commit_creds(new);
@@ -874,14 +940,19 @@ error:
874 return retval; 940 return retval;
875} 941}
876 942
877SYSCALL_DEFINE3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid) 943SYSCALL_DEFINE3(getresgid, gid_t __user *, rgidp, gid_t __user *, egidp, gid_t __user *, sgidp)
878{ 944{
879 const struct cred *cred = current_cred(); 945 const struct cred *cred = current_cred();
880 int retval; 946 int retval;
947 gid_t rgid, egid, sgid;
948
949 rgid = from_kgid_munged(cred->user_ns, cred->gid);
950 egid = from_kgid_munged(cred->user_ns, cred->egid);
951 sgid = from_kgid_munged(cred->user_ns, cred->sgid);
881 952
882 if (!(retval = put_user(cred->gid, rgid)) && 953 if (!(retval = put_user(rgid, rgidp)) &&
883 !(retval = put_user(cred->egid, egid))) 954 !(retval = put_user(egid, egidp)))
884 retval = put_user(cred->sgid, sgid); 955 retval = put_user(sgid, sgidp);
885 956
886 return retval; 957 return retval;
887} 958}
@@ -898,18 +969,24 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
898 const struct cred *old; 969 const struct cred *old;
899 struct cred *new; 970 struct cred *new;
900 uid_t old_fsuid; 971 uid_t old_fsuid;
972 kuid_t kuid;
973
974 old = current_cred();
975 old_fsuid = from_kuid_munged(old->user_ns, old->fsuid);
976
977 kuid = make_kuid(old->user_ns, uid);
978 if (!uid_valid(kuid))
979 return old_fsuid;
901 980
902 new = prepare_creds(); 981 new = prepare_creds();
903 if (!new) 982 if (!new)
904 return current_fsuid(); 983 return old_fsuid;
905 old = current_cred();
906 old_fsuid = old->fsuid;
907 984
908 if (uid == old->uid || uid == old->euid || 985 if (uid_eq(kuid, old->uid) || uid_eq(kuid, old->euid) ||
909 uid == old->suid || uid == old->fsuid || 986 uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) ||
910 nsown_capable(CAP_SETUID)) { 987 nsown_capable(CAP_SETUID)) {
911 if (uid != old_fsuid) { 988 if (!uid_eq(kuid, old->fsuid)) {
912 new->fsuid = uid; 989 new->fsuid = kuid;
913 if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0) 990 if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
914 goto change_okay; 991 goto change_okay;
915 } 992 }
@@ -931,18 +1008,24 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
931 const struct cred *old; 1008 const struct cred *old;
932 struct cred *new; 1009 struct cred *new;
933 gid_t old_fsgid; 1010 gid_t old_fsgid;
1011 kgid_t kgid;
1012
1013 old = current_cred();
1014 old_fsgid = from_kgid_munged(old->user_ns, old->fsgid);
1015
1016 kgid = make_kgid(old->user_ns, gid);
1017 if (!gid_valid(kgid))
1018 return old_fsgid;
934 1019
935 new = prepare_creds(); 1020 new = prepare_creds();
936 if (!new) 1021 if (!new)
937 return current_fsgid(); 1022 return old_fsgid;
938 old = current_cred();
939 old_fsgid = old->fsgid;
940 1023
941 if (gid == old->gid || gid == old->egid || 1024 if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->egid) ||
942 gid == old->sgid || gid == old->fsgid || 1025 gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) ||
943 nsown_capable(CAP_SETGID)) { 1026 nsown_capable(CAP_SETGID)) {
944 if (gid != old_fsgid) { 1027 if (!gid_eq(kgid, old->fsgid)) {
945 new->fsgid = gid; 1028 new->fsgid = kgid;
946 goto change_okay; 1029 goto change_okay;
947 } 1030 }
948 } 1031 }
@@ -1498,15 +1581,14 @@ static int check_prlimit_permission(struct task_struct *task)
1498 return 0; 1581 return 0;
1499 1582
1500 tcred = __task_cred(task); 1583 tcred = __task_cred(task);
1501 if (cred->user->user_ns == tcred->user->user_ns && 1584 if (uid_eq(cred->uid, tcred->euid) &&
1502 (cred->uid == tcred->euid && 1585 uid_eq(cred->uid, tcred->suid) &&
1503 cred->uid == tcred->suid && 1586 uid_eq(cred->uid, tcred->uid) &&
1504 cred->uid == tcred->uid && 1587 gid_eq(cred->gid, tcred->egid) &&
1505 cred->gid == tcred->egid && 1588 gid_eq(cred->gid, tcred->sgid) &&
1506 cred->gid == tcred->sgid && 1589 gid_eq(cred->gid, tcred->gid))
1507 cred->gid == tcred->gid))
1508 return 0; 1590 return 0;
1509 if (ns_capable(tcred->user->user_ns, CAP_SYS_RESOURCE)) 1591 if (ns_capable(tcred->user_ns, CAP_SYS_RESOURCE))
1510 return 0; 1592 return 0;
1511 1593
1512 return -EPERM; 1594 return -EPERM;