---------- Forwarded Message ----------
Subject: [BUG] 2.6.16 extra ptrace trap on syscall exit
Date: Monday 22 May 2006 15:22
From: Steven James <[email protected]>
To: Roland McGrath <[email protected]>
Cc: [email protected], Blaisorblade
<[email protected]>, Jeff Dike <[email protected]>
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;
}
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]