diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 14:35:36 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-10 14:35:36 -0500 |
| commit | 4ba24fef3eb3b142197135223b90ced2f319cd53 (patch) | |
| tree | a20c125b27740ec7b4c761b11d801108e1b316b2 /kernel/sys.c | |
| parent | 47c1ffb2b6b630894e9a16442611c056ab21c057 (diff) | |
| parent | 98a4a59ee31a12105a2b84f5b8b515ac2cb208ef (diff) | |
Merge branch 'next' into for-linus
Prepare first round of input updates for 3.20.
Diffstat (limited to 'kernel/sys.c')
| -rw-r--r-- | kernel/sys.c | 503 |
1 files changed, 354 insertions, 149 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index ce8129192a26..a8c9f5a7dda6 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -62,28 +62,28 @@ | |||
| 62 | #include <asm/unistd.h> | 62 | #include <asm/unistd.h> |
| 63 | 63 | ||
| 64 | #ifndef SET_UNALIGN_CTL | 64 | #ifndef SET_UNALIGN_CTL |
| 65 | # define SET_UNALIGN_CTL(a,b) (-EINVAL) | 65 | # define SET_UNALIGN_CTL(a, b) (-EINVAL) |
| 66 | #endif | 66 | #endif |
| 67 | #ifndef GET_UNALIGN_CTL | 67 | #ifndef GET_UNALIGN_CTL |
| 68 | # define GET_UNALIGN_CTL(a,b) (-EINVAL) | 68 | # define GET_UNALIGN_CTL(a, b) (-EINVAL) |
| 69 | #endif | 69 | #endif |
| 70 | #ifndef SET_FPEMU_CTL | 70 | #ifndef SET_FPEMU_CTL |
| 71 | # define SET_FPEMU_CTL(a,b) (-EINVAL) | 71 | # define SET_FPEMU_CTL(a, b) (-EINVAL) |
| 72 | #endif | 72 | #endif |
| 73 | #ifndef GET_FPEMU_CTL | 73 | #ifndef GET_FPEMU_CTL |
| 74 | # define GET_FPEMU_CTL(a,b) (-EINVAL) | 74 | # define GET_FPEMU_CTL(a, b) (-EINVAL) |
| 75 | #endif | 75 | #endif |
| 76 | #ifndef SET_FPEXC_CTL | 76 | #ifndef SET_FPEXC_CTL |
| 77 | # define SET_FPEXC_CTL(a,b) (-EINVAL) | 77 | # define SET_FPEXC_CTL(a, b) (-EINVAL) |
| 78 | #endif | 78 | #endif |
| 79 | #ifndef GET_FPEXC_CTL | 79 | #ifndef GET_FPEXC_CTL |
| 80 | # define GET_FPEXC_CTL(a,b) (-EINVAL) | 80 | # define GET_FPEXC_CTL(a, b) (-EINVAL) |
| 81 | #endif | 81 | #endif |
| 82 | #ifndef GET_ENDIAN | 82 | #ifndef GET_ENDIAN |
| 83 | # define GET_ENDIAN(a,b) (-EINVAL) | 83 | # define GET_ENDIAN(a, b) (-EINVAL) |
| 84 | #endif | 84 | #endif |
| 85 | #ifndef SET_ENDIAN | 85 | #ifndef SET_ENDIAN |
| 86 | # define SET_ENDIAN(a,b) (-EINVAL) | 86 | # define SET_ENDIAN(a, b) (-EINVAL) |
| 87 | #endif | 87 | #endif |
| 88 | #ifndef GET_TSC_CTL | 88 | #ifndef GET_TSC_CTL |
| 89 | # define GET_TSC_CTL(a) (-EINVAL) | 89 | # define GET_TSC_CTL(a) (-EINVAL) |
| @@ -91,6 +91,12 @@ | |||
| 91 | #ifndef SET_TSC_CTL | 91 | #ifndef SET_TSC_CTL |
| 92 | # define SET_TSC_CTL(a) (-EINVAL) | 92 | # define SET_TSC_CTL(a) (-EINVAL) |
| 93 | #endif | 93 | #endif |
| 94 | #ifndef MPX_ENABLE_MANAGEMENT | ||
| 95 | # define MPX_ENABLE_MANAGEMENT(a) (-EINVAL) | ||
| 96 | #endif | ||
| 97 | #ifndef MPX_DISABLE_MANAGEMENT | ||
| 98 | # define MPX_DISABLE_MANAGEMENT(a) (-EINVAL) | ||
| 99 | #endif | ||
| 94 | 100 | ||
| 95 | /* | 101 | /* |
| 96 | * this is where the system-wide overflow UID and GID are defined, for | 102 | * this is where the system-wide overflow UID and GID are defined, for |
| @@ -182,39 +188,40 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval) | |||
| 182 | rcu_read_lock(); | 188 | rcu_read_lock(); |
| 183 | read_lock(&tasklist_lock); | 189 | read_lock(&tasklist_lock); |
| 184 | switch (which) { | 190 | switch (which) { |
| 185 | case PRIO_PROCESS: | 191 | case PRIO_PROCESS: |
| 186 | if (who) | 192 | if (who) |
| 187 | p = find_task_by_vpid(who); | 193 | p = find_task_by_vpid(who); |
| 188 | else | 194 | else |
| 189 | p = current; | 195 | p = current; |
| 190 | if (p) | 196 | if (p) |
| 191 | error = set_one_prio(p, niceval, error); | 197 | error = set_one_prio(p, niceval, error); |
| 192 | break; | 198 | break; |
| 193 | case PRIO_PGRP: | 199 | case PRIO_PGRP: |
| 194 | if (who) | 200 | if (who) |
| 195 | pgrp = find_vpid(who); | 201 | pgrp = find_vpid(who); |
| 196 | else | 202 | else |
| 197 | pgrp = task_pgrp(current); | 203 | pgrp = task_pgrp(current); |
| 198 | do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { | 204 | do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { |
| 199 | error = set_one_prio(p, niceval, error); | 205 | error = set_one_prio(p, niceval, error); |
| 200 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | 206 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); |
| 201 | break; | 207 | break; |
| 202 | case PRIO_USER: | 208 | case PRIO_USER: |
| 203 | uid = make_kuid(cred->user_ns, who); | 209 | uid = make_kuid(cred->user_ns, who); |
| 204 | user = cred->user; | 210 | user = cred->user; |
| 205 | if (!who) | 211 | if (!who) |
| 206 | uid = cred->uid; | 212 | uid = cred->uid; |
| 207 | else if (!uid_eq(uid, cred->uid) && | 213 | else if (!uid_eq(uid, cred->uid)) { |
| 208 | !(user = find_user(uid))) | 214 | user = find_user(uid); |
| 215 | if (!user) | ||
| 209 | goto out_unlock; /* No processes for this user */ | 216 | goto out_unlock; /* No processes for this user */ |
| 210 | 217 | } | |
| 211 | do_each_thread(g, p) { | 218 | do_each_thread(g, p) { |
| 212 | if (uid_eq(task_uid(p), uid)) | 219 | if (uid_eq(task_uid(p), uid)) |
| 213 | error = set_one_prio(p, niceval, error); | 220 | error = set_one_prio(p, niceval, error); |
| 214 | } while_each_thread(g, p); | 221 | } while_each_thread(g, p); |
| 215 | if (!uid_eq(uid, cred->uid)) | 222 | if (!uid_eq(uid, cred->uid)) |
| 216 | free_uid(user); /* For find_user() */ | 223 | free_uid(user); /* For find_user() */ |
| 217 | break; | 224 | break; |
| 218 | } | 225 | } |
| 219 | out_unlock: | 226 | out_unlock: |
| 220 | read_unlock(&tasklist_lock); | 227 | read_unlock(&tasklist_lock); |
| @@ -244,47 +251,48 @@ SYSCALL_DEFINE2(getpriority, int, which, int, who) | |||
| 244 | rcu_read_lock(); | 251 | rcu_read_lock(); |
| 245 | read_lock(&tasklist_lock); | 252 | read_lock(&tasklist_lock); |
| 246 | switch (which) { | 253 | switch (which) { |
| 247 | case PRIO_PROCESS: | 254 | case PRIO_PROCESS: |
| 248 | if (who) | 255 | if (who) |
| 249 | p = find_task_by_vpid(who); | 256 | p = find_task_by_vpid(who); |
| 250 | else | 257 | else |
| 251 | p = current; | 258 | p = current; |
| 252 | if (p) { | 259 | if (p) { |
| 260 | niceval = nice_to_rlimit(task_nice(p)); | ||
| 261 | if (niceval > retval) | ||
| 262 | retval = niceval; | ||
| 263 | } | ||
| 264 | break; | ||
| 265 | case PRIO_PGRP: | ||
| 266 | if (who) | ||
| 267 | pgrp = find_vpid(who); | ||
| 268 | else | ||
| 269 | pgrp = task_pgrp(current); | ||
| 270 | do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { | ||
| 271 | niceval = nice_to_rlimit(task_nice(p)); | ||
| 272 | if (niceval > retval) | ||
| 273 | retval = niceval; | ||
| 274 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | ||
| 275 | break; | ||
| 276 | case PRIO_USER: | ||
| 277 | uid = make_kuid(cred->user_ns, who); | ||
| 278 | user = cred->user; | ||
| 279 | if (!who) | ||
| 280 | uid = cred->uid; | ||
| 281 | else if (!uid_eq(uid, cred->uid)) { | ||
| 282 | user = find_user(uid); | ||
| 283 | if (!user) | ||
| 284 | goto out_unlock; /* No processes for this user */ | ||
| 285 | } | ||
| 286 | do_each_thread(g, p) { | ||
| 287 | if (uid_eq(task_uid(p), uid)) { | ||
| 253 | niceval = nice_to_rlimit(task_nice(p)); | 288 | niceval = nice_to_rlimit(task_nice(p)); |
| 254 | if (niceval > retval) | 289 | if (niceval > retval) |
| 255 | retval = niceval; | 290 | retval = niceval; |
| 256 | } | 291 | } |
| 257 | break; | 292 | } while_each_thread(g, p); |
| 258 | case PRIO_PGRP: | 293 | if (!uid_eq(uid, cred->uid)) |
| 259 | if (who) | 294 | free_uid(user); /* for find_user() */ |
| 260 | pgrp = find_vpid(who); | 295 | break; |
| 261 | else | ||
| 262 | pgrp = task_pgrp(current); | ||
| 263 | do_each_pid_thread(pgrp, PIDTYPE_PGID, p) { | ||
| 264 | niceval = nice_to_rlimit(task_nice(p)); | ||
| 265 | if (niceval > retval) | ||
| 266 | retval = niceval; | ||
| 267 | } while_each_pid_thread(pgrp, PIDTYPE_PGID, p); | ||
| 268 | break; | ||
| 269 | case PRIO_USER: | ||
| 270 | uid = make_kuid(cred->user_ns, who); | ||
| 271 | user = cred->user; | ||
| 272 | if (!who) | ||
| 273 | uid = cred->uid; | ||
| 274 | else if (!uid_eq(uid, cred->uid) && | ||
| 275 | !(user = find_user(uid))) | ||
| 276 | goto out_unlock; /* No processes for this user */ | ||
| 277 | |||
| 278 | do_each_thread(g, p) { | ||
| 279 | if (uid_eq(task_uid(p), uid)) { | ||
| 280 | niceval = nice_to_rlimit(task_nice(p)); | ||
| 281 | if (niceval > retval) | ||
| 282 | retval = niceval; | ||
| 283 | } | ||
| 284 | } while_each_thread(g, p); | ||
| 285 | if (!uid_eq(uid, cred->uid)) | ||
| 286 | free_uid(user); /* for find_user() */ | ||
| 287 | break; | ||
| 288 | } | 296 | } |
| 289 | out_unlock: | 297 | out_unlock: |
| 290 | read_unlock(&tasklist_lock); | 298 | read_unlock(&tasklist_lock); |
| @@ -306,7 +314,7 @@ out_unlock: | |||
| 306 | * | 314 | * |
| 307 | * The general idea is that a program which uses just setregid() will be | 315 | * The general idea is that a program which uses just setregid() will be |
| 308 | * 100% compatible with BSD. A program which uses just setgid() will be | 316 | * 100% compatible with BSD. A program which uses just setgid() will be |
| 309 | * 100% compatible with POSIX with saved IDs. | 317 | * 100% compatible with POSIX with saved IDs. |
| 310 | * | 318 | * |
| 311 | * SMP: There are not races, the GIDs are checked only by filesystem | 319 | * SMP: There are not races, the GIDs are checked only by filesystem |
| 312 | * operations (as far as semantic preservation is concerned). | 320 | * operations (as far as semantic preservation is concerned). |
| @@ -364,7 +372,7 @@ error: | |||
| 364 | } | 372 | } |
| 365 | 373 | ||
| 366 | /* | 374 | /* |
| 367 | * setgid() is implemented like SysV w/ SAVED_IDS | 375 | * setgid() is implemented like SysV w/ SAVED_IDS |
| 368 | * | 376 | * |
| 369 | * SMP: Same implicit races as above. | 377 | * SMP: Same implicit races as above. |
| 370 | */ | 378 | */ |
| @@ -442,7 +450,7 @@ static int set_user(struct cred *new) | |||
| 442 | * | 450 | * |
| 443 | * The general idea is that a program which uses just setreuid() will be | 451 | * The general idea is that a program which uses just setreuid() will be |
| 444 | * 100% compatible with BSD. A program which uses just setuid() will be | 452 | * 100% compatible with BSD. A program which uses just setuid() will be |
| 445 | * 100% compatible with POSIX with saved IDs. | 453 | * 100% compatible with POSIX with saved IDs. |
| 446 | */ | 454 | */ |
| 447 | SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) | 455 | SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid) |
| 448 | { | 456 | { |
| @@ -503,17 +511,17 @@ error: | |||
| 503 | abort_creds(new); | 511 | abort_creds(new); |
| 504 | return retval; | 512 | return retval; |
| 505 | } | 513 | } |
| 506 | 514 | ||
| 507 | /* | 515 | /* |
| 508 | * setuid() is implemented like SysV with SAVED_IDS | 516 | * setuid() is implemented like SysV with SAVED_IDS |
| 509 | * | 517 | * |
| 510 | * Note that SAVED_ID's is deficient in that a setuid root program | 518 | * Note that SAVED_ID's is deficient in that a setuid root program |
| 511 | * like sendmail, for example, cannot set its uid to be a normal | 519 | * like sendmail, for example, cannot set its uid to be a normal |
| 512 | * user and then switch back, because if you're root, setuid() sets | 520 | * user and then switch back, because if you're root, setuid() sets |
| 513 | * the saved uid too. If you don't like this, blame the bright people | 521 | * the saved uid too. If you don't like this, blame the bright people |
| 514 | * in the POSIX committee and/or USG. Note that the BSD-style setreuid() | 522 | * in the POSIX committee and/or USG. Note that the BSD-style setreuid() |
| 515 | * will allow a root program to temporarily drop privileges and be able to | 523 | * will allow a root program to temporarily drop privileges and be able to |
| 516 | * regain them by swapping the real and effective uid. | 524 | * regain them by swapping the real and effective uid. |
| 517 | */ | 525 | */ |
| 518 | SYSCALL_DEFINE1(setuid, uid_t, uid) | 526 | SYSCALL_DEFINE1(setuid, uid_t, uid) |
| 519 | { | 527 | { |
| @@ -637,10 +645,12 @@ SYSCALL_DEFINE3(getresuid, uid_t __user *, ruidp, uid_t __user *, euidp, uid_t _ | |||
| 637 | euid = from_kuid_munged(cred->user_ns, cred->euid); | 645 | euid = from_kuid_munged(cred->user_ns, cred->euid); |
| 638 | suid = from_kuid_munged(cred->user_ns, cred->suid); | 646 | suid = from_kuid_munged(cred->user_ns, cred->suid); |
| 639 | 647 | ||
| 640 | if (!(retval = put_user(ruid, ruidp)) && | 648 | retval = put_user(ruid, ruidp); |
| 641 | !(retval = put_user(euid, euidp))) | 649 | if (!retval) { |
| 642 | retval = put_user(suid, suidp); | 650 | retval = put_user(euid, euidp); |
| 643 | 651 | if (!retval) | |
| 652 | return put_user(suid, suidp); | ||
| 653 | } | ||
| 644 | return retval; | 654 | return retval; |
| 645 | } | 655 | } |
| 646 | 656 | ||
| @@ -709,9 +719,12 @@ SYSCALL_DEFINE3(getresgid, gid_t __user *, rgidp, gid_t __user *, egidp, gid_t _ | |||
| 709 | egid = from_kgid_munged(cred->user_ns, cred->egid); | 719 | egid = from_kgid_munged(cred->user_ns, cred->egid); |
| 710 | sgid = from_kgid_munged(cred->user_ns, cred->sgid); | 720 | sgid = from_kgid_munged(cred->user_ns, cred->sgid); |
| 711 | 721 | ||
| 712 | if (!(retval = put_user(rgid, rgidp)) && | 722 | retval = put_user(rgid, rgidp); |
| 713 | !(retval = put_user(egid, egidp))) | 723 | if (!retval) { |
| 714 | retval = put_user(sgid, sgidp); | 724 | retval = put_user(egid, egidp); |
| 725 | if (!retval) | ||
| 726 | retval = put_user(sgid, sgidp); | ||
| 727 | } | ||
| 715 | 728 | ||
| 716 | return retval; | 729 | return retval; |
| 717 | } | 730 | } |
| @@ -862,11 +875,9 @@ void do_sys_times(struct tms *tms) | |||
| 862 | { | 875 | { |
| 863 | cputime_t tgutime, tgstime, cutime, cstime; | 876 | cputime_t tgutime, tgstime, cutime, cstime; |
| 864 | 877 | ||
| 865 | spin_lock_irq(¤t->sighand->siglock); | ||
| 866 | thread_group_cputime_adjusted(current, &tgutime, &tgstime); | 878 | thread_group_cputime_adjusted(current, &tgutime, &tgstime); |
| 867 | cutime = current->signal->cutime; | 879 | cutime = current->signal->cutime; |
| 868 | cstime = current->signal->cstime; | 880 | cstime = current->signal->cstime; |
| 869 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 870 | tms->tms_utime = cputime_to_clock_t(tgutime); | 881 | tms->tms_utime = cputime_to_clock_t(tgutime); |
| 871 | tms->tms_stime = cputime_to_clock_t(tgstime); | 882 | tms->tms_stime = cputime_to_clock_t(tgstime); |
| 872 | tms->tms_cutime = cputime_to_clock_t(cutime); | 883 | tms->tms_cutime = cputime_to_clock_t(cutime); |
| @@ -1284,7 +1295,6 @@ SYSCALL_DEFINE2(getrlimit, unsigned int, resource, struct rlimit __user *, rlim) | |||
| 1284 | /* | 1295 | /* |
| 1285 | * Back compatibility for getrlimit. Needed for some apps. | 1296 | * Back compatibility for getrlimit. Needed for some apps. |
| 1286 | */ | 1297 | */ |
| 1287 | |||
| 1288 | SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource, | 1298 | SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource, |
| 1289 | struct rlimit __user *, rlim) | 1299 | struct rlimit __user *, rlim) |
| 1290 | { | 1300 | { |
| @@ -1299,7 +1309,7 @@ SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource, | |||
| 1299 | x.rlim_cur = 0x7FFFFFFF; | 1309 | x.rlim_cur = 0x7FFFFFFF; |
| 1300 | if (x.rlim_max > 0x7FFFFFFF) | 1310 | if (x.rlim_max > 0x7FFFFFFF) |
| 1301 | x.rlim_max = 0x7FFFFFFF; | 1311 | x.rlim_max = 0x7FFFFFFF; |
| 1302 | return copy_to_user(rlim, &x, sizeof(x))?-EFAULT:0; | 1312 | return copy_to_user(rlim, &x, sizeof(x)) ? -EFAULT : 0; |
| 1303 | } | 1313 | } |
| 1304 | 1314 | ||
| 1305 | #endif | 1315 | #endif |
| @@ -1527,7 +1537,7 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
| 1527 | cputime_t tgutime, tgstime, utime, stime; | 1537 | cputime_t tgutime, tgstime, utime, stime; |
| 1528 | unsigned long maxrss = 0; | 1538 | unsigned long maxrss = 0; |
| 1529 | 1539 | ||
| 1530 | memset((char *) r, 0, sizeof *r); | 1540 | memset((char *)r, 0, sizeof (*r)); |
| 1531 | utime = stime = 0; | 1541 | utime = stime = 0; |
| 1532 | 1542 | ||
| 1533 | if (who == RUSAGE_THREAD) { | 1543 | if (who == RUSAGE_THREAD) { |
| @@ -1541,41 +1551,41 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
| 1541 | return; | 1551 | return; |
| 1542 | 1552 | ||
| 1543 | switch (who) { | 1553 | switch (who) { |
| 1544 | case RUSAGE_BOTH: | 1554 | case RUSAGE_BOTH: |
| 1545 | case RUSAGE_CHILDREN: | 1555 | case RUSAGE_CHILDREN: |
| 1546 | utime = p->signal->cutime; | 1556 | utime = p->signal->cutime; |
| 1547 | stime = p->signal->cstime; | 1557 | stime = p->signal->cstime; |
| 1548 | r->ru_nvcsw = p->signal->cnvcsw; | 1558 | r->ru_nvcsw = p->signal->cnvcsw; |
| 1549 | r->ru_nivcsw = p->signal->cnivcsw; | 1559 | r->ru_nivcsw = p->signal->cnivcsw; |
| 1550 | r->ru_minflt = p->signal->cmin_flt; | 1560 | r->ru_minflt = p->signal->cmin_flt; |
| 1551 | r->ru_majflt = p->signal->cmaj_flt; | 1561 | r->ru_majflt = p->signal->cmaj_flt; |
| 1552 | r->ru_inblock = p->signal->cinblock; | 1562 | r->ru_inblock = p->signal->cinblock; |
| 1553 | r->ru_oublock = p->signal->coublock; | 1563 | r->ru_oublock = p->signal->coublock; |
| 1554 | maxrss = p->signal->cmaxrss; | 1564 | maxrss = p->signal->cmaxrss; |
| 1555 | 1565 | ||
| 1556 | if (who == RUSAGE_CHILDREN) | 1566 | if (who == RUSAGE_CHILDREN) |
| 1557 | break; | ||
| 1558 | |||
| 1559 | case RUSAGE_SELF: | ||
| 1560 | thread_group_cputime_adjusted(p, &tgutime, &tgstime); | ||
| 1561 | utime += tgutime; | ||
| 1562 | stime += tgstime; | ||
| 1563 | r->ru_nvcsw += p->signal->nvcsw; | ||
| 1564 | r->ru_nivcsw += p->signal->nivcsw; | ||
| 1565 | r->ru_minflt += p->signal->min_flt; | ||
| 1566 | r->ru_majflt += p->signal->maj_flt; | ||
| 1567 | r->ru_inblock += p->signal->inblock; | ||
| 1568 | r->ru_oublock += p->signal->oublock; | ||
| 1569 | if (maxrss < p->signal->maxrss) | ||
| 1570 | maxrss = p->signal->maxrss; | ||
| 1571 | t = p; | ||
| 1572 | do { | ||
| 1573 | accumulate_thread_rusage(t, r); | ||
| 1574 | } while_each_thread(p, t); | ||
| 1575 | break; | 1567 | break; |
| 1576 | 1568 | ||
| 1577 | default: | 1569 | case RUSAGE_SELF: |
| 1578 | BUG(); | 1570 | thread_group_cputime_adjusted(p, &tgutime, &tgstime); |
| 1571 | utime += tgutime; | ||
| 1572 | stime += tgstime; | ||
| 1573 | r->ru_nvcsw += p->signal->nvcsw; | ||
| 1574 | r->ru_nivcsw += p->signal->nivcsw; | ||
| 1575 | r->ru_minflt += p->signal->min_flt; | ||
| 1576 | r->ru_majflt += p->signal->maj_flt; | ||
| 1577 | r->ru_inblock += p->signal->inblock; | ||
| 1578 | r->ru_oublock += p->signal->oublock; | ||
| 1579 | if (maxrss < p->signal->maxrss) | ||
| 1580 | maxrss = p->signal->maxrss; | ||
| 1581 | t = p; | ||
| 1582 | do { | ||
| 1583 | accumulate_thread_rusage(t, r); | ||
| 1584 | } while_each_thread(p, t); | ||
| 1585 | break; | ||
| 1586 | |||
| 1587 | default: | ||
| 1588 | BUG(); | ||
| 1579 | } | 1589 | } |
| 1580 | unlock_task_sighand(p, &flags); | 1590 | unlock_task_sighand(p, &flags); |
| 1581 | 1591 | ||
| @@ -1585,6 +1595,7 @@ out: | |||
| 1585 | 1595 | ||
| 1586 | if (who != RUSAGE_CHILDREN) { | 1596 | if (who != RUSAGE_CHILDREN) { |
| 1587 | struct mm_struct *mm = get_task_mm(p); | 1597 | struct mm_struct *mm = get_task_mm(p); |
| 1598 | |||
| 1588 | if (mm) { | 1599 | if (mm) { |
| 1589 | setmax_mm_hiwater_rss(&maxrss, mm); | 1600 | setmax_mm_hiwater_rss(&maxrss, mm); |
| 1590 | mmput(mm); | 1601 | mmput(mm); |
| @@ -1596,6 +1607,7 @@ out: | |||
| 1596 | int getrusage(struct task_struct *p, int who, struct rusage __user *ru) | 1607 | int getrusage(struct task_struct *p, int who, struct rusage __user *ru) |
| 1597 | { | 1608 | { |
| 1598 | struct rusage r; | 1609 | struct rusage r; |
| 1610 | |||
| 1599 | k_getrusage(p, who, &r); | 1611 | k_getrusage(p, who, &r); |
| 1600 | return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; | 1612 | return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; |
| 1601 | } | 1613 | } |
| @@ -1628,12 +1640,14 @@ SYSCALL_DEFINE1(umask, int, mask) | |||
| 1628 | return mask; | 1640 | return mask; |
| 1629 | } | 1641 | } |
| 1630 | 1642 | ||
| 1631 | static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) | 1643 | static int prctl_set_mm_exe_file_locked(struct mm_struct *mm, unsigned int fd) |
| 1632 | { | 1644 | { |
| 1633 | struct fd exe; | 1645 | struct fd exe; |
| 1634 | struct inode *inode; | 1646 | struct inode *inode; |
| 1635 | int err; | 1647 | int err; |
| 1636 | 1648 | ||
| 1649 | VM_BUG_ON_MM(!rwsem_is_locked(&mm->mmap_sem), mm); | ||
| 1650 | |||
| 1637 | exe = fdget(fd); | 1651 | exe = fdget(fd); |
| 1638 | if (!exe.file) | 1652 | if (!exe.file) |
| 1639 | return -EBADF; | 1653 | return -EBADF; |
| @@ -1654,8 +1668,6 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) | |||
| 1654 | if (err) | 1668 | if (err) |
| 1655 | goto exit; | 1669 | goto exit; |
| 1656 | 1670 | ||
| 1657 | down_write(&mm->mmap_sem); | ||
| 1658 | |||
| 1659 | /* | 1671 | /* |
| 1660 | * Forbid mm->exe_file change if old file still mapped. | 1672 | * Forbid mm->exe_file change if old file still mapped. |
| 1661 | */ | 1673 | */ |
| @@ -1667,7 +1679,7 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) | |||
| 1667 | if (vma->vm_file && | 1679 | if (vma->vm_file && |
| 1668 | path_equal(&vma->vm_file->f_path, | 1680 | path_equal(&vma->vm_file->f_path, |
| 1669 | &mm->exe_file->f_path)) | 1681 | &mm->exe_file->f_path)) |
| 1670 | goto exit_unlock; | 1682 | goto exit; |
| 1671 | } | 1683 | } |
| 1672 | 1684 | ||
| 1673 | /* | 1685 | /* |
| @@ -1678,34 +1690,222 @@ static int prctl_set_mm_exe_file(struct mm_struct *mm, unsigned int fd) | |||
| 1678 | */ | 1690 | */ |
| 1679 | err = -EPERM; | 1691 | err = -EPERM; |
| 1680 | if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags)) | 1692 | if (test_and_set_bit(MMF_EXE_FILE_CHANGED, &mm->flags)) |
| 1681 | goto exit_unlock; | 1693 | goto exit; |
| 1682 | 1694 | ||
| 1683 | err = 0; | 1695 | err = 0; |
| 1684 | set_mm_exe_file(mm, exe.file); /* this grabs a reference to exe.file */ | 1696 | set_mm_exe_file(mm, exe.file); /* this grabs a reference to exe.file */ |
| 1685 | exit_unlock: | ||
| 1686 | up_write(&mm->mmap_sem); | ||
| 1687 | |||
| 1688 | exit: | 1697 | exit: |
| 1689 | fdput(exe); | 1698 | fdput(exe); |
| 1690 | return err; | 1699 | return err; |
| 1691 | } | 1700 | } |
| 1692 | 1701 | ||
| 1702 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
| 1703 | /* | ||
| 1704 | * WARNING: we don't require any capability here so be very careful | ||
| 1705 | * in what is allowed for modification from userspace. | ||
| 1706 | */ | ||
| 1707 | static int validate_prctl_map(struct prctl_mm_map *prctl_map) | ||
| 1708 | { | ||
| 1709 | unsigned long mmap_max_addr = TASK_SIZE; | ||
| 1710 | struct mm_struct *mm = current->mm; | ||
| 1711 | int error = -EINVAL, i; | ||
| 1712 | |||
| 1713 | static const unsigned char offsets[] = { | ||
| 1714 | offsetof(struct prctl_mm_map, start_code), | ||
| 1715 | offsetof(struct prctl_mm_map, end_code), | ||
| 1716 | offsetof(struct prctl_mm_map, start_data), | ||
| 1717 | offsetof(struct prctl_mm_map, end_data), | ||
| 1718 | offsetof(struct prctl_mm_map, start_brk), | ||
| 1719 | offsetof(struct prctl_mm_map, brk), | ||
| 1720 | offsetof(struct prctl_mm_map, start_stack), | ||
| 1721 | offsetof(struct prctl_mm_map, arg_start), | ||
| 1722 | offsetof(struct prctl_mm_map, arg_end), | ||
| 1723 | offsetof(struct prctl_mm_map, env_start), | ||
| 1724 | offsetof(struct prctl_mm_map, env_end), | ||
| 1725 | }; | ||
| 1726 | |||
| 1727 | /* | ||
| 1728 | * Make sure the members are not somewhere outside | ||
| 1729 | * of allowed address space. | ||
| 1730 | */ | ||
| 1731 | for (i = 0; i < ARRAY_SIZE(offsets); i++) { | ||
| 1732 | u64 val = *(u64 *)((char *)prctl_map + offsets[i]); | ||
| 1733 | |||
| 1734 | if ((unsigned long)val >= mmap_max_addr || | ||
| 1735 | (unsigned long)val < mmap_min_addr) | ||
| 1736 | goto out; | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | /* | ||
| 1740 | * Make sure the pairs are ordered. | ||
| 1741 | */ | ||
| 1742 | #define __prctl_check_order(__m1, __op, __m2) \ | ||
| 1743 | ((unsigned long)prctl_map->__m1 __op \ | ||
| 1744 | (unsigned long)prctl_map->__m2) ? 0 : -EINVAL | ||
| 1745 | error = __prctl_check_order(start_code, <, end_code); | ||
| 1746 | error |= __prctl_check_order(start_data, <, end_data); | ||
| 1747 | error |= __prctl_check_order(start_brk, <=, brk); | ||
| 1748 | error |= __prctl_check_order(arg_start, <=, arg_end); | ||
| 1749 | error |= __prctl_check_order(env_start, <=, env_end); | ||
| 1750 | if (error) | ||
| 1751 | goto out; | ||
| 1752 | #undef __prctl_check_order | ||
| 1753 | |||
| 1754 | error = -EINVAL; | ||
| 1755 | |||
| 1756 | /* | ||
| 1757 | * @brk should be after @end_data in traditional maps. | ||
| 1758 | */ | ||
| 1759 | if (prctl_map->start_brk <= prctl_map->end_data || | ||
| 1760 | prctl_map->brk <= prctl_map->end_data) | ||
| 1761 | goto out; | ||
| 1762 | |||
| 1763 | /* | ||
| 1764 | * Neither we should allow to override limits if they set. | ||
| 1765 | */ | ||
| 1766 | if (check_data_rlimit(rlimit(RLIMIT_DATA), prctl_map->brk, | ||
| 1767 | prctl_map->start_brk, prctl_map->end_data, | ||
| 1768 | prctl_map->start_data)) | ||
| 1769 | goto out; | ||
| 1770 | |||
| 1771 | /* | ||
| 1772 | * Someone is trying to cheat the auxv vector. | ||
| 1773 | */ | ||
| 1774 | if (prctl_map->auxv_size) { | ||
| 1775 | if (!prctl_map->auxv || prctl_map->auxv_size > sizeof(mm->saved_auxv)) | ||
| 1776 | goto out; | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | /* | ||
| 1780 | * Finally, make sure the caller has the rights to | ||
| 1781 | * change /proc/pid/exe link: only local root should | ||
| 1782 | * be allowed to. | ||
| 1783 | */ | ||
| 1784 | if (prctl_map->exe_fd != (u32)-1) { | ||
| 1785 | struct user_namespace *ns = current_user_ns(); | ||
| 1786 | const struct cred *cred = current_cred(); | ||
| 1787 | |||
| 1788 | if (!uid_eq(cred->uid, make_kuid(ns, 0)) || | ||
| 1789 | !gid_eq(cred->gid, make_kgid(ns, 0))) | ||
| 1790 | goto out; | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | error = 0; | ||
| 1794 | out: | ||
| 1795 | return error; | ||
| 1796 | } | ||
| 1797 | |||
| 1798 | static int prctl_set_mm_map(int opt, const void __user *addr, unsigned long data_size) | ||
| 1799 | { | ||
| 1800 | struct prctl_mm_map prctl_map = { .exe_fd = (u32)-1, }; | ||
| 1801 | unsigned long user_auxv[AT_VECTOR_SIZE]; | ||
| 1802 | struct mm_struct *mm = current->mm; | ||
| 1803 | int error; | ||
| 1804 | |||
| 1805 | BUILD_BUG_ON(sizeof(user_auxv) != sizeof(mm->saved_auxv)); | ||
| 1806 | BUILD_BUG_ON(sizeof(struct prctl_mm_map) > 256); | ||
| 1807 | |||
| 1808 | if (opt == PR_SET_MM_MAP_SIZE) | ||
| 1809 | return put_user((unsigned int)sizeof(prctl_map), | ||
| 1810 | (unsigned int __user *)addr); | ||
| 1811 | |||
| 1812 | if (data_size != sizeof(prctl_map)) | ||
| 1813 | return -EINVAL; | ||
| 1814 | |||
| 1815 | if (copy_from_user(&prctl_map, addr, sizeof(prctl_map))) | ||
| 1816 | return -EFAULT; | ||
| 1817 | |||
| 1818 | error = validate_prctl_map(&prctl_map); | ||
| 1819 | if (error) | ||
| 1820 | return error; | ||
| 1821 | |||
| 1822 | if (prctl_map.auxv_size) { | ||
| 1823 | memset(user_auxv, 0, sizeof(user_auxv)); | ||
| 1824 | if (copy_from_user(user_auxv, | ||
| 1825 | (const void __user *)prctl_map.auxv, | ||
| 1826 | prctl_map.auxv_size)) | ||
| 1827 | return -EFAULT; | ||
| 1828 | |||
| 1829 | /* Last entry must be AT_NULL as specification requires */ | ||
| 1830 | user_auxv[AT_VECTOR_SIZE - 2] = AT_NULL; | ||
| 1831 | user_auxv[AT_VECTOR_SIZE - 1] = AT_NULL; | ||
| 1832 | } | ||
| 1833 | |||
| 1834 | down_write(&mm->mmap_sem); | ||
| 1835 | if (prctl_map.exe_fd != (u32)-1) | ||
| 1836 | error = prctl_set_mm_exe_file_locked(mm, prctl_map.exe_fd); | ||
| 1837 | downgrade_write(&mm->mmap_sem); | ||
| 1838 | if (error) | ||
| 1839 | goto out; | ||
| 1840 | |||
| 1841 | /* | ||
| 1842 | * We don't validate if these members are pointing to | ||
| 1843 | * real present VMAs because application may have correspond | ||
| 1844 | * VMAs already unmapped and kernel uses these members for statistics | ||
| 1845 | * output in procfs mostly, except | ||
| 1846 | * | ||
| 1847 | * - @start_brk/@brk which are used in do_brk but kernel lookups | ||
| 1848 | * for VMAs when updating these memvers so anything wrong written | ||
| 1849 | * here cause kernel to swear at userspace program but won't lead | ||
| 1850 | * to any problem in kernel itself | ||
| 1851 | */ | ||
| 1852 | |||
| 1853 | mm->start_code = prctl_map.start_code; | ||
| 1854 | mm->end_code = prctl_map.end_code; | ||
| 1855 | mm->start_data = prctl_map.start_data; | ||
| 1856 | mm->end_data = prctl_map.end_data; | ||
| 1857 | mm->start_brk = prctl_map.start_brk; | ||
| 1858 | mm->brk = prctl_map.brk; | ||
| 1859 | mm->start_stack = prctl_map.start_stack; | ||
| 1860 | mm->arg_start = prctl_map.arg_start; | ||
| 1861 | mm->arg_end = prctl_map.arg_end; | ||
| 1862 | mm->env_start = prctl_map.env_start; | ||
| 1863 | mm->env_end = prctl_map.env_end; | ||
| 1864 | |||
| 1865 | /* | ||
| 1866 | * Note this update of @saved_auxv is lockless thus | ||
| 1867 | * if someone reads this member in procfs while we're | ||
| 1868 | * updating -- it may get partly updated results. It's | ||
| 1869 | * known and acceptable trade off: we leave it as is to | ||
| 1870 | * not introduce additional locks here making the kernel | ||
| 1871 | * more complex. | ||
| 1872 | */ | ||
| 1873 | if (prctl_map.auxv_size) | ||
| 1874 | memcpy(mm->saved_auxv, user_auxv, sizeof(user_auxv)); | ||
| 1875 | |||
| 1876 | error = 0; | ||
| 1877 | out: | ||
| 1878 | up_read(&mm->mmap_sem); | ||
| 1879 | return error; | ||
| 1880 | } | ||
| 1881 | #endif /* CONFIG_CHECKPOINT_RESTORE */ | ||
| 1882 | |||
| 1693 | static int prctl_set_mm(int opt, unsigned long addr, | 1883 | static int prctl_set_mm(int opt, unsigned long addr, |
| 1694 | unsigned long arg4, unsigned long arg5) | 1884 | unsigned long arg4, unsigned long arg5) |
| 1695 | { | 1885 | { |
| 1696 | unsigned long rlim = rlimit(RLIMIT_DATA); | ||
| 1697 | struct mm_struct *mm = current->mm; | 1886 | struct mm_struct *mm = current->mm; |
| 1698 | struct vm_area_struct *vma; | 1887 | struct vm_area_struct *vma; |
| 1699 | int error; | 1888 | int error; |
| 1700 | 1889 | ||
| 1701 | if (arg5 || (arg4 && opt != PR_SET_MM_AUXV)) | 1890 | if (arg5 || (arg4 && (opt != PR_SET_MM_AUXV && |
| 1891 | opt != PR_SET_MM_MAP && | ||
| 1892 | opt != PR_SET_MM_MAP_SIZE))) | ||
| 1702 | return -EINVAL; | 1893 | return -EINVAL; |
| 1703 | 1894 | ||
| 1895 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
| 1896 | if (opt == PR_SET_MM_MAP || opt == PR_SET_MM_MAP_SIZE) | ||
| 1897 | return prctl_set_mm_map(opt, (const void __user *)addr, arg4); | ||
| 1898 | #endif | ||
| 1899 | |||
| 1704 | if (!capable(CAP_SYS_RESOURCE)) | 1900 | if (!capable(CAP_SYS_RESOURCE)) |
| 1705 | return -EPERM; | 1901 | return -EPERM; |
| 1706 | 1902 | ||
| 1707 | if (opt == PR_SET_MM_EXE_FILE) | 1903 | if (opt == PR_SET_MM_EXE_FILE) { |
| 1708 | return prctl_set_mm_exe_file(mm, (unsigned int)addr); | 1904 | down_write(&mm->mmap_sem); |
| 1905 | error = prctl_set_mm_exe_file_locked(mm, (unsigned int)addr); | ||
| 1906 | up_write(&mm->mmap_sem); | ||
| 1907 | return error; | ||
| 1908 | } | ||
| 1709 | 1909 | ||
| 1710 | if (addr >= TASK_SIZE || addr < mmap_min_addr) | 1910 | if (addr >= TASK_SIZE || addr < mmap_min_addr) |
| 1711 | return -EINVAL; | 1911 | return -EINVAL; |
| @@ -1733,9 +1933,8 @@ static int prctl_set_mm(int opt, unsigned long addr, | |||
| 1733 | if (addr <= mm->end_data) | 1933 | if (addr <= mm->end_data) |
| 1734 | goto out; | 1934 | goto out; |
| 1735 | 1935 | ||
| 1736 | if (rlim < RLIM_INFINITY && | 1936 | if (check_data_rlimit(rlimit(RLIMIT_DATA), mm->brk, addr, |
| 1737 | (mm->brk - addr) + | 1937 | mm->end_data, mm->start_data)) |
| 1738 | (mm->end_data - mm->start_data) > rlim) | ||
| 1739 | goto out; | 1938 | goto out; |
| 1740 | 1939 | ||
| 1741 | mm->start_brk = addr; | 1940 | mm->start_brk = addr; |
| @@ -1745,9 +1944,8 @@ static int prctl_set_mm(int opt, unsigned long addr, | |||
| 1745 | if (addr <= mm->end_data) | 1944 | if (addr <= mm->end_data) |
| 1746 | goto out; | 1945 | goto out; |
| 1747 | 1946 | ||
| 1748 | if (rlim < RLIM_INFINITY && | 1947 | if (check_data_rlimit(rlimit(RLIMIT_DATA), addr, mm->start_brk, |
| 1749 | (addr - mm->start_brk) + | 1948 | mm->end_data, mm->start_data)) |
| 1750 | (mm->end_data - mm->start_data) > rlim) | ||
| 1751 | goto out; | 1949 | goto out; |
| 1752 | 1950 | ||
| 1753 | mm->brk = addr; | 1951 | mm->brk = addr; |
| @@ -2011,6 +2209,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 2011 | me->mm->def_flags &= ~VM_NOHUGEPAGE; | 2209 | me->mm->def_flags &= ~VM_NOHUGEPAGE; |
| 2012 | up_write(&me->mm->mmap_sem); | 2210 | up_write(&me->mm->mmap_sem); |
| 2013 | break; | 2211 | break; |
| 2212 | case PR_MPX_ENABLE_MANAGEMENT: | ||
| 2213 | error = MPX_ENABLE_MANAGEMENT(me); | ||
| 2214 | break; | ||
| 2215 | case PR_MPX_DISABLE_MANAGEMENT: | ||
| 2216 | error = MPX_DISABLE_MANAGEMENT(me); | ||
| 2217 | break; | ||
| 2014 | default: | 2218 | default: |
| 2015 | error = -EINVAL; | 2219 | error = -EINVAL; |
| 2016 | break; | 2220 | break; |
| @@ -2023,6 +2227,7 @@ SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep, | |||
| 2023 | { | 2227 | { |
| 2024 | int err = 0; | 2228 | int err = 0; |
| 2025 | int cpu = raw_smp_processor_id(); | 2229 | int cpu = raw_smp_processor_id(); |
| 2230 | |||
| 2026 | if (cpup) | 2231 | if (cpup) |
| 2027 | err |= put_user(cpu, cpup); | 2232 | err |= put_user(cpu, cpup); |
| 2028 | if (nodep) | 2233 | if (nodep) |
| @@ -2135,7 +2340,7 @@ COMPAT_SYSCALL_DEFINE1(sysinfo, struct compat_sysinfo __user *, info) | |||
| 2135 | /* Check to see if any memory value is too large for 32-bit and scale | 2340 | /* Check to see if any memory value is too large for 32-bit and scale |
| 2136 | * down if needed | 2341 | * down if needed |
| 2137 | */ | 2342 | */ |
| 2138 | if ((s.totalram >> 32) || (s.totalswap >> 32)) { | 2343 | if (upper_32_bits(s.totalram) || upper_32_bits(s.totalswap)) { |
| 2139 | int bitcount = 0; | 2344 | int bitcount = 0; |
| 2140 | 2345 | ||
| 2141 | while (s.mem_unit < PAGE_SIZE) { | 2346 | while (s.mem_unit < PAGE_SIZE) { |
