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