aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-05-27 16:22:20 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2017-05-27 16:22:20 -0400
commit33dd955df2d35bfca0fc851bcde9189839eb687a (patch)
treea06379ac5a9df04f03c8a150b58e79a5a8e69e88
parent9ba3eb5103cf56f0daaf07de4507df76e7813ed7 (diff)
parent92ebce5ac55dba258c608248dddf59eca3f7f514 (diff)
Merge branch 'work.sys_wait' into misc.alpha
-rw-r--r--arch/alpha/kernel/osf_sys.c51
-rw-r--r--arch/x86/include/asm/uaccess.h2
-rw-r--r--include/linux/resource.h2
-rw-r--r--include/linux/sched/task.h2
-rw-r--r--kernel/compat.c66
-rw-r--r--kernel/exit.c307
-rw-r--r--kernel/sys.c16
7 files changed, 188 insertions, 258 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index c4e135db1704..05dbbf9f42f4 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -1178,46 +1178,23 @@ SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
1178SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, 1178SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
1179 struct rusage32 __user *, ur) 1179 struct rusage32 __user *, ur)
1180{ 1180{
1181 struct rusage r;
1182 long ret, err;
1183 unsigned int status = 0; 1181 unsigned int status = 0;
1184 mm_segment_t old_fs; 1182 struct rusage r;
1185 1183 long err = kernel_wait4(pid, &status, options, &r);
1184 if (err <= 0)
1185 return err;
1186 if (put_user(status, ustatus))
1187 return -EFAULT;
1186 if (!ur) 1188 if (!ur)
1187 return sys_wait4(pid, ustatus, options, NULL); 1189 return err;
1188 1190 if (put_tv32(&ur->ru_utime, &r.ru_utime))
1189 old_fs = get_fs();
1190
1191 set_fs (KERNEL_DS);
1192 ret = sys_wait4(pid, (unsigned int __user *) &status, options,
1193 (struct rusage __user *) &r);
1194 set_fs (old_fs);
1195
1196 if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
1197 return -EFAULT; 1191 return -EFAULT;
1198 1192 if (put_tv32(&ur->ru_stime, &r.ru_stime))
1199 err = 0; 1193 return -EFAULT;
1200 err |= put_user(status, ustatus); 1194 if (copy_to_user(&ur->ru_maxrss, &r.ru_maxrss,
1201 err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); 1195 sizeof(struct rusage32) - offsetof(struct rusage32, ru_maxrss)))
1202 err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); 1196 return -EFAULT;
1203 err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); 1197 return err;
1204 err |= __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
1205 err |= __put_user(r.ru_maxrss, &ur->ru_maxrss);
1206 err |= __put_user(r.ru_ixrss, &ur->ru_ixrss);
1207 err |= __put_user(r.ru_idrss, &ur->ru_idrss);
1208 err |= __put_user(r.ru_isrss, &ur->ru_isrss);
1209 err |= __put_user(r.ru_minflt, &ur->ru_minflt);
1210 err |= __put_user(r.ru_majflt, &ur->ru_majflt);
1211 err |= __put_user(r.ru_nswap, &ur->ru_nswap);
1212 err |= __put_user(r.ru_inblock, &ur->ru_inblock);
1213 err |= __put_user(r.ru_oublock, &ur->ru_oublock);
1214 err |= __put_user(r.ru_msgsnd, &ur->ru_msgsnd);
1215 err |= __put_user(r.ru_msgrcv, &ur->ru_msgrcv);
1216 err |= __put_user(r.ru_nsignals, &ur->ru_nsignals);
1217 err |= __put_user(r.ru_nvcsw, &ur->ru_nvcsw);
1218 err |= __put_user(r.ru_nivcsw, &ur->ru_nivcsw);
1219
1220 return err ? err : ret;
1221} 1198}
1222 1199
1223/* 1200/*
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 68766b276d9e..d9668c3beb5b 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -703,7 +703,7 @@ extern struct movsl_mask {
703#define unsafe_put_user(x, ptr, err_label) \ 703#define unsafe_put_user(x, ptr, err_label) \
704do { \ 704do { \
705 int __pu_err; \ 705 int __pu_err; \
706 __put_user_size((x), (ptr), sizeof(*(ptr)), __pu_err, -EFAULT); \ 706 __put_user_size((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), __pu_err, -EFAULT); \
707 if (unlikely(__pu_err)) goto err_label; \ 707 if (unlikely(__pu_err)) goto err_label; \
708} while (0) 708} while (0)
709 709
diff --git a/include/linux/resource.h b/include/linux/resource.h
index 5bc3116e649c..277afdad6589 100644
--- a/include/linux/resource.h
+++ b/include/linux/resource.h
@@ -6,7 +6,7 @@
6 6
7struct task_struct; 7struct task_struct;
8 8
9int getrusage(struct task_struct *p, int who, struct rusage __user *ru); 9void getrusage(struct task_struct *p, int who, struct rusage *ru);
10int do_prlimit(struct task_struct *tsk, unsigned int resource, 10int do_prlimit(struct task_struct *tsk, unsigned int resource,
11 struct rlimit *new_rlim, struct rlimit *old_rlim); 11 struct rlimit *new_rlim, struct rlimit *old_rlim);
12 12
diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index a978d7189cfd..6b830fd9d809 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -9,6 +9,7 @@
9#include <linux/sched.h> 9#include <linux/sched.h>
10 10
11struct task_struct; 11struct task_struct;
12struct rusage;
12union thread_union; 13union thread_union;
13 14
14/* 15/*
@@ -74,6 +75,7 @@ extern long _do_fork(unsigned long, unsigned long, unsigned long, int __user *,
74extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *); 75extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *);
75struct task_struct *fork_idle(int); 76struct task_struct *fork_idle(int);
76extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 77extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
78extern long kernel_wait4(pid_t, int *, int, struct rusage *);
77 79
78extern void free_task(struct task_struct *tsk); 80extern void free_task(struct task_struct *tsk);
79 81
diff --git a/kernel/compat.c b/kernel/compat.c
index 933bcb31ae10..b4cdba6bbd02 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -543,72 +543,6 @@ int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
543 return 0; 543 return 0;
544} 544}
545 545
546COMPAT_SYSCALL_DEFINE4(wait4,
547 compat_pid_t, pid,
548 compat_uint_t __user *, stat_addr,
549 int, options,
550 struct compat_rusage __user *, ru)
551{
552 if (!ru) {
553 return sys_wait4(pid, stat_addr, options, NULL);
554 } else {
555 struct rusage r;
556 int ret;
557 unsigned int status;
558 mm_segment_t old_fs = get_fs();
559
560 set_fs (KERNEL_DS);
561 ret = sys_wait4(pid,
562 (stat_addr ?
563 (unsigned int __user *) &status : NULL),
564 options, (struct rusage __user *) &r);
565 set_fs (old_fs);
566
567 if (ret > 0) {
568 if (put_compat_rusage(&r, ru))
569 return -EFAULT;
570 if (stat_addr && put_user(status, stat_addr))
571 return -EFAULT;
572 }
573 return ret;
574 }
575}
576
577COMPAT_SYSCALL_DEFINE5(waitid,
578 int, which, compat_pid_t, pid,
579 struct compat_siginfo __user *, uinfo, int, options,
580 struct compat_rusage __user *, uru)
581{
582 siginfo_t info;
583 struct rusage ru;
584 long ret;
585 mm_segment_t old_fs = get_fs();
586
587 memset(&info, 0, sizeof(info));
588
589 set_fs(KERNEL_DS);
590 ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
591 uru ? (struct rusage __user *)&ru : NULL);
592 set_fs(old_fs);
593
594 if ((ret < 0) || (info.si_signo == 0))
595 return ret;
596
597 if (uru) {
598 /* sys_waitid() overwrites everything in ru */
599 if (COMPAT_USE_64BIT_TIME)
600 ret = copy_to_user(uru, &ru, sizeof(ru));
601 else
602 ret = put_compat_rusage(&ru, uru);
603 if (ret)
604 return -EFAULT;
605 }
606
607 BUG_ON(info.si_code & __SI_MASK);
608 info.si_code |= __SI_CHLD;
609 return copy_siginfo_to_user32(uinfo, &info);
610}
611
612static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr, 546static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
613 unsigned len, struct cpumask *new_mask) 547 unsigned len, struct cpumask *new_mask)
614{ 548{
diff --git a/kernel/exit.c b/kernel/exit.c
index 516acdb0e0ec..462fc25eec6e 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -62,6 +62,7 @@
62#include <linux/kcov.h> 62#include <linux/kcov.h>
63#include <linux/random.h> 63#include <linux/random.h>
64#include <linux/rcuwait.h> 64#include <linux/rcuwait.h>
65#include <linux/compat.h>
65 66
66#include <linux/uaccess.h> 67#include <linux/uaccess.h>
67#include <asm/unistd.h> 68#include <asm/unistd.h>
@@ -995,14 +996,21 @@ SYSCALL_DEFINE1(exit_group, int, error_code)
995 return 0; 996 return 0;
996} 997}
997 998
999struct waitid_info {
1000 pid_t pid;
1001 uid_t uid;
1002 int status;
1003 int cause;
1004};
1005
998struct wait_opts { 1006struct wait_opts {
999 enum pid_type wo_type; 1007 enum pid_type wo_type;
1000 int wo_flags; 1008 int wo_flags;
1001 struct pid *wo_pid; 1009 struct pid *wo_pid;
1002 1010
1003 struct siginfo __user *wo_info; 1011 struct waitid_info *wo_info;
1004 int __user *wo_stat; 1012 int wo_stat;
1005 struct rusage __user *wo_rusage; 1013 struct rusage *wo_rusage;
1006 1014
1007 wait_queue_t child_wait; 1015 wait_queue_t child_wait;
1008 int notask_error; 1016 int notask_error;
@@ -1049,34 +1057,6 @@ eligible_child(struct wait_opts *wo, bool ptrace, struct task_struct *p)
1049 return 1; 1057 return 1;
1050} 1058}
1051 1059
1052static int wait_noreap_copyout(struct wait_opts *wo, struct task_struct *p,
1053 pid_t pid, uid_t uid, int why, int status)
1054{
1055 struct siginfo __user *infop;
1056 int retval = wo->wo_rusage
1057 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0;
1058
1059 put_task_struct(p);
1060 infop = wo->wo_info;
1061 if (infop) {
1062 if (!retval)
1063 retval = put_user(SIGCHLD, &infop->si_signo);
1064 if (!retval)
1065 retval = put_user(0, &infop->si_errno);
1066 if (!retval)
1067 retval = put_user((short)why, &infop->si_code);
1068 if (!retval)
1069 retval = put_user(pid, &infop->si_pid);
1070 if (!retval)
1071 retval = put_user(uid, &infop->si_uid);
1072 if (!retval)
1073 retval = put_user(status, &infop->si_status);
1074 }
1075 if (!retval)
1076 retval = pid;
1077 return retval;
1078}
1079
1080/* 1060/*
1081 * Handle sys_wait4 work for one task in state EXIT_ZOMBIE. We hold 1061 * Handle sys_wait4 work for one task in state EXIT_ZOMBIE. We hold
1082 * read_lock(&tasklist_lock) on entry. If we return zero, we still hold 1062 * read_lock(&tasklist_lock) on entry. If we return zero, we still hold
@@ -1085,30 +1065,23 @@ static int wait_noreap_copyout(struct wait_opts *wo, struct task_struct *p,
1085 */ 1065 */
1086static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) 1066static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1087{ 1067{
1088 int state, retval, status; 1068 int state, status;
1089 pid_t pid = task_pid_vnr(p); 1069 pid_t pid = task_pid_vnr(p);
1090 uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p)); 1070 uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p));
1091 struct siginfo __user *infop; 1071 struct waitid_info *infop;
1092 1072
1093 if (!likely(wo->wo_flags & WEXITED)) 1073 if (!likely(wo->wo_flags & WEXITED))
1094 return 0; 1074 return 0;
1095 1075
1096 if (unlikely(wo->wo_flags & WNOWAIT)) { 1076 if (unlikely(wo->wo_flags & WNOWAIT)) {
1097 int exit_code = p->exit_code; 1077 status = p->exit_code;
1098 int why;
1099
1100 get_task_struct(p); 1078 get_task_struct(p);
1101 read_unlock(&tasklist_lock); 1079 read_unlock(&tasklist_lock);
1102 sched_annotate_sleep(); 1080 sched_annotate_sleep();
1103 1081 if (wo->wo_rusage)
1104 if ((exit_code & 0x7f) == 0) { 1082 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1105 why = CLD_EXITED; 1083 put_task_struct(p);
1106 status = exit_code >> 8; 1084 goto out_info;
1107 } else {
1108 why = (exit_code & 0x80) ? CLD_DUMPED : CLD_KILLED;
1109 status = exit_code & 0x7f;
1110 }
1111 return wait_noreap_copyout(wo, p, pid, uid, why, status);
1112 } 1085 }
1113 /* 1086 /*
1114 * Move the task's state to DEAD/TRACE, only one thread can do this. 1087 * Move the task's state to DEAD/TRACE, only one thread can do this.
@@ -1181,38 +1154,11 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1181 spin_unlock_irq(&current->sighand->siglock); 1154 spin_unlock_irq(&current->sighand->siglock);
1182 } 1155 }
1183 1156
1184 retval = wo->wo_rusage 1157 if (wo->wo_rusage)
1185 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0; 1158 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1186 status = (p->signal->flags & SIGNAL_GROUP_EXIT) 1159 status = (p->signal->flags & SIGNAL_GROUP_EXIT)
1187 ? p->signal->group_exit_code : p->exit_code; 1160 ? p->signal->group_exit_code : p->exit_code;
1188 if (!retval && wo->wo_stat) 1161 wo->wo_stat = status;
1189 retval = put_user(status, wo->wo_stat);
1190
1191 infop = wo->wo_info;
1192 if (!retval && infop)
1193 retval = put_user(SIGCHLD, &infop->si_signo);
1194 if (!retval && infop)
1195 retval = put_user(0, &infop->si_errno);
1196 if (!retval && infop) {
1197 int why;
1198
1199 if ((status & 0x7f) == 0) {
1200 why = CLD_EXITED;
1201 status >>= 8;
1202 } else {
1203 why = (status & 0x80) ? CLD_DUMPED : CLD_KILLED;
1204 status &= 0x7f;
1205 }
1206 retval = put_user((short)why, &infop->si_code);
1207 if (!retval)
1208 retval = put_user(status, &infop->si_status);
1209 }
1210 if (!retval && infop)
1211 retval = put_user(pid, &infop->si_pid);
1212 if (!retval && infop)
1213 retval = put_user(uid, &infop->si_uid);
1214 if (!retval)
1215 retval = pid;
1216 1162
1217 if (state == EXIT_TRACE) { 1163 if (state == EXIT_TRACE) {
1218 write_lock_irq(&tasklist_lock); 1164 write_lock_irq(&tasklist_lock);
@@ -1229,7 +1175,21 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1229 if (state == EXIT_DEAD) 1175 if (state == EXIT_DEAD)
1230 release_task(p); 1176 release_task(p);
1231 1177
1232 return retval; 1178out_info:
1179 infop = wo->wo_info;
1180 if (infop) {
1181 if ((status & 0x7f) == 0) {
1182 infop->cause = CLD_EXITED;
1183 infop->status = status >> 8;
1184 } else {
1185 infop->cause = (status & 0x80) ? CLD_DUMPED : CLD_KILLED;
1186 infop->status = status & 0x7f;
1187 }
1188 infop->pid = pid;
1189 infop->uid = uid;
1190 }
1191
1192 return pid;
1233} 1193}
1234 1194
1235static int *task_stopped_code(struct task_struct *p, bool ptrace) 1195static int *task_stopped_code(struct task_struct *p, bool ptrace)
@@ -1265,8 +1225,8 @@ static int *task_stopped_code(struct task_struct *p, bool ptrace)
1265static int wait_task_stopped(struct wait_opts *wo, 1225static int wait_task_stopped(struct wait_opts *wo,
1266 int ptrace, struct task_struct *p) 1226 int ptrace, struct task_struct *p)
1267{ 1227{
1268 struct siginfo __user *infop; 1228 struct waitid_info *infop;
1269 int retval, exit_code, *p_code, why; 1229 int exit_code, *p_code, why;
1270 uid_t uid = 0; /* unneeded, required by compiler */ 1230 uid_t uid = 0; /* unneeded, required by compiler */
1271 pid_t pid; 1231 pid_t pid;
1272 1232
@@ -1311,34 +1271,21 @@ unlock_sig:
1311 why = ptrace ? CLD_TRAPPED : CLD_STOPPED; 1271 why = ptrace ? CLD_TRAPPED : CLD_STOPPED;
1312 read_unlock(&tasklist_lock); 1272 read_unlock(&tasklist_lock);
1313 sched_annotate_sleep(); 1273 sched_annotate_sleep();
1274 if (wo->wo_rusage)
1275 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1276 put_task_struct(p);
1314 1277
1315 if (unlikely(wo->wo_flags & WNOWAIT)) 1278 if (likely(!(wo->wo_flags & WNOWAIT)))
1316 return wait_noreap_copyout(wo, p, pid, uid, why, exit_code); 1279 wo->wo_stat = (exit_code << 8) | 0x7f;
1317
1318 retval = wo->wo_rusage
1319 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0;
1320 if (!retval && wo->wo_stat)
1321 retval = put_user((exit_code << 8) | 0x7f, wo->wo_stat);
1322 1280
1323 infop = wo->wo_info; 1281 infop = wo->wo_info;
1324 if (!retval && infop) 1282 if (infop) {
1325 retval = put_user(SIGCHLD, &infop->si_signo); 1283 infop->cause = why;
1326 if (!retval && infop) 1284 infop->status = exit_code;
1327 retval = put_user(0, &infop->si_errno); 1285 infop->pid = pid;
1328 if (!retval && infop) 1286 infop->uid = uid;
1329 retval = put_user((short)why, &infop->si_code); 1287 }
1330 if (!retval && infop) 1288 return pid;
1331 retval = put_user(exit_code, &infop->si_status);
1332 if (!retval && infop)
1333 retval = put_user(pid, &infop->si_pid);
1334 if (!retval && infop)
1335 retval = put_user(uid, &infop->si_uid);
1336 if (!retval)
1337 retval = pid;
1338 put_task_struct(p);
1339
1340 BUG_ON(!retval);
1341 return retval;
1342} 1289}
1343 1290
1344/* 1291/*
@@ -1349,7 +1296,7 @@ unlock_sig:
1349 */ 1296 */
1350static int wait_task_continued(struct wait_opts *wo, struct task_struct *p) 1297static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
1351{ 1298{
1352 int retval; 1299 struct waitid_info *infop;
1353 pid_t pid; 1300 pid_t pid;
1354 uid_t uid; 1301 uid_t uid;
1355 1302
@@ -1374,22 +1321,20 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
1374 get_task_struct(p); 1321 get_task_struct(p);
1375 read_unlock(&tasklist_lock); 1322 read_unlock(&tasklist_lock);
1376 sched_annotate_sleep(); 1323 sched_annotate_sleep();
1324 if (wo->wo_rusage)
1325 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1326 put_task_struct(p);
1377 1327
1378 if (!wo->wo_info) { 1328 infop = wo->wo_info;
1379 retval = wo->wo_rusage 1329 if (!infop) {
1380 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0; 1330 wo->wo_stat = 0xffff;
1381 put_task_struct(p);
1382 if (!retval && wo->wo_stat)
1383 retval = put_user(0xffff, wo->wo_stat);
1384 if (!retval)
1385 retval = pid;
1386 } else { 1331 } else {
1387 retval = wait_noreap_copyout(wo, p, pid, uid, 1332 infop->cause = CLD_CONTINUED;
1388 CLD_CONTINUED, SIGCONT); 1333 infop->pid = pid;
1389 BUG_ON(retval == 0); 1334 infop->uid = uid;
1335 infop->status = SIGCONT;
1390 } 1336 }
1391 1337 return pid;
1392 return retval;
1393} 1338}
1394 1339
1395/* 1340/*
@@ -1617,8 +1562,8 @@ end:
1617 return retval; 1562 return retval;
1618} 1563}
1619 1564
1620SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *, 1565static long kernel_waitid(int which, pid_t upid, struct waitid_info *infop,
1621 infop, int, options, struct rusage __user *, ru) 1566 int options, struct rusage *ru)
1622{ 1567{
1623 struct wait_opts wo; 1568 struct wait_opts wo;
1624 struct pid *pid = NULL; 1569 struct pid *pid = NULL;
@@ -1656,38 +1601,46 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
1656 wo.wo_pid = pid; 1601 wo.wo_pid = pid;
1657 wo.wo_flags = options; 1602 wo.wo_flags = options;
1658 wo.wo_info = infop; 1603 wo.wo_info = infop;
1659 wo.wo_stat = NULL;
1660 wo.wo_rusage = ru; 1604 wo.wo_rusage = ru;
1661 ret = do_wait(&wo); 1605 ret = do_wait(&wo);
1662 1606
1663 if (ret > 0) { 1607 if (ret > 0)
1664 ret = 0; 1608 ret = 0;
1665 } else if (infop) {
1666 /*
1667 * For a WNOHANG return, clear out all the fields
1668 * we would set so the user can easily tell the
1669 * difference.
1670 */
1671 if (!ret)
1672 ret = put_user(0, &infop->si_signo);
1673 if (!ret)
1674 ret = put_user(0, &infop->si_errno);
1675 if (!ret)
1676 ret = put_user(0, &infop->si_code);
1677 if (!ret)
1678 ret = put_user(0, &infop->si_pid);
1679 if (!ret)
1680 ret = put_user(0, &infop->si_uid);
1681 if (!ret)
1682 ret = put_user(0, &infop->si_status);
1683 }
1684 1609
1685 put_pid(pid); 1610 put_pid(pid);
1686 return ret; 1611 return ret;
1687} 1612}
1688 1613
1689SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr, 1614SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
1690 int, options, struct rusage __user *, ru) 1615 infop, int, options, struct rusage __user *, ru)
1616{
1617 struct rusage r;
1618 struct waitid_info info = {.status = 0};
1619 long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
1620
1621 if (!err) {
1622 if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
1623 return -EFAULT;
1624 }
1625 if (!infop)
1626 return err;
1627
1628 user_access_begin();
1629 unsafe_put_user(err ? 0 : SIGCHLD, &infop->si_signo, Efault);
1630 unsafe_put_user(0, &infop->si_errno, Efault);
1631 unsafe_put_user((short)info.cause, &infop->si_code, Efault);
1632 unsafe_put_user(info.pid, &infop->si_pid, Efault);
1633 unsafe_put_user(info.uid, &infop->si_uid, Efault);
1634 unsafe_put_user(info.status, &infop->si_status, Efault);
1635 user_access_end();
1636 return err;
1637Efault:
1638 user_access_end();
1639 return -EFAULT;
1640}
1641
1642long kernel_wait4(pid_t upid, int __user *stat_addr, int options,
1643 struct rusage *ru)
1691{ 1644{
1692 struct wait_opts wo; 1645 struct wait_opts wo;
1693 struct pid *pid = NULL; 1646 struct pid *pid = NULL;
@@ -1715,14 +1668,29 @@ SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
1715 wo.wo_pid = pid; 1668 wo.wo_pid = pid;
1716 wo.wo_flags = options | WEXITED; 1669 wo.wo_flags = options | WEXITED;
1717 wo.wo_info = NULL; 1670 wo.wo_info = NULL;
1718 wo.wo_stat = stat_addr; 1671 wo.wo_stat = 0;
1719 wo.wo_rusage = ru; 1672 wo.wo_rusage = ru;
1720 ret = do_wait(&wo); 1673 ret = do_wait(&wo);
1721 put_pid(pid); 1674 put_pid(pid);
1675 if (ret > 0 && stat_addr && put_user(wo.wo_stat, stat_addr))
1676 ret = -EFAULT;
1722 1677
1723 return ret; 1678 return ret;
1724} 1679}
1725 1680
1681SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
1682 int, options, struct rusage __user *, ru)
1683{
1684 struct rusage r;
1685 long err = kernel_wait4(upid, stat_addr, options, ru ? &r : NULL);
1686
1687 if (err > 0) {
1688 if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
1689 return -EFAULT;
1690 }
1691 return err;
1692}
1693
1726#ifdef __ARCH_WANT_SYS_WAITPID 1694#ifdef __ARCH_WANT_SYS_WAITPID
1727 1695
1728/* 1696/*
@@ -1735,3 +1703,56 @@ SYSCALL_DEFINE3(waitpid, pid_t, pid, int __user *, stat_addr, int, options)
1735} 1703}
1736 1704
1737#endif 1705#endif
1706
1707#ifdef CONFIG_COMPAT
1708COMPAT_SYSCALL_DEFINE4(wait4,
1709 compat_pid_t, pid,
1710 compat_uint_t __user *, stat_addr,
1711 int, options,
1712 struct compat_rusage __user *, ru)
1713{
1714 struct rusage r;
1715 long err = kernel_wait4(pid, stat_addr, options, ru ? &r : NULL);
1716 if (err > 0) {
1717 if (ru && put_compat_rusage(&r, ru))
1718 return -EFAULT;
1719 }
1720 return err;
1721}
1722
1723COMPAT_SYSCALL_DEFINE5(waitid,
1724 int, which, compat_pid_t, pid,
1725 struct compat_siginfo __user *, infop, int, options,
1726 struct compat_rusage __user *, uru)
1727{
1728 struct rusage ru;
1729 struct waitid_info info = {.status = 0};
1730 long err = kernel_waitid(which, pid, &info, options, uru ? &ru : NULL);
1731
1732 if (!err && uru) {
1733 /* kernel_waitid() overwrites everything in ru */
1734 if (COMPAT_USE_64BIT_TIME)
1735 err = copy_to_user(uru, &ru, sizeof(ru));
1736 else
1737 err = put_compat_rusage(&ru, uru);
1738 if (err)
1739 return -EFAULT;
1740 }
1741
1742 if (!infop)
1743 return err;
1744
1745 user_access_begin();
1746 unsafe_put_user(err ? 0 : SIGCHLD, &infop->si_signo, Efault);
1747 unsafe_put_user(0, &infop->si_errno, Efault);
1748 unsafe_put_user((short)info.cause, &infop->si_code, Efault);
1749 unsafe_put_user(info.pid, &infop->si_pid, Efault);
1750 unsafe_put_user(info.uid, &infop->si_uid, Efault);
1751 unsafe_put_user(info.status, &infop->si_status, Efault);
1752 user_access_end();
1753 return err;
1754Efault:
1755 user_access_end();
1756 return -EFAULT;
1757}
1758#endif
diff --git a/kernel/sys.c b/kernel/sys.c
index 8a94b4eabcaa..dab1a0658a92 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1552,7 +1552,7 @@ static void accumulate_thread_rusage(struct task_struct *t, struct rusage *r)
1552 r->ru_oublock += task_io_get_oublock(t); 1552 r->ru_oublock += task_io_get_oublock(t);
1553} 1553}
1554 1554
1555static void k_getrusage(struct task_struct *p, int who, struct rusage *r) 1555void getrusage(struct task_struct *p, int who, struct rusage *r)
1556{ 1556{
1557 struct task_struct *t; 1557 struct task_struct *t;
1558 unsigned long flags; 1558 unsigned long flags;
@@ -1626,20 +1626,16 @@ out:
1626 r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */ 1626 r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */
1627} 1627}
1628 1628
1629int getrusage(struct task_struct *p, int who, struct rusage __user *ru) 1629SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
1630{ 1630{
1631 struct rusage r; 1631 struct rusage r;
1632 1632
1633 k_getrusage(p, who, &r);
1634 return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
1635}
1636
1637SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
1638{
1639 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN && 1633 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&
1640 who != RUSAGE_THREAD) 1634 who != RUSAGE_THREAD)
1641 return -EINVAL; 1635 return -EINVAL;
1642 return getrusage(current, who, ru); 1636
1637 getrusage(current, who, &r);
1638 return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
1643} 1639}
1644 1640
1645#ifdef CONFIG_COMPAT 1641#ifdef CONFIG_COMPAT
@@ -1651,7 +1647,7 @@ COMPAT_SYSCALL_DEFINE2(getrusage, int, who, struct compat_rusage __user *, ru)
1651 who != RUSAGE_THREAD) 1647 who != RUSAGE_THREAD)
1652 return -EINVAL; 1648 return -EINVAL;
1653 1649
1654 k_getrusage(current, who, &r); 1650 getrusage(current, who, &r);
1655 return put_compat_rusage(&r, ru); 1651 return put_compat_rusage(&r, ru);
1656} 1652}
1657#endif 1653#endif