File Index
Files and directories
Sign in
FILE

map_fixed_noreplace.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/mm/map_fixed_noreplace.c C
  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#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  | new
 86	 *     +1 | mapped | new
 87	 *     +2 | mapped | new
 88	 *     +3 | mapped | new
 89	 *     +4 |  free  | new
 90	 */
 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("Second 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 | new
107	 *     +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 | new
126	 *     +4 |  free  | new
127	 */
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  | new
141	 *     +1 | mapped | new
142	 *     +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  | new
159	 *     +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  |  new
181	 */
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}
~/ Read-only file preview.