diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 168 |
1 files changed, 74 insertions, 94 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 64c5deeaca5d..6705320784fd 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -705,7 +705,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) | |||
705 | 705 | ||
706 | if (why) { | 706 | if (why) { |
707 | /* | 707 | /* |
708 | * The first thread which returns from finish_stop() | 708 | * The first thread which returns from do_signal_stop() |
709 | * will take ->siglock, notice SIGNAL_CLD_MASK, and | 709 | * will take ->siglock, notice SIGNAL_CLD_MASK, and |
710 | * notify its parent. See get_signal_to_deliver(). | 710 | * notify its parent. See get_signal_to_deliver(). |
711 | */ | 711 | */ |
@@ -971,6 +971,20 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) | |||
971 | return send_signal(sig, info, t, 0); | 971 | return send_signal(sig, info, t, 0); |
972 | } | 972 | } |
973 | 973 | ||
974 | int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, | ||
975 | bool group) | ||
976 | { | ||
977 | unsigned long flags; | ||
978 | int ret = -ESRCH; | ||
979 | |||
980 | if (lock_task_sighand(p, &flags)) { | ||
981 | ret = send_signal(sig, info, p, group); | ||
982 | unlock_task_sighand(p, &flags); | ||
983 | } | ||
984 | |||
985 | return ret; | ||
986 | } | ||
987 | |||
974 | /* | 988 | /* |
975 | * Force a signal that the process can't ignore: if necessary | 989 | * Force a signal that the process can't ignore: if necessary |
976 | * we unblock the signal and change any SIG_IGN to SIG_DFL. | 990 | * we unblock the signal and change any SIG_IGN to SIG_DFL. |
@@ -1036,12 +1050,6 @@ void zap_other_threads(struct task_struct *p) | |||
1036 | } | 1050 | } |
1037 | } | 1051 | } |
1038 | 1052 | ||
1039 | int __fatal_signal_pending(struct task_struct *tsk) | ||
1040 | { | ||
1041 | return sigismember(&tsk->pending.signal, SIGKILL); | ||
1042 | } | ||
1043 | EXPORT_SYMBOL(__fatal_signal_pending); | ||
1044 | |||
1045 | struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long *flags) | 1053 | struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long *flags) |
1046 | { | 1054 | { |
1047 | struct sighand_struct *sighand; | 1055 | struct sighand_struct *sighand; |
@@ -1068,18 +1076,10 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long | |||
1068 | */ | 1076 | */ |
1069 | int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | 1077 | int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) |
1070 | { | 1078 | { |
1071 | unsigned long flags; | 1079 | int ret = check_kill_permission(sig, info, p); |
1072 | int ret; | ||
1073 | 1080 | ||
1074 | ret = check_kill_permission(sig, info, p); | 1081 | if (!ret && sig) |
1075 | 1082 | ret = do_send_sig_info(sig, info, p, true); | |
1076 | if (!ret && sig) { | ||
1077 | ret = -ESRCH; | ||
1078 | if (lock_task_sighand(p, &flags)) { | ||
1079 | ret = __group_send_sig_info(sig, info, p); | ||
1080 | unlock_task_sighand(p, &flags); | ||
1081 | } | ||
1082 | } | ||
1083 | 1083 | ||
1084 | return ret; | 1084 | return ret; |
1085 | } | 1085 | } |
@@ -1224,15 +1224,9 @@ static int kill_something_info(int sig, struct siginfo *info, pid_t pid) | |||
1224 | * These are for backward compatibility with the rest of the kernel source. | 1224 | * These are for backward compatibility with the rest of the kernel source. |
1225 | */ | 1225 | */ |
1226 | 1226 | ||
1227 | /* | ||
1228 | * The caller must ensure the task can't exit. | ||
1229 | */ | ||
1230 | int | 1227 | int |
1231 | send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | 1228 | send_sig_info(int sig, struct siginfo *info, struct task_struct *p) |
1232 | { | 1229 | { |
1233 | int ret; | ||
1234 | unsigned long flags; | ||
1235 | |||
1236 | /* | 1230 | /* |
1237 | * Make sure legacy kernel users don't send in bad values | 1231 | * Make sure legacy kernel users don't send in bad values |
1238 | * (normal paths check this in check_kill_permission). | 1232 | * (normal paths check this in check_kill_permission). |
@@ -1240,10 +1234,7 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | |||
1240 | if (!valid_signal(sig)) | 1234 | if (!valid_signal(sig)) |
1241 | return -EINVAL; | 1235 | return -EINVAL; |
1242 | 1236 | ||
1243 | spin_lock_irqsave(&p->sighand->siglock, flags); | 1237 | return do_send_sig_info(sig, info, p, false); |
1244 | ret = specific_send_sig_info(sig, info, p); | ||
1245 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | ||
1246 | return ret; | ||
1247 | } | 1238 | } |
1248 | 1239 | ||
1249 | #define __si_special(priv) \ | 1240 | #define __si_special(priv) \ |
@@ -1383,15 +1374,6 @@ ret: | |||
1383 | } | 1374 | } |
1384 | 1375 | ||
1385 | /* | 1376 | /* |
1386 | * Wake up any threads in the parent blocked in wait* syscalls. | ||
1387 | */ | ||
1388 | static inline void __wake_up_parent(struct task_struct *p, | ||
1389 | struct task_struct *parent) | ||
1390 | { | ||
1391 | wake_up_interruptible_sync(&parent->signal->wait_chldexit); | ||
1392 | } | ||
1393 | |||
1394 | /* | ||
1395 | * Let a parent know about the death of a child. | 1377 | * Let a parent know about the death of a child. |
1396 | * For a stopped/continued status change, use do_notify_parent_cldstop instead. | 1378 | * For a stopped/continued status change, use do_notify_parent_cldstop instead. |
1397 | * | 1379 | * |
@@ -1673,29 +1655,6 @@ void ptrace_notify(int exit_code) | |||
1673 | spin_unlock_irq(¤t->sighand->siglock); | 1655 | spin_unlock_irq(¤t->sighand->siglock); |
1674 | } | 1656 | } |
1675 | 1657 | ||
1676 | static void | ||
1677 | finish_stop(int stop_count) | ||
1678 | { | ||
1679 | /* | ||
1680 | * If there are no other threads in the group, or if there is | ||
1681 | * a group stop in progress and we are the last to stop, | ||
1682 | * report to the parent. When ptraced, every thread reports itself. | ||
1683 | */ | ||
1684 | if (tracehook_notify_jctl(stop_count == 0, CLD_STOPPED)) { | ||
1685 | read_lock(&tasklist_lock); | ||
1686 | do_notify_parent_cldstop(current, CLD_STOPPED); | ||
1687 | read_unlock(&tasklist_lock); | ||
1688 | } | ||
1689 | |||
1690 | do { | ||
1691 | schedule(); | ||
1692 | } while (try_to_freeze()); | ||
1693 | /* | ||
1694 | * Now we don't run again until continued. | ||
1695 | */ | ||
1696 | current->exit_code = 0; | ||
1697 | } | ||
1698 | |||
1699 | /* | 1658 | /* |
1700 | * This performs the stopping for SIGSTOP and other stop signals. | 1659 | * This performs the stopping for SIGSTOP and other stop signals. |
1701 | * We have to stop all threads in the thread group. | 1660 | * We have to stop all threads in the thread group. |
@@ -1705,15 +1664,9 @@ finish_stop(int stop_count) | |||
1705 | static int do_signal_stop(int signr) | 1664 | static int do_signal_stop(int signr) |
1706 | { | 1665 | { |
1707 | struct signal_struct *sig = current->signal; | 1666 | struct signal_struct *sig = current->signal; |
1708 | int stop_count; | 1667 | int notify; |
1709 | 1668 | ||
1710 | if (sig->group_stop_count > 0) { | 1669 | if (!sig->group_stop_count) { |
1711 | /* | ||
1712 | * There is a group stop in progress. We don't need to | ||
1713 | * start another one. | ||
1714 | */ | ||
1715 | stop_count = --sig->group_stop_count; | ||
1716 | } else { | ||
1717 | struct task_struct *t; | 1670 | struct task_struct *t; |
1718 | 1671 | ||
1719 | if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || | 1672 | if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || |
@@ -1725,7 +1678,7 @@ static int do_signal_stop(int signr) | |||
1725 | */ | 1678 | */ |
1726 | sig->group_exit_code = signr; | 1679 | sig->group_exit_code = signr; |
1727 | 1680 | ||
1728 | stop_count = 0; | 1681 | sig->group_stop_count = 1; |
1729 | for (t = next_thread(current); t != current; t = next_thread(t)) | 1682 | for (t = next_thread(current); t != current; t = next_thread(t)) |
1730 | /* | 1683 | /* |
1731 | * Setting state to TASK_STOPPED for a group | 1684 | * Setting state to TASK_STOPPED for a group |
@@ -1734,19 +1687,44 @@ static int do_signal_stop(int signr) | |||
1734 | */ | 1687 | */ |
1735 | if (!(t->flags & PF_EXITING) && | 1688 | if (!(t->flags & PF_EXITING) && |
1736 | !task_is_stopped_or_traced(t)) { | 1689 | !task_is_stopped_or_traced(t)) { |
1737 | stop_count++; | 1690 | sig->group_stop_count++; |
1738 | signal_wake_up(t, 0); | 1691 | signal_wake_up(t, 0); |
1739 | } | 1692 | } |
1740 | sig->group_stop_count = stop_count; | ||
1741 | } | 1693 | } |
1694 | /* | ||
1695 | * If there are no other threads in the group, or if there is | ||
1696 | * a group stop in progress and we are the last to stop, report | ||
1697 | * to the parent. When ptraced, every thread reports itself. | ||
1698 | */ | ||
1699 | notify = sig->group_stop_count == 1 ? CLD_STOPPED : 0; | ||
1700 | notify = tracehook_notify_jctl(notify, CLD_STOPPED); | ||
1701 | /* | ||
1702 | * tracehook_notify_jctl() can drop and reacquire siglock, so | ||
1703 | * we keep ->group_stop_count != 0 before the call. If SIGCONT | ||
1704 | * or SIGKILL comes in between ->group_stop_count == 0. | ||
1705 | */ | ||
1706 | if (sig->group_stop_count) { | ||
1707 | if (!--sig->group_stop_count) | ||
1708 | sig->flags = SIGNAL_STOP_STOPPED; | ||
1709 | current->exit_code = sig->group_exit_code; | ||
1710 | __set_current_state(TASK_STOPPED); | ||
1711 | } | ||
1712 | spin_unlock_irq(¤t->sighand->siglock); | ||
1742 | 1713 | ||
1743 | if (stop_count == 0) | 1714 | if (notify) { |
1744 | sig->flags = SIGNAL_STOP_STOPPED; | 1715 | read_lock(&tasklist_lock); |
1745 | current->exit_code = sig->group_exit_code; | 1716 | do_notify_parent_cldstop(current, notify); |
1746 | __set_current_state(TASK_STOPPED); | 1717 | read_unlock(&tasklist_lock); |
1718 | } | ||
1719 | |||
1720 | /* Now we don't run again until woken by SIGCONT or SIGKILL */ | ||
1721 | do { | ||
1722 | schedule(); | ||
1723 | } while (try_to_freeze()); | ||
1724 | |||
1725 | tracehook_finish_jctl(); | ||
1726 | current->exit_code = 0; | ||
1747 | 1727 | ||
1748 | spin_unlock_irq(¤t->sighand->siglock); | ||
1749 | finish_stop(stop_count); | ||
1750 | return 1; | 1728 | return 1; |
1751 | } | 1729 | } |
1752 | 1730 | ||
@@ -1815,14 +1793,15 @@ relock: | |||
1815 | int why = (signal->flags & SIGNAL_STOP_CONTINUED) | 1793 | int why = (signal->flags & SIGNAL_STOP_CONTINUED) |
1816 | ? CLD_CONTINUED : CLD_STOPPED; | 1794 | ? CLD_CONTINUED : CLD_STOPPED; |
1817 | signal->flags &= ~SIGNAL_CLD_MASK; | 1795 | signal->flags &= ~SIGNAL_CLD_MASK; |
1818 | spin_unlock_irq(&sighand->siglock); | ||
1819 | 1796 | ||
1820 | if (unlikely(!tracehook_notify_jctl(1, why))) | 1797 | why = tracehook_notify_jctl(why, CLD_CONTINUED); |
1821 | goto relock; | 1798 | spin_unlock_irq(&sighand->siglock); |
1822 | 1799 | ||
1823 | read_lock(&tasklist_lock); | 1800 | if (why) { |
1824 | do_notify_parent_cldstop(current->group_leader, why); | 1801 | read_lock(&tasklist_lock); |
1825 | read_unlock(&tasklist_lock); | 1802 | do_notify_parent_cldstop(current->group_leader, why); |
1803 | read_unlock(&tasklist_lock); | ||
1804 | } | ||
1826 | goto relock; | 1805 | goto relock; |
1827 | } | 1806 | } |
1828 | 1807 | ||
@@ -1987,14 +1966,14 @@ void exit_signals(struct task_struct *tsk) | |||
1987 | if (unlikely(tsk->signal->group_stop_count) && | 1966 | if (unlikely(tsk->signal->group_stop_count) && |
1988 | !--tsk->signal->group_stop_count) { | 1967 | !--tsk->signal->group_stop_count) { |
1989 | tsk->signal->flags = SIGNAL_STOP_STOPPED; | 1968 | tsk->signal->flags = SIGNAL_STOP_STOPPED; |
1990 | group_stop = 1; | 1969 | group_stop = tracehook_notify_jctl(CLD_STOPPED, CLD_STOPPED); |
1991 | } | 1970 | } |
1992 | out: | 1971 | out: |
1993 | spin_unlock_irq(&tsk->sighand->siglock); | 1972 | spin_unlock_irq(&tsk->sighand->siglock); |
1994 | 1973 | ||
1995 | if (unlikely(group_stop) && tracehook_notify_jctl(1, CLD_STOPPED)) { | 1974 | if (unlikely(group_stop)) { |
1996 | read_lock(&tasklist_lock); | 1975 | read_lock(&tasklist_lock); |
1997 | do_notify_parent_cldstop(tsk, CLD_STOPPED); | 1976 | do_notify_parent_cldstop(tsk, group_stop); |
1998 | read_unlock(&tasklist_lock); | 1977 | read_unlock(&tasklist_lock); |
1999 | } | 1978 | } |
2000 | } | 1979 | } |
@@ -2290,7 +2269,6 @@ static int | |||
2290 | do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info) | 2269 | do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info) |
2291 | { | 2270 | { |
2292 | struct task_struct *p; | 2271 | struct task_struct *p; |
2293 | unsigned long flags; | ||
2294 | int error = -ESRCH; | 2272 | int error = -ESRCH; |
2295 | 2273 | ||
2296 | rcu_read_lock(); | 2274 | rcu_read_lock(); |
@@ -2300,14 +2278,16 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info) | |||
2300 | /* | 2278 | /* |
2301 | * The null signal is a permissions and process existence | 2279 | * The null signal is a permissions and process existence |
2302 | * probe. No signal is actually delivered. | 2280 | * probe. No signal is actually delivered. |
2303 | * | ||
2304 | * If lock_task_sighand() fails we pretend the task dies | ||
2305 | * after receiving the signal. The window is tiny, and the | ||
2306 | * signal is private anyway. | ||
2307 | */ | 2281 | */ |
2308 | if (!error && sig && lock_task_sighand(p, &flags)) { | 2282 | if (!error && sig) { |
2309 | error = specific_send_sig_info(sig, info, p); | 2283 | error = do_send_sig_info(sig, info, p, false); |
2310 | unlock_task_sighand(p, &flags); | 2284 | /* |
2285 | * If lock_task_sighand() failed we pretend the task | ||
2286 | * dies after receiving the signal. The window is tiny, | ||
2287 | * and the signal is private anyway. | ||
2288 | */ | ||
2289 | if (unlikely(error == -ESRCH)) | ||
2290 | error = 0; | ||
2311 | } | 2291 | } |
2312 | } | 2292 | } |
2313 | rcu_read_unlock(); | 2293 | rcu_read_unlock(); |