[amd64] ptrace,x86: force IRET path after a ptrace_stop() (CVE-2014-4699)
svn path=/dists/sid/linux/; revision=21504
This commit is contained in:
parent
1f2cc7d276
commit
4e3b021352
|
@ -56,6 +56,9 @@ linux (3.14.10-1) UNRELEASED; urgency=medium
|
|||
- builddeb: use $OBJCOPY variable instead of objcopy (regression in 3.12)
|
||||
- [i386] efi-pstore: Fix an overflow on 32-bit builds
|
||||
|
||||
[ Ben Hutchings ]
|
||||
* [amd64] ptrace,x86: force IRET path after a ptrace_stop() (CVE-2014-4699)
|
||||
|
||||
-- Ben Hutchings <ben@decadent.org.uk> Sun, 06 Jul 2014 18:42:50 +0100
|
||||
|
||||
linux (3.14.9-1) unstable; urgency=medium
|
||||
|
|
74
debian/patches/bugfix/all/ptrace-x86-force-IRET-path-after-a-ptrace_stop.patch
vendored
Normal file
74
debian/patches/bugfix/all/ptrace-x86-force-IRET-path-after-a-ptrace_stop.patch
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
From: Tejun Heo <tj@kernel.org>
|
||||
Date: Thu, 3 Jul 2014 15:43:15 -0400
|
||||
Subject: ptrace,x86: force IRET path after a ptrace_stop()
|
||||
Origin: https://git.kernel.org/linus/b9cd18de4db3c9ffa7e17b0dc0ca99ed5aa4d43a
|
||||
|
||||
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>
|
||||
---
|
||||
arch/x86/include/asm/ptrace.h | 16 ++++++++++++++++
|
||||
include/linux/ptrace.h | 3 +++
|
||||
2 files changed, 19 insertions(+)
|
||||
|
||||
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
|
||||
index 14fd6fd..6205f0c 100644
|
||||
--- a/arch/x86/include/asm/ptrace.h
|
||||
+++ b/arch/x86/include/asm/ptrace.h
|
||||
@@ -231,6 +231,22 @@ static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
|
||||
|
||||
#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);
|
||||
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
|
||||
index 077904c..cc79eff 100644
|
||||
--- a/include/linux/ptrace.h
|
||||
+++ b/include/linux/ptrace.h
|
||||
@@ -334,6 +334,9 @@ static inline void user_single_step_siginfo(struct task_struct *tsk,
|
||||
* 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
|
|
@ -91,3 +91,4 @@ debian/drivers-base-platform-avoid-abi-change-in-3.14.6.patch
|
|||
debian/dma-avoid-abi-change-in-3.14.6.patch
|
||||
debian/vfs-avoid-abi-change-for-cve-2014-4014.patch
|
||||
debian/alsa-avoid-abi-change-for-cve-2014-4652-fix.patch
|
||||
bugfix/all/ptrace-x86-force-IRET-path-after-a-ptrace_stop.patch
|
||||
|
|
Loading…
Reference in New Issue