Bug#466491: Reproducer and more information
unarchive 466491
reopen 466491
retitle 466491 libc6: gettimeofday() on amd64 causes segmentation fault if first argument is NULL
thanks
With the following program on a lenny amd64 machine, I can trigger this
bug:
$ cat test.c
#include <stdio.h>
#include <sys/time.h>
int main(void)
{
struct timezone tz;
gettimeofday(NULL, &tz);
return 0;
}
The gettimeofday(2) manual says that if either parameter is NULL, that
structure is not set. It doesn't say that the first parameter
(struct timeval *tv) is required.
Package information:
$ uname -a
Linux ned3g6 2.6.26-2-amd64 #1 SMP Fri Mar 27 04:02:59 UTC 2009 x86_64 GNU/Linux
$ dpkg -l libc6 linux-image-$(uname -r)
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Cfg-files/Unpacked/Failed-cfg/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Name Version Description
+++-==============-==============-============================================
ii libc6 2.7-18 GNU C Library: Shared libraries
ii linux-image-2. 2.6.26-15 Linux 2.6.26 image on AMD64
Here's what I can glean from gdb:
$ gcc -g -o test test.c
$ gdb ./test
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu"...
(gdb) run
Starting program: /home/jswright/test
Program received signal SIGSEGV, Segmentation fault.
0x00007fff031ff5d8 in ?? ()
(gdb) bt
#0 0x00007fff031ff5d8 in ?? ()
#1 0x00007fff031ff69e in gettimeofday ()
#2 0x00007f3ffab3588a in gettimeofday () from /lib/libc.so.6
#3 0x00000000004004f2 in main () at test.c:8
(gdb) disassemble 0x00007fff031ff5d8
No function contains specified address.
(gdb) disassemble 0x00007fff031ff69e
Dump of assembler code for function gettimeofday:
0x00007fff031ff670 <gettimeofday+0>: sub $0x18,%rsp
0x00007fff031ff674 <gettimeofday+4>: mov -0x1ab(%rip),%rax # 0x7fff031ff4d0
0x00007fff031ff67b <gettimeofday+11>: mov %rbx,0x8(%rsp)
0x00007fff031ff680 <gettimeofday+16>: mov %rbp,0x10(%rsp)
0x00007fff031ff685 <gettimeofday+21>: mov %rdi,%rbx
0x00007fff031ff688 <gettimeofday+24>: mov %rsi,%rbp
0x00007fff031ff68b <gettimeofday+27>: mov 0x14(%rax),%edx
0x00007fff031ff68e <gettimeofday+30>: test %edx,%edx
0x00007fff031ff690 <gettimeofday+32>: je 0x7fff031ff6e6 <gettimeofday+118>
0x00007fff031ff692 <gettimeofday+34>: cmpq $0x0,0x20(%rax)
0x00007fff031ff697 <gettimeofday+39>: je 0x7fff031ff6e6 <gettimeofday+118>
0x00007fff031ff699 <gettimeofday+41>: callq 0x7fff031ff5b0
0x00007fff031ff69e <gettimeofday+46>: mov 0x8(%rbx),%rcx
0x00007fff031ff6a2 <gettimeofday+50>: mov $0x20c49ba5e353f7cf,%rdx
0x00007fff031ff6ac <gettimeofday+60>: mov %rcx,%rax
0x00007fff031ff6af <gettimeofday+63>: sar $0x3f,%rcx
0x00007fff031ff6b3 <gettimeofday+67>: imul %rdx
0x00007fff031ff6b6 <gettimeofday+70>: xor %eax,%eax
0x00007fff031ff6b8 <gettimeofday+72>: sar $0x7,%rdx
0x00007fff031ff6bc <gettimeofday+76>: sub %rcx,%rdx
0x00007fff031ff6bf <gettimeofday+79>: test %rbp,%rbp
0x00007fff031ff6c2 <gettimeofday+82>: mov %rdx,0x8(%rbx)
0x00007fff031ff6c6 <gettimeofday+86>: je 0x7fff031ff6f3 <gettimeofday+131>
0x00007fff031ff6c8 <gettimeofday+88>: mov -0x1ff(%rip),%rax # 0x7fff031ff4d0
0x00007fff031ff6cf <gettimeofday+95>: mov 0x18(%rax),%eax
0x00007fff031ff6d2 <gettimeofday+98>: mov %eax,0x0(%rbp)
0x00007fff031ff6d5 <gettimeofday+101>: mov -0x20c(%rip),%rax # 0x7fff031ff4d0
0x00007fff031ff6dc <gettimeofday+108>: mov 0x1c(%rax),%eax
0x00007fff031ff6df <gettimeofday+111>: mov %eax,0x4(%rbp)
0x00007fff031ff6e2 <gettimeofday+114>: xor %eax,%eax
0x00007fff031ff6e4 <gettimeofday+116>: jmp 0x7fff031ff6f3 <gettimeofday+131>
0x00007fff031ff6e6 <gettimeofday+118>: mov $0x60,%eax
0x00007fff031ff6eb <gettimeofday+123>: mov %rbx,%rdi
0x00007fff031ff6ee <gettimeofday+126>: mov %rbp,%rsi
0x00007fff031ff6f1 <gettimeofday+129>: syscall
0x00007fff031ff6f3 <gettimeofday+131>: mov 0x8(%rsp),%rbx
0x00007fff031ff6f8 <gettimeofday+136>: mov 0x10(%rsp),%rbp
0x00007fff031ff6fd <gettimeofday+141>: add $0x18,%rsp
0x00007fff031ff701 <gettimeofday+145>: retq
End of assembler dump.
Note this line:
0x00007fff031ff69e <gettimeofday+46>: mov 0x8(%rbx),%rcx
Earlier, %rbx gets the value from %rdi, the first argument (NULL in our
program above):
0x00007fff031ff685 <gettimeofday+21>: mov %rdi,%rbx
But 0x8(%rbx) means to deference 8 bytes into the memory address pointed
to by %rbx, which in this case is NULL, hence the segmentation fault.
I'm not familiar enough with the glibc code base yet, so I haven't found
the offending code in glibc itself, but this should be a good start.
Also, this program doesn't segfault on i386.
--
+----------------------------------------------------------+
| John Wright <john.wright@hp.com> |
| HP Mission Critical OS Enablement & Solution Test (MOST) |
+----------------------------------------------------------+
Reply to: