diff options
Diffstat (limited to 'kernel/sys.c')
| -rw-r--r-- | kernel/sys.c | 47 |
1 files changed, 24 insertions, 23 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index e7dc0e10a485..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; |
| @@ -1525,22 +1534,14 @@ SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim) | |||
| 1525 | return -EINVAL; | 1534 | return -EINVAL; |
| 1526 | if (copy_from_user(&new_rlim, rlim, sizeof(*rlim))) | 1535 | if (copy_from_user(&new_rlim, rlim, sizeof(*rlim))) |
| 1527 | return -EFAULT; | 1536 | return -EFAULT; |
| 1537 | if (new_rlim.rlim_cur > new_rlim.rlim_max) | ||
| 1538 | return -EINVAL; | ||
| 1528 | old_rlim = current->signal->rlim + resource; | 1539 | old_rlim = current->signal->rlim + resource; |
| 1529 | if ((new_rlim.rlim_max > old_rlim->rlim_max) && | 1540 | if ((new_rlim.rlim_max > old_rlim->rlim_max) && |
| 1530 | !capable(CAP_SYS_RESOURCE)) | 1541 | !capable(CAP_SYS_RESOURCE)) |
| 1531 | return -EPERM; | 1542 | return -EPERM; |
| 1532 | 1543 | if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open) | |
| 1533 | if (resource == RLIMIT_NOFILE) { | 1544 | return -EPERM; |
| 1534 | if (new_rlim.rlim_max == RLIM_INFINITY) | ||
| 1535 | new_rlim.rlim_max = sysctl_nr_open; | ||
| 1536 | if (new_rlim.rlim_cur == RLIM_INFINITY) | ||
| 1537 | new_rlim.rlim_cur = sysctl_nr_open; | ||
| 1538 | if (new_rlim.rlim_max > sysctl_nr_open) | ||
| 1539 | return -EPERM; | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | if (new_rlim.rlim_cur > new_rlim.rlim_max) | ||
| 1543 | return -EINVAL; | ||
| 1544 | 1545 | ||
| 1545 | retval = security_task_setrlimit(resource, &new_rlim); | 1546 | retval = security_task_setrlimit(resource, &new_rlim); |
| 1546 | if (retval) | 1547 | if (retval) |
