Today ptrace_message is easy to overlook as it not a core part of ptrace_stop. It has been overlooked so much that there are places that set ptrace_message and don't clear it, and places that never set it. So if you get an unlucky sequence of events the ptracer may be able to read a ptrace_message that does not apply to the current ptrace stop. Move setting of ptrace_message into ptrace_stop so that it always gets set before the stop, and always gets cleared after the stop. This prevents non-sense from being reported to userspace and makes ptrace_message more visible in the ptrace helper functions so that kernel developers can see it.
Showing the changes to kernel (1 of 3 files). Show all
Unified · Split
| @@ -2191,7 +2191,8 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, · 2190 unmodified lines | |||
| 2191 | * If we actually decide not to stop at all because the tracer | 2191 | * If we actually decide not to stop at all because the tracer |
| 2192 | * is gone, we keep current->exit_code unless clear_code. | 2192 | * is gone, we keep current->exit_code unless clear_code. |
| 2193 | */ | 2193 | */ |
| 2194 | static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t *info) | 2194 | static void ptrace_stop(int exit_code, int why, int clear_code, |
| 2195 | unsigned long message, kernel_siginfo_t *info) | ||
| 2195 | __releases(¤t->sighand->siglock) | 2196 | __releases(¤t->sighand->siglock) |
| 2196 | __acquires(¤t->sighand->siglock) | 2197 | __acquires(¤t->sighand->siglock) |
| 2197 | { | 2198 | { |
| @@ -2237,6 +2238,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t · 39 unmodified lines | |||
| 2237 | */ | 2238 | */ |
| 2238 | smp_wmb(); | 2239 | smp_wmb(); |
| 2239 | 2240 | ||
| 2241 | current->ptrace_message = message; | ||
| 2240 | current->last_siginfo = info; | 2242 | current->last_siginfo = info; |
| 2241 | current->exit_code = exit_code; | 2243 | current->exit_code = exit_code; |
| 2242 | 2244 | ||
| @@ -2315,6 +2317,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t · 72 unmodified lines | |||
| 2315 | */ | 2317 | */ |
| 2316 | spin_lock_irq(¤t->sighand->siglock); | 2318 | spin_lock_irq(¤t->sighand->siglock); |
| 2317 | current->last_siginfo = NULL; | 2319 | current->last_siginfo = NULL; |
| 2320 | current->ptrace_message = 0; | ||
| 2318 | 2321 | ||
| 2319 | /* LISTENING can be set only during STOP traps, clear it */ | 2322 | /* LISTENING can be set only during STOP traps, clear it */ |
| 2320 | current->jobctl &= ~JOBCTL_LISTENING; | 2323 | current->jobctl &= ~JOBCTL_LISTENING; |
| @@ -2327,7 +2330,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t · 6 unmodified lines | |||
| 2327 | recalc_sigpending_tsk(current); | 2330 | recalc_sigpending_tsk(current); |
| 2328 | } | 2331 | } |
| 2329 | 2332 | ||
| 2330 | static void ptrace_do_notify(int signr, int exit_code, int why) | 2333 | static void ptrace_do_notify(int signr, int exit_code, int why, unsigned long message) |
| 2331 | { | 2334 | { |
| 2332 | kernel_siginfo_t info; | 2335 | kernel_siginfo_t info; |
| 2333 | 2336 | ||
| @@ -2338,17 +2341,17 @@ static void ptrace_do_notify(int signr, int exit_code, int why) · 4 unmodified lines | |||
| 2338 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); | 2341 | info.si_uid = from_kuid_munged(current_user_ns(), current_uid()); |
| 2339 | 2342 | ||
| 2340 | /* Let the debugger run. */ | 2343 | /* Let the debugger run. */ |
| 2341 | ptrace_stop(exit_code, why, 1, &info); | 2344 | ptrace_stop(exit_code, why, 1, message, &info); |
| 2342 | } | 2345 | } |
| 2343 | 2346 | ||
| 2344 | void ptrace_notify(int exit_code) | 2347 | void ptrace_notify(int exit_code, unsigned long message) |
| 2345 | { | 2348 | { |
| 2346 | BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP); | 2349 | BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP); |
| 2347 | if (unlikely(task_work_pending(current))) | 2350 | if (unlikely(task_work_pending(current))) |
| 2348 | task_work_run(); | 2351 | task_work_run(); |
| 2349 | 2352 | ||
| 2350 | spin_lock_irq(¤t->sighand->siglock); | 2353 | spin_lock_irq(¤t->sighand->siglock); |
| 2351 | ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED); | 2354 | ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED, message); |
| 2352 | spin_unlock_irq(¤t->sighand->siglock); | 2355 | spin_unlock_irq(¤t->sighand->siglock); |
| 2353 | } | 2356 | } |
| 2354 | 2357 | ||
| @@ -2504,10 +2507,10 @@ static void do_jobctl_trap(void) · 149 unmodified lines | |||
| 2504 | signr = SIGTRAP; | 2507 | signr = SIGTRAP; |
| 2505 | WARN_ON_ONCE(!signr); | 2508 | WARN_ON_ONCE(!signr); |
| 2506 | ptrace_do_notify(signr, signr | (PTRACE_EVENT_STOP << 8), | 2509 | ptrace_do_notify(signr, signr | (PTRACE_EVENT_STOP << 8), |
| 2507 | CLD_STOPPED); | 2510 | CLD_STOPPED, 0); |
| 2508 | } else { | 2511 | } else { |
| 2509 | WARN_ON_ONCE(!signr); | 2512 | WARN_ON_ONCE(!signr); |
| 2510 | ptrace_stop(signr, CLD_STOPPED, 0, NULL); | 2513 | ptrace_stop(signr, CLD_STOPPED, 0, 0, NULL); |
| 2511 | current->exit_code = 0; | 2514 | current->exit_code = 0; |
| 2512 | } | 2515 | } |
| 2513 | } | 2516 | } |
| @@ -2561,7 +2564,7 @@ static int ptrace_signal(int signr, kernel_siginfo_t *info, enum pid_type type) · 47 unmodified lines | |||
| 2561 | * comment in dequeue_signal(). | 2564 | * comment in dequeue_signal(). |
| 2562 | */ | 2565 | */ |
| 2563 | current->jobctl |= JOBCTL_STOP_DEQUEUED; | 2566 | current->jobctl |= JOBCTL_STOP_DEQUEUED; |
| 2564 | ptrace_stop(signr, CLD_TRAPPED, 0, info); | 2567 | ptrace_stop(signr, CLD_TRAPPED, 0, 0, info); |
| 2565 | 2568 | ||
| 2566 | /* We're back. Did the debugger cancel the sig? */ | 2569 | /* We're back. Did the debugger cancel the sig? */ |
| 2567 | signr = current->exit_code; | 2570 | signr = current->exit_code; |
| @@ -2891,7 +2894,7 @@ static void signal_delivered(struct ksignal *ksig, int stepping) · 323 unmodified lines | |||
| 2891 | if (current->sas_ss_flags & SS_AUTODISARM) | 2894 | if (current->sas_ss_flags & SS_AUTODISARM) |
| 2892 | sas_ss_reset(current); | 2895 | sas_ss_reset(current); |
| 2893 | if (stepping) | 2896 | if (stepping) |
| 2894 | ptrace_notify(SIGTRAP); | 2897 | ptrace_notify(SIGTRAP, 0); |
| 2895 | } | 2898 | } |
| 2896 | 2899 | ||
| 2897 | void signal_setup_done(int failed, struct ksignal *ksig, int stepping) | 2900 | void signal_setup_done(int failed, struct ksignal *ksig, int stepping) |