1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Test different kinds of addressability and definedness */
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "../memcheck.h"
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "tests/sys_mman.h"
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/resource.h>
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h>
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/wait.h>
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h>
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <errno.h>
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <string.h>
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pgsz;
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char *mm(char *addr, int size, int prot)
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	int flags = MAP_PRIVATE | MAP_ANONYMOUS;
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	char *ret;
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (addr)
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		flags |= MAP_FIXED;
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ret = mmap(addr, size, prot, flags, -1, 0);
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (ret == (char *)-1) {
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		perror("mmap failed");
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		exit(1);
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return ret;
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Case 1 - mmaped memory is defined */
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void test1()
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	char *m = mm(0, pgsz * 5, PROT_READ);
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all defined */
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Case 2 - unmapped memory is unaddressable+undefined */
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void test2()
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz*5); /* all OK */
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	munmap(&m[pgsz*2], pgsz);
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_CHECK_MEM_IS_DEFINED(&m[pgsz*2], pgsz); /* undefined */
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* XXX need a memcheck request to test addressability */
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	m[pgsz*2] = 'x';	/* unmapped fault */
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Case 3 - memory definedness doesn't survive remapping */
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void test3()
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_MAKE_MEM_UNDEFINED(&m[pgsz], pgsz);
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	mm(&m[pgsz], pgsz, PROT_READ);
61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_CHECK_MEM_IS_DEFINED(&m[pgsz], pgsz); /* OK */
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Case 4 - mprotect doesn't affect addressability */
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void test4()
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	mprotect(m, pgsz, PROT_WRITE);
70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_CHECK_MEM_IS_DEFINED(m, pgsz); /* OK */
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	m[44] = 'y';		/* OK */
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	mprotect(m, pgsz*5, PROT_NONE);
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	m[55] = 'x';		/* permission fault, but no tool complaint */
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Case 5 - mprotect doesn't affect definedness */
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void test5()
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	char *m = mm(0, pgsz * 5, PROT_READ|PROT_WRITE);
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_MAKE_MEM_UNDEFINED(m, pgsz*5);
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	memset(m, 'x', 10);
84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_CHECK_MEM_IS_DEFINED(m, 10);	/* OK */
85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_CHECK_MEM_IS_DEFINED(m+10, 10); /* BAD */
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	mprotect(m, pgsz*5, PROT_NONE);
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	mprotect(m, pgsz*5, PROT_READ);
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_CHECK_MEM_IS_DEFINED(m, 10);	/* still OK */
91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	(void) VALGRIND_CHECK_MEM_IS_DEFINED(m+20, 10); /* BAD */
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic struct test {
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	void (*test)(void);
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	int faults;
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} tests[] = {
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	{ test1, 0 },
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	{ test2, 1 },
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	{ test3, 0 },
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	{ test4, 1 },
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	{ test5, 0 },
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic const int n_tests = sizeof(tests)/sizeof(*tests);
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main()
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	static const struct rlimit zero = { 0, 0 };
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	int i;
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pgsz = getpagesize();
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	setvbuf(stdout, NULL, _IOLBF, 0);
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	setrlimit(RLIMIT_CORE, &zero);
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	for(i = 0; i < n_tests; i++) {
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		int pid;
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		pid = fork();
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		if (pid == -1) {
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			perror("fork");
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			exit(1);
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		}
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		if (pid == 0) {
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			(*tests[i].test)();
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			exit(0);
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		} else {
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			int status;
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			int ret;
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			printf("Test %d: ", i+1);
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			fflush(stdout);
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			while((ret = waitpid(pid, &status, 0)) != pid) {
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				if (errno != EINTR) {
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					perror("waitpid");
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					exit(1);
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				}
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			}
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			if (WIFSIGNALED(status)) {
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				assert(WTERMSIG(status) != 0);
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				if (1 == tests[i].faults &&
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				    (WTERMSIG(status) == SIGSEGV ||
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				     WTERMSIG(status) == SIGBUS))
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					printf("PASS\n");
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				else
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					printf("died with unexpected signal %d\n",
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					       WTERMSIG(status));
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			} else if (WIFEXITED(status)) {
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				if (WEXITSTATUS(status) == 0) {
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					if (tests[i].faults == 0)
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						printf("PASS\n");
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					else
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown						printf("exited without expected SIGSEGV or SIGBUS signal\n");
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				} else
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					printf("exited with unexpected status %d\n",
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown					       WEXITSTATUS(status));
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			} else {
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				printf("strange status %x?\n", status);
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			}
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		}
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	exit(0);
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
166