[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20090830181637.GA7155@wavehammer.waldi.eu.org>
Date: Sun, 30 Aug 2009 20:16:37 +0200
From: Bastian Blank <waldi@...ian.org>
To: linux-kernel@...r.kernel.org, xen-devel@...ts.xensource.com,
544145@...s.debian.org
Cc: Jeremy Fitzhardinge <jeremy.fitzhardinge@...rix.com>,
Keir Fraser <keir.fraser@...citrix.com>
Subject: 32bit 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@....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
Download attachment "signature.asc" of type "application/pgp-signature" (198 bytes)
Powered by blists - more mailing lists