1b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Simplified version of mempool.c, that is more oriented towards 3b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// checking that the description of invalid addresses is correct. 4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 5b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdio.h> 6b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <unistd.h> 7b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "tests/sys_mman.h" 8b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <assert.h> 9b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include <stdlib.h> 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "../memcheck.h" 12b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 13b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define SUPERBLOCK_SIZE 100000 14b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define REDZONE_SIZE 8 15b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 16b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef struct _level_list 17b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 18b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov struct _level_list *next; 19b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char *where; 20b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Padding ensures the struct is the same size on 32-bit and 64-bit 21b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // machines. 22b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char padding[16 - 2*sizeof(char*)]; 23b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} level_list; 24b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 25b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef struct _pool { 26b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char *mem; 27b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char *where; 28b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov level_list *levels; 29b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int size, left; 30b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Padding ensures the struct is the same size on 32-bit and 64-bit 31b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // machines. 32b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char padding[24 - 3*sizeof(char*)]; 33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} pool; 34b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 35b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovpool *make_pool( int use_mmap ) 36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 37b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pool *p; 38b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 39b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (use_mmap) { 40b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p = (pool *)mmap(0, sizeof(pool), PROT_READ|PROT_WRITE|PROT_EXEC, 41b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 42b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p->where = p->mem = (char *)mmap(NULL, SUPERBLOCK_SIZE, 43b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov PROT_READ|PROT_WRITE|PROT_EXEC, 44b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 45b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 46b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p = (pool *)malloc(sizeof(pool)); 47b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p->where = p->mem = (char *)malloc(SUPERBLOCK_SIZE); 48b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 49b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 50b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p->size = p->left = SUPERBLOCK_SIZE; 51b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p->levels = NULL; 52b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_MAKE_MEM_NOACCESS(p->where, SUPERBLOCK_SIZE); 53b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return p; 54b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 55b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 56b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid push(pool *p, int use_mmap ) 57b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 58b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov level_list *l; 59b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 60b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (use_mmap) 61b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov l = (level_list *)mmap(0, sizeof(level_list), 62b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov PROT_READ|PROT_WRITE|PROT_EXEC, 63b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov l = (level_list *)malloc(sizeof(level_list)); 66b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 67b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov l->next = p->levels; 68b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov l->where = p->where; 69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_CREATE_MEMPOOL(l->where, REDZONE_SIZE, 0); 70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p->levels = l; 71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 72b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid pop(pool *p, int use_mmap) 74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov level_list *l = p->levels; 76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p->levels = l->next; 77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_DESTROY_MEMPOOL(l->where); 78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_MAKE_MEM_NOACCESS(l->where, p->where-l->where); 79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p->where = l->where; 80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (use_mmap) 81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov munmap(l, sizeof(level_list)); 82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov free(l); 84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 86b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid destroy_pool(pool *p, int use_mmap) 87b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov level_list *l = p->levels; 89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while(l) { 91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pop(p, use_mmap); 92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (use_mmap) { 94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov munmap(p->mem, SUPERBLOCK_SIZE); 95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov munmap(p, sizeof(pool)); 96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov free(p->mem); 98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov free(p); 99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovchar *allocate(pool *p, int size) 103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char *where; 105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p->left -= size + (REDZONE_SIZE*2); 106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov where = p->where + REDZONE_SIZE; 107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov p->where += size + (REDZONE_SIZE*2); 108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_MEMPOOL_ALLOC(p->levels->where, where, size); 109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return where; 110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//------------------------------------------------------------------------- 113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Rest 114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//------------------------------------------------------------------------- 115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid test(void) 117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char *x1, *x2; 119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char res = 0; 120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // p1 is a malloc-backed pool 122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pool *p1 = make_pool(0); 123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // p2 is a mmap-backed pool 125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pool *p2 = make_pool(1); 126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov push(p1, 0); 128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov push(p2, 1); 129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov x1 = allocate(p1, 10); 131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov x2 = allocate(p2, 20); 132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fprintf(stderr, 134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "\n------ out of range reads in malloc-backed pool ------\n\n"); 135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov res += x1[-1]; 136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov res += x1[10]; 137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fprintf(stderr, 139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "\n------ out of range reads in mmap-backed pool ------\n\n"); 140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov res += x2[-1]; // invalid 141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov res += x2[20]; // invalid 142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fprintf(stderr, 144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "\n------ read free in malloc-backed pool ------\n\n"); 145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_MEMPOOL_FREE(p1, x1); 146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov res += x1[5]; 147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fprintf(stderr, 149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "\n------ read free in mmap-backed pool ------\n\n"); 150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_MEMPOOL_FREE(p2, x2); 151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov res += x2[11]; 152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fprintf(stderr, 154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "\n------ double free in malloc-backed pool ------\n\n"); 155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_MEMPOOL_FREE(p1, x1); 156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fprintf(stderr, 158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "\n------ double free in mmap-backed pool ------\n\n"); 159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_MEMPOOL_FREE(p2, x2); 160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // test that redzone are still protected even if the user forgets 163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // to mark the superblock noaccess. 164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng char superblock[100]; 165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VALGRIND_CREATE_MEMPOOL(superblock, REDZONE_SIZE, 0); 167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // User should mark the superblock no access to benefit 168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // from full Valgrind memcheck protection. 169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // VALGRIND_MEMPOOL_ALLOC will however still ensure the 170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // redzones are protected. 171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VALGRIND_MEMPOOL_ALLOC(superblock, superblock+30, 10); 172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res += superblock[30]; // valid 174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res += superblock[39]; // valid 175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng fprintf(stderr, 177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "\n------ 2 invalid access in 'no no-access superblock' ---\n\n"); 178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res += superblock[29]; // invalid 179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng res += superblock[40]; // invalid 180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VALGRIND_DESTROY_MEMPOOL(superblock); 182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // claim res is used, so gcc can't nuke this all 184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov __asm__ __volatile__("" : : "r"(res)); 185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fprintf(stderr, 187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "\n------ done ------\n\n"); 188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pop(p1, 0); 189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov pop(p2, 1); 190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov destroy_pool(p1, 0); 191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov destroy_pool(p2, 1); 192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovint main(void) 195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov test(); 197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return 0; 198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 199