diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 79 |
1 files changed, 66 insertions, 13 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 418776c41d24..1e199919ae09 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -224,6 +224,26 @@ static inline void print_dropped_signal(int sig) | |||
224 | } | 224 | } |
225 | 225 | ||
226 | /** | 226 | /** |
227 | * task_clear_group_stop_trapping - clear group stop trapping bit | ||
228 | * @task: target task | ||
229 | * | ||
230 | * If GROUP_STOP_TRAPPING is set, a ptracer is waiting for us. Clear it | ||
231 | * and wake up the ptracer. Note that we don't need any further locking. | ||
232 | * @task->siglock guarantees that @task->parent points to the ptracer. | ||
233 | * | ||
234 | * CONTEXT: | ||
235 | * Must be called with @task->sighand->siglock held. | ||
236 | */ | ||
237 | static void task_clear_group_stop_trapping(struct task_struct *task) | ||
238 | { | ||
239 | if (unlikely(task->group_stop & GROUP_STOP_TRAPPING)) { | ||
240 | task->group_stop &= ~GROUP_STOP_TRAPPING; | ||
241 | __wake_up_sync(&task->parent->signal->wait_chldexit, | ||
242 | TASK_UNINTERRUPTIBLE, 1); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | /** | ||
227 | * task_clear_group_stop_pending - clear pending group stop | 247 | * task_clear_group_stop_pending - clear pending group stop |
228 | * @task: target task | 248 | * @task: target task |
229 | * | 249 | * |
@@ -1706,8 +1726,20 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) | |||
1706 | current->last_siginfo = info; | 1726 | current->last_siginfo = info; |
1707 | current->exit_code = exit_code; | 1727 | current->exit_code = exit_code; |
1708 | 1728 | ||
1709 | /* Let the debugger run. */ | 1729 | /* |
1710 | __set_current_state(TASK_TRACED); | 1730 | * TRACED should be visible before TRAPPING is cleared; otherwise, |
1731 | * the tracer might fail do_wait(). | ||
1732 | */ | ||
1733 | set_current_state(TASK_TRACED); | ||
1734 | |||
1735 | /* | ||
1736 | * We're committing to trapping. Clearing GROUP_STOP_TRAPPING and | ||
1737 | * transition to TASK_TRACED should be atomic with respect to | ||
1738 | * siglock. This hsould be done after the arch hook as siglock is | ||
1739 | * released and regrabbed across it. | ||
1740 | */ | ||
1741 | task_clear_group_stop_trapping(current); | ||
1742 | |||
1711 | spin_unlock_irq(¤t->sighand->siglock); | 1743 | spin_unlock_irq(¤t->sighand->siglock); |
1712 | read_lock(&tasklist_lock); | 1744 | read_lock(&tasklist_lock); |
1713 | if (may_ptrace_stop()) { | 1745 | if (may_ptrace_stop()) { |
@@ -1788,6 +1820,9 @@ static int do_signal_stop(int signr) | |||
1788 | unsigned int gstop = GROUP_STOP_PENDING | GROUP_STOP_CONSUME; | 1820 | unsigned int gstop = GROUP_STOP_PENDING | GROUP_STOP_CONSUME; |
1789 | struct task_struct *t; | 1821 | struct task_struct *t; |
1790 | 1822 | ||
1823 | /* signr will be recorded in task->group_stop for retries */ | ||
1824 | WARN_ON_ONCE(signr & ~GROUP_STOP_SIGMASK); | ||
1825 | |||
1791 | if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || | 1826 | if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || |
1792 | unlikely(signal_group_exit(sig))) | 1827 | unlikely(signal_group_exit(sig))) |
1793 | return 0; | 1828 | return 0; |
@@ -1797,25 +1832,27 @@ static int do_signal_stop(int signr) | |||
1797 | */ | 1832 | */ |
1798 | sig->group_exit_code = signr; | 1833 | sig->group_exit_code = signr; |
1799 | 1834 | ||
1800 | current->group_stop = gstop; | 1835 | current->group_stop &= ~GROUP_STOP_SIGMASK; |
1836 | current->group_stop |= signr | gstop; | ||
1801 | sig->group_stop_count = 1; | 1837 | sig->group_stop_count = 1; |
1802 | for (t = next_thread(current); t != current; t = next_thread(t)) | 1838 | for (t = next_thread(current); t != current; |
1839 | t = next_thread(t)) { | ||
1840 | t->group_stop &= ~GROUP_STOP_SIGMASK; | ||
1803 | /* | 1841 | /* |
1804 | * Setting state to TASK_STOPPED for a group | 1842 | * Setting state to TASK_STOPPED for a group |
1805 | * stop is always done with the siglock held, | 1843 | * stop is always done with the siglock held, |
1806 | * so this check has no races. | 1844 | * so this check has no races. |
1807 | */ | 1845 | */ |
1808 | if (!(t->flags & PF_EXITING) && !task_is_stopped(t)) { | 1846 | if (!(t->flags & PF_EXITING) && !task_is_stopped(t)) { |
1809 | t->group_stop = gstop; | 1847 | t->group_stop |= signr | gstop; |
1810 | sig->group_stop_count++; | 1848 | sig->group_stop_count++; |
1811 | signal_wake_up(t, 0); | 1849 | signal_wake_up(t, 0); |
1812 | } else | 1850 | } else { |
1813 | task_clear_group_stop_pending(t); | 1851 | task_clear_group_stop_pending(t); |
1852 | } | ||
1853 | } | ||
1814 | } | 1854 | } |
1815 | 1855 | retry: | |
1816 | current->exit_code = sig->group_exit_code; | ||
1817 | __set_current_state(TASK_STOPPED); | ||
1818 | |||
1819 | if (likely(!task_ptrace(current))) { | 1856 | if (likely(!task_ptrace(current))) { |
1820 | int notify = 0; | 1857 | int notify = 0; |
1821 | 1858 | ||
@@ -1827,6 +1864,7 @@ static int do_signal_stop(int signr) | |||
1827 | if (task_participate_group_stop(current)) | 1864 | if (task_participate_group_stop(current)) |
1828 | notify = CLD_STOPPED; | 1865 | notify = CLD_STOPPED; |
1829 | 1866 | ||
1867 | __set_current_state(TASK_STOPPED); | ||
1830 | spin_unlock_irq(¤t->sighand->siglock); | 1868 | spin_unlock_irq(¤t->sighand->siglock); |
1831 | 1869 | ||
1832 | if (notify) { | 1870 | if (notify) { |
@@ -1839,13 +1877,28 @@ static int do_signal_stop(int signr) | |||
1839 | schedule(); | 1877 | schedule(); |
1840 | 1878 | ||
1841 | spin_lock_irq(¤t->sighand->siglock); | 1879 | spin_lock_irq(¤t->sighand->siglock); |
1842 | } else | 1880 | } else { |
1843 | ptrace_stop(current->exit_code, CLD_STOPPED, 0, NULL); | 1881 | ptrace_stop(current->group_stop & GROUP_STOP_SIGMASK, |
1882 | CLD_STOPPED, 0, NULL); | ||
1883 | current->exit_code = 0; | ||
1884 | } | ||
1885 | |||
1886 | /* | ||
1887 | * GROUP_STOP_PENDING could be set if another group stop has | ||
1888 | * started since being woken up or ptrace wants us to transit | ||
1889 | * between TASK_STOPPED and TRACED. Retry group stop. | ||
1890 | */ | ||
1891 | if (current->group_stop & GROUP_STOP_PENDING) { | ||
1892 | WARN_ON_ONCE(!(current->group_stop & GROUP_STOP_SIGMASK)); | ||
1893 | goto retry; | ||
1894 | } | ||
1895 | |||
1896 | /* PTRACE_ATTACH might have raced with task killing, clear trapping */ | ||
1897 | task_clear_group_stop_trapping(current); | ||
1844 | 1898 | ||
1845 | spin_unlock_irq(¤t->sighand->siglock); | 1899 | spin_unlock_irq(¤t->sighand->siglock); |
1846 | 1900 | ||
1847 | tracehook_finish_jctl(); | 1901 | tracehook_finish_jctl(); |
1848 | current->exit_code = 0; | ||
1849 | 1902 | ||
1850 | return 1; | 1903 | return 1; |
1851 | } | 1904 | } |