~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/x86/test_mremap_vdso.c

Version: ~ [ linux-5.6-rc1 ] ~ [ linux-5.5.2 ] ~ [ linux-5.4.17 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.102 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.170 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.213 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.213 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * 32-bit test to check vDSO mremap.
  3  *
  4  * Copyright (c) 2016 Dmitry Safonov
  5  * Suggested-by: Andrew Lutomirski
  6  *
  7  * This program is free software; you can redistribute it and/or modify
  8  * it under the terms and conditions of the GNU General Public License,
  9  * version 2, as published by the Free Software Foundation.
 10  *
 11  * This program is distributed in the hope it will be useful, but
 12  * WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * General Public License for more details.
 15  */
 16 /*
 17  * Can be built statically:
 18  * gcc -Os -Wall -static -m32 test_mremap_vdso.c
 19  */
 20 #define _GNU_SOURCE
 21 #include <stdio.h>
 22 #include <errno.h>
 23 #include <unistd.h>
 24 #include <string.h>
 25 
 26 #include <sys/mman.h>
 27 #include <sys/auxv.h>
 28 #include <sys/syscall.h>
 29 #include <sys/wait.h>
 30 
 31 #define PAGE_SIZE       4096
 32 
 33 static int try_to_remap(void *vdso_addr, unsigned long size)
 34 {
 35         void *dest_addr, *new_addr;
 36 
 37         /* Searching for memory location where to remap */
 38         dest_addr = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
 39         if (dest_addr == MAP_FAILED) {
 40                 printf("[WARN]\tmmap failed (%d): %m\n", errno);
 41                 return 0;
 42         }
 43 
 44         printf("[NOTE]\tMoving vDSO: [%p, %#lx] -> [%p, %#lx]\n",
 45                 vdso_addr, (unsigned long)vdso_addr + size,
 46                 dest_addr, (unsigned long)dest_addr + size);
 47         fflush(stdout);
 48 
 49         new_addr = mremap(vdso_addr, size, size,
 50                         MREMAP_FIXED|MREMAP_MAYMOVE, dest_addr);
 51         if ((unsigned long)new_addr == (unsigned long)-1) {
 52                 munmap(dest_addr, size);
 53                 if (errno == EINVAL) {
 54                         printf("[NOTE]\tvDSO partial move failed, will try with bigger size\n");
 55                         return -1; /* Retry with larger */
 56                 }
 57                 printf("[FAIL]\tmremap failed (%d): %m\n", errno);
 58                 return 1;
 59         }
 60 
 61         return 0;
 62 
 63 }
 64 
 65 int main(int argc, char **argv, char **envp)
 66 {
 67         pid_t child;
 68 
 69         child = fork();
 70         if (child == -1) {
 71                 printf("[WARN]\tfailed to fork (%d): %m\n", errno);
 72                 return 1;
 73         }
 74 
 75         if (child == 0) {
 76                 unsigned long vdso_size = PAGE_SIZE;
 77                 unsigned long auxval;
 78                 int ret = -1;
 79 
 80                 auxval = getauxval(AT_SYSINFO_EHDR);
 81                 printf("\tAT_SYSINFO_EHDR is %#lx\n", auxval);
 82                 if (!auxval || auxval == -ENOENT) {
 83                         printf("[WARN]\tgetauxval failed\n");
 84                         return 0;
 85                 }
 86 
 87                 /* Simpler than parsing ELF header */
 88                 while (ret < 0) {
 89                         ret = try_to_remap((void *)auxval, vdso_size);
 90                         vdso_size += PAGE_SIZE;
 91                 }
 92 
 93 #ifdef __i386__
 94                 /* Glibc is likely to explode now - exit with raw syscall */
 95                 asm volatile ("int $0x80" : : "a" (__NR_exit), "b" (!!ret));
 96 #else /* __x86_64__ */
 97                 syscall(SYS_exit, ret);
 98 #endif
 99         } else {
100                 int status;
101 
102                 if (waitpid(child, &status, 0) != child ||
103                         !WIFEXITED(status)) {
104                         printf("[FAIL]\tmremap() of the vDSO does not work on this kernel!\n");
105                         return 1;
106                 } else if (WEXITSTATUS(status) != 0) {
107                         printf("[FAIL]\tChild failed with %d\n",
108                                         WEXITSTATUS(status));
109                         return 1;
110                 }
111                 printf("[OK]\n");
112         }
113 
114         return 0;
115 }
116 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp