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. Link: https://lkml.kernel.org/r/87bky67qfv.fsf_-_@email.froward.int.ebiederm.org Acked-by: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
parent
355f841a3f
commit
336d4b814b
3 changed files with 16 additions and 16 deletions
|
|
@ -60,7 +60,7 @@ extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned
|
|||
extern void ptrace_disable(struct task_struct *);
|
||||
extern int ptrace_request(struct task_struct *child, long request,
|
||||
unsigned long addr, unsigned long data);
|
||||
extern void ptrace_notify(int exit_code);
|
||||
extern void ptrace_notify(int exit_code, unsigned long message);
|
||||
extern void __ptrace_link(struct task_struct *child,
|
||||
struct task_struct *new_parent,
|
||||
const struct cred *ptracer_cred);
|
||||
|
|
@ -155,8 +155,7 @@ static inline bool ptrace_event_enabled(struct task_struct *task, int event)
|
|||
static inline void ptrace_event(int event, unsigned long message)
|
||||
{
|
||||
if (unlikely(ptrace_event_enabled(current, event))) {
|
||||
current->ptrace_message = message;
|
||||
ptrace_notify((event << 8) | SIGTRAP);
|
||||
ptrace_notify((event << 8) | SIGTRAP, message);
|
||||
} else if (event == PTRACE_EVENT_EXEC) {
|
||||
/* legacy EXEC report via SIGTRAP */
|
||||
if ((current->ptrace & (PT_PTRACED|PT_SEIZED)) == PT_PTRACED)
|
||||
|
|
@ -424,8 +423,7 @@ static inline int ptrace_report_syscall(unsigned long message)
|
|||
if (!(ptrace & PT_PTRACED))
|
||||
return 0;
|
||||
|
||||
current->ptrace_message = message;
|
||||
ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
|
||||
ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0), message);
|
||||
|
||||
/*
|
||||
* 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)
|
|||
current->exit_code = 0;
|
||||
}
|
||||
|
||||
current->ptrace_message = 0;
|
||||
return fatal_signal_pending(current);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue