History

ptrace: Move setting/clearing ptrace_message into ptrace_stop

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.

Eric W. Biederman committed 4 years ago

Commit 336d4b81 parent 355f8413 files · +16 −16Browse files

Showing the changes to kernel (1 of 3 files). Show all

Unified · Split

kernel/signal.c+12−9
@@ -2191,7 +2191,8 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, · 2190 unmodified lines
21912191 * If we actually decide not to stop at all because the tracer
21922192 * is gone, we keep current->exit_code unless clear_code.
21932193 */
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)
21952196 __releases(&current->sighand->siglock)
21962197 __acquires(&current->sighand->siglock)
21972198 {
@@ -2237,6 +2238,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t · 39 unmodified lines
22372238 */
22382239 smp_wmb();
22392240
2241+ current->ptrace_message = message;
22402242 current->last_siginfo = info;
22412243 current->exit_code = exit_code;
22422244
@@ -2315,6 +2317,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t · 72 unmodified lines
23152317 */
23162318 spin_lock_irq(&current->sighand->siglock);
23172319 current->last_siginfo = NULL;
2320+ current->ptrace_message = 0;
23182321
23192322 /* LISTENING can be set only during STOP traps, clear it */
23202323 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
23272330 recalc_sigpending_tsk(current);
23282331 }
23292332
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)
23312334 {
23322335 kernel_siginfo_t info;
23332336
@@ -2338,17 +2341,17 @@ static void ptrace_do_notify(int signr, int exit_code, int why) · 4 unmodified lines
23382341 info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
23392342
23402343 /* Let the debugger run. */
2341− ptrace_stop(exit_code, why, 1, &info);
2344+ ptrace_stop(exit_code, why, 1, message, &info);
23422345 }
23432346
2344−void ptrace_notify(int exit_code)
2347+void ptrace_notify(int exit_code, unsigned long message)
23452348 {
23462349 BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP);
23472350 if (unlikely(task_work_pending(current)))
23482351 task_work_run();
23492352
23502353 spin_lock_irq(&current->sighand->siglock);
2351− ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED);
2354+ ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED, message);
23522355 spin_unlock_irq(&current->sighand->siglock);
23532356 }
23542357
@@ -2504,10 +2507,10 @@ static void do_jobctl_trap(void) · 149 unmodified lines
25042507 signr = SIGTRAP;
25052508 WARN_ON_ONCE(!signr);
25062509 ptrace_do_notify(signr, signr | (PTRACE_EVENT_STOP << 8),
2507− CLD_STOPPED);
2510+ CLD_STOPPED, 0);
25082511 } else {
25092512 WARN_ON_ONCE(!signr);
2510− ptrace_stop(signr, CLD_STOPPED, 0, NULL);
2513+ ptrace_stop(signr, CLD_STOPPED, 0, 0, NULL);
25112514 current->exit_code = 0;
25122515 }
25132516 }
@@ -2561,7 +2564,7 @@ static int ptrace_signal(int signr, kernel_siginfo_t *info, enum pid_type type) · 47 unmodified lines
25612564 * comment in dequeue_signal().
25622565 */
25632566 current->jobctl |= JOBCTL_STOP_DEQUEUED;
2564− ptrace_stop(signr, CLD_TRAPPED, 0, info);
2567+ ptrace_stop(signr, CLD_TRAPPED, 0, 0, info);
25652568
25662569 /* We're back. Did the debugger cancel the sig? */
25672570 signr = current->exit_code;
@@ -2891,7 +2894,7 @@ static void signal_delivered(struct ksignal *ksig, int stepping) · 323 unmodified lines
28912894 if (current->sas_ss_flags & SS_AUTODISARM)
28922895 sas_ss_reset(current);
28932896 if (stepping)
2894− ptrace_notify(SIGTRAP);
2897+ ptrace_notify(SIGTRAP, 0);
28952898 }
28962899
28972900 void signal_setup_done(int failed, struct ksignal *ksig, int stepping)