aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 17:10:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 17:10:19 -0400
commit4be95131bf3bca97b6a7db9c6fb63db2cb94da06 (patch)
treec623b98ba6aa37299f5109cb8bd0e53be547c72d
parent3bad2f1c676581d01e7645eb03e9b27e28b0a92e (diff)
parent92ebce5ac55dba258c608248dddf59eca3f7f514 (diff)
Merge branch 'work.sys_wait' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull wait syscall updates from Al Viro: "Consolidating sys_wait* and compat counterparts. Gets rid of set_fs()/double-copy mess, simplifies the whole thing (lifting the copyouts to the syscalls means less headache in the part that does actual work - fewer failure exits, to start with), gets rid of the overhead of field-by-field __put_user()" * 'work.sys_wait' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: osf_wait4: switch to kernel_wait4() waitid(): switch copyout of siginfo to unsafe_put_user() wait_task_zombie: consolidate info logics kill wait_noreap_copyout() lift getrusage() from wait_noreap_copyout() waitid(2): leave copyout of siginfo to syscall itself kernel_wait4()/kernel_waitid(): delay copying status to userland wait4(2)/waitid(2): separate copying rusage to userland move compat wait4 and waitid next to native variants
-rw-r--r--arch/alpha/kernel/osf_sys.c53
-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
6 files changed, 187 insertions, 259 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index ce93124a850b..b23d6fbbb225 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -1183,48 +1183,23 @@ SYSCALL_DEFINE2(osf_getrusage, int, who, struct rusage32 __user *, ru)
1183SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, 1183SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
1184 struct rusage32 __user *, ur) 1184 struct rusage32 __user *, ur)
1185{ 1185{
1186 struct rusage r;
1187 long ret, err;
1188 unsigned int status = 0; 1186 unsigned int status = 0;
1189 mm_segment_t old_fs; 1187 struct rusage r;
1190 1188 long err = kernel_wait4(pid, &status, options, &r);
1189 if (err <= 0)
1190 return err;
1191 if (put_user(status, ustatus))
1192 return -EFAULT;
1191 if (!ur) 1193 if (!ur)
1192 return sys_wait4(pid, ustatus, options, NULL); 1194 return err;
1193 1195 if (put_tv32(&ur->ru_utime, &r.ru_utime))
1194 old_fs = get_fs();
1195
1196 set_fs (KERNEL_DS);
1197 ret = sys_wait4(pid, (unsigned int __user *) &status, options,
1198 (struct rusage __user *) &r);
1199 set_fs (old_fs);
1200
1201 if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
1202 return -EFAULT; 1196 return -EFAULT;
1203 1197 if (put_tv32(&ur->ru_stime, &r.ru_stime))
1204 err = put_user(status, ustatus); 1198 return -EFAULT;
1205 if (ret < 0) 1199 if (copy_to_user(&ur->ru_maxrss, &r.ru_maxrss,
1206 return err ? err : ret; 1200 sizeof(struct rusage32) - offsetof(struct rusage32, ru_maxrss)))
1207 1201 return -EFAULT;
1208 err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); 1202 return err;
1209 err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
1210 err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
1211 err |= __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
1212 err |= __put_user(r.ru_maxrss, &ur->ru_maxrss);
1213 err |= __put_user(r.ru_ixrss, &ur->ru_ixrss);
1214 err |= __put_user(r.ru_idrss, &ur->ru_idrss);
1215 err |= __put_user(r.ru_isrss, &ur->ru_isrss);
1216 err |= __put_user(r.ru_minflt, &ur->ru_minflt);
1217 err |= __put_user(r.ru_majflt, &ur->ru_majflt);
1218 err |= __put_user(r.ru_nswap, &ur->ru_nswap);
1219 err |= __put_user(r.ru_inblock, &ur->ru_inblock);
1220 err |= __put_user(r.ru_oublock, &ur->ru_oublock);
1221 err |= __put_user(r.ru_msgsnd, &ur->ru_msgsnd);
1222 err |= __put_user(r.ru_msgrcv, &ur->ru_msgrcv);
1223 err |= __put_user(r.ru_nsignals, &ur->ru_nsignals);
1224 err |= __put_user(r.ru_nvcsw, &ur->ru_nvcsw);
1225 err |= __put_user(r.ru_nivcsw, &ur->ru_nivcsw);
1226
1227 return err ? err : ret;
1228} 1203}
1229 1204
1230/* 1205/*
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 f0f065c5afcf..c97e5f096927 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 ebd8bdc3fd68..9ce1d4876e60 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -396,72 +396,6 @@ int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
396 return 0; 396 return 0;
397} 397}
398 398
399COMPAT_SYSCALL_DEFINE4(wait4,
400 compat_pid_t, pid,
401 compat_uint_t __user *, stat_addr,
402 int, options,
403 struct compat_rusage __user *, ru)
404{
405 if (!ru) {
406 return sys_wait4(pid, stat_addr, options, NULL);
407 } else {
408 struct rusage r;
409 int ret;
410 unsigned int status;
411 mm_segment_t old_fs = get_fs();
412
413 set_fs (KERNEL_DS);
414 ret = sys_wait4(pid,
415 (stat_addr ?
416 (unsigned int __user *) &status : NULL),
417 options, (struct rusage __user *) &r);
418 set_fs (old_fs);
419
420 if (ret > 0) {
421 if (put_compat_rusage(&r, ru))
422 return -EFAULT;
423 if (stat_addr && put_user(status, stat_addr))
424 return -EFAULT;
425 }
426 return ret;
427 }
428}
429
430COMPAT_SYSCALL_DEFINE5(waitid,
431 int, which, compat_pid_t, pid,
432 struct compat_siginfo __user *, uinfo, int, options,
433 struct compat_rusage __user *, uru)
434{
435 siginfo_t info;
436 struct rusage ru;
437 long ret;
438 mm_segment_t old_fs = get_fs();
439
440 memset(&info, 0, sizeof(info));
441
442 set_fs(KERNEL_DS);
443 ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
444 uru ? (struct rusage __user *)&ru : NULL);
445 set_fs(old_fs);
446
447 if ((ret < 0) || (info.si_signo == 0))
448 return ret;
449
450 if (uru) {
451 /* sys_waitid() overwrites everything in ru */
452 if (COMPAT_USE_64BIT_TIME)
453 ret = copy_to_user(uru, &ru, sizeof(ru));
454 else
455 ret = put_compat_rusage(&ru, uru);
456 if (ret)
457 return -EFAULT;
458 }
459
460 BUG_ON(info.si_code & __SI_MASK);
461 info.si_code |= __SI_CHLD;
462 return copy_siginfo_to_user32(uinfo, &info);
463}
464
465static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr, 399static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
466 unsigned len, struct cpumask *new_mask) 400 unsigned len, struct cpumask *new_mask)
467{ 401{
diff --git a/kernel/exit.c b/kernel/exit.c
index c63226283aef..b0cc86a2d00b 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>
@@ -982,14 +983,21 @@ SYSCALL_DEFINE1(exit_group, int, error_code)
982 return 0; 983 return 0;
983} 984}
984 985
986struct waitid_info {
987 pid_t pid;
988 uid_t uid;
989 int status;
990 int cause;
991};
992
985struct wait_opts { 993struct wait_opts {
986 enum pid_type wo_type; 994 enum pid_type wo_type;
987 int wo_flags; 995 int wo_flags;
988 struct pid *wo_pid; 996 struct pid *wo_pid;
989 997
990 struct siginfo __user *wo_info; 998 struct waitid_info *wo_info;
991 int __user *wo_stat; 999 int wo_stat;
992 struct rusage __user *wo_rusage; 1000 struct rusage *wo_rusage;
993 1001
994 wait_queue_entry_t child_wait; 1002 wait_queue_entry_t child_wait;
995 int notask_error; 1003 int notask_error;
@@ -1036,34 +1044,6 @@ eligible_child(struct wait_opts *wo, bool ptrace, struct task_struct *p)
1036 return 1; 1044 return 1;
1037} 1045}
1038 1046
1039static int wait_noreap_copyout(struct wait_opts *wo, struct task_struct *p,
1040 pid_t pid, uid_t uid, int why, int status)
1041{
1042 struct siginfo __user *infop;
1043 int retval = wo->wo_rusage
1044 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0;
1045
1046 put_task_struct(p);
1047 infop = wo->wo_info;
1048 if (infop) {
1049 if (!retval)
1050 retval = put_user(SIGCHLD, &infop->si_signo);
1051 if (!retval)
1052 retval = put_user(0, &infop->si_errno);
1053 if (!retval)
1054 retval = put_user((short)why, &infop->si_code);
1055 if (!retval)
1056 retval = put_user(pid, &infop->si_pid);
1057 if (!retval)
1058 retval = put_user(uid, &infop->si_uid);
1059 if (!retval)
1060 retval = put_user(status, &infop->si_status);
1061 }
1062 if (!retval)
1063 retval = pid;
1064 return retval;
1065}
1066
1067/* 1047/*
1068 * Handle sys_wait4 work for one task in state EXIT_ZOMBIE. We hold 1048 * Handle sys_wait4 work for one task in state EXIT_ZOMBIE. We hold
1069 * read_lock(&tasklist_lock) on entry. If we return zero, we still hold 1049 * read_lock(&tasklist_lock) on entry. If we return zero, we still hold
@@ -1072,30 +1052,23 @@ static int wait_noreap_copyout(struct wait_opts *wo, struct task_struct *p,
1072 */ 1052 */
1073static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p) 1053static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1074{ 1054{
1075 int state, retval, status; 1055 int state, status;
1076 pid_t pid = task_pid_vnr(p); 1056 pid_t pid = task_pid_vnr(p);
1077 uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p)); 1057 uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p));
1078 struct siginfo __user *infop; 1058 struct waitid_info *infop;
1079 1059
1080 if (!likely(wo->wo_flags & WEXITED)) 1060 if (!likely(wo->wo_flags & WEXITED))
1081 return 0; 1061 return 0;
1082 1062
1083 if (unlikely(wo->wo_flags & WNOWAIT)) { 1063 if (unlikely(wo->wo_flags & WNOWAIT)) {
1084 int exit_code = p->exit_code; 1064 status = p->exit_code;
1085 int why;
1086
1087 get_task_struct(p); 1065 get_task_struct(p);
1088 read_unlock(&tasklist_lock); 1066 read_unlock(&tasklist_lock);
1089 sched_annotate_sleep(); 1067 sched_annotate_sleep();
1090 1068 if (wo->wo_rusage)
1091 if ((exit_code & 0x7f) == 0) { 1069 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1092 why = CLD_EXITED; 1070 put_task_struct(p);
1093 status = exit_code >> 8; 1071 goto out_info;
1094 } else {
1095 why = (exit_code & 0x80) ? CLD_DUMPED : CLD_KILLED;
1096 status = exit_code & 0x7f;
1097 }
1098 return wait_noreap_copyout(wo, p, pid, uid, why, status);
1099 } 1072 }
1100 /* 1073 /*
1101 * Move the task's state to DEAD/TRACE, only one thread can do this. 1074 * Move the task's state to DEAD/TRACE, only one thread can do this.
@@ -1168,38 +1141,11 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1168 spin_unlock_irq(&current->sighand->siglock); 1141 spin_unlock_irq(&current->sighand->siglock);
1169 } 1142 }
1170 1143
1171 retval = wo->wo_rusage 1144 if (wo->wo_rusage)
1172 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0; 1145 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1173 status = (p->signal->flags & SIGNAL_GROUP_EXIT) 1146 status = (p->signal->flags & SIGNAL_GROUP_EXIT)
1174 ? p->signal->group_exit_code : p->exit_code; 1147 ? p->signal->group_exit_code : p->exit_code;
1175 if (!retval && wo->wo_stat) 1148 wo->wo_stat = status;
1176 retval = put_user(status, wo->wo_stat);
1177
1178 infop = wo->wo_info;
1179 if (!retval && infop)
1180 retval = put_user(SIGCHLD, &infop->si_signo);
1181 if (!retval && infop)
1182 retval = put_user(0, &infop->si_errno);
1183 if (!retval && infop) {
1184 int why;
1185
1186 if ((status & 0x7f) == 0) {
1187 why = CLD_EXITED;
1188 status >>= 8;
1189 } else {
1190 why = (status & 0x80) ? CLD_DUMPED : CLD_KILLED;
1191 status &= 0x7f;
1192 }
1193 retval = put_user((short)why, &infop->si_code);
1194 if (!retval)
1195 retval = put_user(status, &infop->si_status);
1196 }
1197 if (!retval && infop)
1198 retval = put_user(pid, &infop->si_pid);
1199 if (!retval && infop)
1200 retval = put_user(uid, &infop->si_uid);
1201 if (!retval)
1202 retval = pid;
1203 1149
1204 if (state == EXIT_TRACE) { 1150 if (state == EXIT_TRACE) {
1205 write_lock_irq(&tasklist_lock); 1151 write_lock_irq(&tasklist_lock);
@@ -1216,7 +1162,21 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1216 if (state == EXIT_DEAD) 1162 if (state == EXIT_DEAD)
1217 release_task(p); 1163 release_task(p);
1218 1164
1219 return retval; 1165out_info:
1166 infop = wo->wo_info;
1167 if (infop) {
1168 if ((status & 0x7f) == 0) {
1169 infop->cause = CLD_EXITED;
1170 infop->status = status >> 8;
1171 } else {
1172 infop->cause = (status & 0x80) ? CLD_DUMPED : CLD_KILLED;
1173 infop->status = status & 0x7f;
1174 }
1175 infop->pid = pid;
1176 infop->uid = uid;
1177 }
1178
1179 return pid;
1220} 1180}
1221 1181
1222static int *task_stopped_code(struct task_struct *p, bool ptrace) 1182static int *task_stopped_code(struct task_struct *p, bool ptrace)
@@ -1252,8 +1212,8 @@ static int *task_stopped_code(struct task_struct *p, bool ptrace)
1252static int wait_task_stopped(struct wait_opts *wo, 1212static int wait_task_stopped(struct wait_opts *wo,
1253 int ptrace, struct task_struct *p) 1213 int ptrace, struct task_struct *p)
1254{ 1214{
1255 struct siginfo __user *infop; 1215 struct waitid_info *infop;
1256 int retval, exit_code, *p_code, why; 1216 int exit_code, *p_code, why;
1257 uid_t uid = 0; /* unneeded, required by compiler */ 1217 uid_t uid = 0; /* unneeded, required by compiler */
1258 pid_t pid; 1218 pid_t pid;
1259 1219
@@ -1298,34 +1258,21 @@ unlock_sig:
1298 why = ptrace ? CLD_TRAPPED : CLD_STOPPED; 1258 why = ptrace ? CLD_TRAPPED : CLD_STOPPED;
1299 read_unlock(&tasklist_lock); 1259 read_unlock(&tasklist_lock);
1300 sched_annotate_sleep(); 1260 sched_annotate_sleep();
1261 if (wo->wo_rusage)
1262 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1263 put_task_struct(p);
1301 1264
1302 if (unlikely(wo->wo_flags & WNOWAIT)) 1265 if (likely(!(wo->wo_flags & WNOWAIT)))
1303 return wait_noreap_copyout(wo, p, pid, uid, why, exit_code); 1266 wo->wo_stat = (exit_code << 8) | 0x7f;
1304
1305 retval = wo->wo_rusage
1306 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0;
1307 if (!retval && wo->wo_stat)
1308 retval = put_user((exit_code << 8) | 0x7f, wo->wo_stat);
1309 1267
1310 infop = wo->wo_info; 1268 infop = wo->wo_info;
1311 if (!retval && infop) 1269 if (infop) {
1312 retval = put_user(SIGCHLD, &infop->si_signo); 1270 infop->cause = why;
1313 if (!retval && infop) 1271 infop->status = exit_code;
1314 retval = put_user(0, &infop->si_errno); 1272 infop->pid = pid;
1315 if (!retval && infop) 1273 infop->uid = uid;
1316 retval = put_user((short)why, &infop->si_code); 1274 }
1317 if (!retval && infop) 1275 return pid;
1318 retval = put_user(exit_code, &infop->si_status);
1319 if (!retval && infop)
1320 retval = put_user(pid, &infop->si_pid);
1321 if (!retval && infop)
1322 retval = put_user(uid, &infop->si_uid);
1323 if (!retval)
1324 retval = pid;
1325 put_task_struct(p);
1326
1327 BUG_ON(!retval);
1328 return retval;
1329} 1276}
1330 1277
1331/* 1278/*
@@ -1336,7 +1283,7 @@ unlock_sig:
1336 */ 1283 */
1337static int wait_task_continued(struct wait_opts *wo, struct task_struct *p) 1284static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
1338{ 1285{
1339 int retval; 1286 struct waitid_info *infop;
1340 pid_t pid; 1287 pid_t pid;
1341 uid_t uid; 1288 uid_t uid;
1342 1289
@@ -1361,22 +1308,20 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
1361 get_task_struct(p); 1308 get_task_struct(p);
1362 read_unlock(&tasklist_lock); 1309 read_unlock(&tasklist_lock);
1363 sched_annotate_sleep(); 1310 sched_annotate_sleep();
1311 if (wo->wo_rusage)
1312 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1313 put_task_struct(p);
1364 1314
1365 if (!wo->wo_info) { 1315 infop = wo->wo_info;
1366 retval = wo->wo_rusage 1316 if (!infop) {
1367 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0; 1317 wo->wo_stat = 0xffff;
1368 put_task_struct(p);
1369 if (!retval && wo->wo_stat)
1370 retval = put_user(0xffff, wo->wo_stat);
1371 if (!retval)
1372 retval = pid;
1373 } else { 1318 } else {
1374 retval = wait_noreap_copyout(wo, p, pid, uid, 1319 infop->cause = CLD_CONTINUED;
1375 CLD_CONTINUED, SIGCONT); 1320 infop->pid = pid;
1376 BUG_ON(retval == 0); 1321 infop->uid = uid;
1322 infop->status = SIGCONT;
1377 } 1323 }
1378 1324 return pid;
1379 return retval;
1380} 1325}
1381 1326
1382/* 1327/*
@@ -1604,8 +1549,8 @@ end:
1604 return retval; 1549 return retval;
1605} 1550}
1606 1551
1607SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *, 1552static long kernel_waitid(int which, pid_t upid, struct waitid_info *infop,
1608 infop, int, options, struct rusage __user *, ru) 1553 int options, struct rusage *ru)
1609{ 1554{
1610 struct wait_opts wo; 1555 struct wait_opts wo;
1611 struct pid *pid = NULL; 1556 struct pid *pid = NULL;
@@ -1643,38 +1588,46 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
1643 wo.wo_pid = pid; 1588 wo.wo_pid = pid;
1644 wo.wo_flags = options; 1589 wo.wo_flags = options;
1645 wo.wo_info = infop; 1590 wo.wo_info = infop;
1646 wo.wo_stat = NULL;
1647 wo.wo_rusage = ru; 1591 wo.wo_rusage = ru;
1648 ret = do_wait(&wo); 1592 ret = do_wait(&wo);
1649 1593
1650 if (ret > 0) { 1594 if (ret > 0)
1651 ret = 0; 1595 ret = 0;
1652 } else if (infop) {
1653 /*
1654 * For a WNOHANG return, clear out all the fields
1655 * we would set so the user can easily tell the
1656 * difference.
1657 */
1658 if (!ret)
1659 ret = put_user(0, &infop->si_signo);
1660 if (!ret)
1661 ret = put_user(0, &infop->si_errno);
1662 if (!ret)
1663 ret = put_user(0, &infop->si_code);
1664 if (!ret)
1665 ret = put_user(0, &infop->si_pid);
1666 if (!ret)
1667 ret = put_user(0, &infop->si_uid);
1668 if (!ret)
1669 ret = put_user(0, &infop->si_status);
1670 }
1671 1596
1672 put_pid(pid); 1597 put_pid(pid);
1673 return ret; 1598 return ret;
1674} 1599}
1675 1600
1676SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr, 1601SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
1677 int, options, struct rusage __user *, ru) 1602 infop, int, options, struct rusage __user *, ru)
1603{
1604 struct rusage r;
1605 struct waitid_info info = {.status = 0};
1606 long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
1607
1608 if (!err) {
1609 if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
1610 return -EFAULT;
1611 }
1612 if (!infop)
1613 return err;
1614
1615 user_access_begin();
1616 unsafe_put_user(err ? 0 : SIGCHLD, &infop->si_signo, Efault);
1617 unsafe_put_user(0, &infop->si_errno, Efault);
1618 unsafe_put_user((short)info.cause, &infop->si_code, Efault);
1619 unsafe_put_user(info.pid, &infop->si_pid, Efault);
1620 unsafe_put_user(info.uid, &infop->si_uid, Efault);
1621 unsafe_put_user(info.status, &infop->si_status, Efault);
1622 user_access_end();
1623 return err;
1624Efault:
1625 user_access_end();
1626 return -EFAULT;
1627}
1628
1629long kernel_wait4(pid_t upid, int __user *stat_addr, int options,
1630 struct rusage *ru)
1678{ 1631{
1679 struct wait_opts wo; 1632 struct wait_opts wo;
1680 struct pid *pid = NULL; 1633 struct pid *pid = NULL;
@@ -1702,14 +1655,29 @@ SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
1702 wo.wo_pid = pid; 1655 wo.wo_pid = pid;
1703 wo.wo_flags = options | WEXITED; 1656 wo.wo_flags = options | WEXITED;
1704 wo.wo_info = NULL; 1657 wo.wo_info = NULL;
1705 wo.wo_stat = stat_addr; 1658 wo.wo_stat = 0;
1706 wo.wo_rusage = ru; 1659 wo.wo_rusage = ru;
1707 ret = do_wait(&wo); 1660 ret = do_wait(&wo);
1708 put_pid(pid); 1661 put_pid(pid);
1662 if (ret > 0 && stat_addr && put_user(wo.wo_stat, stat_addr))
1663 ret = -EFAULT;
1709 1664
1710 return ret; 1665 return ret;
1711} 1666}
1712 1667
1668SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
1669 int, options, struct rusage __user *, ru)
1670{
1671 struct rusage r;
1672 long err = kernel_wait4(upid, stat_addr, options, ru ? &r : NULL);
1673
1674 if (err > 0) {
1675 if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
1676 return -EFAULT;
1677 }
1678 return err;
1679}
1680
1713#ifdef __ARCH_WANT_SYS_WAITPID 1681#ifdef __ARCH_WANT_SYS_WAITPID
1714 1682
1715/* 1683/*
@@ -1722,3 +1690,56 @@ SYSCALL_DEFINE3(waitpid, pid_t, pid, int __user *, stat_addr, int, options)
1722} 1690}
1723 1691
1724#endif 1692#endif
1693
1694#ifdef CONFIG_COMPAT
1695COMPAT_SYSCALL_DEFINE4(wait4,
1696 compat_pid_t, pid,
1697 compat_uint_t __user *, stat_addr,
1698 int, options,
1699 struct compat_rusage __user *, ru)
1700{
1701 struct rusage r;
1702 long err = kernel_wait4(pid, stat_addr, options, ru ? &r : NULL);
1703 if (err > 0) {
1704 if (ru && put_compat_rusage(&r, ru))
1705 return -EFAULT;
1706 }
1707 return err;
1708}
1709
1710COMPAT_SYSCALL_DEFINE5(waitid,
1711 int, which, compat_pid_t, pid,
1712 struct compat_siginfo __user *, infop, int, options,
1713 struct compat_rusage __user *, uru)
1714{
1715 struct rusage ru;
1716 struct waitid_info info = {.status = 0};
1717 long err = kernel_waitid(which, pid, &info, options, uru ? &ru : NULL);
1718
1719 if (!err && uru) {
1720 /* kernel_waitid() overwrites everything in ru */
1721 if (COMPAT_USE_64BIT_TIME)
1722 err = copy_to_user(uru, &ru, sizeof(ru));
1723 else
1724 err = put_compat_rusage(&ru, uru);
1725 if (err)
1726 return -EFAULT;
1727 }
1728
1729 if (!infop)
1730 return err;
1731
1732 user_access_begin();
1733 unsafe_put_user(err ? 0 : SIGCHLD, &infop->si_signo, Efault);
1734 unsafe_put_user(0, &infop->si_errno, Efault);
1735 unsafe_put_user((short)info.cause, &infop->si_code, Efault);
1736 unsafe_put_user(info.pid, &infop->si_pid, Efault);
1737 unsafe_put_user(info.uid, &infop->si_uid, Efault);
1738 unsafe_put_user(info.status, &infop->si_status, Efault);
1739 user_access_end();
1740 return err;
1741Efault:
1742 user_access_end();
1743 return -EFAULT;
1744}
1745#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