diff options
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 89 |
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(¤t->sighand->siglock); | 1184 | spin_unlock_irq(¤t->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 | ||
1621 | SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *, | 1626 | static 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 | ||
1690 | SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr, | 1695 | SYSCALL_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 | |||
1708 | static 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 | ||
1745 | SYSCALL_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 | ||
1772 | COMPAT_SYSCALL_DEFINE5(waitid, | 1787 | COMPAT_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)) |