aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sys.c')
-rw-r--r--kernel/sys.c68
1 files changed, 36 insertions, 32 deletions
diff --git a/kernel/sys.c b/kernel/sys.c
index c0fcad9f826c..38bc73ede2ba 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -224,18 +224,6 @@ int unregister_reboot_notifier(struct notifier_block * nb)
224 224
225EXPORT_SYMBOL(unregister_reboot_notifier); 225EXPORT_SYMBOL(unregister_reboot_notifier);
226 226
227#ifndef CONFIG_SECURITY
228int capable(int cap)
229{
230 if (cap_raised(current->cap_effective, cap)) {
231 current->flags |= PF_SUPERPRIV;
232 return 1;
233 }
234 return 0;
235}
236EXPORT_SYMBOL(capable);
237#endif
238
239static int set_one_prio(struct task_struct *p, int niceval, int error) 227static int set_one_prio(struct task_struct *p, int niceval, int error)
240{ 228{
241 int no_nice; 229 int no_nice;
@@ -1375,7 +1363,7 @@ static void groups_sort(struct group_info *group_info)
1375/* a simple bsearch */ 1363/* a simple bsearch */
1376int groups_search(struct group_info *group_info, gid_t grp) 1364int groups_search(struct group_info *group_info, gid_t grp)
1377{ 1365{
1378 int left, right; 1366 unsigned int left, right;
1379 1367
1380 if (!group_info) 1368 if (!group_info)
1381 return 0; 1369 return 0;
@@ -1383,7 +1371,7 @@ int groups_search(struct group_info *group_info, gid_t grp)
1383 left = 0; 1371 left = 0;
1384 right = group_info->ngroups; 1372 right = group_info->ngroups;
1385 while (left < right) { 1373 while (left < right) {
1386 int mid = (left+right)/2; 1374 unsigned int mid = (left+right)/2;
1387 int cmp = grp - GROUP_AT(group_info, mid); 1375 int cmp = grp - GROUP_AT(group_info, mid);
1388 if (cmp > 0) 1376 if (cmp > 0)
1389 left = mid + 1; 1377 left = mid + 1;
@@ -1433,7 +1421,6 @@ asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
1433 return -EINVAL; 1421 return -EINVAL;
1434 1422
1435 /* no need to grab task_lock here; it cannot change */ 1423 /* no need to grab task_lock here; it cannot change */
1436 get_group_info(current->group_info);
1437 i = current->group_info->ngroups; 1424 i = current->group_info->ngroups;
1438 if (gidsetsize) { 1425 if (gidsetsize) {
1439 if (i > gidsetsize) { 1426 if (i > gidsetsize) {
@@ -1446,7 +1433,6 @@ asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
1446 } 1433 }
1447 } 1434 }
1448out: 1435out:
1449 put_group_info(current->group_info);
1450 return i; 1436 return i;
1451} 1437}
1452 1438
@@ -1487,9 +1473,7 @@ int in_group_p(gid_t grp)
1487{ 1473{
1488 int retval = 1; 1474 int retval = 1;
1489 if (grp != current->fsgid) { 1475 if (grp != current->fsgid) {
1490 get_group_info(current->group_info);
1491 retval = groups_search(current->group_info, grp); 1476 retval = groups_search(current->group_info, grp);
1492 put_group_info(current->group_info);
1493 } 1477 }
1494 return retval; 1478 return retval;
1495} 1479}
@@ -1500,9 +1484,7 @@ int in_egroup_p(gid_t grp)
1500{ 1484{
1501 int retval = 1; 1485 int retval = 1;
1502 if (grp != current->egid) { 1486 if (grp != current->egid) {
1503 get_group_info(current->group_info);
1504 retval = groups_search(current->group_info, grp); 1487 retval = groups_search(current->group_info, grp);
1505 put_group_info(current->group_info);
1506 } 1488 }
1507 return retval; 1489 return retval;
1508} 1490}
@@ -1630,20 +1612,21 @@ asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *r
1630asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim) 1612asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim)
1631{ 1613{
1632 struct rlimit new_rlim, *old_rlim; 1614 struct rlimit new_rlim, *old_rlim;
1615 unsigned long it_prof_secs;
1633 int retval; 1616 int retval;
1634 1617
1635 if (resource >= RLIM_NLIMITS) 1618 if (resource >= RLIM_NLIMITS)
1636 return -EINVAL; 1619 return -EINVAL;
1637 if(copy_from_user(&new_rlim, rlim, sizeof(*rlim))) 1620 if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
1638 return -EFAULT; 1621 return -EFAULT;
1639 if (new_rlim.rlim_cur > new_rlim.rlim_max) 1622 if (new_rlim.rlim_cur > new_rlim.rlim_max)
1640 return -EINVAL; 1623 return -EINVAL;
1641 old_rlim = current->signal->rlim + resource; 1624 old_rlim = current->signal->rlim + resource;
1642 if ((new_rlim.rlim_max > old_rlim->rlim_max) && 1625 if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
1643 !capable(CAP_SYS_RESOURCE)) 1626 !capable(CAP_SYS_RESOURCE))
1644 return -EPERM; 1627 return -EPERM;
1645 if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > NR_OPEN) 1628 if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > NR_OPEN)
1646 return -EPERM; 1629 return -EPERM;
1647 1630
1648 retval = security_task_setrlimit(resource, &new_rlim); 1631 retval = security_task_setrlimit(resource, &new_rlim);
1649 if (retval) 1632 if (retval)
@@ -1653,19 +1636,40 @@ asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim)
1653 *old_rlim = new_rlim; 1636 *old_rlim = new_rlim;
1654 task_unlock(current->group_leader); 1637 task_unlock(current->group_leader);
1655 1638
1656 if (resource == RLIMIT_CPU && new_rlim.rlim_cur != RLIM_INFINITY && 1639 if (resource != RLIMIT_CPU)
1657 (cputime_eq(current->signal->it_prof_expires, cputime_zero) || 1640 goto out;
1658 new_rlim.rlim_cur <= cputime_to_secs( 1641
1659 current->signal->it_prof_expires))) { 1642 /*
1660 cputime_t cputime = secs_to_cputime(new_rlim.rlim_cur); 1643 * RLIMIT_CPU handling. Note that the kernel fails to return an error
1644 * code if it rejected the user's attempt to set RLIMIT_CPU. This is a
1645 * very long-standing error, and fixing it now risks breakage of
1646 * applications, so we live with it
1647 */
1648 if (new_rlim.rlim_cur == RLIM_INFINITY)
1649 goto out;
1650
1651 it_prof_secs = cputime_to_secs(current->signal->it_prof_expires);
1652 if (it_prof_secs == 0 || new_rlim.rlim_cur <= it_prof_secs) {
1653 unsigned long rlim_cur = new_rlim.rlim_cur;
1654 cputime_t cputime;
1655
1656 if (rlim_cur == 0) {
1657 /*
1658 * The caller is asking for an immediate RLIMIT_CPU
1659 * expiry. But we use the zero value to mean "it was
1660 * never set". So let's cheat and make it one second
1661 * instead
1662 */
1663 rlim_cur = 1;
1664 }
1665 cputime = secs_to_cputime(rlim_cur);
1661 read_lock(&tasklist_lock); 1666 read_lock(&tasklist_lock);
1662 spin_lock_irq(&current->sighand->siglock); 1667 spin_lock_irq(&current->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(&current->sighand->siglock); 1669 spin_unlock_irq(&current->sighand->siglock);
1666 read_unlock(&tasklist_lock); 1670 read_unlock(&tasklist_lock);
1667 } 1671 }
1668 1672out:
1669 return 0; 1673 return 0;
1670} 1674}
1671 1675