diff options
author | Dhaval Giani <dhaval@linux.vnet.ibm.com> | 2009-02-27 04:43:54 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-27 05:11:53 -0500 |
commit | 54e991242850edc8c53f71fa5aa3ba7a93ce38f5 (patch) | |
tree | 7f136214aab690a8ee4a294ca9c1a7e01de0dc49 /kernel/sys.c | |
parent | cac64d00c256e65776d575e82aaf540632b66178 (diff) |
sched: don't allow setuid to succeed if the user does not have rt bandwidth
Impact: fix hung task with certain (non-default) rt-limit settings
Corey Hickey reported that on using setuid to change the uid of a
rt process, the process would be unkillable and not be running.
This is because there was no rt runtime for that user group. Add
in a check to see if a user can attach an rt task to its task group.
On failure, return EINVAL, which is also returned in
CONFIG_CGROUP_SCHED.
Reported-by: Corey Hickey <bugfood-ml@fatooh.org>
Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index f145c415bc16..37f458e6882a 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -559,7 +559,7 @@ error: | |||
559 | abort_creds(new); | 559 | abort_creds(new); |
560 | return retval; | 560 | return retval; |
561 | } | 561 | } |
562 | 562 | ||
563 | /* | 563 | /* |
564 | * change the user struct in a credentials set to match the new UID | 564 | * change the user struct in a credentials set to match the new UID |
565 | */ | 565 | */ |
@@ -571,6 +571,11 @@ static int set_user(struct cred *new) | |||
571 | if (!new_user) | 571 | if (!new_user) |
572 | return -EAGAIN; | 572 | return -EAGAIN; |
573 | 573 | ||
574 | if (!task_can_switch_user(new_user, current)) { | ||
575 | free_uid(new_user); | ||
576 | return -EINVAL; | ||
577 | } | ||
578 | |||
574 | if (atomic_read(&new_user->processes) >= | 579 | if (atomic_read(&new_user->processes) >= |
575 | current->signal->rlim[RLIMIT_NPROC].rlim_cur && | 580 | current->signal->rlim[RLIMIT_NPROC].rlim_cur && |
576 | new_user != INIT_USER) { | 581 | new_user != INIT_USER) { |
@@ -631,10 +636,11 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) | |||
631 | goto error; | 636 | goto error; |
632 | } | 637 | } |
633 | 638 | ||
634 | retval = -EAGAIN; | 639 | if (new->uid != old->uid) { |
635 | if (new->uid != old->uid && set_user(new) < 0) | 640 | retval = set_user(new); |
636 | goto error; | 641 | if (retval < 0) |
637 | 642 | goto error; | |
643 | } | ||
638 | if (ruid != (uid_t) -1 || | 644 | if (ruid != (uid_t) -1 || |
639 | (euid != (uid_t) -1 && euid != old->uid)) | 645 | (euid != (uid_t) -1 && euid != old->uid)) |
640 | new->suid = new->euid; | 646 | new->suid = new->euid; |
@@ -680,9 +686,10 @@ SYSCALL_DEFINE1(setuid, uid_t, uid) | |||
680 | retval = -EPERM; | 686 | retval = -EPERM; |
681 | if (capable(CAP_SETUID)) { | 687 | if (capable(CAP_SETUID)) { |
682 | new->suid = new->uid = uid; | 688 | new->suid = new->uid = uid; |
683 | if (uid != old->uid && set_user(new) < 0) { | 689 | if (uid != old->uid) { |
684 | retval = -EAGAIN; | 690 | retval = set_user(new); |
685 | goto error; | 691 | if (retval < 0) |
692 | goto error; | ||
686 | } | 693 | } |
687 | } else if (uid != old->uid && uid != new->suid) { | 694 | } else if (uid != old->uid && uid != new->suid) { |
688 | goto error; | 695 | goto error; |
@@ -734,11 +741,13 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) | |||
734 | goto error; | 741 | goto error; |
735 | } | 742 | } |
736 | 743 | ||
737 | retval = -EAGAIN; | ||
738 | if (ruid != (uid_t) -1) { | 744 | if (ruid != (uid_t) -1) { |
739 | new->uid = ruid; | 745 | new->uid = ruid; |
740 | if (ruid != old->uid && set_user(new) < 0) | 746 | if (ruid != old->uid) { |
741 | goto error; | 747 | retval = set_user(new); |
748 | if (retval < 0) | ||
749 | goto error; | ||
750 | } | ||
742 | } | 751 | } |
743 | if (euid != (uid_t) -1) | 752 | if (euid != (uid_t) -1) |
744 | new->euid = euid; | 753 | new->euid = euid; |