aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h2
-rw-r--r--kernel/ptrace.c49
-rw-r--r--kernel/signal.c79
3 files changed, 112 insertions, 18 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b2a17dfbdbad..456d80ed3b78 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1775,8 +1775,10 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
1775/* 1775/*
1776 * task->group_stop flags 1776 * task->group_stop flags
1777 */ 1777 */
1778#define GROUP_STOP_SIGMASK 0xffff /* signr of the last group stop */
1778#define GROUP_STOP_PENDING (1 << 16) /* task should stop for group stop */ 1779#define GROUP_STOP_PENDING (1 << 16) /* task should stop for group stop */
1779#define GROUP_STOP_CONSUME (1 << 17) /* consume group stop count */ 1780#define GROUP_STOP_CONSUME (1 << 17) /* consume group stop count */
1781#define GROUP_STOP_TRAPPING (1 << 18) /* switching from STOPPED to TRACED */
1780 1782
1781extern void task_clear_group_stop_pending(struct task_struct *task); 1783extern void task_clear_group_stop_pending(struct task_struct *task);
1782 1784
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 6acf8954017c..745fc2dd00c5 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -49,14 +49,22 @@ static void ptrace_untrace(struct task_struct *child)
49 spin_lock(&child->sighand->siglock); 49 spin_lock(&child->sighand->siglock);
50 if (task_is_traced(child)) { 50 if (task_is_traced(child)) {
51 /* 51 /*
52 * If the group stop is completed or in progress, 52 * If group stop is completed or in progress, it should
53 * this thread was already counted as stopped. 53 * participate in the group stop. Set GROUP_STOP_PENDING
54 * before kicking it.
55 *
56 * This involves TRACED -> RUNNING -> STOPPED transition
57 * which is similar to but in the opposite direction of
58 * what happens while attaching to a stopped task.
59 * However, in this direction, the intermediate RUNNING
60 * state is not hidden even from the current ptracer and if
61 * it immediately re-attaches and performs a WNOHANG
62 * wait(2), it may fail.
54 */ 63 */
55 if (child->signal->flags & SIGNAL_STOP_STOPPED || 64 if (child->signal->flags & SIGNAL_STOP_STOPPED ||
56 child->signal->group_stop_count) 65 child->signal->group_stop_count)
57 __set_task_state(child, TASK_STOPPED); 66 child->group_stop |= GROUP_STOP_PENDING;
58 else 67 signal_wake_up(child, 1);
59 signal_wake_up(child, 1);
60 } 68 }
61 spin_unlock(&child->sighand->siglock); 69 spin_unlock(&child->sighand->siglock);
62} 70}
@@ -165,6 +173,7 @@ bool ptrace_may_access(struct task_struct *task, unsigned int mode)
165 173
166static int ptrace_attach(struct task_struct *task) 174static int ptrace_attach(struct task_struct *task)
167{ 175{
176 bool wait_trap = false;
168 int retval; 177 int retval;
169 178
170 audit_ptrace(task); 179 audit_ptrace(task);
@@ -204,12 +213,42 @@ static int ptrace_attach(struct task_struct *task)
204 __ptrace_link(task, current); 213 __ptrace_link(task, current);
205 send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); 214 send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
206 215
216 spin_lock(&task->sighand->siglock);
217
218 /*
219 * If the task is already STOPPED, set GROUP_STOP_PENDING and
220 * TRAPPING, and kick it so that it transits to TRACED. TRAPPING
221 * will be cleared if the child completes the transition or any
222 * event which clears the group stop states happens. We'll wait
223 * for the transition to complete before returning from this
224 * function.
225 *
226 * This hides STOPPED -> RUNNING -> TRACED transition from the
227 * attaching thread but a different thread in the same group can
228 * still observe the transient RUNNING state. IOW, if another
229 * thread's WNOHANG wait(2) on the stopped tracee races against
230 * ATTACH, the wait(2) may fail due to the transient RUNNING.
231 *
232 * The following task_is_stopped() test is safe as both transitions
233 * in and out of STOPPED are protected by siglock.
234 */
235 if (task_is_stopped(task)) {
236 task->group_stop |= GROUP_STOP_PENDING | GROUP_STOP_TRAPPING;
237 signal_wake_up(task, 1);
238 wait_trap = true;
239 }
240
241 spin_unlock(&task->sighand->siglock);
242
207 retval = 0; 243 retval = 0;
208unlock_tasklist: 244unlock_tasklist:
209 write_unlock_irq(&tasklist_lock); 245 write_unlock_irq(&tasklist_lock);
210unlock_creds: 246unlock_creds:
211 mutex_unlock(&task->signal->cred_guard_mutex); 247 mutex_unlock(&task->signal->cred_guard_mutex);
212out: 248out:
249 if (wait_trap)
250 wait_event(current->signal->wait_chldexit,
251 !(task->group_stop & GROUP_STOP_TRAPPING));
213 return retval; 252 return retval;
214} 253}
215 254
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 */
237static 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(&current->sighand->siglock); 1743 spin_unlock_irq(&current->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 1855retry:
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(&current->sighand->siglock); 1868 spin_unlock_irq(&current->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(&current->sighand->siglock); 1879 spin_lock_irq(&current->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(&current->sighand->siglock); 1899 spin_unlock_irq(&current->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}