linux/tools/testing/selftests/vm/map_fixed_noreplace.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3/*
   4 * Test that MAP_FIXED_NOREPLACE works.
   5 *
   6 * Copyright 2018, Jann Horn <jannh@google.com>
   7 * Copyright 2018, Michael Ellerman, IBM Corporation.
   8 */
   9
  10#include <sys/mman.h>
  11#include <errno.h>
  12#include <stdio.h>
  13#include <stdlib.h>
  14#include <unistd.h>
  15
  16#ifndef MAP_FIXED_NOREPLACE
  17#define MAP_FIXED_NOREPLACE 0x100000
  18#endif
  19
  20#define BASE_ADDRESS    (256ul * 1024 * 1024)
  21
  22
  23static void dump_maps(void)
  24{
  25        char cmd[32];
  26
  27        snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid());
  28        system(cmd);
  29}
  30
  31int main(void)
  32{
  33        unsigned long flags, addr, size, page_size;
  34        char *p;
  35
  36        page_size = sysconf(_SC_PAGE_SIZE);
  37
  38        flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE;
  39
  40        // Check we can map all the areas we need below
  41        errno = 0;
  42        addr = BASE_ADDRESS;
  43        size = 5 * page_size;
  44        p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  45
  46        printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  47
  48        if (p == MAP_FAILED) {
  49                dump_maps();
  50                printf("Error: couldn't map the space we need for the test\n");
  51                return 1;
  52        }
  53
  54        errno = 0;
  55        if (munmap((void *)addr, 5 * page_size) != 0) {
  56                dump_maps();
  57                printf("Error: munmap failed!?\n");
  58                return 1;
  59        }
  60        printf("unmap() successful\n");
  61
  62        errno = 0;
  63        addr = BASE_ADDRESS + page_size;
  64        size = 3 * page_size;
  65        p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  66        printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  67
  68        if (p == MAP_FAILED) {
  69                dump_maps();
  70                printf("Error: first mmap() failed unexpectedly\n");
  71                return 1;
  72        }
  73
  74        /*
  75         * Exact same mapping again:
  76         *   base |  free  | new
  77         *     +1 | mapped | new
  78         *     +2 | mapped | new
  79         *     +3 | mapped | new
  80         *     +4 |  free  | new
  81         */
  82        errno = 0;
  83        addr = BASE_ADDRESS;
  84        size = 5 * page_size;
  85        p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  86        printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  87
  88        if (p != MAP_FAILED) {
  89                dump_maps();
  90                printf("Error:1: mmap() succeeded when it shouldn't have\n");
  91                return 1;
  92        }
  93
  94        /*
  95         * Second mapping contained within first:
  96         *
  97         *   base |  free  |
  98         *     +1 | mapped |
  99         *     +2 | mapped | new
 100         *     +3 | mapped |
 101         *     +4 |  free  |
 102         */
 103        errno = 0;
 104        addr = BASE_ADDRESS + (2 * page_size);
 105        size = page_size;
 106        p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
 107        printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
 108
 109        if (p != MAP_FAILED) {
 110                dump_maps();
 111                printf("Error:2: mmap() succeeded when it shouldn't have\n");
 112                return 1;
 113        }
 114
 115        /*
 116         * Overlap end of existing mapping:
 117         *   base |  free  |
 118         *     +1 | mapped |
 119         *     +2 | mapped |
 120         *     +3 | mapped | new
 121         *     +4 |  free  | new
 122         */
 123        errno = 0;
 124        addr = BASE_ADDRESS + (3 * page_size);
 125        size = 2 * page_size;
 126        p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
 127        printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
 128
 129        if (p != MAP_FAILED) {
 130                dump_maps();
 131                printf("Error:3: mmap() succeeded when it shouldn't have\n");
 132                return 1;
 133        }
 134
 135        /*
 136         * Overlap start of existing mapping:
 137         *   base |  free  | new
 138         *     +1 | mapped | new
 139         *     +2 | mapped |
 140         *     +3 | mapped |
 141         *     +4 |  free  |
 142         */
 143        errno = 0;
 144        addr = BASE_ADDRESS;
 145        size = 2 * page_size;
 146        p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
 147        printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
 148
 149        if (p != MAP_FAILED) {
 150                dump_maps();
 151                printf("Error:4: mmap() succeeded when it shouldn't have\n");
 152                return 1;
 153        }
 154
 155        /*
 156         * Adjacent to start of existing mapping:
 157         *   base |  free  | new
 158         *     +1 | mapped |
 159         *     +2 | mapped |
 160         *     +3 | mapped |
 161         *     +4 |  free  |
 162         */
 163        errno = 0;
 164        addr = BASE_ADDRESS;
 165        size = page_size;
 166        p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
 167        printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
 168
 169        if (p == MAP_FAILED) {
 170                dump_maps();
 171                printf("Error:5: mmap() failed when it shouldn't have\n");
 172                return 1;
 173        }
 174
 175        /*
 176         * Adjacent to end of existing mapping:
 177         *   base |  free  |
 178         *     +1 | mapped |
 179         *     +2 | mapped |
 180         *     +3 | mapped |
 181         *     +4 |  free  |  new
 182         */
 183        errno = 0;
 184        addr = BASE_ADDRESS + (4 * page_size);
 185        size = page_size;
 186        p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
 187        printf("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
 188
 189        if (p == MAP_FAILED) {
 190                dump_maps();
 191                printf("Error:6: mmap() failed when it shouldn't have\n");
 192                return 1;
 193        }
 194
 195        addr = BASE_ADDRESS;
 196        size = 5 * page_size;
 197        if (munmap((void *)addr, size) != 0) {
 198                dump_maps();
 199                printf("Error: munmap failed!?\n");
 200                return 1;
 201        }
 202        printf("unmap() successful\n");
 203
 204        printf("OK\n");
 205        return 0;
 206}
 207