-
+ 739F6960D138E5AB2EB53F41872BEF6DE1A66EE43161B6B8A69D12849F13332E48DB2392566A8736D6B2BF7272DFC01AA2BFE927D917F152BE75AE821DE1AFD6
eucrypt/mpi/memory.c
(0 . 0)(1 . 671)
2028 /* memory.c - memory allocation
2029 * Modified by No Such Labs. (C) 2015. See README.
2030 *
2031 * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
2032 * SHA256(gnupg-1.4.10.tar.gz):
2033 * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
2034 * (C) 1994-2005 Free Software Foundation, Inc.
2035 *
2036 * This program is free software: you can redistribute it and/or modify
2037 * it under the terms of the GNU General Public License as published by
2038 * the Free Software Foundation, either version 3 of the License, or
2039 * (at your option) any later version.
2040 *
2041 * This program is distributed in the hope that it will be useful,
2042 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2043 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2044 * GNU General Public License for more details.
2045 *
2046 * You should have received a copy of the GNU General Public License
2047 * along with this program. If not, see <http://www.gnu.org/licenses/>.
2048 */
2049
2050 /* We use our own memory allocation functions instead of plain malloc(),
2051 * so that we can provide some special enhancements:
2052 * a) functions to provide memory from a secure memory.
2053 * b) by looking at the requested allocation size we
2054 * can reuse memory very quickly (e.g. MPI storage)
2055 * (really needed?)
2056 * c) memory usage reporting if compiled with M_DEBUG
2057 * d) memory checking if compiled with M_GUARD
2058 */
2059
2060 #include <stdio.h>
2061 #include <stdlib.h>
2062 #include <stdarg.h>
2063 #include <string.h>
2064
2065 #include "knobs.h"
2066 #include "types.h"
2067 #include "memory.h"
2068 #include "util.h"
2069
2070 #define MAGIC_NOR_BYTE 0x55
2071 #define MAGIC_SEC_BYTE 0xcc
2072 #define MAGIC_END_BYTE 0xaa
2073
2074 /* This is a very crude alignment check which does not work on all CPUs
2075 * IIRC, I once introduced it for testing on an Alpha. We should better
2076 * replace this guard stuff with one provided by a modern malloc library
2077 */
2078 #if SIZEOF_UNSIGNED_LONG == 8
2079 #define EXTRA_ALIGN 4
2080 #else
2081 #define EXTRA_ALIGN 0
2082 #endif
2083
2084 #if defined(M_DEBUG) || defined(M_GUARD)
2085 static void membug( const char *fmt, ... );
2086 #endif
2087
2088 #ifdef M_DEBUG
2089
2090 #ifndef M_GUARD
2091 #define M_GUARD 1
2092 #endif
2093 #undef xmalloc
2094 #undef xtrymalloc
2095 #undef xmalloc_clear
2096 #undef xmalloc_secure
2097 #undef xmalloc_secure_clear
2098 #undef xrealloc
2099 #undef xfree
2100 #undef m_check
2101 #undef xstrdup
2102 #undef xtrystrdup
2103 #define FNAME(a) m_debug_ ##a
2104 #define FNAMEX(a) m_debug_ ##a
2105 #define FNAMEXM(a) m_debug_ ##a
2106 #define FNAMEPRT , const char *info
2107 #define FNAMEARG , info
2108
2109 #define store_len(p,n,m) do { add_entry(p,n,m, \
2110 info, __FUNCTION__); } while(0)
2111 #else
2112 #define FNAME(a) m_ ##a
2113 #define FNAMEX(a) x ##a
2114 #define FNAMEXM(a) xm ##a
2115 #define FNAMEPRT
2116 #define FNAMEARG
2117 #define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \
2118 ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \
2119 ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \
2120 ((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \
2121 : MAGIC_NOR_BYTE; \
2122 } while(0)
2123 #endif
2124
2125
2126 #ifdef M_GUARD
2127 static long used_memory;
2128 #endif
2129
2130 #ifdef M_DEBUG /* stuff used for memory debuging */
2131
2132 struct info_entry {
2133 struct info_entry *next;
2134 unsigned count; /* call count */
2135 const char *info; /* the reference to the info string */
2136 };
2137
2138 struct memtbl_entry {
2139 const void *user_p; /* for reference: the pointer given to the user */
2140 size_t user_n; /* length requested by the user */
2141 struct memtbl_entry *next; /* to build a list of unused entries */
2142 const struct info_entry *info; /* points into the table with */
2143 /* the info strings */
2144 unsigned inuse:1; /* this entry is in use */
2145 unsigned count:31;
2146 };
2147
2148
2149 #define INFO_BUCKETS 53
2150 #define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS )
2151 static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */
2152
2153 static struct memtbl_entry *memtbl; /* the table with the memory info */
2154 static unsigned memtbl_size; /* number of allocated entries */
2155 static unsigned memtbl_len; /* number of used entries */
2156 static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */
2157
2158 static void dump_table_at_exit(void);
2159 static void dump_table(void);
2160 static void check_allmem( const char *info );
2161
2162 /****************
2163 * Put the new P into the debug table and return a pointer to the table entry.
2164 * mode is true for security. BY is the name of the function which called us.
2165 */
2166 static void
2167 add_entry( byte *p, unsigned n, int mode, const char *info, const char *by )
2168 {
2169 unsigned index;
2170 struct memtbl_entry *e;
2171 struct info_entry *ie;
2172
2173 if( memtbl_len < memtbl_size )
2174 index = memtbl_len++;
2175 else {
2176 struct memtbl_entry *e;
2177 /* look for a used entry in the table. We take the first one,
2178 * so that freed entries remain as long as possible in the table
2179 * (free appends a new one)
2180 */
2181 if( (e = memtbl_unused) ) {
2182 index = e - memtbl;
2183 memtbl_unused = e->next;
2184 e->next = NULL;
2185 }
2186 else { /* no free entries in the table: extend the table */
2187 if( !memtbl_size ) { /* first time */
2188 memtbl_size = 100;
2189 if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) )
2190 membug("memory debug table malloc failed\n");
2191 index = 0;
2192 memtbl_len = 1;
2193 atexit( dump_table_at_exit );
2194 }
2195 else { /* realloc */
2196 unsigned n = memtbl_size / 4; /* enlarge by 25% */
2197 if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl)))
2198 membug("memory debug table realloc failed\n");
2199 memset(memtbl+memtbl_size, 0, n*sizeof *memtbl );
2200 memtbl_size += n;
2201 index = memtbl_len++;
2202 }
2203 }
2204 }
2205 e = memtbl+index;
2206 if( e->inuse )
2207 membug("Ooops: entry %u is flagged as in use\n", index);
2208 e->user_p = p + EXTRA_ALIGN + 4;
2209 e->user_n = n;
2210 e->count++;
2211 if( e->next )
2212 membug("Ooops: entry is in free entry list\n");
2213 /* do we already have this info string */
2214 for( ie = info_strings[info_hash(info)]; ie; ie = ie->next )
2215 if( ie->info == info )
2216 break;
2217 if( !ie ) { /* no: make a new entry */
2218 if( !(ie = malloc( sizeof *ie )) )
2219 membug("can't allocate info entry\n");
2220 ie->next = info_strings[info_hash(info)];
2221 info_strings[info_hash(info)] = ie;
2222 ie->info = info;
2223 ie->count = 0;
2224 }
2225 ie->count++;
2226 e->info = ie;
2227 e->inuse = 1;
2228
2229 /* put the index at the start of the memory */
2230 p[EXTRA_ALIGN+0] = index;
2231 p[EXTRA_ALIGN+1] = index >> 8 ;
2232 p[EXTRA_ALIGN+2] = index >> 16 ;
2233 p[EXTRA_ALIGN+3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ;
2234 if( DBG_MEMORY )
2235 log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by );
2236 }
2237
2238
2239
2240 /****************
2241 * Check that the memory block is correct. The magic byte has already been
2242 * checked. Checks which are done here:
2243 * - see whether the index points into our memory table
2244 * - see whether P is the same as the one stored in the table
2245 * - see whether we have already freed this block.
2246 */
2247 struct memtbl_entry *
2248 check_mem( const byte *p, const char *info )
2249 {
2250 unsigned n;
2251 struct memtbl_entry *e;
2252
2253 n = p[EXTRA_ALIGN+0];
2254 n |= p[EXTRA_ALIGN+1] << 8;
2255 n |= p[EXTRA_ALIGN+2] << 16;
2256
2257 if( n >= memtbl_len )
2258 membug("memory at %p corrupted: index=%u table_len=%u (%s)\n",
2259 p+EXTRA_ALIGN+4, n, memtbl_len, info );
2260 e = memtbl+n;
2261
2262 if( e->user_p != p+EXTRA_ALIGN+4 )
2263 membug("memory at %p corrupted: reference mismatch (%s)\n",
2264 p+EXTRA_ALIGN+4, info );
2265 if( !e->inuse )
2266 membug("memory at %p corrupted: marked as free (%s)\n",
2267 p+EXTRA_ALIGN+4, info );
2268
2269 if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE
2270 || p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) )
2271 membug("memory at %p corrupted: underflow=%02x (%s)\n",
2272 p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info );
2273 if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE )
2274 membug("memory at %p corrupted: overflow=%02x (%s)\n",
2275 p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info );
2276 return e;
2277 }
2278
2279
2280 /****************
2281 * free the entry and the memory (replaces free)
2282 */
2283 static void
2284 free_entry( byte *p, const char *info )
2285 {
2286 struct memtbl_entry *e, *e2;
2287
2288 check_allmem("add_entry");
2289
2290 e = check_mem(p, info);
2291 if( DBG_MEMORY )
2292 log_debug( "%s frees %u bytes alloced by %s\n",
2293 info, e->user_n, e->info->info );
2294 if( !e->inuse ) {
2295 if( e->user_p == p + EXTRA_ALIGN+ 4 )
2296 membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 );
2297 else
2298 membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 );
2299 }
2300
2301 e->inuse = 0;
2302 e->next = NULL;
2303 if( !memtbl_unused )
2304 memtbl_unused = e;
2305 else {
2306 for(e2=memtbl_unused; e2->next; e2 = e2->next )
2307 ;
2308 e2->next = e;
2309 }
2310 if( m_is_secure(p+EXTRA_ALIGN+4) )
2311 secmem_free(p);
2312 else {
2313 memset(p,'f', e->user_n+5);
2314 free(p);
2315 }
2316 }
2317
2318 static void
2319 dump_entry(struct memtbl_entry *e )
2320 {
2321 unsigned n = e - memtbl;
2322
2323 fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n",
2324 n, e->inuse?'a':'u', e->count, e->user_p, e->user_n,
2325 e->info->info, e->info->count );
2326
2327
2328 }
2329
2330
2331 static void
2332 dump_table_at_exit( void)
2333 {
2334 if( DBG_MEMSTAT )
2335 dump_table();
2336 }
2337
2338 static void
2339 dump_table( void)
2340 {
2341 unsigned n;
2342 struct memtbl_entry *e;
2343 ulong sum = 0, chunks =0;
2344
2345 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
2346 if(e->inuse) {
2347 dump_entry(e);
2348 sum += e->user_n;
2349 chunks++;
2350 }
2351 }
2352 fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n",
2353 sum, chunks );
2354 }
2355
2356
2357 static void
2358 check_allmem( const char *info )
2359 {
2360 unsigned n;
2361 struct memtbl_entry *e;
2362
2363 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
2364 if( e->inuse ) {
2365 check_mem(e->user_p-4-EXTRA_ALIGN, info);
2366 }
2367 }
2368 }
2369
2370 #endif /* M_DEBUG */
2371
2372 #if defined(M_DEBUG) || defined(M_GUARD)
2373 static void
2374 membug( const char *fmt, ... )
2375 {
2376 va_list arg_ptr ;
2377
2378 fprintf(stderr, "\nMemory Error: " ) ;
2379 va_start( arg_ptr, fmt ) ;
2380 vfprintf(stderr,fmt,arg_ptr) ;
2381 va_end(arg_ptr);
2382 fflush(stderr);
2383 #ifdef M_DEBUG
2384 if( DBG_MEMSTAT )
2385 dump_table();
2386 #endif
2387 abort();
2388 }
2389 #endif
2390
2391 void
2392 m_print_stats( const char *prefix )
2393 {
2394 #ifdef M_DEBUG
2395 unsigned n;
2396 struct memtbl_entry *e;
2397 ulong sum = 0, chunks =0;
2398
2399 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
2400 if(e->inuse) {
2401 sum += e->user_n;
2402 chunks++;
2403 }
2404 }
2405
2406 log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n",
2407 prefix? prefix:"", prefix? ": ":"", sum, chunks );
2408 #elif defined(M_GUARD)
2409 log_debug( "%s%smemstat: %8ld bytes\n",
2410 prefix? prefix:"", prefix? ": ":"", used_memory );
2411 #endif
2412 }
2413
2414 void
2415 m_dump_table( const char *prefix )
2416 {
2417 #ifdef M_DEBUG
2418 fprintf(stderr,"Memory-Table-Dump: %s\n", prefix);
2419 dump_table();
2420 #endif
2421 m_print_stats( prefix );
2422 }
2423
2424
2425 static void
2426 out_of_core(size_t n, int secure)
2427 {
2428 log_error ("out of %s memory while allocating %u bytes\n",
2429 secure? "secure":"" ,(unsigned)n );
2430 if (secure) {
2431 /*secmem_dump_stats ();*/
2432 log_info ("(this may be caused by too many secret keys used "
2433 "simultaneously or due to excessive large key sizes)\n");
2434 }
2435 exit(2);
2436 }
2437
2438 /****************
2439 * Allocate memory of size n.
2440 * This function gives up if we do not have enough memory
2441 */
2442 void *
2443 FNAMEXM(alloc)( size_t n FNAMEPRT )
2444 {
2445 char *p;
2446
2447 #ifdef M_GUARD
2448 if(!n)
2449 out_of_core(n,0); /* should never happen */
2450 if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
2451 out_of_core(n,0);
2452 store_len(p,n,0);
2453 used_memory += n;
2454 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
2455 return p+EXTRA_ALIGN+4;
2456 #else
2457 /* mallocing zero bytes is undefined by ISO-C, so we better make
2458 sure that it won't happen */
2459 if (!n)
2460 n = 1;
2461 if( !(p = malloc( n )) )
2462 out_of_core(n,0);
2463 return p;
2464 #endif
2465 }
2466
2467 /* Allocate memory of size n. This function returns NULL if we do not
2468 have enough memory. */
2469 void *
2470 FNAMEX(trymalloc)(size_t n FNAMEPRT)
2471 {
2472 #ifdef M_GUARD
2473 char *p;
2474
2475 if (!n)
2476 n = 1;
2477 p = malloc (n + EXTRA_ALIGN+5);
2478 if (!p)
2479 return NULL;
2480 store_len(p,n,0);
2481 used_memory += n;
2482 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
2483 return p+EXTRA_ALIGN+4;
2484 #else
2485 /* Mallocing zero bytes is undefined by ISO-C, so we better make
2486 sure that it won't happen. */
2487 return malloc (n? n: 1);
2488 #endif
2489 }
2490
2491 /****************
2492 * Allocate memory of size n from the secure memory pool.
2493 * This function gives up if we do not have enough memory
2494 */
2495 void *
2496 FNAMEXM(alloc_secure)( size_t n FNAMEPRT )
2497 {
2498 char *p;
2499
2500 #ifdef M_GUARD
2501 if(!n)
2502 out_of_core(n,1); /* should never happen */
2503 if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
2504 out_of_core(n,1);
2505 store_len(p,n,1);
2506 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
2507 return p+EXTRA_ALIGN+4;
2508 #else
2509 /* mallocing zero bytes is undefined by ISO-C, so we better make
2510 sure that it won't happen */
2511 if (!n)
2512 n = 1;
2513 if( !(p = secmem_malloc( n )) )
2514 out_of_core(n,1);
2515 return p;
2516 #endif
2517 }
2518
2519 void *
2520 FNAMEXM(alloc_clear)( size_t n FNAMEPRT )
2521 {
2522 void *p;
2523 p = FNAMEXM(alloc)( n FNAMEARG );
2524 memset(p, 0, n );
2525 return p;
2526 }
2527
2528 void *
2529 FNAMEXM(alloc_secure_clear)( size_t n FNAMEPRT)
2530 {
2531 void *p;
2532 p = FNAMEXM(alloc_secure)( n FNAMEARG );
2533 memset(p, 0, n );
2534 return p;
2535 }
2536
2537
2538 /****************
2539 * realloc and clear the old space
2540 */
2541 void *
2542 FNAMEX(realloc)( void *a, size_t n FNAMEPRT )
2543 {
2544 void *b;
2545
2546 #ifdef M_GUARD
2547 if( a ) {
2548 #error "--enable-m-guard does not currently work"
2549 unsigned char *p = a;
2550 size_t len = m_size(a);
2551
2552 if( len >= n ) /* we don't shrink for now */
2553 return a;
2554 if( p[-1] == MAGIC_SEC_BYTE )
2555 b = FNAME(alloc_secure_clear)(n FNAMEARG);
2556 else
2557 b = FNAME(alloc_clear)(n FNAMEARG);
2558 FNAME(check)(NULL FNAMEARG);
2559 memcpy(b, a, len );
2560 FNAME(free)(p FNAMEARG);
2561 }
2562 else
2563 b = FNAME(alloc)(n FNAMEARG);
2564 #else
2565 if( m_is_secure(a) ) {
2566 if( !(b = secmexrealloc( a, n )) )
2567 out_of_core(n,1);
2568 }
2569 else {
2570 if( !(b = realloc( a, n )) )
2571 out_of_core(n,0);
2572 }
2573 #endif
2574
2575 return b;
2576 }
2577
2578
2579
2580 /****************
2581 * Free a pointer
2582 */
2583 void
2584 FNAMEX(free)( void *a FNAMEPRT )
2585 {
2586 byte *p = a;
2587
2588 if( !p )
2589 return;
2590 #ifdef M_DEBUG
2591 free_entry(p-EXTRA_ALIGN-4, info);
2592 #elif defined M_GUARD
2593 m_check(p);
2594 if( m_is_secure(a) )
2595 secmem_free(p-EXTRA_ALIGN-4);
2596 else {
2597 used_memory -= m_size(a);
2598 free(p-EXTRA_ALIGN-4);
2599 }
2600 #else
2601 if( m_is_secure(a) )
2602 secmem_free(p);
2603 else
2604 free(p);
2605 #endif
2606 }
2607
2608
2609 void
2610 FNAME(check)( const void *a FNAMEPRT )
2611 {
2612 #ifdef M_GUARD
2613 const byte *p = a;
2614
2615 #ifdef M_DEBUG
2616 if( p )
2617 check_mem(p-EXTRA_ALIGN-4, info);
2618 else
2619 check_allmem(info);
2620 #else
2621 if( !p )
2622 return;
2623 if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
2624 membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
2625 else if( p[m_size(p)] != MAGIC_END_BYTE )
2626 membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
2627 #endif
2628 #endif
2629 }
2630
2631
2632 size_t
2633 m_size( const void *a )
2634 {
2635 #ifndef M_GUARD
2636 log_debug("dummy m_size called\n");
2637 return 0;
2638 #else
2639 const byte *p = a;
2640 size_t n;
2641
2642 #ifdef M_DEBUG
2643 n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n;
2644 #else
2645 n = ((byte*)p)[-4];
2646 n |= ((byte*)p)[-3] << 8;
2647 n |= ((byte*)p)[-2] << 16;
2648 #endif
2649 return n;
2650 #endif
2651 }
2652
2653
2654 char *
2655 FNAMEX(strdup)( const char *a FNAMEPRT )
2656 {
2657 size_t n = strlen(a);
2658 char *p = FNAMEXM(alloc)(n+1 FNAMEARG);
2659 strcpy(p, a);
2660 return p;
2661 }
2662
2663 char *
2664 FNAMEX(trystrdup)(const char *a FNAMEPRT)
2665 {
2666 size_t n = strlen (a);
2667 char *p = FNAMEX(trymalloc)(n+1 FNAMEARG);
2668 if (p)
2669 strcpy (p, a);
2670 return p;
2671 }
2672
2673
2674 /* Wrapper around xmalloc_clear to take the usual 2 arguments of a
2675 calloc style function. */
2676 void *
2677 xcalloc (size_t n, size_t m)
2678 {
2679 size_t nbytes;
2680
2681 nbytes = n * m;
2682 if (m && nbytes / m != n)
2683 out_of_core (nbytes, 0);
2684 return xmalloc_clear (nbytes);
2685 }
2686
2687 /* Wrapper around xmalloc_csecure_lear to take the usual 2 arguments
2688 of a calloc style function. */
2689 void *
2690 xcalloc_secure (size_t n, size_t m)
2691 {
2692 size_t nbytes;
2693
2694 nbytes = n * m;
2695 if (m && nbytes / m != n)
2696 out_of_core (nbytes, 1);
2697 return xmalloc_secure_clear (nbytes);
2698 }