1 /* 2 * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 #include <sys/types.h> 30 #include <sys/mman.h> 31 #include <stdlib.h> 32 #include <stdio.h> 33 #include <string.h> 34 35 #include "safe_mem.h" 36 37 struct safe_mem_hdr { 38 struct safe_mem_hdr *prev; 39 struct safe_mem_hdr *next; 40 struct safe_mem_tail *tail; 41 const char *file; 42 int line; 43 size_t alloc_sz; 44 char sig[8]; /* SAFEMEM */ 45 }; 46 47 struct safe_mem_tail { 48 char sig[8]; /* SAFEMEM */ 49 }; 50 51 static struct safe_mem_hdr *safe_mem_hdr_first = NULL; 52 53 void * 54 _alloc_safe_mem(size_t req_sz, const char *file, int line) 55 { 56 struct safe_mem_hdr *hdr, *hdrp; 57 struct safe_mem_tail *tail; 58 size_t alloc_sz; 59 char *mem, *user_mem; 60 61 alloc_sz = req_sz + sizeof(*hdr) + sizeof(*tail); 62 if ((mem = malloc(alloc_sz)) == NULL) 63 return NULL; 64 65 if (mlock(mem, alloc_sz) < 0) { 66 free(mem); 67 return NULL; 68 } 69 70 memset(mem, 0, alloc_sz); 71 72 hdr = (struct safe_mem_hdr *)mem; 73 tail = (struct safe_mem_tail *)(mem + alloc_sz - sizeof(*tail)); 74 user_mem = mem + sizeof(*hdr); 75 76 strcpy(hdr->sig, "SAFEMEM"); 77 strcpy(tail->sig, "SAFEMEM"); 78 hdr->tail = tail; 79 hdr->alloc_sz = alloc_sz; 80 hdr->file = file; 81 hdr->line = line; 82 hdr->next = NULL; 83 84 if (safe_mem_hdr_first == NULL) { 85 safe_mem_hdr_first = hdr; 86 } else { 87 hdrp = safe_mem_hdr_first; 88 while (hdrp->next != NULL) 89 hdrp = hdrp->next; 90 hdr->prev = hdrp; 91 hdrp->next = hdr; 92 } 93 94 return user_mem; 95 } 96 97 void 98 _free_safe_mem(void *mem_ptr, const char *file, int line) 99 { 100 struct safe_mem_hdr *hdr; 101 struct safe_mem_tail *tail; 102 size_t alloc_sz; 103 char *mem = mem_ptr; 104 105 mem -= sizeof(*hdr); 106 hdr = (struct safe_mem_hdr *)mem; 107 tail = (struct safe_mem_tail *)(mem + hdr->alloc_sz - sizeof(*tail)); 108 109 #ifdef DEBUG 110 fprintf(stderr, "freeing safe_mem (hdr): %#lx (%s:%d)\n", 111 (unsigned long)(void *)hdr, hdr->file, hdr->line); 112 #endif 113 114 if (hdr->alloc_sz == 0) { 115 fprintf(stderr, "BUG: double-free at %s:%d !!!\n", file, line); 116 return; 117 } 118 119 /* Integrity checks */ 120 if ((memcmp(hdr->sig, "SAFEMEM\0", 8) != 0) || 121 (memcmp(tail->sig, "SAFEMEM\0", 8) != 0)) { 122 fprintf(stderr, "BUG: safe_mem buffer under- or overflow at " 123 "%s:%d !!!\n", file, line); 124 return; 125 } 126 127 if (safe_mem_hdr_first == NULL) { 128 fprintf(stderr, "BUG: safe_mem list should not be empty at " 129 "%s:%d !!!\n", file, line); 130 return; 131 } 132 133 if (hdr->prev != NULL) 134 hdr->prev->next = hdr->next; 135 if (hdr->next != NULL) 136 hdr->next->prev = hdr->prev; 137 if (safe_mem_hdr_first == hdr) 138 safe_mem_hdr_first = hdr->next; 139 140 alloc_sz = hdr->alloc_sz; 141 memset(mem, 0xFF, alloc_sz); 142 memset(mem, 0, alloc_sz); 143 144 free(mem); 145 } 146 147 void 148 check_and_purge_safe_mem(void) 149 { 150 struct safe_mem_hdr *hdr; 151 char *mem; 152 int ok; 153 154 if (safe_mem_hdr_first == NULL) 155 return; 156 157 hdr = safe_mem_hdr_first; 158 while ((hdr = safe_mem_hdr_first) != NULL) { 159 if ((hdr->alloc_sz > 0) && 160 (memcmp(hdr->sig, "SAFEMEM\0", 8) == 0) && 161 (memcmp(hdr->tail->sig, "SAFEMEM\0", 8) == 0)) 162 ok = 1; 163 else 164 ok = 0; 165 166 #ifdef DEBUG 167 fprintf(stderr, "un-freed safe_mem: %#lx (%s:%d) [integrity=%s]\n", 168 (unsigned long)(void *)hdr, hdr->file, hdr->line, 169 ok? "ok" : "failed"); 170 #endif 171 mem = (void *)hdr; 172 mem += sizeof(*hdr); 173 _free_safe_mem(mem, "check_and_purge_safe_mem", 0); 174 } 175 } 176