diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sys.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index c0fcad9f826c..9bdf94f3ae29 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1630,20 +1630,21 @@ asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *r | |||
1630 | asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim) | 1630 | asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim) |
1631 | { | 1631 | { |
1632 | struct rlimit new_rlim, *old_rlim; | 1632 | struct rlimit new_rlim, *old_rlim; |
1633 | unsigned long it_prof_secs; | ||
1633 | int retval; | 1634 | int retval; |
1634 | 1635 | ||
1635 | if (resource >= RLIM_NLIMITS) | 1636 | if (resource >= RLIM_NLIMITS) |
1636 | return -EINVAL; | 1637 | return -EINVAL; |
1637 | if(copy_from_user(&new_rlim, rlim, sizeof(*rlim))) | 1638 | if (copy_from_user(&new_rlim, rlim, sizeof(*rlim))) |
1638 | return -EFAULT; | 1639 | return -EFAULT; |
1639 | if (new_rlim.rlim_cur > new_rlim.rlim_max) | 1640 | if (new_rlim.rlim_cur > new_rlim.rlim_max) |
1640 | return -EINVAL; | 1641 | return -EINVAL; |
1641 | old_rlim = current->signal->rlim + resource; | 1642 | old_rlim = current->signal->rlim + resource; |
1642 | if ((new_rlim.rlim_max > old_rlim->rlim_max) && | 1643 | if ((new_rlim.rlim_max > old_rlim->rlim_max) && |
1643 | !capable(CAP_SYS_RESOURCE)) | 1644 | !capable(CAP_SYS_RESOURCE)) |
1644 | return -EPERM; | 1645 | return -EPERM; |
1645 | if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > NR_OPEN) | 1646 | if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > NR_OPEN) |
1646 | return -EPERM; | 1647 | return -EPERM; |
1647 | 1648 | ||
1648 | retval = security_task_setrlimit(resource, &new_rlim); | 1649 | retval = security_task_setrlimit(resource, &new_rlim); |
1649 | if (retval) | 1650 | if (retval) |
@@ -1653,19 +1654,22 @@ asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim) | |||
1653 | *old_rlim = new_rlim; | 1654 | *old_rlim = new_rlim; |
1654 | task_unlock(current->group_leader); | 1655 | task_unlock(current->group_leader); |
1655 | 1656 | ||
1656 | if (resource == RLIMIT_CPU && new_rlim.rlim_cur != RLIM_INFINITY && | 1657 | if (resource != RLIMIT_CPU) |
1657 | (cputime_eq(current->signal->it_prof_expires, cputime_zero) || | 1658 | goto out; |
1658 | new_rlim.rlim_cur <= cputime_to_secs( | 1659 | if (new_rlim.rlim_cur == RLIM_INFINITY) |
1659 | current->signal->it_prof_expires))) { | 1660 | goto out; |
1661 | |||
1662 | it_prof_secs = cputime_to_secs(current->signal->it_prof_expires); | ||
1663 | if (it_prof_secs == 0 || new_rlim.rlim_cur <= it_prof_secs) { | ||
1660 | cputime_t cputime = secs_to_cputime(new_rlim.rlim_cur); | 1664 | cputime_t cputime = secs_to_cputime(new_rlim.rlim_cur); |
1665 | |||
1661 | read_lock(&tasklist_lock); | 1666 | read_lock(&tasklist_lock); |
1662 | spin_lock_irq(¤t->sighand->siglock); | 1667 | spin_lock_irq(¤t->sighand->siglock); |
1663 | set_process_cpu_timer(current, CPUCLOCK_PROF, | 1668 | set_process_cpu_timer(current, CPUCLOCK_PROF, &cputime, NULL); |
1664 | &cputime, NULL); | ||
1665 | spin_unlock_irq(¤t->sighand->siglock); | 1669 | spin_unlock_irq(¤t->sighand->siglock); |
1666 | read_unlock(&tasklist_lock); | 1670 | read_unlock(&tasklist_lock); |
1667 | } | 1671 | } |
1668 | 1672 | out: | |
1669 | return 0; | 1673 | return 0; |
1670 | } | 1674 | } |
1671 | 1675 | ||