diff options
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; |
