lkml.org 
[lkml]   [2009]   [Aug]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
Subject32bit binaries on x86_64/Xen segfaults in syscall-vdso
Hi folks

I upgraded one of my 32bit chroots on a x86-64 machine runing under Xen
lately. All binaries started to segfault. Some extensive checks later
show the vdso as the culprit. Later I found <gpe0vg$j67$1@ger.gmane.org>
with the same problem. The full story can be found in the Debian bug
544145[1].

It happens with Linux 2.6.30 and 2.6.31-rc8 on Xen 3.2 and 3.4.

For the tests I set the vdso to compat mode to have it loaded on a fixed
location.

The following program is a minimal test case for the vdso in compat
mode, it can be compiled against dietlibc to minimize other effects.

| int main() {
| unsigned int resultvar;
| asm volatile (
| "movl %1, %%eax\n\t"
| "call 0xffffe420\n\t"
| : "=a" (resultvar) : "i" (0) : "memory", "cc");
| }
| (gdb) run
| Starting program: /test
|
| Program received signal SIGSEGV, Segmentation fault.
| 0xffffe42f in ?? ()
| (gdb) bt
| #0 0xffffe42f in ?? ()
| #1 0xf7eb17a5 in __libc_start_main (main=0x8048394 <main>, argc=1, ubp_av=0xffffd884, init=0x80483d0 <__libc_csu_init>,
| fini=0x80483c0 <__libc_csu_fini>, rtld_fini=0xf7fee6e0 <_dl_fini>, stack_end=0xffffd87c) at libc-start.c:222
| #2 0x08048301 in _start () at ../sysdeps/i386/elf/start.S:119
| (gdb) disassemble 0xffffe420 0xffffe430
| Dump of assembler code from 0xffffe420 to 0xffffe430:
| 0xffffe420: push %ebp
| 0xffffe421: mov %ecx,%ebp
| 0xffffe423: syscall
| 0xffffe425: mov $0x2b,%ecx
| 0xffffe42a: mov %ecx,%ss
| 0xffffe42c: mov %ebp,%ecx
| 0xffffe42e: pop %ebp
| 0xffffe42f: ret
| End of assembler dump.

It segfaults on the ret opcode, in some variants also directly after the
ret. If I single-step over the syscall opcode it works. The register
contents slightly differ in this case.

Break on last opcode, state at the last opcode:
| (gdb) b *0xffffe42f
| Breakpoint 7 at 0xffffe42f
| (gdb) run
| Starting program: /test
|
| Breakpoint 7, 0xffffe42f in ?? ()
| (gdb) info registers
| eax 0xfffffffc -4
| ecx 0xffffd800 -10240
| edx 0xffffd820 -10208
| ebx 0xf7fd7ff4 -134381580
| esp 0xffffd7d0 0xffffd7d0
| ebp 0xffffd7e8 0xffffd7e8
| esi 0x80483d0 134513616
| edi 0x80482e0 134513376
| eip 0xffffe42f 0xffffe42f
| eflags 0x282 [ SF IF ]
| cs 0xe033 57395
| ss 0x2b 43
| ds 0x2b 43
| es 0x2b 43
| fs 0x0 0
| gs 0x63 99

Break on first opcode, state at the last opcode:
| (gdb) b *0xffffe420
| Breakpoint 8 at 0xffffe420
| (gdb) run
| Starting program: /test
|
| Breakpoint 8, 0xffffe420 in ?? ()
| (gdb) stepi
| 0xffffe421 in ?? ()
[...]
| 0xffffe42f in ?? ()
| (gdb) info registers
| eax 0xfffffffc -4
| ecx 0xffffd800 -10240
| edx 0xffffd820 -10208
| ebx 0xf7fd7ff4 -134381580
| esp 0xffffd7cc 0xffffd7cc
| ebp 0xffffd7e8 0xffffd7e8
| esi 0x80483d0 134513616
| edi 0x80482e0 134513376
| eip 0xffffe42f 0xffffe42f
| eflags 0x282 [ SF IF ]
| cs 0x23 35
| ss 0x2b 43
| ds 0x2b 43
| es 0x2b 43
| fs 0x0 0
| gs 0x63 99

The stack pointer and code segment are different in this two cases.

I think I found the problem. In the normal codeflow, sysret is used to
return as expected. In the compat codeflow, iret is used.

Bastian

[1]: http://bugs.debian.org/544145
--
Wait! You have not been prepared!
-- Mr. Atoz, "Tomorrow is Yesterday", stardate 3113.2
[unhandled content-type:application/pgp-signature]
\
 
 \ /
  Last update: 2009-08-30 20:27    [W:0.077 / U:0.044 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site