aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-07-25 22:45:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-26 15:00:09 -0400
commit7bcf6a2ca5f639b038c48711ebe6c4eca2036641 (patch)
tree4219a0725d581310f729d4616361febd700f0574
parent283d7559e7712f95a05331eb0a85394c6368101b (diff)
tracehook: get_signal_to_deliver
This defines the tracehook_get_signal() hook to allow tracing code to slip in before normal signal dequeuing. This lays the groundwork for new tracing features that can inject synthetic signals outside the normal queue or control the disposition of delivered signals. The calling convention lets tracehook_get_signal() decide both exactly what will happen and what signal number to report in the handler/exit. Signed-off-by: Roland McGrath <roland@redhat.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Reviewed-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/tracehook.h29
-rw-r--r--kernel/signal.c38
2 files changed, 56 insertions, 11 deletions
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 3548694a24db..42a0d7b11959 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -422,4 +422,33 @@ static inline int tracehook_consider_fatal_signal(struct task_struct *task,
422 return (task_ptrace(task) & PT_PTRACED) != 0; 422 return (task_ptrace(task) & PT_PTRACED) != 0;
423} 423}
424 424
425/**
426 * tracehook_get_signal - deliver synthetic signal to traced task
427 * @task: @current
428 * @regs: task_pt_regs(@current)
429 * @info: details of synthetic signal
430 * @return_ka: sigaction for synthetic signal
431 *
432 * Return zero to check for a real pending signal normally.
433 * Return -1 after releasing the siglock to repeat the check.
434 * Return a signal number to induce an artifical signal delivery,
435 * setting *@info and *@return_ka to specify its details and behavior.
436 *
437 * The @return_ka->sa_handler value controls the disposition of the
438 * signal, no matter the signal number. For %SIG_DFL, the return value
439 * is a representative signal to indicate the behavior (e.g. %SIGTERM
440 * for death, %SIGQUIT for core dump, %SIGSTOP for job control stop,
441 * %SIGTSTP for stop unless in an orphaned pgrp), but the signal number
442 * reported will be @info->si_signo instead.
443 *
444 * Called with @task->sighand->siglock held, before dequeuing pending signals.
445 */
446static inline int tracehook_get_signal(struct task_struct *task,
447 struct pt_regs *regs,
448 siginfo_t *info,
449 struct k_sigaction *return_ka)
450{
451 return 0;
452}
453
425#endif /* <linux/tracehook.h> */ 454#endif /* <linux/tracehook.h> */
diff --git a/kernel/signal.c b/kernel/signal.c
index 1a942ce32ba0..10b31ecdd9c8 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1754,17 +1754,33 @@ relock:
1754 do_signal_stop(0)) 1754 do_signal_stop(0))
1755 goto relock; 1755 goto relock;
1756 1756
1757 signr = dequeue_signal(current, &current->blocked, info); 1757 /*
1758 if (!signr) 1758 * Tracing can induce an artifical signal and choose sigaction.
1759 break; /* will return 0 */ 1759 * The return value in @signr determines the default action,
1760 * but @info->si_signo is the signal number we will report.
1761 */
1762 signr = tracehook_get_signal(current, regs, info, return_ka);
1763 if (unlikely(signr < 0))
1764 goto relock;
1765 if (unlikely(signr != 0))
1766 ka = return_ka;
1767 else {
1768 signr = dequeue_signal(current, &current->blocked,
1769 info);
1760 1770
1761 if (signr != SIGKILL) {
1762 signr = ptrace_signal(signr, info, regs, cookie);
1763 if (!signr) 1771 if (!signr)
1764 continue; 1772 break; /* will return 0 */
1773
1774 if (signr != SIGKILL) {
1775 signr = ptrace_signal(signr, info,
1776 regs, cookie);
1777 if (!signr)
1778 continue;
1779 }
1780
1781 ka = &sighand->action[signr-1];
1765 } 1782 }
1766 1783
1767 ka = &sighand->action[signr-1];
1768 if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ 1784 if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */
1769 continue; 1785 continue;
1770 if (ka->sa.sa_handler != SIG_DFL) { 1786 if (ka->sa.sa_handler != SIG_DFL) {
@@ -1812,7 +1828,7 @@ relock:
1812 spin_lock_irq(&sighand->siglock); 1828 spin_lock_irq(&sighand->siglock);
1813 } 1829 }
1814 1830
1815 if (likely(do_signal_stop(signr))) { 1831 if (likely(do_signal_stop(info->si_signo))) {
1816 /* It released the siglock. */ 1832 /* It released the siglock. */
1817 goto relock; 1833 goto relock;
1818 } 1834 }
@@ -1833,7 +1849,7 @@ relock:
1833 1849
1834 if (sig_kernel_coredump(signr)) { 1850 if (sig_kernel_coredump(signr)) {
1835 if (print_fatal_signals) 1851 if (print_fatal_signals)
1836 print_fatal_signal(regs, signr); 1852 print_fatal_signal(regs, info->si_signo);
1837 /* 1853 /*
1838 * If it was able to dump core, this kills all 1854 * If it was able to dump core, this kills all
1839 * other threads in the group and synchronizes with 1855 * other threads in the group and synchronizes with
@@ -1842,13 +1858,13 @@ relock:
1842 * first and our do_group_exit call below will use 1858 * first and our do_group_exit call below will use
1843 * that value and ignore the one we pass it. 1859 * that value and ignore the one we pass it.
1844 */ 1860 */
1845 do_coredump((long)signr, signr, regs); 1861 do_coredump(info->si_signo, info->si_signo, regs);
1846 } 1862 }
1847 1863
1848 /* 1864 /*
1849 * Death signals, no core dump. 1865 * Death signals, no core dump.
1850 */ 1866 */
1851 do_group_exit(signr); 1867 do_group_exit(info->si_signo);
1852 /* NOTREACHED */ 1868 /* NOTREACHED */
1853 } 1869 }
1854 spin_unlock_irq(&sighand->siglock); 1870 spin_unlock_irq(&sighand->siglock);