kprobes-x86-fix-kprobes-to-skip-prefixes-correctly.patch (#610941)
This commit is contained in:
parent
b30c150da1
commit
8f132e348c
@ -710,6 +710,8 @@ Patch12050: direct-io-move-aio_complete-into-end_io.patch
|
|||||||
Patch12060: ext4-move-aio-completion-after-unwritten-extent-conversion.patch
|
Patch12060: ext4-move-aio-completion-after-unwritten-extent-conversion.patch
|
||||||
Patch12070: xfs-move-aio-completion-after-unwritten-extent-conversion.patch
|
Patch12070: xfs-move-aio-completion-after-unwritten-extent-conversion.patch
|
||||||
|
|
||||||
|
Patch12080: kprobes-x86-fix-kprobes-to-skip-prefixes-correctly.patch
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
|
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
|
||||||
@ -1305,6 +1307,9 @@ ApplyPatch direct-io-move-aio_complete-into-end_io.patch
|
|||||||
ApplyPatch ext4-move-aio-completion-after-unwritten-extent-conversion.patch
|
ApplyPatch ext4-move-aio-completion-after-unwritten-extent-conversion.patch
|
||||||
ApplyPatch xfs-move-aio-completion-after-unwritten-extent-conversion.patch
|
ApplyPatch xfs-move-aio-completion-after-unwritten-extent-conversion.patch
|
||||||
|
|
||||||
|
# bz 610941
|
||||||
|
ApplyPatch kprobes-x86-fix-kprobes-to-skip-prefixes-correctly.patch
|
||||||
|
|
||||||
# END OF PATCH APPLICATIONS
|
# END OF PATCH APPLICATIONS
|
||||||
|
|
||||||
%endif
|
%endif
|
||||||
@ -1893,6 +1898,7 @@ fi
|
|||||||
%changelog
|
%changelog
|
||||||
* Fri Aug 27 2010 Chuck Ebbert <cebbert@redhat.com> 2.6.35.4-12
|
* Fri Aug 27 2010 Chuck Ebbert <cebbert@redhat.com> 2.6.35.4-12
|
||||||
- Linux 2.6.35.4
|
- Linux 2.6.35.4
|
||||||
|
- kprobes-x86-fix-kprobes-to-skip-prefixes-correctly.patch (#610941)
|
||||||
|
|
||||||
* Wed Aug 25 2010 Chuck Ebbert <cebbert@redhat.com> 2.6.35.4-11.rc1
|
* Wed Aug 25 2010 Chuck Ebbert <cebbert@redhat.com> 2.6.35.4-11.rc1
|
||||||
- Linux 2.6.35.4-rc1
|
- Linux 2.6.35.4-rc1
|
||||||
|
98
kprobes-x86-fix-kprobes-to-skip-prefixes-correctly.patch
Normal file
98
kprobes-x86-fix-kprobes-to-skip-prefixes-correctly.patch
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
|
||||||
|
Date: Tue, 29 Jun 2010 05:53:50 +0000 (+0900)
|
||||||
|
Subject: kprobes/x86: Fix kprobes to skip prefixes correctly
|
||||||
|
X-Git-Tag: v2.6.36-rc1~41^2~53
|
||||||
|
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=567a9fd86735ccdc897768ed2dacdd5e83a13509
|
||||||
|
|
||||||
|
kprobes/x86: Fix kprobes to skip prefixes correctly
|
||||||
|
|
||||||
|
Fix resume_execution() and is_IF_modifier() to skip x86
|
||||||
|
instruction prefixes correctly by using x86 instruction
|
||||||
|
attribute.
|
||||||
|
|
||||||
|
Without this fix, resume_execution() can't handle instructions
|
||||||
|
which have non-REX prefixes (REX prefixes are skipped). This
|
||||||
|
will cause unexpected kernel panic by hitting bad address when a
|
||||||
|
kprobe hits on two-byte ret (e.g. "repz ret" generated for
|
||||||
|
Athlon/K8 optimization), because it just checks "repz" and can't
|
||||||
|
recognize the "ret" instruction.
|
||||||
|
|
||||||
|
These prefixes can be found easily with x86 instruction
|
||||||
|
attribute. This patch introduces skip_prefixes() and uses it in
|
||||||
|
resume_execution() and is_IF_modifier() to skip prefixes.
|
||||||
|
|
||||||
|
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
|
||||||
|
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
|
||||||
|
LKML-Reference: <4C298A6E.8070609@hitachi.com>
|
||||||
|
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
|
||||||
|
index 345a4b1..175f85c 100644
|
||||||
|
--- a/arch/x86/kernel/kprobes.c
|
||||||
|
+++ b/arch/x86/kernel/kprobes.c
|
||||||
|
@@ -126,16 +126,22 @@ static void __kprobes synthesize_reljump(void *from, void *to)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Check for the REX prefix which can only exist on X86_64
|
||||||
|
- * X86_32 always returns 0
|
||||||
|
+ * Skip the prefixes of the instruction.
|
||||||
|
*/
|
||||||
|
-static int __kprobes is_REX_prefix(kprobe_opcode_t *insn)
|
||||||
|
+static kprobe_opcode_t *__kprobes skip_prefixes(kprobe_opcode_t *insn)
|
||||||
|
{
|
||||||
|
+ insn_attr_t attr;
|
||||||
|
+
|
||||||
|
+ attr = inat_get_opcode_attribute((insn_byte_t)*insn);
|
||||||
|
+ while (inat_is_legacy_prefix(attr)) {
|
||||||
|
+ insn++;
|
||||||
|
+ attr = inat_get_opcode_attribute((insn_byte_t)*insn);
|
||||||
|
+ }
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
- if ((*insn & 0xf0) == 0x40)
|
||||||
|
- return 1;
|
||||||
|
+ if (inat_is_rex_prefix(attr))
|
||||||
|
+ insn++;
|
||||||
|
#endif
|
||||||
|
- return 0;
|
||||||
|
+ return insn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -272,6 +278,9 @@ static int __kprobes can_probe(unsigned long paddr)
|
||||||
|
*/
|
||||||
|
static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
|
||||||
|
{
|
||||||
|
+ /* Skip prefixes */
|
||||||
|
+ insn = skip_prefixes(insn);
|
||||||
|
+
|
||||||
|
switch (*insn) {
|
||||||
|
case 0xfa: /* cli */
|
||||||
|
case 0xfb: /* sti */
|
||||||
|
@@ -280,13 +289,6 @@ static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * on X86_64, 0x40-0x4f are REX prefixes so we need to look
|
||||||
|
- * at the next byte instead.. but of course not recurse infinitely
|
||||||
|
- */
|
||||||
|
- if (is_REX_prefix(insn))
|
||||||
|
- return is_IF_modifier(++insn);
|
||||||
|
-
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -803,9 +805,8 @@ static void __kprobes resume_execution(struct kprobe *p,
|
||||||
|
unsigned long orig_ip = (unsigned long)p->addr;
|
||||||
|
kprobe_opcode_t *insn = p->ainsn.insn;
|
||||||
|
|
||||||
|
- /*skip the REX prefix*/
|
||||||
|
- if (is_REX_prefix(insn))
|
||||||
|
- insn++;
|
||||||
|
+ /* Skip prefixes */
|
||||||
|
+ insn = skip_prefixes(insn);
|
||||||
|
|
||||||
|
regs->flags &= ~X86_EFLAGS_TF;
|
||||||
|
switch (*insn) {
|
Loading…
Reference in New Issue
Block a user