2006-05-18 21:32:49

by Satoshi Oshima

[permalink] [raw]
Subject: [PATCH] kprobes: bad manupilation of 2 byte opcode on x86_64

Hi Andi and Andrew,

I found a bug of kprobes on x86_64.
I attached the fix of this bug.


Problem:

If we put a probe onto a callq instruction and the probe
is executed, kernel panic of Bad RIP value occurs.

Root cause:

If resume_execution() found 0xff at first byte of
p->ainsn.insn, it must check the _second_ byte.
But current resume_execution check _first_ byte again.


I changed it checks second byte of p->ainsn.insn.

Kprobes on i386 don't have this problem, because
the implementation is a little bit different from
x86_64.


Regards,

Satoshi Oshima
Hitachi Computer Product (America) Inc.

----------------------------------------------

diff -Narup linux-2.6.17-rc3-mm1.orig/arch/x86_64/kernel/kprobes.c x86_64_bugifx/arch/x86_64/kernel/kprobes.c
--- linux-2.6.17-rc3-mm1.orig/arch/x86_64/kernel/kprobes.c 2006-05-04 12:34:44.000000000 -0400
+++ x86_64_bugifx/arch/x86_64/kernel/kprobes.c 2006-05-12 16:02:35.000000000 -0400
@@ -514,13 +514,13 @@ static void __kprobes resume_execution(s
*tos = orig_rip + (*tos - copy_rip);
break;
case 0xff:
- if ((*insn & 0x30) == 0x10) {
+ if ((insn[1] & 0x30) == 0x10) {
/* call absolute, indirect */
/* Fix return addr; rip is correct. */
next_rip = regs->rip;
*tos = orig_rip + (*tos - copy_rip);
- } else if (((*insn & 0x31) == 0x20) || /* jmp near, absolute indirect */
- ((*insn & 0x31) == 0x21)) { /* jmp far, absolute indirect */
+ } else if (((insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
+ ((insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */
/* rip is correct. */
next_rip = regs->rip;
}


2006-05-19 08:29:09

by Richard J Moore

[permalink] [raw]
Subject: Re: [PATCH] kprobes: bad manipulation of 2 byte opcode on x86_64





Is there any possibility of a inducing a page fault when checking the
second byte?
- -
Richard J Moore
IBM Advanced Linux Response Team - Linux Technology Centre
MOBEX: 264807; Mobile (+44) (0)7739-875237
Office: (+44) (0)1962-817072



Satoshi Oshima
<soshima@redhat
.com> To
Sent by: Andi Kleen <[email protected]>, Andrew
systemtap-owner Morton <[email protected]>
@sourceware.org cc
[email protected],
[email protected],
18/05/2006 "Keshavamurthy, Anil S"
22:32 <[email protected]>,
Ananth N Mavinakayanahalli
<[email protected]>, Jim Keniston
<[email protected]>, Prasanna S
Panchamukhi <[email protected]>,
"Hideo AOKI@redhat"
<[email protected]>, Masami
Hiramatsu
<[email protected]>,
sugita <[email protected]>
bcc

Subject
[PATCH] kprobes: bad manupilation
of 2 byte opcode on x86_64






Hi Andi and Andrew,

I found a bug of kprobes on x86_64.
I attached the fix of this bug.


Problem:

If we put a probe onto a callq instruction and the probe
is executed, kernel panic of Bad RIP value occurs.

Root cause:

If resume_execution() found 0xff at first byte of
p->ainsn.insn, it must check the _second_ byte.
But current resume_execution check _first_ byte again.


I changed it checks second byte of p->ainsn.insn.

Kprobes on i386 don't have this problem, because
the implementation is a little bit different from
x86_64.


Regards,

Satoshi Oshima
Hitachi Computer Product (America) Inc.

----------------------------------------------

diff -Narup linux-2.6.17-rc3-mm1.orig/arch/x86_64/kernel/kprobes.c
x86_64_bugifx/arch/x86_64/kernel/kprobes.c
--- linux-2.6.17-rc3-mm1.orig/arch/x86_64/kernel/kprobes.c
2006-05-04 12:34:44.000000000 -0400
+++ x86_64_bugifx/arch/x86_64/kernel/kprobes.c 2006-05-12
16:02:35.000000000 -0400
@@ -514,13 +514,13 @@ static void __kprobes resume_execution(s
*tos = orig_rip + (*tos - copy_rip);
break;
case 0xff:
- if ((*insn & 0x30) == 0x10) {
+ if ((insn[1] & 0x30) == 0x10) {
/* call absolute, indirect */
/* Fix return addr; rip is correct. */
next_rip = regs->rip;
*tos = orig_rip + (*tos - copy_rip);
- } else if (((*insn & 0x31) == 0x20) || /*
jmp near, absolute indirect */
- ((*insn & 0x31) == 0x21)) {
/* jmp far, absolute indirect */
+ } else if (((insn[1] & 0x31) == 0x20) || /*
jmp near, absolute indirect */
+ ((insn[1] & 0x31) == 0x21)) {
/* jmp far, absolute indirect */
/* rip is correct. */
next_rip = regs->rip;
}



2006-05-19 12:34:24

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH] kprobes: bad manipulation of 2 byte opcode on x86_64

On Friday 19 May 2006 10:29, Richard J Moore wrote:
> Is there any possibility of a inducing a page fault when checking the
> second byte?

AFAIK instr is in the out of line instruction copy. Kernel would need
to be pretty broken already if that page faulted.

-Andi

2006-05-19 14:14:21

by Satoshi Oshima

[permalink] [raw]
Subject: Re: [PATCH] kprobes: bad manipulation of 2 byte opcode on x86_64

Andi Kleen wrote:
> On Friday 19 May 2006 10:29, Richard J Moore wrote:
>> Is there any possibility of a inducing a page fault when checking the
>> second byte?
>
> AFAIK instr is in the out of line instruction copy. Kernel would need
> to be pretty broken already if that page faulted.

There is no possibility that copied instruction step over
a page boundary. Instruction slot is in the page that
is allocated in get_insn_slot(). And get_insn_slot()
acquires the page by module_alloc(), and divides into
slots.

Satoshi Oshima