I was wondering if there is a way to capture (in other words observe) vDSO calls like gettimeofday
in strace
.
Also, is there a way to execute a binary without loading linux-vdso.so.1
(a flag or env variable)?
And lastly, what if I write a program that delete the linux-vdso.so.1
address from the auxiliary vector and then execve
my program? Has anyone ever tried that?
You can capture calls to system calls which have been implemented via the vDSO by using
ltrace
instead ofstrace
. This is because calls to system calls implemented via the vDSO work differently than "normal" system calls and the methodstrace
uses to trace system calls does not work with vDSO-implemented system calls. To learn more about howstrace
works, check out this blog post I wrote about strace. And, to learn more about howltrace
works, check out this other blog post I wrote about ltrace.No, it is not possible to execute a binary without loading
linux-vdso.so.1
. At least, not on my version of libc on Ubuntu precise. It is certainly possible that newer versions of libc/eglibc/etc have added this as a feature but it seems very unlikely. See the next answer for why.If you delete the address from the auxillary vector, your binary will probably crash. libc has a piece of code which will first attempt to walk the vDSO ELF object, and if this fails, will fall back to a hardcoded vsyscall address. The only way it will avoid this is if you've compiled glibc with the vDSO disabled.
There is another workaround, though, if you really, really don't want to use the vDSO. You can try using glibc's
syscall
function and pass in the syscall number forgettimeofday
. This will force glibc to callgettimeofday
via the kernel instead of the vDSO.I've included a sample program below illustrating this. You can read more about how system calls work by reading my syscall blog post.
Compile with
gcc -o test test.c
and strace withstrace -ttTf ./test 2>&1 | grep gettimeofday
:09:57:32.651876 gettimeofday({1467305852, 651888}, {420, 140735905220705}) = 0 <0.000006>