2005-01-18 01:29:02

by Juho Snellman

[permalink] [raw]
Subject: x86-64: int3 no longer causes SIGTRAP in 2.6.10

2.6.10 changed the behaviour of the int3 instruction on x86-64. It
used to result in a SIGTRAP, now it's a SIGSEGV in both native and
32-bit legacy modes. This was apparently caused by the kprobe port,
specifically this part:

--- a/arch/x86_64/kernel/traps.c 2004-12-24 13:36:17 -08:00
+++ b/arch/x86_64/kernel/traps.c 2004-12-24 13:36:17 -08:00
@@ -862,8 +910,8 @@
set_intr_gate(0,&divide_error);
set_intr_gate_ist(1,&debug,DEBUG_STACK);
set_intr_gate_ist(2,&nmi,NMI_STACK);
- set_system_gate(3,&int3); /* int3-5 can be called from all */
- set_system_gate(4,&overflow);
+ set_intr_gate(3,&int3);
+ set_system_gate(4,&overflow); /* int4-5 can be called from all */

Was effectively disabling int3 a conscious decision, or just an
unintended side-effect? This breaks at least Steel Bank Common Lisp
(x86 and x86-64) and CMU Common Lisp (x86), which use int3 for error
traps and breakpoints.

Simple test case:

% cat foo.c
int main (void) {
asm("int3");
return 0;
}
% gcc -o foo foo.c
% ./foo
zsh: trace trap ./foo
% gcc -m32 -o foo-32 foo.c
% ./foo-32
zsh: trace trap ./foo-32

[ reboot ]

% uname -a
Linux kiki 2.6.10 #2 Sun Dec 26 04:54:05 EET 2004 x86_64 x86_64 x86_64
% ./foo
zsh: segmentation fault ./foo
% ./foo-32
zsh: segmentation fault ./foo-32

--
Juho Snellman


2005-01-18 02:14:49

by Andi Kleen

[permalink] [raw]
Subject: Re: x86-64: int3 no longer causes SIGTRAP in 2.6.10

Juho Snellman <[email protected]> writes:

> 2.6.10 changed the behaviour of the int3 instruction on x86-64. It
> used to result in a SIGTRAP, now it's a SIGSEGV in both native and
> 32-bit legacy modes. This was apparently caused by the kprobe port,
> specifically this part:
>
> --- a/arch/x86_64/kernel/traps.c 2004-12-24 13:36:17 -08:00
> +++ b/arch/x86_64/kernel/traps.c 2004-12-24 13:36:17 -08:00
> @@ -862,8 +910,8 @@
> set_intr_gate(0,&divide_error);
> set_intr_gate_ist(1,&debug,DEBUG_STACK);
> set_intr_gate_ist(2,&nmi,NMI_STACK);
> - set_system_gate(3,&int3); /* int3-5 can be called from all */
> - set_system_gate(4,&overflow);
> + set_intr_gate(3,&int3);
> + set_system_gate(4,&overflow); /* int4-5 can be called from all */
>
> Was effectively disabling int3 a conscious decision, or just an
> unintended side-effect? This breaks at least Steel Bank Common Lisp

It's a bug. Thanks for the report.

I'm not sure why it was even changed. Prasanna?

I think it should be just changed back. If kprobes cannot
deal with traps for user space it needs to be fixed. e.g.
by adding a user space check in kprobe_handler().

-Andi

Like this patch.

