raw
smg_comms_c_wrappers    1 /* memory.c  -	memory allocation
smg_comms_c_wrappers 2 * Modified by No Such Labs. (C) 2015. See README.
smg_comms_c_wrappers 3 *
smg_comms_c_wrappers 4 * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
smg_comms_c_wrappers 5 * SHA256(gnupg-1.4.10.tar.gz):
smg_comms_c_wrappers 6 * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
smg_comms_c_wrappers 7 * (C) 1994-2005 Free Software Foundation, Inc.
smg_comms_c_wrappers 8 *
smg_comms_c_wrappers 9 * This program is free software: you can redistribute it and/or modify
smg_comms_c_wrappers 10 * it under the terms of the GNU General Public License as published by
smg_comms_c_wrappers 11 * the Free Software Foundation, either version 3 of the License, or
smg_comms_c_wrappers 12 * (at your option) any later version.
smg_comms_c_wrappers 13 *
smg_comms_c_wrappers 14 * This program is distributed in the hope that it will be useful,
smg_comms_c_wrappers 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
smg_comms_c_wrappers 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
smg_comms_c_wrappers 17 * GNU General Public License for more details.
smg_comms_c_wrappers 18 *
smg_comms_c_wrappers 19 * You should have received a copy of the GNU General Public License
smg_comms_c_wrappers 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
smg_comms_c_wrappers 21 */
smg_comms_c_wrappers 22
smg_comms_c_wrappers 23 /* We use our own memory allocation functions instead of plain malloc(),
smg_comms_c_wrappers 24 * so that we can provide some special enhancements:
smg_comms_c_wrappers 25 * a) functions to provide memory from a secure memory.
smg_comms_c_wrappers 26 * b) by looking at the requested allocation size we
smg_comms_c_wrappers 27 * can reuse memory very quickly (e.g. MPI storage)
smg_comms_c_wrappers 28 * (really needed?)
smg_comms_c_wrappers 29 * c) memory usage reporting if compiled with M_DEBUG
smg_comms_c_wrappers 30 * d) memory checking if compiled with M_GUARD
smg_comms_c_wrappers 31 */
smg_comms_c_wrappers 32
smg_comms_c_wrappers 33 #include <stdio.h>
smg_comms_c_wrappers 34 #include <stdlib.h>
smg_comms_c_wrappers 35 #include <stdarg.h>
smg_comms_c_wrappers 36 #include <string.h>
smg_comms_c_wrappers 37
smg_comms_c_wrappers 38 #include "knobs.h"
smg_comms_c_wrappers 39 #include "types.h"
smg_comms_c_wrappers 40 #include "memory.h"
smg_comms_c_wrappers 41 #include "util.h"
smg_comms_c_wrappers 42
smg_comms_c_wrappers 43 #define MAGIC_NOR_BYTE 0x55
smg_comms_c_wrappers 44 #define MAGIC_SEC_BYTE 0xcc
smg_comms_c_wrappers 45 #define MAGIC_END_BYTE 0xaa
smg_comms_c_wrappers 46
smg_comms_c_wrappers 47 /* This is a very crude alignment check which does not work on all CPUs
smg_comms_c_wrappers 48 * IIRC, I once introduced it for testing on an Alpha. We should better
smg_comms_c_wrappers 49 * replace this guard stuff with one provided by a modern malloc library
smg_comms_c_wrappers 50 */
smg_comms_c_wrappers 51 #if SIZEOF_UNSIGNED_LONG == 8
smg_comms_c_wrappers 52 #define EXTRA_ALIGN 4
smg_comms_c_wrappers 53 #else
smg_comms_c_wrappers 54 #define EXTRA_ALIGN 0
smg_comms_c_wrappers 55 #endif
smg_comms_c_wrappers 56
smg_comms_c_wrappers 57 #if defined(M_DEBUG) || defined(M_GUARD)
smg_comms_c_wrappers 58 static void membug( const char *fmt, ... );
smg_comms_c_wrappers 59 #endif
smg_comms_c_wrappers 60
smg_comms_c_wrappers 61 #ifdef M_DEBUG
smg_comms_c_wrappers 62
smg_comms_c_wrappers 63 #ifndef M_GUARD
smg_comms_c_wrappers 64 #define M_GUARD 1
smg_comms_c_wrappers 65 #endif
smg_comms_c_wrappers 66 #undef xmalloc
smg_comms_c_wrappers 67 #undef xtrymalloc
smg_comms_c_wrappers 68 #undef xmalloc_clear
smg_comms_c_wrappers 69 #undef xmalloc_secure
smg_comms_c_wrappers 70 #undef xmalloc_secure_clear
smg_comms_c_wrappers 71 #undef xrealloc
smg_comms_c_wrappers 72 #undef xfree
smg_comms_c_wrappers 73 #undef m_check
smg_comms_c_wrappers 74 #undef xstrdup
smg_comms_c_wrappers 75 #undef xtrystrdup
smg_comms_c_wrappers 76 #define FNAME(a) m_debug_ ##a
smg_comms_c_wrappers 77 #define FNAMEX(a) m_debug_ ##a
smg_comms_c_wrappers 78 #define FNAMEXM(a) m_debug_ ##a
smg_comms_c_wrappers 79 #define FNAMEPRT , const char *info
smg_comms_c_wrappers 80 #define FNAMEARG , info
smg_comms_c_wrappers 81
smg_comms_c_wrappers 82 #define store_len(p,n,m) do { add_entry(p,n,m, \
smg_comms_c_wrappers 83 info, __FUNCTION__); } while(0)
smg_comms_c_wrappers 84 #else
smg_comms_c_wrappers 85 #define FNAME(a) m_ ##a
smg_comms_c_wrappers 86 #define FNAMEX(a) x ##a
smg_comms_c_wrappers 87 #define FNAMEXM(a) xm ##a
smg_comms_c_wrappers 88 #define FNAMEPRT
smg_comms_c_wrappers 89 #define FNAMEARG
smg_comms_c_wrappers 90 #define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \
smg_comms_c_wrappers 91 ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \
smg_comms_c_wrappers 92 ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \
smg_comms_c_wrappers 93 ((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \
smg_comms_c_wrappers 94 : MAGIC_NOR_BYTE; \
smg_comms_c_wrappers 95 } while(0)
smg_comms_c_wrappers 96 #endif
smg_comms_c_wrappers 97
smg_comms_c_wrappers 98
smg_comms_c_wrappers 99 #ifdef M_GUARD
smg_comms_c_wrappers 100 static long used_memory;
smg_comms_c_wrappers 101 #endif
smg_comms_c_wrappers 102
smg_comms_c_wrappers 103 #ifdef M_DEBUG /* stuff used for memory debuging */
smg_comms_c_wrappers 104
smg_comms_c_wrappers 105 struct info_entry {
smg_comms_c_wrappers 106 struct info_entry *next;
smg_comms_c_wrappers 107 unsigned count; /* call count */
smg_comms_c_wrappers 108 const char *info; /* the reference to the info string */
smg_comms_c_wrappers 109 };
smg_comms_c_wrappers 110
smg_comms_c_wrappers 111 struct memtbl_entry {
smg_comms_c_wrappers 112 const void *user_p; /* for reference: the pointer given to the user */
smg_comms_c_wrappers 113 size_t user_n; /* length requested by the user */
smg_comms_c_wrappers 114 struct memtbl_entry *next; /* to build a list of unused entries */
smg_comms_c_wrappers 115 const struct info_entry *info; /* points into the table with */
smg_comms_c_wrappers 116 /* the info strings */
smg_comms_c_wrappers 117 unsigned inuse:1; /* this entry is in use */
smg_comms_c_wrappers 118 unsigned count:31;
smg_comms_c_wrappers 119 };
smg_comms_c_wrappers 120
smg_comms_c_wrappers 121
smg_comms_c_wrappers 122 #define INFO_BUCKETS 53
smg_comms_c_wrappers 123 #define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS )
smg_comms_c_wrappers 124 static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */
smg_comms_c_wrappers 125
smg_comms_c_wrappers 126 static struct memtbl_entry *memtbl; /* the table with the memory info */
smg_comms_c_wrappers 127 static unsigned memtbl_size; /* number of allocated entries */
smg_comms_c_wrappers 128 static unsigned memtbl_len; /* number of used entries */
smg_comms_c_wrappers 129 static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */
smg_comms_c_wrappers 130
smg_comms_c_wrappers 131 static void dump_table_at_exit(void);
smg_comms_c_wrappers 132 static void dump_table(void);
smg_comms_c_wrappers 133 static void check_allmem( const char *info );
smg_comms_c_wrappers 134
smg_comms_c_wrappers 135 /****************
smg_comms_c_wrappers 136 * Put the new P into the debug table and return a pointer to the table entry.
smg_comms_c_wrappers 137 * mode is true for security. BY is the name of the function which called us.
smg_comms_c_wrappers 138 */
smg_comms_c_wrappers 139 static void
smg_comms_c_wrappers 140 add_entry( byte *p, unsigned n, int mode, const char *info, const char *by )
smg_comms_c_wrappers 141 {
smg_comms_c_wrappers 142 unsigned index;
smg_comms_c_wrappers 143 struct memtbl_entry *e;
smg_comms_c_wrappers 144 struct info_entry *ie;
smg_comms_c_wrappers 145
smg_comms_c_wrappers 146 if( memtbl_len < memtbl_size )
smg_comms_c_wrappers 147 index = memtbl_len++;
smg_comms_c_wrappers 148 else {
smg_comms_c_wrappers 149 struct memtbl_entry *e;
smg_comms_c_wrappers 150 /* look for a used entry in the table. We take the first one,
smg_comms_c_wrappers 151 * so that freed entries remain as long as possible in the table
smg_comms_c_wrappers 152 * (free appends a new one)
smg_comms_c_wrappers 153 */
smg_comms_c_wrappers 154 if( (e = memtbl_unused) ) {
smg_comms_c_wrappers 155 index = e - memtbl;
smg_comms_c_wrappers 156 memtbl_unused = e->next;
smg_comms_c_wrappers 157 e->next = NULL;
smg_comms_c_wrappers 158 }
smg_comms_c_wrappers 159 else { /* no free entries in the table: extend the table */
smg_comms_c_wrappers 160 if( !memtbl_size ) { /* first time */
smg_comms_c_wrappers 161 memtbl_size = 100;
smg_comms_c_wrappers 162 if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) )
smg_comms_c_wrappers 163 membug("memory debug table malloc failed\n");
smg_comms_c_wrappers 164 index = 0;
smg_comms_c_wrappers 165 memtbl_len = 1;
smg_comms_c_wrappers 166 atexit( dump_table_at_exit );
smg_comms_c_wrappers 167 }
smg_comms_c_wrappers 168 else { /* realloc */
smg_comms_c_wrappers 169 unsigned n = memtbl_size / 4; /* enlarge by 25% */
smg_comms_c_wrappers 170 if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl)))
smg_comms_c_wrappers 171 membug("memory debug table realloc failed\n");
smg_comms_c_wrappers 172 memset(memtbl+memtbl_size, 0, n*sizeof *memtbl );
smg_comms_c_wrappers 173 memtbl_size += n;
smg_comms_c_wrappers 174 index = memtbl_len++;
smg_comms_c_wrappers 175 }
smg_comms_c_wrappers 176 }
smg_comms_c_wrappers 177 }
smg_comms_c_wrappers 178 e = memtbl+index;
smg_comms_c_wrappers 179 if( e->inuse )
smg_comms_c_wrappers 180 membug("Ooops: entry %u is flagged as in use\n", index);
smg_comms_c_wrappers 181 e->user_p = p + EXTRA_ALIGN + 4;
smg_comms_c_wrappers 182 e->user_n = n;
smg_comms_c_wrappers 183 e->count++;
smg_comms_c_wrappers 184 if( e->next )
smg_comms_c_wrappers 185 membug("Ooops: entry is in free entry list\n");
smg_comms_c_wrappers 186 /* do we already have this info string */
smg_comms_c_wrappers 187 for( ie = info_strings[info_hash(info)]; ie; ie = ie->next )
smg_comms_c_wrappers 188 if( ie->info == info )
smg_comms_c_wrappers 189 break;
smg_comms_c_wrappers 190 if( !ie ) { /* no: make a new entry */
smg_comms_c_wrappers 191 if( !(ie = malloc( sizeof *ie )) )
smg_comms_c_wrappers 192 membug("can't allocate info entry\n");
smg_comms_c_wrappers 193 ie->next = info_strings[info_hash(info)];
smg_comms_c_wrappers 194 info_strings[info_hash(info)] = ie;
smg_comms_c_wrappers 195 ie->info = info;
smg_comms_c_wrappers 196 ie->count = 0;
smg_comms_c_wrappers 197 }
smg_comms_c_wrappers 198 ie->count++;
smg_comms_c_wrappers 199 e->info = ie;
smg_comms_c_wrappers 200 e->inuse = 1;
smg_comms_c_wrappers 201
smg_comms_c_wrappers 202 /* put the index at the start of the memory */
smg_comms_c_wrappers 203 p[EXTRA_ALIGN+0] = index;
smg_comms_c_wrappers 204 p[EXTRA_ALIGN+1] = index >> 8 ;
smg_comms_c_wrappers 205 p[EXTRA_ALIGN+2] = index >> 16 ;
smg_comms_c_wrappers 206 p[EXTRA_ALIGN+3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ;
smg_comms_c_wrappers 207 if( DBG_MEMORY )
smg_comms_c_wrappers 208 log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by );
smg_comms_c_wrappers 209 }
smg_comms_c_wrappers 210
smg_comms_c_wrappers 211
smg_comms_c_wrappers 212
smg_comms_c_wrappers 213 /****************
smg_comms_c_wrappers 214 * Check that the memory block is correct. The magic byte has already been
smg_comms_c_wrappers 215 * checked. Checks which are done here:
smg_comms_c_wrappers 216 * - see whether the index points into our memory table
smg_comms_c_wrappers 217 * - see whether P is the same as the one stored in the table
smg_comms_c_wrappers 218 * - see whether we have already freed this block.
smg_comms_c_wrappers 219 */
smg_comms_c_wrappers 220 struct memtbl_entry *
smg_comms_c_wrappers 221 check_mem( const byte *p, const char *info )
smg_comms_c_wrappers 222 {
smg_comms_c_wrappers 223 unsigned n;
smg_comms_c_wrappers 224 struct memtbl_entry *e;
smg_comms_c_wrappers 225
smg_comms_c_wrappers 226 n = p[EXTRA_ALIGN+0];
smg_comms_c_wrappers 227 n |= p[EXTRA_ALIGN+1] << 8;
smg_comms_c_wrappers 228 n |= p[EXTRA_ALIGN+2] << 16;
smg_comms_c_wrappers 229
smg_comms_c_wrappers 230 if( n >= memtbl_len )
smg_comms_c_wrappers 231 membug("memory at %p corrupted: index=%u table_len=%u (%s)\n",
smg_comms_c_wrappers 232 p+EXTRA_ALIGN+4, n, memtbl_len, info );
smg_comms_c_wrappers 233 e = memtbl+n;
smg_comms_c_wrappers 234
smg_comms_c_wrappers 235 if( e->user_p != p+EXTRA_ALIGN+4 )
smg_comms_c_wrappers 236 membug("memory at %p corrupted: reference mismatch (%s)\n",
smg_comms_c_wrappers 237 p+EXTRA_ALIGN+4, info );
smg_comms_c_wrappers 238 if( !e->inuse )
smg_comms_c_wrappers 239 membug("memory at %p corrupted: marked as free (%s)\n",
smg_comms_c_wrappers 240 p+EXTRA_ALIGN+4, info );
smg_comms_c_wrappers 241
smg_comms_c_wrappers 242 if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE
smg_comms_c_wrappers 243 || p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) )
smg_comms_c_wrappers 244 membug("memory at %p corrupted: underflow=%02x (%s)\n",
smg_comms_c_wrappers 245 p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info );
smg_comms_c_wrappers 246 if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE )
smg_comms_c_wrappers 247 membug("memory at %p corrupted: overflow=%02x (%s)\n",
smg_comms_c_wrappers 248 p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info );
smg_comms_c_wrappers 249 return e;
smg_comms_c_wrappers 250 }
smg_comms_c_wrappers 251
smg_comms_c_wrappers 252
smg_comms_c_wrappers 253 /****************
smg_comms_c_wrappers 254 * free the entry and the memory (replaces free)
smg_comms_c_wrappers 255 */
smg_comms_c_wrappers 256 static void
smg_comms_c_wrappers 257 free_entry( byte *p, const char *info )
smg_comms_c_wrappers 258 {
smg_comms_c_wrappers 259 struct memtbl_entry *e, *e2;
smg_comms_c_wrappers 260
smg_comms_c_wrappers 261 check_allmem("add_entry");
smg_comms_c_wrappers 262
smg_comms_c_wrappers 263 e = check_mem(p, info);
smg_comms_c_wrappers 264 if( DBG_MEMORY )
smg_comms_c_wrappers 265 log_debug( "%s frees %u bytes alloced by %s\n",
smg_comms_c_wrappers 266 info, e->user_n, e->info->info );
smg_comms_c_wrappers 267 if( !e->inuse ) {
smg_comms_c_wrappers 268 if( e->user_p == p + EXTRA_ALIGN+ 4 )
smg_comms_c_wrappers 269 membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 );
smg_comms_c_wrappers 270 else
smg_comms_c_wrappers 271 membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 );
smg_comms_c_wrappers 272 }
smg_comms_c_wrappers 273
smg_comms_c_wrappers 274 e->inuse = 0;
smg_comms_c_wrappers 275 e->next = NULL;
smg_comms_c_wrappers 276 if( !memtbl_unused )
smg_comms_c_wrappers 277 memtbl_unused = e;
smg_comms_c_wrappers 278 else {
smg_comms_c_wrappers 279 for(e2=memtbl_unused; e2->next; e2 = e2->next )
smg_comms_c_wrappers 280 ;
smg_comms_c_wrappers 281 e2->next = e;
smg_comms_c_wrappers 282 }
smg_comms_c_wrappers 283 if( m_is_secure(p+EXTRA_ALIGN+4) )
smg_comms_c_wrappers 284 secmem_free(p);
smg_comms_c_wrappers 285 else {
smg_comms_c_wrappers 286 memset(p,'f', e->user_n+5);
smg_comms_c_wrappers 287 free(p);
smg_comms_c_wrappers 288 }
smg_comms_c_wrappers 289 }
smg_comms_c_wrappers 290
smg_comms_c_wrappers 291 static void
smg_comms_c_wrappers 292 dump_entry(struct memtbl_entry *e )
smg_comms_c_wrappers 293 {
smg_comms_c_wrappers 294 unsigned n = e - memtbl;
smg_comms_c_wrappers 295
smg_comms_c_wrappers 296 fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n",
smg_comms_c_wrappers 297 n, e->inuse?'a':'u', e->count, e->user_p, e->user_n,
smg_comms_c_wrappers 298 e->info->info, e->info->count );
smg_comms_c_wrappers 299
smg_comms_c_wrappers 300
smg_comms_c_wrappers 301 }
smg_comms_c_wrappers 302
smg_comms_c_wrappers 303
smg_comms_c_wrappers 304 static void
smg_comms_c_wrappers 305 dump_table_at_exit( void)
smg_comms_c_wrappers 306 {
smg_comms_c_wrappers 307 if( DBG_MEMSTAT )
smg_comms_c_wrappers 308 dump_table();
smg_comms_c_wrappers 309 }
smg_comms_c_wrappers 310
smg_comms_c_wrappers 311 static void
smg_comms_c_wrappers 312 dump_table( void)
smg_comms_c_wrappers 313 {
smg_comms_c_wrappers 314 unsigned n;
smg_comms_c_wrappers 315 struct memtbl_entry *e;
smg_comms_c_wrappers 316 ulong sum = 0, chunks =0;
smg_comms_c_wrappers 317
smg_comms_c_wrappers 318 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
smg_comms_c_wrappers 319 if(e->inuse) {
smg_comms_c_wrappers 320 dump_entry(e);
smg_comms_c_wrappers 321 sum += e->user_n;
smg_comms_c_wrappers 322 chunks++;
smg_comms_c_wrappers 323 }
smg_comms_c_wrappers 324 }
smg_comms_c_wrappers 325 fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n",
smg_comms_c_wrappers 326 sum, chunks );
smg_comms_c_wrappers 327 }
smg_comms_c_wrappers 328
smg_comms_c_wrappers 329
smg_comms_c_wrappers 330 static void
smg_comms_c_wrappers 331 check_allmem( const char *info )
smg_comms_c_wrappers 332 {
smg_comms_c_wrappers 333 unsigned n;
smg_comms_c_wrappers 334 struct memtbl_entry *e;
smg_comms_c_wrappers 335
smg_comms_c_wrappers 336 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
smg_comms_c_wrappers 337 if( e->inuse ) {
smg_comms_c_wrappers 338 check_mem(e->user_p-4-EXTRA_ALIGN, info);
smg_comms_c_wrappers 339 }
smg_comms_c_wrappers 340 }
smg_comms_c_wrappers 341 }
smg_comms_c_wrappers 342
smg_comms_c_wrappers 343 #endif /* M_DEBUG */
smg_comms_c_wrappers 344
smg_comms_c_wrappers 345 #if defined(M_DEBUG) || defined(M_GUARD)
smg_comms_c_wrappers 346 static void
smg_comms_c_wrappers 347 membug( const char *fmt, ... )
smg_comms_c_wrappers 348 {
smg_comms_c_wrappers 349 va_list arg_ptr ;
smg_comms_c_wrappers 350
smg_comms_c_wrappers 351 fprintf(stderr, "\nMemory Error: " ) ;
smg_comms_c_wrappers 352 va_start( arg_ptr, fmt ) ;
smg_comms_c_wrappers 353 vfprintf(stderr,fmt,arg_ptr) ;
smg_comms_c_wrappers 354 va_end(arg_ptr);
smg_comms_c_wrappers 355 fflush(stderr);
smg_comms_c_wrappers 356 #ifdef M_DEBUG
smg_comms_c_wrappers 357 if( DBG_MEMSTAT )
smg_comms_c_wrappers 358 dump_table();
smg_comms_c_wrappers 359 #endif
smg_comms_c_wrappers 360 abort();
smg_comms_c_wrappers 361 }
smg_comms_c_wrappers 362 #endif
smg_comms_c_wrappers 363
smg_comms_c_wrappers 364 void
smg_comms_c_wrappers 365 m_print_stats( const char *prefix )
smg_comms_c_wrappers 366 {
smg_comms_c_wrappers 367 #ifdef M_DEBUG
smg_comms_c_wrappers 368 unsigned n;
smg_comms_c_wrappers 369 struct memtbl_entry *e;
smg_comms_c_wrappers 370 ulong sum = 0, chunks =0;
smg_comms_c_wrappers 371
smg_comms_c_wrappers 372 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
smg_comms_c_wrappers 373 if(e->inuse) {
smg_comms_c_wrappers 374 sum += e->user_n;
smg_comms_c_wrappers 375 chunks++;
smg_comms_c_wrappers 376 }
smg_comms_c_wrappers 377 }
smg_comms_c_wrappers 378
smg_comms_c_wrappers 379 log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n",
smg_comms_c_wrappers 380 prefix? prefix:"", prefix? ": ":"", sum, chunks );
smg_comms_c_wrappers 381 #elif defined(M_GUARD)
smg_comms_c_wrappers 382 log_debug( "%s%smemstat: %8ld bytes\n",
smg_comms_c_wrappers 383 prefix? prefix:"", prefix? ": ":"", used_memory );
smg_comms_c_wrappers 384 #endif
smg_comms_c_wrappers 385 }
smg_comms_c_wrappers 386
smg_comms_c_wrappers 387 void
smg_comms_c_wrappers 388 m_dump_table( const char *prefix )
smg_comms_c_wrappers 389 {
smg_comms_c_wrappers 390 #ifdef M_DEBUG
smg_comms_c_wrappers 391 fprintf(stderr,"Memory-Table-Dump: %s\n", prefix);
smg_comms_c_wrappers 392 dump_table();
smg_comms_c_wrappers 393 #endif
smg_comms_c_wrappers 394 m_print_stats( prefix );
smg_comms_c_wrappers 395 }
smg_comms_c_wrappers 396
smg_comms_c_wrappers 397
smg_comms_c_wrappers 398 static void
smg_comms_c_wrappers 399 out_of_core(size_t n, int secure)
smg_comms_c_wrappers 400 {
smg_comms_c_wrappers 401 log_error ("out of %s memory while allocating %u bytes\n",
smg_comms_c_wrappers 402 secure? "secure":"" ,(unsigned)n );
smg_comms_c_wrappers 403 if (secure) {
smg_comms_c_wrappers 404 /*secmem_dump_stats ();*/
smg_comms_c_wrappers 405 log_info ("(this may be caused by too many secret keys used "
smg_comms_c_wrappers 406 "simultaneously or due to excessive large key sizes)\n");
smg_comms_c_wrappers 407 }
smg_comms_c_wrappers 408 exit(2);
smg_comms_c_wrappers 409 }
smg_comms_c_wrappers 410
smg_comms_c_wrappers 411 /****************
smg_comms_c_wrappers 412 * Allocate memory of size n.
smg_comms_c_wrappers 413 * This function gives up if we do not have enough memory
smg_comms_c_wrappers 414 */
smg_comms_c_wrappers 415 void *
smg_comms_c_wrappers 416 FNAMEXM(alloc)( size_t n FNAMEPRT )
smg_comms_c_wrappers 417 {
smg_comms_c_wrappers 418 char *p;
smg_comms_c_wrappers 419
smg_comms_c_wrappers 420 #ifdef M_GUARD
smg_comms_c_wrappers 421 if(!n)
smg_comms_c_wrappers 422 out_of_core(n,0); /* should never happen */
smg_comms_c_wrappers 423 if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
smg_comms_c_wrappers 424 out_of_core(n,0);
smg_comms_c_wrappers 425 store_len(p,n,0);
smg_comms_c_wrappers 426 used_memory += n;
smg_comms_c_wrappers 427 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
smg_comms_c_wrappers 428 return p+EXTRA_ALIGN+4;
smg_comms_c_wrappers 429 #else
smg_comms_c_wrappers 430 /* mallocing zero bytes is undefined by ISO-C, so we better make
smg_comms_c_wrappers 431 sure that it won't happen */
smg_comms_c_wrappers 432 if (!n)
smg_comms_c_wrappers 433 n = 1;
smg_comms_c_wrappers 434 if( !(p = malloc( n )) )
smg_comms_c_wrappers 435 out_of_core(n,0);
smg_comms_c_wrappers 436 return p;
smg_comms_c_wrappers 437 #endif
smg_comms_c_wrappers 438 }
smg_comms_c_wrappers 439
smg_comms_c_wrappers 440 /* Allocate memory of size n. This function returns NULL if we do not
smg_comms_c_wrappers 441 have enough memory. */
smg_comms_c_wrappers 442 void *
smg_comms_c_wrappers 443 FNAMEX(trymalloc)(size_t n FNAMEPRT)
smg_comms_c_wrappers 444 {
smg_comms_c_wrappers 445 #ifdef M_GUARD
smg_comms_c_wrappers 446 char *p;
smg_comms_c_wrappers 447
smg_comms_c_wrappers 448 if (!n)
smg_comms_c_wrappers 449 n = 1;
smg_comms_c_wrappers 450 p = malloc (n + EXTRA_ALIGN+5);
smg_comms_c_wrappers 451 if (!p)
smg_comms_c_wrappers 452 return NULL;
smg_comms_c_wrappers 453 store_len(p,n,0);
smg_comms_c_wrappers 454 used_memory += n;
smg_comms_c_wrappers 455 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
smg_comms_c_wrappers 456 return p+EXTRA_ALIGN+4;
smg_comms_c_wrappers 457 #else
smg_comms_c_wrappers 458 /* Mallocing zero bytes is undefined by ISO-C, so we better make
smg_comms_c_wrappers 459 sure that it won't happen. */
smg_comms_c_wrappers 460 return malloc (n? n: 1);
smg_comms_c_wrappers 461 #endif
smg_comms_c_wrappers 462 }
smg_comms_c_wrappers 463
smg_comms_c_wrappers 464 /****************
smg_comms_c_wrappers 465 * Allocate memory of size n from the secure memory pool.
smg_comms_c_wrappers 466 * This function gives up if we do not have enough memory
smg_comms_c_wrappers 467 */
smg_comms_c_wrappers 468 void *
smg_comms_c_wrappers 469 FNAMEXM(alloc_secure)( size_t n FNAMEPRT )
smg_comms_c_wrappers 470 {
smg_comms_c_wrappers 471 char *p;
smg_comms_c_wrappers 472
smg_comms_c_wrappers 473 #ifdef M_GUARD
smg_comms_c_wrappers 474 if(!n)
smg_comms_c_wrappers 475 out_of_core(n,1); /* should never happen */
smg_comms_c_wrappers 476 if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
smg_comms_c_wrappers 477 out_of_core(n,1);
smg_comms_c_wrappers 478 store_len(p,n,1);
smg_comms_c_wrappers 479 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
smg_comms_c_wrappers 480 return p+EXTRA_ALIGN+4;
smg_comms_c_wrappers 481 #else
smg_comms_c_wrappers 482 /* mallocing zero bytes is undefined by ISO-C, so we better make
smg_comms_c_wrappers 483 sure that it won't happen */
smg_comms_c_wrappers 484 if (!n)
smg_comms_c_wrappers 485 n = 1;
smg_comms_c_wrappers 486 if( !(p = secmem_malloc( n )) )
smg_comms_c_wrappers 487 out_of_core(n,1);
smg_comms_c_wrappers 488 return p;
smg_comms_c_wrappers 489 #endif
smg_comms_c_wrappers 490 }
smg_comms_c_wrappers 491
smg_comms_c_wrappers 492 void *
smg_comms_c_wrappers 493 FNAMEXM(alloc_clear)( size_t n FNAMEPRT )
smg_comms_c_wrappers 494 {
smg_comms_c_wrappers 495 void *p;
smg_comms_c_wrappers 496 p = FNAMEXM(alloc)( n FNAMEARG );
smg_comms_c_wrappers 497 memset(p, 0, n );
smg_comms_c_wrappers 498 return p;
smg_comms_c_wrappers 499 }
smg_comms_c_wrappers 500
smg_comms_c_wrappers 501 void *
smg_comms_c_wrappers 502 FNAMEXM(alloc_secure_clear)( size_t n FNAMEPRT)
smg_comms_c_wrappers 503 {
smg_comms_c_wrappers 504 void *p;
smg_comms_c_wrappers 505 p = FNAMEXM(alloc_secure)( n FNAMEARG );
smg_comms_c_wrappers 506 memset(p, 0, n );
smg_comms_c_wrappers 507 return p;
smg_comms_c_wrappers 508 }
smg_comms_c_wrappers 509
smg_comms_c_wrappers 510
smg_comms_c_wrappers 511 /****************
smg_comms_c_wrappers 512 * realloc and clear the old space
smg_comms_c_wrappers 513 */
smg_comms_c_wrappers 514 void *
smg_comms_c_wrappers 515 FNAMEX(realloc)( void *a, size_t n FNAMEPRT )
smg_comms_c_wrappers 516 {
smg_comms_c_wrappers 517 void *b;
smg_comms_c_wrappers 518
smg_comms_c_wrappers 519 #ifdef M_GUARD
smg_comms_c_wrappers 520 if( a ) {
smg_comms_c_wrappers 521 #error "--enable-m-guard does not currently work"
smg_comms_c_wrappers 522 unsigned char *p = a;
smg_comms_c_wrappers 523 size_t len = m_size(a);
smg_comms_c_wrappers 524
smg_comms_c_wrappers 525 if( len >= n ) /* we don't shrink for now */
smg_comms_c_wrappers 526 return a;
smg_comms_c_wrappers 527 if( p[-1] == MAGIC_SEC_BYTE )
smg_comms_c_wrappers 528 b = FNAME(alloc_secure_clear)(n FNAMEARG);
smg_comms_c_wrappers 529 else
smg_comms_c_wrappers 530 b = FNAME(alloc_clear)(n FNAMEARG);
smg_comms_c_wrappers 531 FNAME(check)(NULL FNAMEARG);
smg_comms_c_wrappers 532 memcpy(b, a, len );
smg_comms_c_wrappers 533 FNAME(free)(p FNAMEARG);
smg_comms_c_wrappers 534 }
smg_comms_c_wrappers 535 else
smg_comms_c_wrappers 536 b = FNAME(alloc)(n FNAMEARG);
smg_comms_c_wrappers 537 #else
smg_comms_c_wrappers 538 if( m_is_secure(a) ) {
smg_comms_c_wrappers 539 if( !(b = secmexrealloc( a, n )) )
smg_comms_c_wrappers 540 out_of_core(n,1);
smg_comms_c_wrappers 541 }
smg_comms_c_wrappers 542 else {
smg_comms_c_wrappers 543 if( !(b = realloc( a, n )) )
smg_comms_c_wrappers 544 out_of_core(n,0);
smg_comms_c_wrappers 545 }
smg_comms_c_wrappers 546 #endif
smg_comms_c_wrappers 547
smg_comms_c_wrappers 548 return b;
smg_comms_c_wrappers 549 }
smg_comms_c_wrappers 550
smg_comms_c_wrappers 551
smg_comms_c_wrappers 552
smg_comms_c_wrappers 553 /****************
smg_comms_c_wrappers 554 * Free a pointer
smg_comms_c_wrappers 555 */
smg_comms_c_wrappers 556 void
smg_comms_c_wrappers 557 FNAMEX(free)( void *a FNAMEPRT )
smg_comms_c_wrappers 558 {
smg_comms_c_wrappers 559 byte *p = a;
smg_comms_c_wrappers 560
smg_comms_c_wrappers 561 if( !p )
smg_comms_c_wrappers 562 return;
smg_comms_c_wrappers 563 #ifdef M_DEBUG
smg_comms_c_wrappers 564 free_entry(p-EXTRA_ALIGN-4, info);
smg_comms_c_wrappers 565 #elif defined M_GUARD
smg_comms_c_wrappers 566 m_check(p);
smg_comms_c_wrappers 567 if( m_is_secure(a) )
smg_comms_c_wrappers 568 secmem_free(p-EXTRA_ALIGN-4);
smg_comms_c_wrappers 569 else {
smg_comms_c_wrappers 570 used_memory -= m_size(a);
smg_comms_c_wrappers 571 free(p-EXTRA_ALIGN-4);
smg_comms_c_wrappers 572 }
smg_comms_c_wrappers 573 #else
smg_comms_c_wrappers 574 if( m_is_secure(a) )
smg_comms_c_wrappers 575 secmem_free(p);
smg_comms_c_wrappers 576 else
smg_comms_c_wrappers 577 free(p);
smg_comms_c_wrappers 578 #endif
smg_comms_c_wrappers 579 }
smg_comms_c_wrappers 580
smg_comms_c_wrappers 581
smg_comms_c_wrappers 582 void
smg_comms_c_wrappers 583 FNAME(check)( const void *a FNAMEPRT )
smg_comms_c_wrappers 584 {
smg_comms_c_wrappers 585 #ifdef M_GUARD
smg_comms_c_wrappers 586 const byte *p = a;
smg_comms_c_wrappers 587
smg_comms_c_wrappers 588 #ifdef M_DEBUG
smg_comms_c_wrappers 589 if( p )
smg_comms_c_wrappers 590 check_mem(p-EXTRA_ALIGN-4, info);
smg_comms_c_wrappers 591 else
smg_comms_c_wrappers 592 check_allmem(info);
smg_comms_c_wrappers 593 #else
smg_comms_c_wrappers 594 if( !p )
smg_comms_c_wrappers 595 return;
smg_comms_c_wrappers 596 if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
smg_comms_c_wrappers 597 membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
smg_comms_c_wrappers 598 else if( p[m_size(p)] != MAGIC_END_BYTE )
smg_comms_c_wrappers 599 membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
smg_comms_c_wrappers 600 #endif
smg_comms_c_wrappers 601 #endif
smg_comms_c_wrappers 602 }
smg_comms_c_wrappers 603
smg_comms_c_wrappers 604
smg_comms_c_wrappers 605 size_t
smg_comms_c_wrappers 606 m_size( const void *a )
smg_comms_c_wrappers 607 {
smg_comms_c_wrappers 608 #ifndef M_GUARD
smg_comms_c_wrappers 609 log_debug("dummy m_size called\n");
smg_comms_c_wrappers 610 return 0;
smg_comms_c_wrappers 611 #else
smg_comms_c_wrappers 612 const byte *p = a;
smg_comms_c_wrappers 613 size_t n;
smg_comms_c_wrappers 614
smg_comms_c_wrappers 615 #ifdef M_DEBUG
smg_comms_c_wrappers 616 n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n;
smg_comms_c_wrappers 617 #else
smg_comms_c_wrappers 618 n = ((byte*)p)[-4];
smg_comms_c_wrappers 619 n |= ((byte*)p)[-3] << 8;
smg_comms_c_wrappers 620 n |= ((byte*)p)[-2] << 16;
smg_comms_c_wrappers 621 #endif
smg_comms_c_wrappers 622 return n;
smg_comms_c_wrappers 623 #endif
smg_comms_c_wrappers 624 }
smg_comms_c_wrappers 625
smg_comms_c_wrappers 626
smg_comms_c_wrappers 627 char *
smg_comms_c_wrappers 628 FNAMEX(strdup)( const char *a FNAMEPRT )
smg_comms_c_wrappers 629 {
smg_comms_c_wrappers 630 size_t n = strlen(a);
smg_comms_c_wrappers 631 char *p = FNAMEXM(alloc)(n+1 FNAMEARG);
smg_comms_c_wrappers 632 strcpy(p, a);
smg_comms_c_wrappers 633 return p;
smg_comms_c_wrappers 634 }
smg_comms_c_wrappers 635
smg_comms_c_wrappers 636 char *
smg_comms_c_wrappers 637 FNAMEX(trystrdup)(const char *a FNAMEPRT)
smg_comms_c_wrappers 638 {
smg_comms_c_wrappers 639 size_t n = strlen (a);
smg_comms_c_wrappers 640 char *p = FNAMEX(trymalloc)(n+1 FNAMEARG);
smg_comms_c_wrappers 641 if (p)
smg_comms_c_wrappers 642 strcpy (p, a);
smg_comms_c_wrappers 643 return p;
smg_comms_c_wrappers 644 }
smg_comms_c_wrappers 645
smg_comms_c_wrappers 646
smg_comms_c_wrappers 647 /* Wrapper around xmalloc_clear to take the usual 2 arguments of a
smg_comms_c_wrappers 648 calloc style function. */
smg_comms_c_wrappers 649 void *
smg_comms_c_wrappers 650 xcalloc (size_t n, size_t m)
smg_comms_c_wrappers 651 {
smg_comms_c_wrappers 652 size_t nbytes;
smg_comms_c_wrappers 653
smg_comms_c_wrappers 654 nbytes = n * m;
smg_comms_c_wrappers 655 if (m && nbytes / m != n)
smg_comms_c_wrappers 656 out_of_core (nbytes, 0);
smg_comms_c_wrappers 657 return xmalloc_clear (nbytes);
smg_comms_c_wrappers 658 }
smg_comms_c_wrappers 659
smg_comms_c_wrappers 660 /* Wrapper around xmalloc_csecure_lear to take the usual 2 arguments
smg_comms_c_wrappers 661 of a calloc style function. */
smg_comms_c_wrappers 662 void *
smg_comms_c_wrappers 663 xcalloc_secure (size_t n, size_t m)
smg_comms_c_wrappers 664 {
smg_comms_c_wrappers 665 size_t nbytes;
smg_comms_c_wrappers 666
smg_comms_c_wrappers 667 nbytes = n * m;
smg_comms_c_wrappers 668 if (m && nbytes / m != n)
smg_comms_c_wrappers 669 out_of_core (nbytes, 1);
smg_comms_c_wrappers 670 return xmalloc_secure_clear (nbytes);
smg_comms_c_wrappers 671 }