aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/exit.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-05-14 20:25:02 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2017-05-21 13:11:00 -0400
commitce72a16fa705f960ca2352e95a7c5f4801475e75 (patch)
tree6dcdf27d851b4c9e50f689611a26f1dfc10ebef0 /kernel/exit.c
parent7e95a225901a5d2fd140f14b4302805cecc22da7 (diff)
wait4(2)/waitid(2): separate copying rusage to userland
New helpers: kernel_waitid() and kernel_wait4(). sys_waitid(), sys_wait4() and their compat variants switched to those. Copying struct rusage to userland is left to syscall itself. For compat_sys_wait4() that eliminates the use of set_fs() completely. For compat_sys_waitid() it's still needed (for siginfo handling); that will change shortly. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/exit.c')
-rw-r--r--kernel/exit.c89
1 files changed, 52 insertions, 37 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index f98782bd27b6..d44f12948c5f 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1003,7 +1003,7 @@ struct wait_opts {
1003 1003
1004 struct siginfo __user *wo_info; 1004 struct siginfo __user *wo_info;
1005 int __user *wo_stat; 1005 int __user *wo_stat;
1006 struct rusage __user *wo_rusage; 1006 struct rusage *wo_rusage;
1007 1007
1008 wait_queue_t child_wait; 1008 wait_queue_t child_wait;
1009 int notask_error; 1009 int notask_error;
@@ -1054,8 +1054,10 @@ static int wait_noreap_copyout(struct wait_opts *wo, struct task_struct *p,
1054 pid_t pid, uid_t uid, int why, int status) 1054 pid_t pid, uid_t uid, int why, int status)
1055{ 1055{
1056 struct siginfo __user *infop; 1056 struct siginfo __user *infop;
1057 int retval = wo->wo_rusage 1057 int retval = 0;
1058 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0; 1058
1059 if (wo->wo_rusage)
1060 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1059 1061
1060 put_task_struct(p); 1062 put_task_struct(p);
1061 infop = wo->wo_info; 1063 infop = wo->wo_info;
@@ -1182,8 +1184,9 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1182 spin_unlock_irq(&current->sighand->siglock); 1184 spin_unlock_irq(&current->sighand->siglock);
1183 } 1185 }
1184 1186
1185 retval = wo->wo_rusage 1187 if (wo->wo_rusage)
1186 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0; 1188 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1189 retval = 0;
1187 status = (p->signal->flags & SIGNAL_GROUP_EXIT) 1190 status = (p->signal->flags & SIGNAL_GROUP_EXIT)
1188 ? p->signal->group_exit_code : p->exit_code; 1191 ? p->signal->group_exit_code : p->exit_code;
1189 if (!retval && wo->wo_stat) 1192 if (!retval && wo->wo_stat)
@@ -1316,8 +1319,9 @@ unlock_sig:
1316 if (unlikely(wo->wo_flags & WNOWAIT)) 1319 if (unlikely(wo->wo_flags & WNOWAIT))
1317 return wait_noreap_copyout(wo, p, pid, uid, why, exit_code); 1320 return wait_noreap_copyout(wo, p, pid, uid, why, exit_code);
1318 1321
1319 retval = wo->wo_rusage 1322 if (wo->wo_rusage)
1320 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0; 1323 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1324 retval = 0;
1321 if (!retval && wo->wo_stat) 1325 if (!retval && wo->wo_stat)
1322 retval = put_user((exit_code << 8) | 0x7f, wo->wo_stat); 1326 retval = put_user((exit_code << 8) | 0x7f, wo->wo_stat);
1323 1327
@@ -1377,8 +1381,9 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
1377 sched_annotate_sleep(); 1381 sched_annotate_sleep();
1378 1382
1379 if (!wo->wo_info) { 1383 if (!wo->wo_info) {
1380 retval = wo->wo_rusage 1384 if (wo->wo_rusage)
1381 ? getrusage(p, RUSAGE_BOTH, wo->wo_rusage) : 0; 1385 getrusage(p, RUSAGE_BOTH, wo->wo_rusage);
1386 retval = 0;
1382 put_task_struct(p); 1387 put_task_struct(p);
1383 if (!retval && wo->wo_stat) 1388 if (!retval && wo->wo_stat)
1384 retval = put_user(0xffff, wo->wo_stat); 1389 retval = put_user(0xffff, wo->wo_stat);
@@ -1618,8 +1623,8 @@ end:
1618 return retval; 1623 return retval;
1619} 1624}
1620 1625
1621SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *, 1626static long kernel_waitid(int which, pid_t upid, struct siginfo __user *infop,
1622 infop, int, options, struct rusage __user *, ru) 1627 int options, struct rusage *ru)
1623{ 1628{
1624 struct wait_opts wo; 1629 struct wait_opts wo;
1625 struct pid *pid = NULL; 1630 struct pid *pid = NULL;
@@ -1687,8 +1692,21 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
1687 return ret; 1692 return ret;
1688} 1693}
1689 1694
1690SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr, 1695SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
1691 int, options, struct rusage __user *, ru) 1696 infop, int, options, struct rusage __user *, ru)
1697{
1698 struct rusage r;
1699 long err = kernel_waitid(which, upid, infop, options, ru ? &r : NULL);
1700
1701 if (!err) {
1702 if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
1703 return -EFAULT;
1704 }
1705 return err;
1706}
1707
1708static long kernel_wait4(pid_t upid, int __user *stat_addr,
1709 int options, struct rusage *ru)
1692{ 1710{
1693 struct wait_opts wo; 1711 struct wait_opts wo;
1694 struct pid *pid = NULL; 1712 struct pid *pid = NULL;
@@ -1724,6 +1742,19 @@ SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
1724 return ret; 1742 return ret;
1725} 1743}
1726 1744
1745SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr,
1746 int, options, struct rusage __user *, ru)
1747{
1748 struct rusage r;
1749 long err = kernel_wait4(upid, stat_addr, options, ru ? &r : NULL);
1750
1751 if (err > 0) {
1752 if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
1753 return -EFAULT;
1754 }
1755 return err;
1756}
1757
1727#ifdef __ARCH_WANT_SYS_WAITPID 1758#ifdef __ARCH_WANT_SYS_WAITPID
1728 1759
1729/* 1760/*
@@ -1744,29 +1775,13 @@ COMPAT_SYSCALL_DEFINE4(wait4,
1744 int, options, 1775 int, options,
1745 struct compat_rusage __user *, ru) 1776 struct compat_rusage __user *, ru)
1746{ 1777{
1747 if (!ru) { 1778 struct rusage r;
1748 return sys_wait4(pid, stat_addr, options, NULL); 1779 long err = kernel_wait4(pid, stat_addr, options, ru ? &r : NULL);
1749 } else { 1780 if (err > 0) {
1750 struct rusage r; 1781 if (ru && put_compat_rusage(&r, ru))
1751 int ret; 1782 return -EFAULT;
1752 unsigned int status;
1753 mm_segment_t old_fs = get_fs();
1754
1755 set_fs (KERNEL_DS);
1756 ret = sys_wait4(pid,
1757 (stat_addr ?
1758 (unsigned int __user *) &status : NULL),
1759 options, (struct rusage __user *) &r);
1760 set_fs (old_fs);
1761
1762 if (ret > 0) {
1763 if (put_compat_rusage(&r, ru))
1764 return -EFAULT;
1765 if (stat_addr && put_user(status, stat_addr))
1766 return -EFAULT;
1767 }
1768 return ret;
1769 } 1783 }
1784 return err;
1770} 1785}
1771 1786
1772COMPAT_SYSCALL_DEFINE5(waitid, 1787COMPAT_SYSCALL_DEFINE5(waitid,
@@ -1782,8 +1797,8 @@ COMPAT_SYSCALL_DEFINE5(waitid,
1782 memset(&info, 0, sizeof(info)); 1797 memset(&info, 0, sizeof(info));
1783 1798
1784 set_fs(KERNEL_DS); 1799 set_fs(KERNEL_DS);
1785 ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options, 1800 ret = kernel_waitid(which, pid, (siginfo_t __user *)&info, options,
1786 uru ? (struct rusage __user *)&ru : NULL); 1801 uru ? &ru : NULL);
1787 set_fs(old_fs); 1802 set_fs(old_fs);
1788 1803
1789 if ((ret < 0) || (info.si_signo == 0)) 1804 if ((ret < 0) || (info.si_signo == 0))