xref: /haiku/src/tests/system/libroot/posix/mprotect_test.cpp (revision 3521e43f979d060726757bf5ca74cfd816e947ad)
1*3521e43fSIngo Weinhold /*
2*3521e43fSIngo Weinhold  * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3*3521e43fSIngo Weinhold  * Distributed under the terms of the MIT License.
4*3521e43fSIngo Weinhold  */
5*3521e43fSIngo Weinhold 
6*3521e43fSIngo Weinhold #include <errno.h>
7*3521e43fSIngo Weinhold #include <limits.h>
8*3521e43fSIngo Weinhold #include <signal.h>
9*3521e43fSIngo Weinhold #include <stdint.h>
10*3521e43fSIngo Weinhold #include <stdio.h>
11*3521e43fSIngo Weinhold #include <stdlib.h>
12*3521e43fSIngo Weinhold #include <signal.h>
13*3521e43fSIngo Weinhold #include <string.h>
14*3521e43fSIngo Weinhold #include <sys/mman.h>
15*3521e43fSIngo Weinhold 
16*3521e43fSIngo Weinhold 
17*3521e43fSIngo Weinhold #ifndef PAGE_SIZE
18*3521e43fSIngo Weinhold #	define PAGE_SIZE 4096
19*3521e43fSIngo Weinhold #endif
20*3521e43fSIngo Weinhold 
21*3521e43fSIngo Weinhold 
22*3521e43fSIngo Weinhold static const size_t kMapChunkSize = 4 * PAGE_SIZE;
23*3521e43fSIngo Weinhold static const size_t kTestSize = 256 * PAGE_SIZE;
24*3521e43fSIngo Weinhold 
25*3521e43fSIngo Weinhold static int64_t sHandledSignals = 0;
26*3521e43fSIngo Weinhold 
27*3521e43fSIngo Weinhold static uint8_t* sMappedBase;
28*3521e43fSIngo Weinhold static size_t sMappedSize;
29*3521e43fSIngo Weinhold static uint8_t* sTouchedAddress;
30*3521e43fSIngo Weinhold 
31*3521e43fSIngo Weinhold 
32*3521e43fSIngo Weinhold static void
signal_handler(int signal)33*3521e43fSIngo Weinhold signal_handler(int signal)
34*3521e43fSIngo Weinhold {
35*3521e43fSIngo Weinhold 	sHandledSignals++;
36*3521e43fSIngo Weinhold 
37*3521e43fSIngo Weinhold 	//printf("SIGSEGV at %p\n", sTouchedAddress);
38*3521e43fSIngo Weinhold 
39*3521e43fSIngo Weinhold 	// protect the last page of the current allocation writable
40*3521e43fSIngo Weinhold 	if (mprotect(sMappedBase + sMappedSize - PAGE_SIZE, PAGE_SIZE,
41*3521e43fSIngo Weinhold 			PROT_READ | PROT_WRITE) < 0) {
42*3521e43fSIngo Weinhold 		fprintf(stderr, "SIGSEGV: mprotect() failed: %s\n", strerror(errno));
43*3521e43fSIngo Weinhold 		exit(1);
44*3521e43fSIngo Weinhold 	}
45*3521e43fSIngo Weinhold 
46*3521e43fSIngo Weinhold 	// allocate the next chunk
47*3521e43fSIngo Weinhold 	void* mappedAddress = mmap(sMappedBase + sMappedSize, kMapChunkSize,
48*3521e43fSIngo Weinhold 		PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
49*3521e43fSIngo Weinhold 	if (mappedAddress == MAP_FAILED) {
50*3521e43fSIngo Weinhold 		fprintf(stderr, "SIGSEGV: mmap() failed: %s\n", strerror(errno));
51*3521e43fSIngo Weinhold 		exit(1);
52*3521e43fSIngo Weinhold 	}
53*3521e43fSIngo Weinhold 
54*3521e43fSIngo Weinhold 	printf("mapped %d bytes at %p\n", (int)kMapChunkSize, mappedAddress);
55*3521e43fSIngo Weinhold 
56*3521e43fSIngo Weinhold 	sMappedSize += kMapChunkSize;
57*3521e43fSIngo Weinhold 
58*3521e43fSIngo Weinhold 	// map the last page read-only
59*3521e43fSIngo Weinhold 	if (mprotect(sMappedBase + sMappedSize - PAGE_SIZE, PAGE_SIZE, PROT_READ)
60*3521e43fSIngo Weinhold 			< 0) {
61*3521e43fSIngo Weinhold 		fprintf(stderr, "SIGSEGV: mprotect() failed: %s\n", strerror(errno));
62*3521e43fSIngo Weinhold 		exit(1);
63*3521e43fSIngo Weinhold 	}
64*3521e43fSIngo Weinhold }
65*3521e43fSIngo Weinhold 
66*3521e43fSIngo Weinhold 
67*3521e43fSIngo Weinhold int
main()68*3521e43fSIngo Weinhold main()
69*3521e43fSIngo Weinhold {
70*3521e43fSIngo Weinhold 	// install signal handler
71*3521e43fSIngo Weinhold 	if (signal(SIGSEGV, signal_handler) == SIG_ERR) {
72*3521e43fSIngo Weinhold 		fprintf(stderr, "Error: Failed to install signal handler: %s\n",
73*3521e43fSIngo Weinhold 			strerror(errno));
74*3521e43fSIngo Weinhold 		exit(1);
75*3521e43fSIngo Weinhold 	}
76*3521e43fSIngo Weinhold 
77*3521e43fSIngo Weinhold 	// Map the complete test size plus one chunk and unmap all but the first
78*3521e43fSIngo Weinhold 	// chunk again, so no other memory gets into the way, when we mmap() the
79*3521e43fSIngo Weinhold 	// other chunks with MAP_FIXED.
80*3521e43fSIngo Weinhold 	sMappedBase = (uint8_t*)mmap(NULL, kTestSize + kMapChunkSize,
81*3521e43fSIngo Weinhold 		PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
82*3521e43fSIngo Weinhold 	if (sMappedBase == MAP_FAILED) {
83*3521e43fSIngo Weinhold 		fprintf(stderr, "mmap() failed: %s\n", strerror(errno));
84*3521e43fSIngo Weinhold 		return 1;
85*3521e43fSIngo Weinhold 	}
86*3521e43fSIngo Weinhold 	munmap(sMappedBase + kMapChunkSize, kTestSize);
87*3521e43fSIngo Weinhold 
88*3521e43fSIngo Weinhold 	sMappedSize = kMapChunkSize;
89*3521e43fSIngo Weinhold 
90*3521e43fSIngo Weinhold 	printf("mapped %d bytes at %p\n", (int)sMappedSize, sMappedBase);
91*3521e43fSIngo Weinhold 
92*3521e43fSIngo Weinhold 	if (mprotect(sMappedBase + sMappedSize - PAGE_SIZE, PAGE_SIZE, PROT_READ)
93*3521e43fSIngo Weinhold 			< 0) {
94*3521e43fSIngo Weinhold 		fprintf(stderr, "mprotect() failed: %s\n", strerror(errno));
95*3521e43fSIngo Weinhold 		return 1;
96*3521e43fSIngo Weinhold 	}
97*3521e43fSIngo Weinhold 
98*3521e43fSIngo Weinhold 	for (int i = 0; i < 256 * PAGE_SIZE; i++) {
99*3521e43fSIngo Weinhold 		sTouchedAddress = sMappedBase + i;
100*3521e43fSIngo Weinhold 		*sTouchedAddress = 1;
101*3521e43fSIngo Weinhold 	}
102*3521e43fSIngo Weinhold 
103*3521e43fSIngo Weinhold 	printf("test finished successfully!\n");
104*3521e43fSIngo Weinhold 
105*3521e43fSIngo Weinhold 	return 0;
106*3521e43fSIngo Weinhold }
107