diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-07-28 15:14:43 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-07-28 15:14:43 -0400 |
| commit | 414f746d232d41ed6ae8632c4495ae795373c44b (patch) | |
| tree | 167f9bc8f139c6e82e6732b38c7a938b8a9d31cd /kernel/signal.c | |
| parent | 5a7a201c51c324876d00a54e7208af6af12d1ca4 (diff) | |
| parent | c9272c4f9fbe2087beb3392f526dc5b19efaa56b (diff) | |
Merge branch 'linus' into cpus4096
Diffstat (limited to 'kernel/signal.c')
| -rw-r--r-- | kernel/signal.c | 99 |
1 files changed, 63 insertions, 36 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 82c3545596c5..954f77d7e3bc 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/ptrace.h> | 22 | #include <linux/ptrace.h> |
| 23 | #include <linux/signal.h> | 23 | #include <linux/signal.h> |
| 24 | #include <linux/signalfd.h> | 24 | #include <linux/signalfd.h> |
| 25 | #include <linux/tracehook.h> | ||
| 25 | #include <linux/capability.h> | 26 | #include <linux/capability.h> |
| 26 | #include <linux/freezer.h> | 27 | #include <linux/freezer.h> |
| 27 | #include <linux/pid_namespace.h> | 28 | #include <linux/pid_namespace.h> |
| @@ -39,24 +40,21 @@ | |||
| 39 | 40 | ||
| 40 | static struct kmem_cache *sigqueue_cachep; | 41 | static struct kmem_cache *sigqueue_cachep; |
| 41 | 42 | ||
| 42 | static int __sig_ignored(struct task_struct *t, int sig) | 43 | static void __user *sig_handler(struct task_struct *t, int sig) |
| 43 | { | 44 | { |
| 44 | void __user *handler; | 45 | return t->sighand->action[sig - 1].sa.sa_handler; |
| 46 | } | ||
| 45 | 47 | ||
| 48 | static int sig_handler_ignored(void __user *handler, int sig) | ||
| 49 | { | ||
| 46 | /* Is it explicitly or implicitly ignored? */ | 50 | /* Is it explicitly or implicitly ignored? */ |
| 47 | |||
| 48 | handler = t->sighand->action[sig - 1].sa.sa_handler; | ||
| 49 | return handler == SIG_IGN || | 51 | return handler == SIG_IGN || |
| 50 | (handler == SIG_DFL && sig_kernel_ignore(sig)); | 52 | (handler == SIG_DFL && sig_kernel_ignore(sig)); |
| 51 | } | 53 | } |
| 52 | 54 | ||
| 53 | static int sig_ignored(struct task_struct *t, int sig) | 55 | static int sig_ignored(struct task_struct *t, int sig) |
| 54 | { | 56 | { |
| 55 | /* | 57 | void __user *handler; |
| 56 | * Tracers always want to know about signals.. | ||
| 57 | */ | ||
| 58 | if (t->ptrace & PT_PTRACED) | ||
| 59 | return 0; | ||
| 60 | 58 | ||
| 61 | /* | 59 | /* |
| 62 | * Blocked signals are never ignored, since the | 60 | * Blocked signals are never ignored, since the |
| @@ -66,7 +64,14 @@ static int sig_ignored(struct task_struct *t, int sig) | |||
| 66 | if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig)) | 64 | if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig)) |
| 67 | return 0; | 65 | return 0; |
| 68 | 66 | ||
| 69 | return __sig_ignored(t, sig); | 67 | handler = sig_handler(t, sig); |
| 68 | if (!sig_handler_ignored(handler, sig)) | ||
| 69 | return 0; | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Tracers may want to know about even ignored signals. | ||
| 73 | */ | ||
| 74 | return !tracehook_consider_ignored_signal(t, sig, handler); | ||
| 70 | } | 75 | } |
| 71 | 76 | ||
| 72 | /* | 77 | /* |
| @@ -129,7 +134,9 @@ void recalc_sigpending_and_wake(struct task_struct *t) | |||
| 129 | 134 | ||
| 130 | void recalc_sigpending(void) | 135 | void recalc_sigpending(void) |
| 131 | { | 136 | { |
| 132 | if (!recalc_sigpending_tsk(current) && !freezing(current)) | 137 | if (unlikely(tracehook_force_sigpending())) |
| 138 | set_thread_flag(TIF_SIGPENDING); | ||
| 139 | else if (!recalc_sigpending_tsk(current) && !freezing(current)) | ||
| 133 | clear_thread_flag(TIF_SIGPENDING); | 140 | clear_thread_flag(TIF_SIGPENDING); |
| 134 | 141 | ||
| 135 | } | 142 | } |
| @@ -295,12 +302,12 @@ flush_signal_handlers(struct task_struct *t, int force_default) | |||
| 295 | 302 | ||
| 296 | int unhandled_signal(struct task_struct *tsk, int sig) | 303 | int unhandled_signal(struct task_struct *tsk, int sig) |
| 297 | { | 304 | { |
| 305 | void __user *handler = tsk->sighand->action[sig-1].sa.sa_handler; | ||
| 298 | if (is_global_init(tsk)) | 306 | if (is_global_init(tsk)) |
| 299 | return 1; | 307 | return 1; |
| 300 | if (tsk->ptrace & PT_PTRACED) | 308 | if (handler != SIG_IGN && handler != SIG_DFL) |
| 301 | return 0; | 309 | return 0; |
| 302 | return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) || | 310 | return !tracehook_consider_fatal_signal(tsk, sig, handler); |
| 303 | (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL); | ||
| 304 | } | 311 | } |
| 305 | 312 | ||
| 306 | 313 | ||
| @@ -591,9 +598,6 @@ static int check_kill_permission(int sig, struct siginfo *info, | |||
| 591 | return security_task_kill(t, info, sig, 0); | 598 | return security_task_kill(t, info, sig, 0); |
| 592 | } | 599 | } |
| 593 | 600 | ||
| 594 | /* forward decl */ | ||
| 595 | static void do_notify_parent_cldstop(struct task_struct *tsk, int why); | ||
| 596 | |||
| 597 | /* | 601 | /* |
| 598 | * Handle magic process-wide effects of stop/continue signals. Unlike | 602 | * Handle magic process-wide effects of stop/continue signals. Unlike |
| 599 | * the signal actions, these happen immediately at signal-generation | 603 | * the signal actions, these happen immediately at signal-generation |
| @@ -756,7 +760,8 @@ static void complete_signal(int sig, struct task_struct *p, int group) | |||
| 756 | if (sig_fatal(p, sig) && | 760 | if (sig_fatal(p, sig) && |
| 757 | !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && | 761 | !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && |
| 758 | !sigismember(&t->real_blocked, sig) && | 762 | !sigismember(&t->real_blocked, sig) && |
| 759 | (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) { | 763 | (sig == SIGKILL || |
| 764 | !tracehook_consider_fatal_signal(t, sig, SIG_DFL))) { | ||
| 760 | /* | 765 | /* |
| 761 | * This signal will be fatal to the whole group. | 766 | * This signal will be fatal to the whole group. |
| 762 | */ | 767 | */ |
| @@ -1323,9 +1328,11 @@ static inline void __wake_up_parent(struct task_struct *p, | |||
| 1323 | /* | 1328 | /* |
| 1324 | * Let a parent know about the death of a child. | 1329 | * Let a parent know about the death of a child. |
| 1325 | * For a stopped/continued status change, use do_notify_parent_cldstop instead. | 1330 | * For a stopped/continued status change, use do_notify_parent_cldstop instead. |
| 1331 | * | ||
| 1332 | * Returns -1 if our parent ignored us and so we've switched to | ||
| 1333 | * self-reaping, or else @sig. | ||
| 1326 | */ | 1334 | */ |
| 1327 | 1335 | int do_notify_parent(struct task_struct *tsk, int sig) | |
| 1328 | void do_notify_parent(struct task_struct *tsk, int sig) | ||
| 1329 | { | 1336 | { |
| 1330 | struct siginfo info; | 1337 | struct siginfo info; |
| 1331 | unsigned long flags; | 1338 | unsigned long flags; |
| @@ -1396,12 +1403,14 @@ void do_notify_parent(struct task_struct *tsk, int sig) | |||
| 1396 | */ | 1403 | */ |
| 1397 | tsk->exit_signal = -1; | 1404 | tsk->exit_signal = -1; |
| 1398 | if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) | 1405 | if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) |
| 1399 | sig = 0; | 1406 | sig = -1; |
| 1400 | } | 1407 | } |
| 1401 | if (valid_signal(sig) && sig > 0) | 1408 | if (valid_signal(sig) && sig > 0) |
| 1402 | __group_send_sig_info(sig, &info, tsk->parent); | 1409 | __group_send_sig_info(sig, &info, tsk->parent); |
| 1403 | __wake_up_parent(tsk, tsk->parent); | 1410 | __wake_up_parent(tsk, tsk->parent); |
| 1404 | spin_unlock_irqrestore(&psig->siglock, flags); | 1411 | spin_unlock_irqrestore(&psig->siglock, flags); |
| 1412 | |||
| 1413 | return sig; | ||
| 1405 | } | 1414 | } |
| 1406 | 1415 | ||
| 1407 | static void do_notify_parent_cldstop(struct task_struct *tsk, int why) | 1416 | static void do_notify_parent_cldstop(struct task_struct *tsk, int why) |
| @@ -1599,7 +1608,7 @@ finish_stop(int stop_count) | |||
| 1599 | * a group stop in progress and we are the last to stop, | 1608 | * a group stop in progress and we are the last to stop, |
| 1600 | * report to the parent. When ptraced, every thread reports itself. | 1609 | * report to the parent. When ptraced, every thread reports itself. |
| 1601 | */ | 1610 | */ |
| 1602 | if (stop_count == 0 || (current->ptrace & PT_PTRACED)) { | 1611 | if (tracehook_notify_jctl(stop_count == 0, CLD_STOPPED)) { |
| 1603 | read_lock(&tasklist_lock); | 1612 | read_lock(&tasklist_lock); |
| 1604 | do_notify_parent_cldstop(current, CLD_STOPPED); | 1613 | do_notify_parent_cldstop(current, CLD_STOPPED); |
| 1605 | read_unlock(&tasklist_lock); | 1614 | read_unlock(&tasklist_lock); |
| @@ -1735,6 +1744,9 @@ relock: | |||
| 1735 | signal->flags &= ~SIGNAL_CLD_MASK; | 1744 | signal->flags &= ~SIGNAL_CLD_MASK; |
| 1736 | spin_unlock_irq(&sighand->siglock); | 1745 | spin_unlock_irq(&sighand->siglock); |
| 1737 | 1746 | ||
| 1747 | if (unlikely(!tracehook_notify_jctl(1, why))) | ||
| 1748 | goto relock; | ||
| 1749 | |||
| 1738 | read_lock(&tasklist_lock); | 1750 | read_lock(&tasklist_lock); |
| 1739 | do_notify_parent_cldstop(current->group_leader, why); | 1751 | do_notify_parent_cldstop(current->group_leader, why); |
| 1740 | read_unlock(&tasklist_lock); | 1752 | read_unlock(&tasklist_lock); |
| @@ -1748,17 +1760,33 @@ relock: | |||
| 1748 | do_signal_stop(0)) | 1760 | do_signal_stop(0)) |
| 1749 | goto relock; | 1761 | goto relock; |
| 1750 | 1762 | ||
| 1751 | signr = dequeue_signal(current, ¤t->blocked, info); | 1763 | /* |
| 1752 | if (!signr) | 1764 | * Tracing can induce an artifical signal and choose sigaction. |
| 1753 | break; /* will return 0 */ | 1765 | * The return value in @signr determines the default action, |
| 1766 | * but @info->si_signo is the signal number we will report. | ||
| 1767 | */ | ||
| 1768 | signr = tracehook_get_signal(current, regs, info, return_ka); | ||
| 1769 | if (unlikely(signr < 0)) | ||
| 1770 | goto relock; | ||
| 1771 | if (unlikely(signr != 0)) | ||
| 1772 | ka = return_ka; | ||
| 1773 | else { | ||
| 1774 | signr = dequeue_signal(current, ¤t->blocked, | ||
| 1775 | info); | ||
| 1754 | 1776 | ||
| 1755 | if (signr != SIGKILL) { | ||
| 1756 | signr = ptrace_signal(signr, info, regs, cookie); | ||
| 1757 | if (!signr) | 1777 | if (!signr) |
| 1758 | continue; | 1778 | break; /* will return 0 */ |
| 1779 | |||
| 1780 | if (signr != SIGKILL) { | ||
| 1781 | signr = ptrace_signal(signr, info, | ||
| 1782 | regs, cookie); | ||
| 1783 | if (!signr) | ||
| 1784 | continue; | ||
| 1785 | } | ||
| 1786 | |||
| 1787 | ka = &sighand->action[signr-1]; | ||
| 1759 | } | 1788 | } |
| 1760 | 1789 | ||
| 1761 | ka = &sighand->action[signr-1]; | ||
| 1762 | if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ | 1790 | if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ |
| 1763 | continue; | 1791 | continue; |
| 1764 | if (ka->sa.sa_handler != SIG_DFL) { | 1792 | if (ka->sa.sa_handler != SIG_DFL) { |
| @@ -1806,7 +1834,7 @@ relock: | |||
| 1806 | spin_lock_irq(&sighand->siglock); | 1834 | spin_lock_irq(&sighand->siglock); |
| 1807 | } | 1835 | } |
| 1808 | 1836 | ||
| 1809 | if (likely(do_signal_stop(signr))) { | 1837 | if (likely(do_signal_stop(info->si_signo))) { |
| 1810 | /* It released the siglock. */ | 1838 | /* It released the siglock. */ |
| 1811 | goto relock; | 1839 | goto relock; |
| 1812 | } | 1840 | } |
| @@ -1827,7 +1855,7 @@ relock: | |||
| 1827 | 1855 | ||
| 1828 | if (sig_kernel_coredump(signr)) { | 1856 | if (sig_kernel_coredump(signr)) { |
| 1829 | if (print_fatal_signals) | 1857 | if (print_fatal_signals) |
| 1830 | print_fatal_signal(regs, signr); | 1858 | print_fatal_signal(regs, info->si_signo); |
| 1831 | /* | 1859 | /* |
| 1832 | * If it was able to dump core, this kills all | 1860 | * If it was able to dump core, this kills all |
| 1833 | * other threads in the group and synchronizes with | 1861 | * other threads in the group and synchronizes with |
| @@ -1836,13 +1864,13 @@ relock: | |||
| 1836 | * first and our do_group_exit call below will use | 1864 | * first and our do_group_exit call below will use |
| 1837 | * that value and ignore the one we pass it. | 1865 | * that value and ignore the one we pass it. |
| 1838 | */ | 1866 | */ |
| 1839 | do_coredump((long)signr, signr, regs); | 1867 | do_coredump(info->si_signo, info->si_signo, regs); |
| 1840 | } | 1868 | } |
| 1841 | 1869 | ||
| 1842 | /* | 1870 | /* |
| 1843 | * Death signals, no core dump. | 1871 | * Death signals, no core dump. |
| 1844 | */ | 1872 | */ |
| 1845 | do_group_exit(signr); | 1873 | do_group_exit(info->si_signo); |
| 1846 | /* NOTREACHED */ | 1874 | /* NOTREACHED */ |
| 1847 | } | 1875 | } |
| 1848 | spin_unlock_irq(&sighand->siglock); | 1876 | spin_unlock_irq(&sighand->siglock); |
| @@ -1884,7 +1912,7 @@ void exit_signals(struct task_struct *tsk) | |||
| 1884 | out: | 1912 | out: |
| 1885 | spin_unlock_irq(&tsk->sighand->siglock); | 1913 | spin_unlock_irq(&tsk->sighand->siglock); |
| 1886 | 1914 | ||
| 1887 | if (unlikely(group_stop)) { | 1915 | if (unlikely(group_stop) && tracehook_notify_jctl(1, CLD_STOPPED)) { |
| 1888 | read_lock(&tasklist_lock); | 1916 | read_lock(&tasklist_lock); |
| 1889 | do_notify_parent_cldstop(tsk, CLD_STOPPED); | 1917 | do_notify_parent_cldstop(tsk, CLD_STOPPED); |
| 1890 | read_unlock(&tasklist_lock); | 1918 | read_unlock(&tasklist_lock); |
| @@ -1895,7 +1923,6 @@ EXPORT_SYMBOL(recalc_sigpending); | |||
| 1895 | EXPORT_SYMBOL_GPL(dequeue_signal); | 1923 | EXPORT_SYMBOL_GPL(dequeue_signal); |
| 1896 | EXPORT_SYMBOL(flush_signals); | 1924 | EXPORT_SYMBOL(flush_signals); |
| 1897 | EXPORT_SYMBOL(force_sig); | 1925 | EXPORT_SYMBOL(force_sig); |
| 1898 | EXPORT_SYMBOL(ptrace_notify); | ||
| 1899 | EXPORT_SYMBOL(send_sig); | 1926 | EXPORT_SYMBOL(send_sig); |
| 1900 | EXPORT_SYMBOL(send_sig_info); | 1927 | EXPORT_SYMBOL(send_sig_info); |
| 1901 | EXPORT_SYMBOL(sigprocmask); | 1928 | EXPORT_SYMBOL(sigprocmask); |
| @@ -2299,7 +2326,7 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) | |||
| 2299 | * (for example, SIGCHLD), shall cause the pending signal to | 2326 | * (for example, SIGCHLD), shall cause the pending signal to |
| 2300 | * be discarded, whether or not it is blocked" | 2327 | * be discarded, whether or not it is blocked" |
| 2301 | */ | 2328 | */ |
| 2302 | if (__sig_ignored(t, sig)) { | 2329 | if (sig_handler_ignored(sig_handler(t, sig), sig)) { |
| 2303 | sigemptyset(&mask); | 2330 | sigemptyset(&mask); |
| 2304 | sigaddset(&mask, sig); | 2331 | sigaddset(&mask, sig); |
| 2305 | rm_from_queue_full(&mask, &t->signal->shared_pending); | 2332 | rm_from_queue_full(&mask, &t->signal->shared_pending); |
