Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ptrace,x86: force IRET path after a ptrace_stop()

The 'sysret' fastpath does not correctly restore even all regular
registers, much less any segment registers or reflags values. That is
very much part of why it's faster than 'iret'.

Normally that isn't a problem, because the normal ptrace() interface
catches the process using the signal handler infrastructure, which
always returns with an iret.

However, some paths can get caught using ptrace_event() instead of the
signal path, and for those we need to make sure that we aren't going to
return to user space using 'sysret'. Otherwise the modifications that
may have been done to the register set by the tracer wouldn't
necessarily take effect.

Fix it by forcing IRET path by setting TIF_NOTIFY_RESUME from
arch_ptrace_stop_needed() which is invoked from ptrace_stop().

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Andy Lutomirski <luto@amacapital.net>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: stable@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Tejun Heo and committed by
Linus Torvalds
b9cd18de 5170a3b2

+19
+16
arch/x86/include/asm/ptrace.h
··· 231 231 232 232 #define ARCH_HAS_USER_SINGLE_STEP_INFO 233 233 234 + /* 235 + * When hitting ptrace_stop(), we cannot return using SYSRET because 236 + * that does not restore the full CPU state, only a minimal set. The 237 + * ptracer can change arbitrary register values, which is usually okay 238 + * because the usual ptrace stops run off the signal delivery path which 239 + * forces IRET; however, ptrace_event() stops happen in arbitrary places 240 + * in the kernel and don't force IRET path. 241 + * 242 + * So force IRET path after a ptrace stop. 243 + */ 244 + #define arch_ptrace_stop_needed(code, info) \ 245 + ({ \ 246 + set_thread_flag(TIF_NOTIFY_RESUME); \ 247 + false; \ 248 + }) 249 + 234 250 struct user_desc; 235 251 extern int do_get_thread_area(struct task_struct *p, int idx, 236 252 struct user_desc __user *info);
+3
include/linux/ptrace.h
··· 334 334 * calling arch_ptrace_stop() when it would be superfluous. For example, 335 335 * if the thread has not been back to user mode since the last stop, the 336 336 * thread state might indicate that nothing needs to be done. 337 + * 338 + * This is guaranteed to be invoked once before a task stops for ptrace and 339 + * may include arch-specific operations necessary prior to a ptrace stop. 337 340 */ 338 341 #define arch_ptrace_stop_needed(code, info) (0) 339 342 #endif