diff options
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 68 |
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 | ||
225 | EXPORT_SYMBOL(unregister_reboot_notifier); | 225 | EXPORT_SYMBOL(unregister_reboot_notifier); |
226 | 226 | ||
227 | #ifndef CONFIG_SECURITY | ||
228 | int 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 | } | ||
236 | EXPORT_SYMBOL(capable); | ||
237 | #endif | ||
238 | |||
239 | static int set_one_prio(struct task_struct *p, int niceval, int error) | 227 | static 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 */ |
1376 | int groups_search(struct group_info *group_info, gid_t grp) | 1364 | int 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 | } |
1448 | out: | 1435 | out: |
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 | |||
1630 | asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim) | 1612 | asmlinkage 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(¤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 | ||