diff options
-rw-r--r-- | include/linux/sched.h | 6 | ||||
-rw-r--r-- | kernel/ptrace.c | 12 | ||||
-rw-r--r-- | kernel/signal.c | 90 |
3 files changed, 75 insertions, 33 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h index 5157bd9eee37..8bd84b83a35b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1810,17 +1810,21 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t * | |||
1810 | #define JOBCTL_STOP_DEQUEUED_BIT 16 /* stop signal dequeued */ | 1810 | #define JOBCTL_STOP_DEQUEUED_BIT 16 /* stop signal dequeued */ |
1811 | #define JOBCTL_STOP_PENDING_BIT 17 /* task should stop for group stop */ | 1811 | #define JOBCTL_STOP_PENDING_BIT 17 /* task should stop for group stop */ |
1812 | #define JOBCTL_STOP_CONSUME_BIT 18 /* consume group stop count */ | 1812 | #define JOBCTL_STOP_CONSUME_BIT 18 /* consume group stop count */ |
1813 | #define JOBCTL_TRAP_STOP_BIT 19 /* trap for STOP */ | ||
1813 | #define JOBCTL_TRAPPING_BIT 21 /* switching to TRACED */ | 1814 | #define JOBCTL_TRAPPING_BIT 21 /* switching to TRACED */ |
1814 | 1815 | ||
1815 | #define JOBCTL_STOP_DEQUEUED (1 << JOBCTL_STOP_DEQUEUED_BIT) | 1816 | #define JOBCTL_STOP_DEQUEUED (1 << JOBCTL_STOP_DEQUEUED_BIT) |
1816 | #define JOBCTL_STOP_PENDING (1 << JOBCTL_STOP_PENDING_BIT) | 1817 | #define JOBCTL_STOP_PENDING (1 << JOBCTL_STOP_PENDING_BIT) |
1817 | #define JOBCTL_STOP_CONSUME (1 << JOBCTL_STOP_CONSUME_BIT) | 1818 | #define JOBCTL_STOP_CONSUME (1 << JOBCTL_STOP_CONSUME_BIT) |
1819 | #define JOBCTL_TRAP_STOP (1 << JOBCTL_TRAP_STOP_BIT) | ||
1818 | #define JOBCTL_TRAPPING (1 << JOBCTL_TRAPPING_BIT) | 1820 | #define JOBCTL_TRAPPING (1 << JOBCTL_TRAPPING_BIT) |
1819 | 1821 | ||
1820 | #define JOBCTL_PENDING_MASK JOBCTL_STOP_PENDING | 1822 | #define JOBCTL_TRAP_MASK JOBCTL_TRAP_STOP |
1823 | #define JOBCTL_PENDING_MASK (JOBCTL_STOP_PENDING | JOBCTL_TRAP_MASK) | ||
1821 | 1824 | ||
1822 | extern bool task_set_jobctl_pending(struct task_struct *task, | 1825 | extern bool task_set_jobctl_pending(struct task_struct *task, |
1823 | unsigned int mask); | 1826 | unsigned int mask); |
1827 | extern void task_clear_jobctl_trapping(struct task_struct *task); | ||
1824 | extern void task_clear_jobctl_pending(struct task_struct *task, | 1828 | extern void task_clear_jobctl_pending(struct task_struct *task, |
1825 | unsigned int mask); | 1829 | unsigned int mask); |
1826 | 1830 | ||
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 7f05f3a1267b..45a8a4c5d8b2 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -83,6 +83,13 @@ void __ptrace_unlink(struct task_struct *child) | |||
83 | spin_lock(&child->sighand->siglock); | 83 | spin_lock(&child->sighand->siglock); |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * Clear all pending traps and TRAPPING. TRAPPING should be | ||
87 | * cleared regardless of JOBCTL_STOP_PENDING. Do it explicitly. | ||
88 | */ | ||
89 | task_clear_jobctl_pending(child, JOBCTL_TRAP_MASK); | ||
90 | task_clear_jobctl_trapping(child); | ||
91 | |||
92 | /* | ||
86 | * Reinstate JOBCTL_STOP_PENDING if group stop is in effect and | 93 | * Reinstate JOBCTL_STOP_PENDING if group stop is in effect and |
87 | * @child isn't dead. | 94 | * @child isn't dead. |
88 | */ | 95 | */ |
@@ -246,7 +253,7 @@ static int ptrace_attach(struct task_struct *task) | |||
246 | spin_lock(&task->sighand->siglock); | 253 | spin_lock(&task->sighand->siglock); |
247 | 254 | ||
248 | /* | 255 | /* |
249 | * If the task is already STOPPED, set JOBCTL_STOP_PENDING and | 256 | * If the task is already STOPPED, set JOBCTL_TRAP_STOP and |
250 | * TRAPPING, and kick it so that it transits to TRACED. TRAPPING | 257 | * TRAPPING, and kick it so that it transits to TRACED. TRAPPING |
251 | * will be cleared if the child completes the transition or any | 258 | * will be cleared if the child completes the transition or any |
252 | * event which clears the group stop states happens. We'll wait | 259 | * event which clears the group stop states happens. We'll wait |
@@ -263,8 +270,7 @@ static int ptrace_attach(struct task_struct *task) | |||
263 | * in and out of STOPPED are protected by siglock. | 270 | * in and out of STOPPED are protected by siglock. |
264 | */ | 271 | */ |
265 | if (task_is_stopped(task) && | 272 | if (task_is_stopped(task) && |
266 | task_set_jobctl_pending(task, | 273 | task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) |
267 | JOBCTL_STOP_PENDING | JOBCTL_TRAPPING)) | ||
268 | signal_wake_up(task, 1); | 274 | signal_wake_up(task, 1); |
269 | 275 | ||
270 | spin_unlock(&task->sighand->siglock); | 276 | spin_unlock(&task->sighand->siglock); |
diff --git a/kernel/signal.c b/kernel/signal.c index c99b8b5c0be7..b5f55ca1f43f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -266,7 +266,7 @@ bool task_set_jobctl_pending(struct task_struct *task, unsigned int mask) | |||
266 | * CONTEXT: | 266 | * CONTEXT: |
267 | * Must be called with @task->sighand->siglock held. | 267 | * Must be called with @task->sighand->siglock held. |
268 | */ | 268 | */ |
269 | static void task_clear_jobctl_trapping(struct task_struct *task) | 269 | void task_clear_jobctl_trapping(struct task_struct *task) |
270 | { | 270 | { |
271 | if (unlikely(task->jobctl & JOBCTL_TRAPPING)) { | 271 | if (unlikely(task->jobctl & JOBCTL_TRAPPING)) { |
272 | task->jobctl &= ~JOBCTL_TRAPPING; | 272 | task->jobctl &= ~JOBCTL_TRAPPING; |
@@ -1790,13 +1790,16 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) | |||
1790 | /* | 1790 | /* |
1791 | * If @why is CLD_STOPPED, we're trapping to participate in a group | 1791 | * If @why is CLD_STOPPED, we're trapping to participate in a group |
1792 | * stop. Do the bookkeeping. Note that if SIGCONT was delievered | 1792 | * stop. Do the bookkeeping. Note that if SIGCONT was delievered |
1793 | * while siglock was released for the arch hook, PENDING could be | 1793 | * across siglock relocks since INTERRUPT was scheduled, PENDING |
1794 | * clear now. We act as if SIGCONT is received after TASK_TRACED | 1794 | * could be clear now. We act as if SIGCONT is received after |
1795 | * is entered - ignore it. | 1795 | * TASK_TRACED is entered - ignore it. |
1796 | */ | 1796 | */ |
1797 | if (why == CLD_STOPPED && (current->jobctl & JOBCTL_STOP_PENDING)) | 1797 | if (why == CLD_STOPPED && (current->jobctl & JOBCTL_STOP_PENDING)) |
1798 | gstop_done = task_participate_group_stop(current); | 1798 | gstop_done = task_participate_group_stop(current); |
1799 | 1799 | ||
1800 | /* any trap clears pending STOP trap */ | ||
1801 | task_clear_jobctl_pending(current, JOBCTL_TRAP_STOP); | ||
1802 | |||
1800 | /* entering a trap, clear TRAPPING */ | 1803 | /* entering a trap, clear TRAPPING */ |
1801 | task_clear_jobctl_trapping(current); | 1804 | task_clear_jobctl_trapping(current); |
1802 | 1805 | ||
@@ -1888,13 +1891,30 @@ void ptrace_notify(int exit_code) | |||
1888 | spin_unlock_irq(¤t->sighand->siglock); | 1891 | spin_unlock_irq(¤t->sighand->siglock); |
1889 | } | 1892 | } |
1890 | 1893 | ||
1891 | /* | 1894 | /** |
1892 | * This performs the stopping for SIGSTOP and other stop signals. | 1895 | * do_signal_stop - handle group stop for SIGSTOP and other stop signals |
1893 | * We have to stop all threads in the thread group. | 1896 | * @signr: signr causing group stop if initiating |
1894 | * Returns non-zero if we've actually stopped and released the siglock. | 1897 | * |
1895 | * Returns zero if we didn't stop and still hold the siglock. | 1898 | * If %JOBCTL_STOP_PENDING is not set yet, initiate group stop with @signr |
1899 | * and participate in it. If already set, participate in the existing | ||
1900 | * group stop. If participated in a group stop (and thus slept), %true is | ||
1901 | * returned with siglock released. | ||
1902 | * | ||
1903 | * If ptraced, this function doesn't handle stop itself. Instead, | ||
1904 | * %JOBCTL_TRAP_STOP is scheduled and %false is returned with siglock | ||
1905 | * untouched. The caller must ensure that INTERRUPT trap handling takes | ||
1906 | * places afterwards. | ||
1907 | * | ||
1908 | * CONTEXT: | ||
1909 | * Must be called with @current->sighand->siglock held, which is released | ||
1910 | * on %true return. | ||
1911 | * | ||
1912 | * RETURNS: | ||
1913 | * %false if group stop is already cancelled or ptrace trap is scheduled. | ||
1914 | * %true if participated in group stop. | ||
1896 | */ | 1915 | */ |
1897 | static int do_signal_stop(int signr) | 1916 | static bool do_signal_stop(int signr) |
1917 | __releases(¤t->sighand->siglock) | ||
1898 | { | 1918 | { |
1899 | struct signal_struct *sig = current->signal; | 1919 | struct signal_struct *sig = current->signal; |
1900 | 1920 | ||
@@ -1907,7 +1927,7 @@ static int do_signal_stop(int signr) | |||
1907 | 1927 | ||
1908 | if (!likely(current->jobctl & JOBCTL_STOP_DEQUEUED) || | 1928 | if (!likely(current->jobctl & JOBCTL_STOP_DEQUEUED) || |
1909 | unlikely(signal_group_exit(sig))) | 1929 | unlikely(signal_group_exit(sig))) |
1910 | return 0; | 1930 | return false; |
1911 | /* | 1931 | /* |
1912 | * There is no group stop already in progress. We must | 1932 | * There is no group stop already in progress. We must |
1913 | * initiate one now. | 1933 | * initiate one now. |
@@ -1951,7 +1971,7 @@ static int do_signal_stop(int signr) | |||
1951 | } | 1971 | } |
1952 | } | 1972 | } |
1953 | } | 1973 | } |
1954 | retry: | 1974 | |
1955 | if (likely(!task_ptrace(current))) { | 1975 | if (likely(!task_ptrace(current))) { |
1956 | int notify = 0; | 1976 | int notify = 0; |
1957 | 1977 | ||
@@ -1983,27 +2003,33 @@ retry: | |||
1983 | 2003 | ||
1984 | /* Now we don't run again until woken by SIGCONT or SIGKILL */ | 2004 | /* Now we don't run again until woken by SIGCONT or SIGKILL */ |
1985 | schedule(); | 2005 | schedule(); |
1986 | 2006 | return true; | |
1987 | spin_lock_irq(¤t->sighand->siglock); | ||
1988 | } else { | 2007 | } else { |
1989 | ptrace_stop(current->jobctl & JOBCTL_STOP_SIGMASK, | 2008 | /* |
1990 | CLD_STOPPED, 0, NULL); | 2009 | * While ptraced, group stop is handled by STOP trap. |
1991 | current->exit_code = 0; | 2010 | * Schedule it and let the caller deal with it. |
1992 | } | 2011 | */ |
1993 | 2012 | task_set_jobctl_pending(current, JOBCTL_TRAP_STOP); | |
1994 | /* | 2013 | return false; |
1995 | * JOBCTL_STOP_PENDING could be set if another group stop has | ||
1996 | * started since being woken up or ptrace wants us to transit | ||
1997 | * between TASK_STOPPED and TRACED. Retry group stop. | ||
1998 | */ | ||
1999 | if (current->jobctl & JOBCTL_STOP_PENDING) { | ||
2000 | WARN_ON_ONCE(!(current->jobctl & JOBCTL_STOP_SIGMASK)); | ||
2001 | goto retry; | ||
2002 | } | 2014 | } |
2015 | } | ||
2003 | 2016 | ||
2004 | spin_unlock_irq(¤t->sighand->siglock); | 2017 | /** |
2018 | * do_jobctl_trap - take care of ptrace jobctl traps | ||
2019 | * | ||
2020 | * It is currently used only to trap for group stop while ptraced. | ||
2021 | * | ||
2022 | * CONTEXT: | ||
2023 | * Must be called with @current->sighand->siglock held, which may be | ||
2024 | * released and re-acquired before returning with intervening sleep. | ||
2025 | */ | ||
2026 | static void do_jobctl_trap(void) | ||
2027 | { | ||
2028 | int signr = current->jobctl & JOBCTL_STOP_SIGMASK; | ||
2005 | 2029 | ||
2006 | return 1; | 2030 | WARN_ON_ONCE(!signr); |
2031 | ptrace_stop(signr, CLD_STOPPED, 0, NULL); | ||
2032 | current->exit_code = 0; | ||
2007 | } | 2033 | } |
2008 | 2034 | ||
2009 | static int ptrace_signal(int signr, siginfo_t *info, | 2035 | static int ptrace_signal(int signr, siginfo_t *info, |
@@ -2110,6 +2136,12 @@ relock: | |||
2110 | do_signal_stop(0)) | 2136 | do_signal_stop(0)) |
2111 | goto relock; | 2137 | goto relock; |
2112 | 2138 | ||
2139 | if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { | ||
2140 | do_jobctl_trap(); | ||
2141 | spin_unlock_irq(&sighand->siglock); | ||
2142 | goto relock; | ||
2143 | } | ||
2144 | |||
2113 | signr = dequeue_signal(current, ¤t->blocked, info); | 2145 | signr = dequeue_signal(current, ¤t->blocked, info); |
2114 | 2146 | ||
2115 | if (!signr) | 2147 | if (!signr) |