diff options
Diffstat (limited to 'kernel/sys.c')
| -rw-r--r-- | kernel/sys.c | 122 |
1 files changed, 108 insertions, 14 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 8a94b4eabcaa..2855ee73acd0 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -886,7 +886,7 @@ SYSCALL_DEFINE0(getegid) | |||
| 886 | return from_kgid_munged(current_user_ns(), current_egid()); | 886 | return from_kgid_munged(current_user_ns(), current_egid()); |
| 887 | } | 887 | } |
| 888 | 888 | ||
| 889 | void do_sys_times(struct tms *tms) | 889 | static void do_sys_times(struct tms *tms) |
| 890 | { | 890 | { |
| 891 | u64 tgutime, tgstime, cutime, cstime; | 891 | u64 tgutime, tgstime, cutime, cstime; |
| 892 | 892 | ||
| @@ -912,6 +912,32 @@ SYSCALL_DEFINE1(times, struct tms __user *, tbuf) | |||
| 912 | return (long) jiffies_64_to_clock_t(get_jiffies_64()); | 912 | return (long) jiffies_64_to_clock_t(get_jiffies_64()); |
| 913 | } | 913 | } |
| 914 | 914 | ||
| 915 | #ifdef CONFIG_COMPAT | ||
| 916 | static compat_clock_t clock_t_to_compat_clock_t(clock_t x) | ||
| 917 | { | ||
| 918 | return compat_jiffies_to_clock_t(clock_t_to_jiffies(x)); | ||
| 919 | } | ||
| 920 | |||
| 921 | COMPAT_SYSCALL_DEFINE1(times, struct compat_tms __user *, tbuf) | ||
| 922 | { | ||
| 923 | if (tbuf) { | ||
| 924 | struct tms tms; | ||
| 925 | struct compat_tms tmp; | ||
| 926 | |||
| 927 | do_sys_times(&tms); | ||
| 928 | /* Convert our struct tms to the compat version. */ | ||
| 929 | tmp.tms_utime = clock_t_to_compat_clock_t(tms.tms_utime); | ||
| 930 | tmp.tms_stime = clock_t_to_compat_clock_t(tms.tms_stime); | ||
| 931 | tmp.tms_cutime = clock_t_to_compat_clock_t(tms.tms_cutime); | ||
| 932 | tmp.tms_cstime = clock_t_to_compat_clock_t(tms.tms_cstime); | ||
| 933 | if (copy_to_user(tbuf, &tmp, sizeof(tmp))) | ||
| 934 | return -EFAULT; | ||
| 935 | } | ||
| 936 | force_successful_syscall_return(); | ||
| 937 | return compat_jiffies_to_clock_t(jiffies); | ||
| 938 | } | ||
| 939 | #endif | ||
| 940 | |||
| 915 | /* | 941 | /* |
| 916 | * This needs some heavy checking ... | 942 | * This needs some heavy checking ... |
| 917 | * I just haven't the stomach for it. I also don't fully | 943 | * I just haven't the stomach for it. I also don't fully |
| @@ -1306,6 +1332,54 @@ SYSCALL_DEFINE2(getrlimit, unsigned int, resource, struct rlimit __user *, rlim) | |||
| 1306 | return ret; | 1332 | return ret; |
| 1307 | } | 1333 | } |
| 1308 | 1334 | ||
| 1335 | #ifdef CONFIG_COMPAT | ||
| 1336 | |||
| 1337 | COMPAT_SYSCALL_DEFINE2(setrlimit, unsigned int, resource, | ||
| 1338 | struct compat_rlimit __user *, rlim) | ||
| 1339 | { | ||
| 1340 | struct rlimit r; | ||
| 1341 | struct compat_rlimit r32; | ||
| 1342 | |||
| 1343 | if (copy_from_user(&r32, rlim, sizeof(struct compat_rlimit))) | ||
| 1344 | return -EFAULT; | ||
| 1345 | |||
| 1346 | if (r32.rlim_cur == COMPAT_RLIM_INFINITY) | ||
| 1347 | r.rlim_cur = RLIM_INFINITY; | ||
| 1348 | else | ||
| 1349 | r.rlim_cur = r32.rlim_cur; | ||
| 1350 | if (r32.rlim_max == COMPAT_RLIM_INFINITY) | ||
| 1351 | r.rlim_max = RLIM_INFINITY; | ||
| 1352 | else | ||
| 1353 | r.rlim_max = r32.rlim_max; | ||
| 1354 | return do_prlimit(current, resource, &r, NULL); | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | COMPAT_SYSCALL_DEFINE2(getrlimit, unsigned int, resource, | ||
| 1358 | struct compat_rlimit __user *, rlim) | ||
| 1359 | { | ||
| 1360 | struct rlimit r; | ||
| 1361 | int ret; | ||
| 1362 | |||
| 1363 | ret = do_prlimit(current, resource, NULL, &r); | ||
| 1364 | if (!ret) { | ||
| 1365 | struct compat_rlimit r32; | ||
| 1366 | if (r.rlim_cur > COMPAT_RLIM_INFINITY) | ||
| 1367 | r32.rlim_cur = COMPAT_RLIM_INFINITY; | ||
| 1368 | else | ||
| 1369 | r32.rlim_cur = r.rlim_cur; | ||
| 1370 | if (r.rlim_max > COMPAT_RLIM_INFINITY) | ||
| 1371 | r32.rlim_max = COMPAT_RLIM_INFINITY; | ||
| 1372 | else | ||
| 1373 | r32.rlim_max = r.rlim_max; | ||
| 1374 | |||
| 1375 | if (copy_to_user(rlim, &r32, sizeof(struct compat_rlimit))) | ||
| 1376 | return -EFAULT; | ||
| 1377 | } | ||
| 1378 | return ret; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | #endif | ||
| 1382 | |||
| 1309 | #ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT | 1383 | #ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT |
| 1310 | 1384 | ||
| 1311 | /* | 1385 | /* |
| @@ -1328,6 +1402,30 @@ SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource, | |||
| 1328 | return copy_to_user(rlim, &x, sizeof(x)) ? -EFAULT : 0; | 1402 | return copy_to_user(rlim, &x, sizeof(x)) ? -EFAULT : 0; |
| 1329 | } | 1403 | } |
| 1330 | 1404 | ||
| 1405 | #ifdef CONFIG_COMPAT | ||
| 1406 | COMPAT_SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource, | ||
| 1407 | struct compat_rlimit __user *, rlim) | ||
| 1408 | { | ||
| 1409 | struct rlimit r; | ||
| 1410 | |||
| 1411 | if (resource >= RLIM_NLIMITS) | ||
| 1412 | return -EINVAL; | ||
| 1413 | |||
| 1414 | task_lock(current->group_leader); | ||
| 1415 | r = current->signal->rlim[resource]; | ||
| 1416 | task_unlock(current->group_leader); | ||
| 1417 | if (r.rlim_cur > 0x7FFFFFFF) | ||
| 1418 | r.rlim_cur = 0x7FFFFFFF; | ||
| 1419 | if (r.rlim_max > 0x7FFFFFFF) | ||
| 1420 | r.rlim_max = 0x7FFFFFFF; | ||
| 1421 | |||
| 1422 | if (put_user(r.rlim_cur, &rlim->rlim_cur) || | ||
| 1423 | put_user(r.rlim_max, &rlim->rlim_max)) | ||
| 1424 | return -EFAULT; | ||
| 1425 | return 0; | ||
| 1426 | } | ||
| 1427 | #endif | ||
| 1428 | |||
| 1331 | #endif | 1429 | #endif |
| 1332 | 1430 | ||
| 1333 | static inline bool rlim64_is_infinity(__u64 rlim64) | 1431 | static inline bool rlim64_is_infinity(__u64 rlim64) |
| @@ -1552,7 +1650,7 @@ static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r) | |||
| 1552 | r->ru_oublock += task_io_get_oublock(t); | 1650 | r->ru_oublock += task_io_get_oublock(t); |
| 1553 | } | 1651 | } |
| 1554 | 1652 | ||
| 1555 | static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | 1653 | void getrusage(struct task_struct *p, int who, struct rusage *r) |
| 1556 | { | 1654 | { |
| 1557 | struct task_struct *t; | 1655 | struct task_struct *t; |
| 1558 | unsigned long flags; | 1656 | unsigned long flags; |
| @@ -1626,20 +1724,16 @@ out: | |||
| 1626 | r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */ | 1724 | r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */ |
| 1627 | } | 1725 | } |
| 1628 | 1726 | ||
| 1629 | int getrusage(struct task_struct *p, int who, struct rusage __user *ru) | 1727 | SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru) |
| 1630 | { | 1728 | { |
| 1631 | struct rusage r; | 1729 | struct rusage r; |
| 1632 | 1730 | ||
| 1633 | k_getrusage(p, who, &r); | ||
| 1634 | return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; | ||
| 1635 | } | ||
| 1636 | |||
| 1637 | SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru) | ||
| 1638 | { | ||
| 1639 | if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN && | 1731 | if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN && |
| 1640 | who != RUSAGE_THREAD) | 1732 | who != RUSAGE_THREAD) |
| 1641 | return -EINVAL; | 1733 | return -EINVAL; |
| 1642 | return getrusage(current, who, ru); | 1734 | |
| 1735 | getrusage(current, who, &r); | ||
| 1736 | return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; | ||
| 1643 | } | 1737 | } |
| 1644 | 1738 | ||
| 1645 | #ifdef CONFIG_COMPAT | 1739 | #ifdef CONFIG_COMPAT |
| @@ -1651,7 +1745,7 @@ COMPAT_SYSCALL_DEFINE2(getrusage, int, who, struct compat_rusage __user *, ru) | |||
| 1651 | who != RUSAGE_THREAD) | 1745 | who != RUSAGE_THREAD) |
| 1652 | return -EINVAL; | 1746 | return -EINVAL; |
| 1653 | 1747 | ||
| 1654 | k_getrusage(current, who, &r); | 1748 | getrusage(current, who, &r); |
| 1655 | return put_compat_rusage(&r, ru); | 1749 | return put_compat_rusage(&r, ru); |
| 1656 | } | 1750 | } |
| 1657 | #endif | 1751 | #endif |
| @@ -2266,7 +2360,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 2266 | case PR_GET_THP_DISABLE: | 2360 | case PR_GET_THP_DISABLE: |
| 2267 | if (arg2 || arg3 || arg4 || arg5) | 2361 | if (arg2 || arg3 || arg4 || arg5) |
| 2268 | return -EINVAL; | 2362 | return -EINVAL; |
| 2269 | error = !!(me->mm->def_flags & VM_NOHUGEPAGE); | 2363 | error = !!test_bit(MMF_DISABLE_THP, &me->mm->flags); |
| 2270 | break; | 2364 | break; |
| 2271 | case PR_SET_THP_DISABLE: | 2365 | case PR_SET_THP_DISABLE: |
| 2272 | if (arg3 || arg4 || arg5) | 2366 | if (arg3 || arg4 || arg5) |
| @@ -2274,9 +2368,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 2274 | if (down_write_killable(&me->mm->mmap_sem)) | 2368 | if (down_write_killable(&me->mm->mmap_sem)) |
| 2275 | return -EINTR; | 2369 | return -EINTR; |
| 2276 | if (arg2) | 2370 | if (arg2) |
| 2277 | me->mm->def_flags |= VM_NOHUGEPAGE; | 2371 | set_bit(MMF_DISABLE_THP, &me->mm->flags); |
| 2278 | else | 2372 | else |
| 2279 | me->mm->def_flags &= ~VM_NOHUGEPAGE; | 2373 | clear_bit(MMF_DISABLE_THP, &me->mm->flags); |
| 2280 | up_write(&me->mm->mmap_sem); | 2374 | up_write(&me->mm->mmap_sem); |
| 2281 | break; | 2375 | break; |
| 2282 | case PR_MPX_ENABLE_MANAGEMENT: | 2376 | case PR_MPX_ENABLE_MANAGEMENT: |
