Messages in this thread | | | From | Blaisorblade <> | Subject | Fwd: [BUG] 2.6.16 extra ptrace trap on syscall exit | Date | Mon, 22 May 2006 16:40:36 +0200 |
| |
---------- Forwarded Message ----------
Subject: [BUG] 2.6.16 extra ptrace trap on syscall exit Date: Monday 22 May 2006 15:22 From: Steven James <pyro@linuxlabs.com> To: Roland McGrath <roland@redhat.com> Cc: User-mode-linux-devel@lists.sourceforge.net, Blaisorblade <blaisorblade@yahoo.it>, Jeff Dike <jdike@addtoit.com>
Greetings,
While working on a syscall emulator similar in structure to user-mode-linux, I found that for many but not all system calls, the ptracing parent is notified of the system call exit twice on x86_64 hosts.
This can be trivially demonstrated by running strace on a test program that makes a non-existant system call such as the attached ptrace_test.c (see output below)
Further testing shows that the bug only occurs when ptracing a 64 bit process. 32 bit target processes ptrace fine.
This problem also appears to crash user-mode-linux guest kernels running on x86_64.
From Blaisorblade: >I have uml/64-bit (AMD64) not working on 2.6.16/64bit, while uml-32bit >works fine on it, and the same uml/64-bit binaries work fine on 2.6.15. I
haven't
>tracked it down fully, but could it be related? Possibly yes because I
now
>seem to recall you run 64-bit host. So you likely found our bug!
I confirm the problem does not occur on the 2.6.15.7 kernel.
strace ./ptrace_test on 2.6.16.16: strace ./ptrace_test execve("./ptrace_test", ["./ptrace_test"], [/* 24 vars */]) = 0 uname({sys="Linux", node="prime", ...}) = 0 brk(0) = 0x501000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b2cf0826000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=142523, ...}) = 0 mmap(NULL, 142523, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2b2cf0827000 close(3) = 0 open("/lib64/tls/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\305\1\356"..., 640) = 640 lseek(3, 624, SEEK_SET) = 624 read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\4\0\0\0"..., 32) = 32 fstat(3, {st_mode=S_IFREG|0755, st_size=1613968, ...}) = 0 mmap(0x33ee000000, 2305992, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x33ee000000 mprotect(0x33ee12a000, 1085384, PROT_NONE) = 0 mmap(0x33ee229000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x129000) = 0x33ee229000 mmap(0x33ee22f000, 16328, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x33ee22f000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b2cf084a000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b2cf084b000 mprotect(0x33ee229000, 16384, PROT_READ) = 0 mprotect(0x33edd14000, 4096, PROT_READ) = 0 arch_prctl(0x1002, 0x2b2cf084ab00) = 0 munmap(0x2b2cf0827000, 142523) = 0 write(1, "Pyro was here!\n", 15Pyro was here! ) = 15 write(1, "last write returned 15, (errno=0"..., 34last write returned 15, (errno=0) ) = 34 syscall_500(0x1, 0x22, 0xffffffffffffffff, 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = -1 (errno 38) syscall_500(0x1, 0x22, 0xffffffffffffffff, 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = -1 (errno 38) inval(1) returned -1, (errno=38) exit_group(0, 0, 0x33ee065280, 0x2, 0x3c <unfinished ... exit status 0> ============================================================================= =
strace ./ptrac_test32 on 2.6.16.16: strace ./ptrace_test32 execve("./ptrace_test32", ["./ptrace_test32"], [/* 24 vars */]) = 0 [ Process PID=3538 runs in 32 bit mode. ] uname({sys="Linux", node="prime", ...}) = 0 brk(0) = 0x804a000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat64(0x3, 0xffffbf18) = 0 old_mmap(0x22cbb00000000, 8589934593, PROT_READ|PROT_WRITE, 0xf /* MAP_??? */|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE|MAP_POPULATE|MAP_NONBLOCK|MAP_GROWSD OWN|MAP_DENYWRITE|MAP_EXECUTABLE|MAP_LOCKED|0xfffe06c0, 64768, 0x1af3ef00000000) = 0xfffffffff7fcd000 close(3) = 0 open("/lib/tls/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\20\357"..., 512) = 512 fstat64(0x3, 0xffffbfac) = 0 old_mmap(0x100000000000, 146028888067, PROT_READ|PROT_WRITE|PROT_EXEC|PROT_GROWSDOWN|PROT_GROWSUP|0xfcfffff8, 0x4 /* MAP_??? */|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE|MAP_NONBLOCK|MAP_GROWSDOWN|MAP_DENYW RITE|MAP_LOCKED|0x47dc0680, 1205695736, 0x847dd0435) = 0xfffffffff7fcc000 old_mmap(0x12acbc47dda000, 8804682956805, PROT_READ|PROT_WRITE, MAP_FILE, 0, 0) = 0x47dda000 mprotect(0x47efe000, 27836, PROT_NONE) = 0 old_mmap(0x400047eff000, 8873402433539, PROT_READ|PROT_WRITE, MAP_FILE, 0, 0) = 0x47eff000 old_mmap(0x1cbc47f03000, 214748364803, PROT_READ|PROT_WRITE|PROT_EXEC|PROT_GROWSDOWN|PROT_GROWSUP|0xfcfffff8, MAP_FILE, 0, 0) = 0x47f03000 close(3) = 0 old_mmap(0x100000000000, 146028888067, PROT_READ|PROT_WRITE|PROT_EXEC|PROT_GROWSDOWN|PROT_GROWSUP|0xfcfffff8, 0x4 /* MAP_??? */|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE|MAP_NONBLOCK|MAP_GROWSDOWN|MAP_DENYW RITE|MAP_LOCKED|0x47dc0680, 2832, 0x2047dce4a2) = 0xfffffffff7fcb000 mprotect(0x47eff000, 8192, PROT_READ) = 0 mprotect(0x47dd6000, 4096, PROT_READ) = 0 set_thread_area(0xffffc724) = 0 munmap(0xf7fcd000, 142523) = 0 write(1, "Pyro was here!\n", 15Pyro was here! ) = 15 write(1, "last write returned 15, (errno=0"..., 34last write returned 15, (errno=0) ) = 34 syscall_500(0x1, 0xffffc9c8, 0x80484fe, 0x80484fe, 0x1, 0xffffc5b0, 0xffffc9c8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = -1 (errno 38) write(1, "inval(1) returned -1, (errno=38)"..., 33inval(1) returned -1, (errno=38) ) = 33 exit_group(0) = ? =============================================================================
and strace ./ptrace_test on 2.6.15.7: strace ./ptrace_test execve("./ptrace_test", ["./ptrace_test"], [/* 24 vars */]) = 0 uname({sys="Linux", node="prime", ...}) = 0 brk(0) = 0x501000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aaaaaaab000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=142523, ...}) = 0 mmap(NULL, 142523, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2aaaaaaac000 close(3) = 0 open("/lib64/tls/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\305\1\356"..., 640) = 640 lseek(3, 624, SEEK_SET) = 624 read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\4\0\0\0"..., 32) = 32 fstat(3, {st_mode=S_IFREG|0755, st_size=1613968, ...}) = 0 mmap(0x33ee000000, 2305992, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x33ee000000 mprotect(0x33ee12a000, 1085384, PROT_NONE) = 0 mmap(0x33ee229000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x129000) = 0x33ee229000 mmap(0x33ee22f000, 16328, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x33ee22f000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aaaaaacf000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aaaaaad0000 mprotect(0x33ee229000, 16384, PROT_READ) = 0 mprotect(0x33edd14000, 4096, PROT_READ) = 0 arch_prctl(0x1002, 0x2aaaaaacfb00) = 0 munmap(0x2aaaaaaac000, 142523) = 0 write(1, "Pyro was here!\n", 15Pyro was here! ) = 15 write(1, "last write returned 15, (errno=0"..., 34last write returned 15, (errno=0) ) = 34 syscall_500(0x1, 0x22, 0x33ee0b8642, 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) = -1 (errno 38) write(1, "inval(1) returned -1, (errno=38)"..., 33inval(1) returned -1, (errno=38) ) = 33 exit_group(0, 0, 0x33ee065280, 0x2, 0x3c <unfinished ... exit status 0> ============================================================================
G'day, sjames
by Linux Labs International, Inc. Steven James, CTO
55 Marietta Street Suite 1830 Atlanta, Ga 30303 866 824 9737 support
-------------------------------------------------------
-- Inform me of my mistakes, so I can keep imitating Homer Simpson's "Doh!". Paolo Giarrusso, aka Blaisorblade (Skype ID "PaoloGiarrusso", ICQ 215621894) http://www.user-mode-linux.org/~blaisorblade #include <stdio.h> #include <errno.h> #include <unistd.h>
#include <linux/unistd.h> #define __NR_inval 500
_syscall1(long, inval, long, val);
int main(int argc, char *argv[]) { int ret; char *msg = "Pyro was here!\n"; char buffer[1024];
ret = write(1, msg, strlen(msg)); ret = sprintf( buffer, "last write returned %d, (errno=%d)\n", ret, errno); write(1, buffer, ret);
ret = inval(1); ret = sprintf( buffer, "inval(1) returned %d, (errno=%d)\n", ret, errno); write(1, buffer, ret);
return 0; }
| |