Messages in this thread | | | From | Andrew Lutomirski <> | Date | Sun, 29 May 2011 11:28:12 -0400 | Subject | Re: [GIT pull] x86 vdso updates |
| |
On Sun, May 29, 2011 at 11:10 AM, richard -rw- weinberger <richard.weinberger@gmail.com> wrote: > On Sun, May 29, 2011 at 4:57 PM, Andrew Lutomirski <luto@mit.edu> wrote: >> On Sun, May 29, 2011 at 5:51 AM, richard -rw- weinberger >> <richard.weinberger@gmail.com> wrote: >>> Yesterday I had a closer look at 64bit UML. >>> Glibc is always using vsyscalls because 64bit UML does not support the vDSO. >>> >>> On 32bit UML simply scans the ELF auxiliary vector provided by the host to >>> get the address of the vDSO. >>> How can I get this address on a 64bit host? >> >> I believe it's exactly the same. There's an auxv entry that points to the vDSO. > > I don't think so. > See: > http://www.win.tue.nl/~aeb/linux/lk/lk-4.html > Section "Address space randomization". > The demo program finds the vDSO only on x86. > > UML uses quite the same method to find it. > arch/um/os-Linux/elf_aux.c
The attached program works for me.
I don't know what this is supposed to mean, though:
/* See if the page is under TASK_SIZE */ if (vsyscall_ehdr < (unsigned long) envp) vsyscall_ehdr = 0;
First, envp != TASK_SIZE.
Second, the vDSO can be wherever it wants. On current kernels at least it is *always* mapped below TASK_SIZE (in the unsigned sense) because it's mapped into user address space.
--Andy #include <unistd.h> #include <string.h> #include <stdio.h> #include <elf.h> #include <stdlib.h>
extern char **environ;
int __captured_argc; char **__captured_argv; char **__captured_envp; Elf64_auxv_t *__captured_auxv;
void _capture_args(int argc, char **argv, char **envp) { __captured_argc = argc; __captured_argv = argv; __captured_envp = envp;
while(*envp) envp++;
__captured_auxv = (Elf64_auxv_t*)(envp + 1); }
static void * initarray_entry __attribute__((section(".preinit_array"), used)) = (void*)_capture_args;
int main() { printf("envp = %p\n", __captured_envp);
for (int i = 0; __captured_auxv[i].a_type != AT_NULL; i++) { char *desc = ""; if (__captured_auxv[i].a_type == AT_SYSINFO) desc = "AT_SYSINFO"; else if (__captured_auxv[i].a_type == AT_SYSINFO_EHDR) desc = "AT_SYSINFO_EHDR"; printf("aux type %02u = 0x%016lX %s\n", __captured_auxv[i].a_type, (long)__captured_auxv[i].a_un.a_val, desc); } return 0; }
| |