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 include (2 of 3 files). Show all
Unified · Split
| @@ -60,7 +60,7 @@ extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned · 59 unmodified lines | |||
| 60 | extern void ptrace_disable(struct task_struct *); | 60 | extern void ptrace_disable(struct task_struct *); |
| 61 | extern int ptrace_request(struct task_struct *child, long request, | 61 | extern int ptrace_request(struct task_struct *child, long request, |
| 62 | unsigned long addr, unsigned long data); | 62 | unsigned long addr, unsigned long data); |
| 63 | extern void ptrace_notify(int exit_code); | 63 | extern void ptrace_notify(int exit_code, unsigned long message); |
| 64 | extern void __ptrace_link(struct task_struct *child, | 64 | extern void __ptrace_link(struct task_struct *child, |
| 65 | struct task_struct *new_parent, | 65 | struct task_struct *new_parent, |
| 66 | const struct cred *ptracer_cred); | 66 | const struct cred *ptracer_cred); |
| @@ -155,8 +155,7 @@ static inline bool ptrace_event_enabled(struct task_struct *task, int event) · 88 unmodified lines | |||
| 155 | static inline void ptrace_event(int event, unsigned long message) | 155 | static inline void ptrace_event(int event, unsigned long message) |
| 156 | { | 156 | { |
| 157 | if (unlikely(ptrace_event_enabled(current, event))) { | 157 | if (unlikely(ptrace_event_enabled(current, event))) { |
| 158 | current->ptrace_message = message; | 158 | ptrace_notify((event << 8) | SIGTRAP, message); |
| 159 | ptrace_notify((event << 8) | SIGTRAP); | ||
| 160 | } else if (event == PTRACE_EVENT_EXEC) { | 159 | } else if (event == PTRACE_EVENT_EXEC) { |
| 161 | /* legacy EXEC report via SIGTRAP */ | 160 | /* legacy EXEC report via SIGTRAP */ |
| 162 | if ((current->ptrace & (PT_PTRACED|PT_SEIZED)) == PT_PTRACED) | 161 | if ((current->ptrace & (PT_PTRACED|PT_SEIZED)) == PT_PTRACED) |
| @@ -424,8 +423,7 @@ static inline int ptrace_report_syscall(unsigned long message) · 261 unmodified lines | |||
| 424 | if (!(ptrace & PT_PTRACED)) | 423 | if (!(ptrace & PT_PTRACED)) |
| 425 | return 0; | 424 | return 0; |
| 426 | 425 | ||
| 427 | current->ptrace_message = message; | 426 | ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0), message); |
| 428 | ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); | ||
| 429 | 427 | ||
| 430 | /* | 428 | /* |
| 431 | * this isn't the same as continuing with a signal, but it will do | 429 | * this isn't the same as continuing with a signal, but it will do |
| @@ -437,7 +435,6 @@ static inline int ptrace_report_syscall(unsigned long message) · 5 unmodified lines | |||
| 437 | current->exit_code = 0; | 435 | current->exit_code = 0; |
| 438 | } | 436 | } |
| 439 | 437 | ||
| 440 | current->ptrace_message = 0; | ||
| 441 | return fatal_signal_pending(current); | 438 | return fatal_signal_pending(current); |
| 442 | } | 439 | } |
| 443 | 440 | ||
| @@ -114,7 +114,7 @@ struct ptrace_rseq_configuration { · 113 unmodified lines | |||
| 114 | 114 | ||
| 115 | /* | 115 | /* |
| 116 | * These values are stored in task->ptrace_message | 116 | * These values are stored in task->ptrace_message |
| 117 | * by ptrace_report_syscall_* to describe the current syscall-stop. | 117 | * by ptrace_stop to describe the current syscall-stop. |
| 118 | */ | 118 | */ |
| 119 | #define PTRACE_EVENTMSG_SYSCALL_ENTRY 1 | 119 | #define PTRACE_EVENTMSG_SYSCALL_ENTRY 1 |
| 120 | #define PTRACE_EVENTMSG_SYSCALL_EXIT 2 | 120 | #define PTRACE_EVENTMSG_SYSCALL_EXIT 2 |