From aeb368a54a8f71014d4662c0fb99f76245d47c01 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 4 Jul 2014 14:43:01 -0700 Subject: [PATCH] 3.14-stable patches added patches: ptrace-x86-force-iret-path-after-a-ptrace_stop.patch --- ...-force-iret-path-after-a-ptrace_stop.patch | 75 +++++++++++++++++++ queue-3.14/series | 1 + 2 files changed, 76 insertions(+) create mode 100644 queue-3.14/ptrace-x86-force-iret-path-after-a-ptrace_stop.patch diff --git a/queue-3.14/ptrace-x86-force-iret-path-after-a-ptrace_stop.patch b/queue-3.14/ptrace-x86-force-iret-path-after-a-ptrace_stop.patch new file mode 100644 index 00000000000..3a1094e0de2 --- /dev/null +++ b/queue-3.14/ptrace-x86-force-iret-path-after-a-ptrace_stop.patch @@ -0,0 +1,75 @@ +From b9cd18de4db3c9ffa7e17b0dc0ca99ed5aa4d43a Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Thu, 3 Jul 2014 15:43:15 -0400 +Subject: ptrace,x86: force IRET path after a ptrace_stop() + +From: Tejun Heo + +commit b9cd18de4db3c9ffa7e17b0dc0ca99ed5aa4d43a upstream. + +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 +Reported-by: Andy Lutomirski +Acked-by: Oleg Nesterov +Suggested-by: Linus Torvalds +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/ptrace.h | 16 ++++++++++++++++ + include/linux/ptrace.h | 3 +++ + 2 files changed, 19 insertions(+) + +--- a/arch/x86/include/asm/ptrace.h ++++ b/arch/x86/include/asm/ptrace.h +@@ -231,6 +231,22 @@ static inline unsigned long regs_get_ker + + #define ARCH_HAS_USER_SINGLE_STEP_INFO + ++/* ++ * When hitting ptrace_stop(), we cannot return using SYSRET because ++ * that does not restore the full CPU state, only a minimal set. The ++ * ptracer can change arbitrary register values, which is usually okay ++ * because the usual ptrace stops run off the signal delivery path which ++ * forces IRET; however, ptrace_event() stops happen in arbitrary places ++ * in the kernel and don't force IRET path. ++ * ++ * So force IRET path after a ptrace stop. ++ */ ++#define arch_ptrace_stop_needed(code, info) \ ++({ \ ++ set_thread_flag(TIF_NOTIFY_RESUME); \ ++ false; \ ++}) ++ + struct user_desc; + extern int do_get_thread_area(struct task_struct *p, int idx, + struct user_desc __user *info); +--- a/include/linux/ptrace.h ++++ b/include/linux/ptrace.h +@@ -334,6 +334,9 @@ static inline void user_single_step_sigi + * calling arch_ptrace_stop() when it would be superfluous. For example, + * if the thread has not been back to user mode since the last stop, the + * thread state might indicate that nothing needs to be done. ++ * ++ * This is guaranteed to be invoked once before a task stops for ptrace and ++ * may include arch-specific operations necessary prior to a ptrace stop. + */ + #define arch_ptrace_stop_needed(code, info) (0) + #endif diff --git a/queue-3.14/series b/queue-3.14/series index a2c8cc3b65e..8b60be2c79c 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -49,3 +49,4 @@ reiserfs-call-truncate_setsize-under-tailpack-mutex.patch mips-kvm-remove-redundant-null-checks-before-kfree.patch mips-kvm-fix-memory-leak-on-vcpu.patch ipvs-fix-panic-due-to-non-linear-skb.patch +ptrace-x86-force-iret-path-after-a-ptrace_stop.patch -- 2.47.3