diff options
Diffstat (limited to 'tags/2.6.18-5/30031_ptrace-handle-bogus-selector.patch')
-rw-r--r-- | tags/2.6.18-5/30031_ptrace-handle-bogus-selector.patch | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/tags/2.6.18-5/30031_ptrace-handle-bogus-selector.patch b/tags/2.6.18-5/30031_ptrace-handle-bogus-selector.patch new file mode 100644 index 0000000..2aacd3b --- /dev/null +++ b/tags/2.6.18-5/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; + } + |