summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'tags/2.6.18-11/30031_ptrace-handle-bogus-selector.patch')
-rw-r--r--tags/2.6.18-11/30031_ptrace-handle-bogus-selector.patch86
1 files changed, 86 insertions, 0 deletions
diff --git a/tags/2.6.18-11/30031_ptrace-handle-bogus-selector.patch b/tags/2.6.18-11/30031_ptrace-handle-bogus-selector.patch
new file mode 100644
index 0000000..2aacd3b
--- /dev/null
+++ b/tags/2.6.18-11/30031_ptrace-handle-bogus-selector.patch
@@ -0,0 +1,86 @@
+From: Roland McGrath <roland@redhat.com>
+Date: Mon, 16 Jul 2007 08:03:16 +0000 (-0700)
+Subject: Handle bogus %cs selector in single-step instruction decoding
+X-Git-Tag: v2.6.23-rc1~492
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=29eb51101c02df517ca64ec472d7501127ad1da8
+
+Handle bogus %cs selector in single-step instruction decoding
+
+The code for LDT segment selectors was not robust in the face of a bogus
+selector set in %cs via ptrace before the single-step was done.
+
+Signed-off-by: Roland McGrath <roland@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+---
+
+Adjusted to apply to Debian's 2.6.18 by dann frazier <dannf@debian.org>
+
+diff -urpN linux-source-2.6.18.orig/arch/i386/kernel/ptrace.c linux-source-2.6.18/arch/i386/kernel/ptrace.c
+--- linux-source-2.6.18.orig/arch/i386/kernel/ptrace.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/arch/i386/kernel/ptrace.c 2007-09-19 23:45:45.949576125 -0600
+@@ -172,14 +172,22 @@ static unsigned long convert_eip_to_line
+ u32 *desc;
+ unsigned long base;
+
+- down(&child->mm->context.sem);
+- desc = child->mm->context.ldt + (seg & ~7);
+- base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
++ seg &= ~7UL;
+
+- /* 16-bit code segment? */
+- if (!((desc[1] >> 22) & 1))
+- addr &= 0xffff;
+- addr += base;
++ down(&child->mm->context.sem);
++ if (unlikely((seg >> 3) >= child->mm->context.size))
++ addr = -1L; /* bogus selector, access would fault */
++ else {
++ desc = child->mm->context.ldt + seg;
++ base = ((desc[0] >> 16) |
++ ((desc[1] & 0xff) << 16) |
++ (desc[1] & 0xff000000));
++
++ /* 16-bit code segment? */
++ if (!((desc[1] >> 22) & 1))
++ addr &= 0xffff;
++ addr += base;
++ }
+ up(&child->mm->context.sem);
+ }
+ return addr;
+diff -urpN linux-source-2.6.18.orig/arch/x86_64/kernel/ptrace.c linux-source-2.6.18/arch/x86_64/kernel/ptrace.c
+--- linux-source-2.6.18.orig/arch/x86_64/kernel/ptrace.c 2006-09-19 21:42:06.000000000 -0600
++++ linux-source-2.6.18/arch/x86_64/kernel/ptrace.c 2007-09-19 23:45:45.953575027 -0600
+@@ -103,16 +103,25 @@ unsigned long convert_rip_to_linear(stru
+ u32 *desc;
+ unsigned long base;
+
+- down(&child->mm->context.sem);
+- desc = child->mm->context.ldt + (seg & ~7);
+- base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000);
++ seg &= ~7UL;
+
+- /* 16-bit code segment? */
+- if (!((desc[1] >> 22) & 1))
+- addr &= 0xffff;
+- addr += base;
++ down(&child->mm->context.sem);
++ if (unlikely((seg >> 3) >= child->mm->context.size))
++ addr = -1L; /* bogus selector, access would fault */
++ else {
++ desc = child->mm->context.ldt + seg;
++ base = ((desc[0] >> 16) |
++ ((desc[1] & 0xff) << 16) |
++ (desc[1] & 0xff000000));
++
++ /* 16-bit code segment? */
++ if (!((desc[1] >> 22) & 1))
++ addr &= 0xffff;
++ addr += base;
++ }
+ up(&child->mm->context.sem);
+ }
++
+ return addr;
+ }
+