202 lines · c
1// SPDX-License-Identifier: GPL-2.02 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#include "../kselftest.h"16 17static void dump_maps(void)18{19 char cmd[32];20 21 snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid());22 system(cmd);23}24 25static unsigned long find_base_addr(unsigned long size)26{27 void *addr;28 unsigned long flags;29 30 flags = MAP_PRIVATE | MAP_ANONYMOUS;31 addr = mmap(NULL, size, PROT_NONE, flags, -1, 0);32 if (addr == MAP_FAILED)33 ksft_exit_fail_msg("Error: couldn't map the space we need for the test\n");34 35 if (munmap(addr, size) != 0)36 ksft_exit_fail_msg("Error: munmap failed\n");37 38 return (unsigned long)addr;39}40 41int main(void)42{43 unsigned long base_addr;44 unsigned long flags, addr, size, page_size;45 char *p;46 47 ksft_print_header();48 ksft_set_plan(9);49 50 page_size = sysconf(_SC_PAGE_SIZE);51 52 /* let's find a base addr that is free before we start the tests */53 size = 5 * page_size;54 base_addr = find_base_addr(size);55 56 flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE;57 58 /* Check we can map all the areas we need below */59 addr = base_addr;60 size = 5 * page_size;61 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);62 if (p == MAP_FAILED) {63 dump_maps();64 ksft_exit_fail_msg("Error: couldn't map the space we need for the test\n");65 }66 if (munmap((void *)addr, 5 * page_size) != 0) {67 dump_maps();68 ksft_exit_fail_msg("Error: munmap failed!?\n");69 }70 ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);71 ksft_test_result_pass("mmap() 5*PAGE_SIZE at base\n");72 73 addr = base_addr + page_size;74 size = 3 * page_size;75 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);76 if (p == MAP_FAILED) {77 dump_maps();78 ksft_exit_fail_msg("Error: first mmap() failed unexpectedly\n");79 }80 ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);81 ksft_test_result_pass("mmap() 3*PAGE_SIZE at base+PAGE_SIZE\n");82 83 /*84 * Exact same mapping again:85 * base | free | new86 * +1 | mapped | new87 * +2 | mapped | new88 * +3 | mapped | new89 * +4 | free | new90 */91 addr = base_addr;92 size = 5 * page_size;93 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);94 if (p != MAP_FAILED) {95 dump_maps();96 ksft_exit_fail_msg("Error:1: mmap() succeeded when it shouldn't have\n");97 }98 ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);99 ksft_test_result_pass("mmap() 5*PAGE_SIZE at base\n");100 101 /*102 * Second mapping contained within first:103 *104 * base | free |105 * +1 | mapped |106 * +2 | mapped | new107 * +3 | mapped |108 * +4 | free |109 */110 addr = base_addr + (2 * page_size);111 size = page_size;112 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);113 if (p != MAP_FAILED) {114 dump_maps();115 ksft_exit_fail_msg("Error:2: mmap() succeeded when it shouldn't have\n");116 }117 ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);118 ksft_test_result_pass("mmap() 2*PAGE_SIZE at base+PAGE_SIZE\n");119 120 /*121 * Overlap end of existing mapping:122 * base | free |123 * +1 | mapped |124 * +2 | mapped |125 * +3 | mapped | new126 * +4 | free | new127 */128 addr = base_addr + (3 * page_size);129 size = 2 * page_size;130 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);131 if (p != MAP_FAILED) {132 dump_maps();133 ksft_exit_fail_msg("Error:3: mmap() succeeded when it shouldn't have\n");134 }135 ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);136 ksft_test_result_pass("mmap() 2*PAGE_SIZE at base+(3*PAGE_SIZE)\n");137 138 /*139 * Overlap start of existing mapping:140 * base | free | new141 * +1 | mapped | new142 * +2 | mapped |143 * +3 | mapped |144 * +4 | free |145 */146 addr = base_addr;147 size = 2 * page_size;148 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);149 if (p != MAP_FAILED) {150 dump_maps();151 ksft_exit_fail_msg("Error:4: mmap() succeeded when it shouldn't have\n");152 }153 ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);154 ksft_test_result_pass("mmap() 2*PAGE_SIZE bytes at base\n");155 156 /*157 * Adjacent to start of existing mapping:158 * base | free | new159 * +1 | mapped |160 * +2 | mapped |161 * +3 | mapped |162 * +4 | free |163 */164 addr = base_addr;165 size = page_size;166 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);167 if (p == MAP_FAILED) {168 dump_maps();169 ksft_exit_fail_msg("Error:5: mmap() failed when it shouldn't have\n");170 }171 ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);172 ksft_test_result_pass("mmap() PAGE_SIZE at base\n");173 174 /*175 * Adjacent to end of existing mapping:176 * base | free |177 * +1 | mapped |178 * +2 | mapped |179 * +3 | mapped |180 * +4 | free | new181 */182 addr = base_addr + (4 * page_size);183 size = page_size;184 p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);185 if (p == MAP_FAILED) {186 dump_maps();187 ksft_exit_fail_msg("Error:6: mmap() failed when it shouldn't have\n");188 }189 ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);190 ksft_test_result_pass("mmap() PAGE_SIZE at base+(4*PAGE_SIZE)\n");191 192 addr = base_addr;193 size = 5 * page_size;194 if (munmap((void *)addr, size) != 0) {195 dump_maps();196 ksft_exit_fail_msg("Error: munmap failed!?\n");197 }198 ksft_test_result_pass("Base Address unmap() successful\n");199 200 ksft_finished();201}202