Index: linux/arch/x86_64/kernel/traps.c
===================================================================
--- linux.orig/arch/x86_64/kernel/traps.c 2005-01-17 10:34:24.%N +0100
+++ linux/arch/x86_64/kernel/traps.c 2005-01-18 02:42:02.%N +0100
@@ -908,7 +908,7 @@
set_intr_gate(0,&divide_error);
set_intr_gate_ist(1,&debug,DEBUG_STACK);
set_intr_gate_ist(2,&nmi,NMI_STACK);
- set_intr_gate(3,&int3);
+ set_system_gate(3,&int3);
set_system_gate(4,&overflow); /* int4-5 can be called from all */
set_system_gate(5,&bounds);
set_intr_gate(6,&invalid_op);
Index: linux/arch/x86_64/kernel/kprobes.c
===================================================================
--- linux.orig/arch/x86_64/kernel/kprobes.c 2005-01-04 12:12:39.%N +0100
+++ linux/arch/x86_64/kernel/kprobes.c 2005-01-18 02:46:05.%N +0100
@@ -297,6 +297,8 @@
struct die_args *args = (struct die_args *)data;
switch (val) {
case DIE_INT3:
+ if (args->regs->cs & 3)
+ return NOTIFY_DONE;
if (kprobe_handler(args->regs))
return NOTIFY_STOP;
break;


2005-01-18 08:48:32

by S. P. Prasanna

[permalink] [raw]
Subject: Re: x86-64: int3 no longer causes SIGTRAP in 2.6.10

On Tue, Jan 18, 2005 at 02:47:08AM +0100, Andi Kleen wrote:
> Juho Snellman <[email protected]> writes:
>
> > 2.6.10 changed the behaviour of the int3 instruction on x86-64. It
> > used to result in a SIGTRAP, now it's a SIGSEGV in both native and
> > 32-bit legacy modes. This was apparently caused by the kprobe port,
> > specifically this part:
> >
> > --- a/arch/x86_64/kernel/traps.c 2004-12-24 13:36:17 -08:00
> > +++ b/arch/x86_64/kernel/traps.c 2004-12-24 13:36:17 -08:00
> > @@ -862,8 +910,8 @@
> > set_intr_gate(0,&divide_error);
> > set_intr_gate_ist(1,&debug,DEBUG_STACK);
> > set_intr_gate_ist(2,&nmi,NMI_STACK);
> > - set_system_gate(3,&int3); /* int3-5 can be called from all */
> > - set_system_gate(4,&overflow);
> > + set_intr_gate(3,&int3);
> > + set_system_gate(4,&overflow); /* int4-5 can be called from all */
> >
> > Was effectively disabling int3 a conscious decision, or just an
> > unintended side-effect? This breaks at least Steel Bank Common Lisp
>
> It's a bug. Thanks for the report.
>
> I'm not sure why it was even changed. Prasanna?
>
> I think it should be just changed back. If kprobes cannot
> deal with traps for user space it needs to be fixed. e.g.
> by adding a user space check in kprobe_handler().
>
Yes its a bug, we turn trap 3 into interrupt gates to ensure that it is not preemtable.

Thanks
Prasanna
> -Andi
>
> Like this patch.
>
> Index: linux/arch/x86_64/kernel/traps.c
> ===================================================================
> --- linux.orig/arch/x86_64/kernel/traps.c 2005-01-17 10:34:24.%N +0100
> +++ linux/arch/x86_64/kernel/traps.c 2005-01-18 02:42:02.%N +0100
> @@ -908,7 +908,7 @@
> set_intr_gate(0,&divide_error);
> set_intr_gate_ist(1,&debug,DEBUG_STACK);
> set_intr_gate_ist(2,&nmi,NMI_STACK);
> - set_intr_gate(3,&int3);
> + set_system_gate(3,&int3);
> set_system_gate(4,&overflow); /* int4-5 can be called from all */
> set_system_gate(5,&bounds);
> set_intr_gate(6,&invalid_op);
> Index: linux/arch/x86_64/kernel/kprobes.c
> ===================================================================
> --- linux.orig/arch/x86_64/kernel/kprobes.c 2005-01-04 12:12:39.%N +0100
> +++ linux/arch/x86_64/kernel/kprobes.c 2005-01-18 02:46:05.%N +0100
> @@ -297,6 +297,8 @@
> struct die_args *args = (struct die_args *)data;
> switch (val) {
> case DIE_INT3:
> + if (args->regs->cs & 3)
> + return NOTIFY_DONE;
> if (kprobe_handler(args->regs))
> return NOTIFY_STOP;
> break;
>
>

--
Have a Nice Day!

Thanks & Regards
Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<[email protected]>

2005-01-18 08:52:51

by Andi Kleen

[permalink] [raw]
Subject: Re: x86-64: int3 no longer causes SIGTRAP in 2.6.10

> Yes its a bug, we turn trap 3 into interrupt gates to ensure that it is not preemtable.

Is the patch ok for you?

-Andi

> > Like this patch.
> >
> > Index: linux/arch/x86_64/kernel/traps.c
> > ===================================================================
> > --- linux.orig/arch/x86_64/kernel/traps.c 2005-01-17 10:34:24.%N +0100
> > +++ linux/arch/x86_64/kernel/traps.c 2005-01-18 02:42:02.%N +0100
> > @@ -908,7 +908,7 @@
> > set_intr_gate(0,&divide_error);
> > set_intr_gate_ist(1,&debug,DEBUG_STACK);
> > set_intr_gate_ist(2,&nmi,NMI_STACK);
> > - set_intr_gate(3,&int3);
> > + set_system_gate(3,&int3);
> > set_system_gate(4,&overflow); /* int4-5 can be called from all */
> > set_system_gate(5,&bounds);
> > set_intr_gate(6,&invalid_op);
> > Index: linux/arch/x86_64/kernel/kprobes.c
> > ===================================================================
> > --- linux.orig/arch/x86_64/kernel/kprobes.c 2005-01-04 12:12:39.%N +0100
> > +++ linux/arch/x86_64/kernel/kprobes.c 2005-01-18 02:46:05.%N +0100
> > @@ -297,6 +297,8 @@
> > struct die_args *args = (struct die_args *)data;
> > switch (val) {
> > case DIE_INT3:
> > + if (args->regs->cs & 3)
> > + return NOTIFY_DONE;
> > if (kprobe_handler(args->regs))
> > return NOTIFY_STOP;
> > break;
> >
> >

2005-01-19 11:34:18

by S. P. Prasanna

[permalink] [raw]
Subject: Re: x86-64: int3 no longer causes SIGTRAP in 2.6.10

Hi Andi,

> > > - set_intr_gate(3,&int3);
> > > + set_system_gate(3,&int3);
> > > set_system_gate(4,&overflow); /* int4-5 can be called from all */
> > > set_system_gate(5,&bounds);
> > > set_intr_gate(6,&invalid_op);
> > > Index: linux/arch/x86_64/kernel/kprobes.c

This looks good to me. Andi do you see any thing that will cause premption
by moving int3 to system gate.

> > > ===================================================================
> > > --- linux.orig/arch/x86_64/kernel/kprobes.c 2005-01-04 12:12:39.%N +0100
> > > +++ linux/arch/x86_64/kernel/kprobes.c 2005-01-18 02:46:05.%N +0100
> > > @@ -297,6 +297,8 @@
> > > struct die_args *args = (struct die_args *)data;
> > > switch (val) {
> > > case DIE_INT3:
> > > + if (args->regs->cs & 3)
> > > + return NOTIFY_DONE;

This will prevent handling of userspace probes (privilege level 3). The
kprobe_exception handler will return from here and registered user space probe
handler won't be called.

Thanks
Prasanna
--

Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<[email protected]>

2005-01-19 12:19:32

by Andi Kleen

[permalink] [raw]
Subject: Re: x86-64: int3 no longer causes SIGTRAP in 2.6.10

On Wed, Jan 19, 2005 at 05:06:36PM +0530, Prasanna S Panchamukhi wrote:
> Hi Andi,
>
> > > > - set_intr_gate(3,&int3);
> > > > + set_system_gate(3,&int3);
> > > > set_system_gate(4,&overflow); /* int4-5 can be called from all */
> > > > set_system_gate(5,&bounds);
> > > > set_intr_gate(6,&invalid_op);
> > > > Index: linux/arch/x86_64/kernel/kprobes.c
>
> This looks good to me. Andi do you see any thing that will cause premption
> by moving int3 to system gate.

The only difference between an interrupt gate and a system gate is
that a system gate can be called directly from user space using "int".

I don't see how that would affect preemption.



>
> > > > ===================================================================
> > > > --- linux.orig/arch/x86_64/kernel/kprobes.c 2005-01-04 12:12:39.%N +0100
> > > > +++ linux/arch/x86_64/kernel/kprobes.c 2005-01-18 02:46:05.%N +0100
> > > > @@ -297,6 +297,8 @@
> > > > struct die_args *args = (struct die_args *)data;
> > > > switch (val) {
> > > > case DIE_INT3:
> > > > + if (args->regs->cs & 3)
> > > > + return NOTIFY_DONE;
>
> This will prevent handling of userspace probes (privilege level 3). The
> kprobe_exception handler will return from here and registered user space probe
> handler won't be called.

It's equivalent to the previous code - previously the CPU would reject
the int 3 call though and turn it into an GPF. If you prefer it I can
remove it. But were user space probes ever tested? It doesn't look like it.
If they're broken perhaps it would be better to disable it for now
to prevent any unintended security issues.

-Andi