0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #define _GNU_SOURCE
0013 #include <stdio.h>
0014 #include <errno.h>
0015 #include <unistd.h>
0016 #include <string.h>
0017
0018 #include <sys/mman.h>
0019 #include <sys/auxv.h>
0020 #include <sys/syscall.h>
0021 #include <sys/wait.h>
0022
0023 #define PAGE_SIZE 4096
0024
0025 static int try_to_remap(void *vdso_addr, unsigned long size)
0026 {
0027 void *dest_addr, *new_addr;
0028
0029
0030 dest_addr = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
0031 if (dest_addr == MAP_FAILED) {
0032 printf("[WARN]\tmmap failed (%d): %m\n", errno);
0033 return 0;
0034 }
0035
0036 printf("[NOTE]\tMoving vDSO: [%p, %#lx] -> [%p, %#lx]\n",
0037 vdso_addr, (unsigned long)vdso_addr + size,
0038 dest_addr, (unsigned long)dest_addr + size);
0039 fflush(stdout);
0040
0041 new_addr = mremap(vdso_addr, size, size,
0042 MREMAP_FIXED|MREMAP_MAYMOVE, dest_addr);
0043 if ((unsigned long)new_addr == (unsigned long)-1) {
0044 munmap(dest_addr, size);
0045 if (errno == EINVAL) {
0046 printf("[NOTE]\tvDSO partial move failed, will try with bigger size\n");
0047 return -1;
0048 }
0049 printf("[FAIL]\tmremap failed (%d): %m\n", errno);
0050 return 1;
0051 }
0052
0053 return 0;
0054
0055 }
0056
0057 int main(int argc, char **argv, char **envp)
0058 {
0059 pid_t child;
0060
0061 child = fork();
0062 if (child == -1) {
0063 printf("[WARN]\tfailed to fork (%d): %m\n", errno);
0064 return 1;
0065 }
0066
0067 if (child == 0) {
0068 unsigned long vdso_size = PAGE_SIZE;
0069 unsigned long auxval;
0070 int ret = -1;
0071
0072 auxval = getauxval(AT_SYSINFO_EHDR);
0073 printf("\tAT_SYSINFO_EHDR is %#lx\n", auxval);
0074 if (!auxval || auxval == -ENOENT) {
0075 printf("[WARN]\tgetauxval failed\n");
0076 return 0;
0077 }
0078
0079
0080 while (ret < 0) {
0081 ret = try_to_remap((void *)auxval, vdso_size);
0082 vdso_size += PAGE_SIZE;
0083 }
0084
0085 #ifdef __i386__
0086
0087 asm volatile ("int $0x80" : : "a" (__NR_exit), "b" (!!ret));
0088 #else
0089 syscall(SYS_exit, ret);
0090 #endif
0091 } else {
0092 int status;
0093
0094 if (waitpid(child, &status, 0) != child ||
0095 !WIFEXITED(status)) {
0096 printf("[FAIL]\tmremap() of the vDSO does not work on this kernel!\n");
0097 return 1;
0098 } else if (WEXITSTATUS(status) != 0) {
0099 printf("[FAIL]\tChild failed with %d\n",
0100 WEXITSTATUS(status));
0101 return 1;
0102 }
0103 printf("[OK]\n");
0104 }
0105
0106 return 0;
0107 }