aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-05-14 20:39:39 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2017-05-21 13:11:07 -0400
commit359566faefa850504d146839d74496f0cf12d3b9 (patch)
tree2000268b17f7fa236643c9d572147d883ace81ed
parentce72a16fa705f960ca2352e95a7c5f4801475e75 (diff)
kernel_wait4()/kernel_waitid(): delay copying status to userland
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--kernel/exit.c20
1 files changed, 8 insertions, 12 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index d44f12948c5f..94cdccf8e7e7 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1002,7 +1002,7 @@ struct wait_opts {
1002 struct pid *wo_pid; 1002 struct pid *wo_pid;
1003 1003
1004 struct siginfo __user *wo_info; 1004 struct siginfo __user *wo_info;
1005 int __user *wo_stat; 1005 int wo_stat;
1006 struct rusage *wo_rusage; 1006 struct rusage *wo_rusage;
1007 1007
1008 wait_queue_t child_wait; 1008 wait_queue_t child_wait;
@@ -1189,8 +1189,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1189 retval = 0; 1189 retval = 0;
1190 status = (p->signal->flags & SIGNAL_GROUP_EXIT) 1190 status = (p->signal->flags & SIGNAL_GROUP_EXIT)
1191 ? p->signal->group_exit_code : p->exit_code; 1191 ? p->signal->group_exit_code : p->exit_code;
1192 if (!retval && wo->wo_stat) 1192 wo->wo_stat = status;
1193 retval = put_user(status, wo->wo_stat);
1194 1193
1195 infop = wo->wo_info; 1194 infop = wo->wo_info;
1196 if (!retval && infop) 1195 if (!retval && infop)
@@ -1322,8 +1321,7 @@ unlock_sig:
1322 if (wo->wo_rusage) 1321 if (wo->wo_rusage)
1323 getrusage(p, RUSAGE_BOTH, wo->wo_rusage); 1322 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1324 retval = 0; 1323 retval = 0;
1325 if (!retval && wo->wo_stat) 1324 wo->wo_stat = (exit_code << 8) | 0x7f;
1326 retval = put_user((exit_code << 8) | 0x7f, wo->wo_stat);
1327 1325
1328 infop = wo->wo_info; 1326 infop = wo->wo_info;
1329 if (!retval && infop) 1327 if (!retval && infop)
@@ -1383,12 +1381,9 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
1383 if (!wo->wo_info) { 1381 if (!wo->wo_info) {
1384 if (wo->wo_rusage) 1382 if (wo->wo_rusage)
1385 getrusage(p, RUSAGE_BOTH, wo->wo_rusage); 1383 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1386 retval = 0;
1387 put_task_struct(p); 1384 put_task_struct(p);
1388 if (!retval && wo->wo_stat) 1385 wo->wo_stat = 0xffff;
1389 retval = put_user(0xffff, wo->wo_stat); 1386 retval = pid;
1390 if (!retval)
1391 retval = pid;
1392 } else { 1387 } else {
1393 retval = wait_noreap_copyout(wo, p, pid, uid, 1388 retval = wait_noreap_copyout(wo, p, pid, uid,
1394 CLD_CONTINUED, SIGCONT); 1389 CLD_CONTINUED, SIGCONT);
@@ -1662,7 +1657,6 @@ static long kernel_waitid(int which, pid_t upid, struct siginfo __user *infop,
1662 wo.wo_pid = pid; 1657 wo.wo_pid = pid;
1663 wo.wo_flags = options; 1658 wo.wo_flags = options;
1664 wo.wo_info = infop; 1659 wo.wo_info = infop;
1665 wo.wo_stat = NULL;
1666 wo.wo_rusage = ru; 1660 wo.wo_rusage = ru;
1667 ret = do_wait(&wo); 1661 ret = do_wait(&wo);
1668 1662
@@ -1734,10 +1728,12 @@ static long kernel_wait4(pid_t upid, int __user *stat_addr,
1734 wo.wo_pid = pid; 1728 wo.wo_pid = pid;
1735 wo.wo_flags = options | WEXITED; 1729 wo.wo_flags = options | WEXITED;
1736 wo.wo_info = NULL; 1730 wo.wo_info = NULL;
1737 wo.wo_stat = stat_addr; 1731 wo.wo_stat = 0;
1738 wo.wo_rusage = ru; 1732 wo.wo_rusage = ru;
1739 ret = do_wait(&wo); 1733 ret = do_wait(&wo);
1740 put_pid(pid); 1734 put_pid(pid);
1735 if (ret > 0 && stat_addr && put_user(wo.wo_stat, stat_addr))
1736 ret = -EFAULT;
1741 1737
1742 return ret; 1738 return ret;
1743} 1739}