-
+ 739F6960D138E5AB2EB53F41872BEF6DE1A66EE43161B6B8A69D12849F13332E48DB2392566A8736D6B2BF7272DFC01AA2BFE927D917F152BE75AE821DE1AFD6
smg_comms/mpi/memory.c
(0 . 0)(1 . 671)
2763 /* memory.c - memory allocation
2764 * Modified by No Such Labs. (C) 2015. See README.
2765 *
2766 * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
2767 * SHA256(gnupg-1.4.10.tar.gz):
2768 * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
2769 * (C) 1994-2005 Free Software Foundation, Inc.
2770 *
2771 * This program is free software: you can redistribute it and/or modify
2772 * it under the terms of the GNU General Public License as published by
2773 * the Free Software Foundation, either version 3 of the License, or
2774 * (at your option) any later version.
2775 *
2776 * This program is distributed in the hope that it will be useful,
2777 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2778 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2779 * GNU General Public License for more details.
2780 *
2781 * You should have received a copy of the GNU General Public License
2782 * along with this program. If not, see <http://www.gnu.org/licenses/>.
2783 */
2784
2785 /* We use our own memory allocation functions instead of plain malloc(),
2786 * so that we can provide some special enhancements:
2787 * a) functions to provide memory from a secure memory.
2788 * b) by looking at the requested allocation size we
2789 * can reuse memory very quickly (e.g. MPI storage)
2790 * (really needed?)
2791 * c) memory usage reporting if compiled with M_DEBUG
2792 * d) memory checking if compiled with M_GUARD
2793 */
2794
2795 #include <stdio.h>
2796 #include <stdlib.h>
2797 #include <stdarg.h>
2798 #include <string.h>
2799
2800 #include "knobs.h"
2801 #include "types.h"
2802 #include "memory.h"
2803 #include "util.h"
2804
2805 #define MAGIC_NOR_BYTE 0x55
2806 #define MAGIC_SEC_BYTE 0xcc
2807 #define MAGIC_END_BYTE 0xaa
2808
2809 /* This is a very crude alignment check which does not work on all CPUs
2810 * IIRC, I once introduced it for testing on an Alpha. We should better
2811 * replace this guard stuff with one provided by a modern malloc library
2812 */
2813 #if SIZEOF_UNSIGNED_LONG == 8
2814 #define EXTRA_ALIGN 4
2815 #else
2816 #define EXTRA_ALIGN 0
2817 #endif
2818
2819 #if defined(M_DEBUG) || defined(M_GUARD)
2820 static void membug( const char *fmt, ... );
2821 #endif
2822
2823 #ifdef M_DEBUG
2824
2825 #ifndef M_GUARD
2826 #define M_GUARD 1
2827 #endif
2828 #undef xmalloc
2829 #undef xtrymalloc
2830 #undef xmalloc_clear
2831 #undef xmalloc_secure
2832 #undef xmalloc_secure_clear
2833 #undef xrealloc
2834 #undef xfree
2835 #undef m_check
2836 #undef xstrdup
2837 #undef xtrystrdup
2838 #define FNAME(a) m_debug_ ##a
2839 #define FNAMEX(a) m_debug_ ##a
2840 #define FNAMEXM(a) m_debug_ ##a
2841 #define FNAMEPRT , const char *info
2842 #define FNAMEARG , info
2843
2844 #define store_len(p,n,m) do { add_entry(p,n,m, \
2845 info, __FUNCTION__); } while(0)
2846 #else
2847 #define FNAME(a) m_ ##a
2848 #define FNAMEX(a) x ##a
2849 #define FNAMEXM(a) xm ##a
2850 #define FNAMEPRT
2851 #define FNAMEARG
2852 #define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \
2853 ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \
2854 ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \
2855 ((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \
2856 : MAGIC_NOR_BYTE; \
2857 } while(0)
2858 #endif
2859
2860
2861 #ifdef M_GUARD
2862 static long used_memory;
2863 #endif
2864
2865 #ifdef M_DEBUG /* stuff used for memory debuging */
2866
2867 struct info_entry {
2868 struct info_entry *next;
2869 unsigned count; /* call count */
2870 const char *info; /* the reference to the info string */
2871 };
2872
2873 struct memtbl_entry {
2874 const void *user_p; /* for reference: the pointer given to the user */
2875 size_t user_n; /* length requested by the user */
2876 struct memtbl_entry *next; /* to build a list of unused entries */
2877 const struct info_entry *info; /* points into the table with */
2878 /* the info strings */
2879 unsigned inuse:1; /* this entry is in use */
2880 unsigned count:31;
2881 };
2882
2883
2884 #define INFO_BUCKETS 53
2885 #define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS )
2886 static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */
2887
2888 static struct memtbl_entry *memtbl; /* the table with the memory info */
2889 static unsigned memtbl_size; /* number of allocated entries */
2890 static unsigned memtbl_len; /* number of used entries */
2891 static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */
2892
2893 static void dump_table_at_exit(void);
2894 static void dump_table(void);
2895 static void check_allmem( const char *info );
2896
2897 /****************
2898 * Put the new P into the debug table and return a pointer to the table entry.
2899 * mode is true for security. BY is the name of the function which called us.
2900 */
2901 static void
2902 add_entry( byte *p, unsigned n, int mode, const char *info, const char *by )
2903 {
2904 unsigned index;
2905 struct memtbl_entry *e;
2906 struct info_entry *ie;
2907
2908 if( memtbl_len < memtbl_size )
2909 index = memtbl_len++;
2910 else {
2911 struct memtbl_entry *e;
2912 /* look for a used entry in the table. We take the first one,
2913 * so that freed entries remain as long as possible in the table
2914 * (free appends a new one)
2915 */
2916 if( (e = memtbl_unused) ) {
2917 index = e - memtbl;
2918 memtbl_unused = e->next;
2919 e->next = NULL;
2920 }
2921 else { /* no free entries in the table: extend the table */
2922 if( !memtbl_size ) { /* first time */
2923 memtbl_size = 100;
2924 if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) )
2925 membug("memory debug table malloc failed\n");
2926 index = 0;
2927 memtbl_len = 1;
2928 atexit( dump_table_at_exit );
2929 }
2930 else { /* realloc */
2931 unsigned n = memtbl_size / 4; /* enlarge by 25% */
2932 if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl)))
2933 membug("memory debug table realloc failed\n");
2934 memset(memtbl+memtbl_size, 0, n*sizeof *memtbl );
2935 memtbl_size += n;
2936 index = memtbl_len++;
2937 }
2938 }
2939 }
2940 e = memtbl+index;
2941 if( e->inuse )
2942 membug("Ooops: entry %u is flagged as in use\n", index);
2943 e->user_p = p + EXTRA_ALIGN + 4;
2944 e->user_n = n;
2945 e->count++;
2946 if( e->next )
2947 membug("Ooops: entry is in free entry list\n");
2948 /* do we already have this info string */
2949 for( ie = info_strings[info_hash(info)]; ie; ie = ie->next )
2950 if( ie->info == info )
2951 break;
2952 if( !ie ) { /* no: make a new entry */
2953 if( !(ie = malloc( sizeof *ie )) )
2954 membug("can't allocate info entry\n");
2955 ie->next = info_strings[info_hash(info)];
2956 info_strings[info_hash(info)] = ie;
2957 ie->info = info;
2958 ie->count = 0;
2959 }
2960 ie->count++;
2961 e->info = ie;
2962 e->inuse = 1;
2963
2964 /* put the index at the start of the memory */
2965 p[EXTRA_ALIGN+0] = index;
2966 p[EXTRA_ALIGN+1] = index >> 8 ;
2967 p[EXTRA_ALIGN+2] = index >> 16 ;
2968 p[EXTRA_ALIGN+3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ;
2969 if( DBG_MEMORY )
2970 log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by );
2971 }
2972
2973
2974
2975 /****************
2976 * Check that the memory block is correct. The magic byte has already been
2977 * checked. Checks which are done here:
2978 * - see whether the index points into our memory table
2979 * - see whether P is the same as the one stored in the table
2980 * - see whether we have already freed this block.
2981 */
2982 struct memtbl_entry *
2983 check_mem( const byte *p, const char *info )
2984 {
2985 unsigned n;
2986 struct memtbl_entry *e;
2987
2988 n = p[EXTRA_ALIGN+0];
2989 n |= p[EXTRA_ALIGN+1] << 8;
2990 n |= p[EXTRA_ALIGN+2] << 16;
2991
2992 if( n >= memtbl_len )
2993 membug("memory at %p corrupted: index=%u table_len=%u (%s)\n",
2994 p+EXTRA_ALIGN+4, n, memtbl_len, info );
2995 e = memtbl+n;
2996
2997 if( e->user_p != p+EXTRA_ALIGN+4 )
2998 membug("memory at %p corrupted: reference mismatch (%s)\n",
2999 p+EXTRA_ALIGN+4, info );
3000 if( !e->inuse )
3001 membug("memory at %p corrupted: marked as free (%s)\n",
3002 p+EXTRA_ALIGN+4, info );
3003
3004 if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE
3005 || p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) )
3006 membug("memory at %p corrupted: underflow=%02x (%s)\n",
3007 p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info );
3008 if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE )
3009 membug("memory at %p corrupted: overflow=%02x (%s)\n",
3010 p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info );
3011 return e;
3012 }
3013
3014
3015 /****************
3016 * free the entry and the memory (replaces free)
3017 */
3018 static void
3019 free_entry( byte *p, const char *info )
3020 {
3021 struct memtbl_entry *e, *e2;
3022
3023 check_allmem("add_entry");
3024
3025 e = check_mem(p, info);
3026 if( DBG_MEMORY )
3027 log_debug( "%s frees %u bytes alloced by %s\n",
3028 info, e->user_n, e->info->info );
3029 if( !e->inuse ) {
3030 if( e->user_p == p + EXTRA_ALIGN+ 4 )
3031 membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 );
3032 else
3033 membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 );
3034 }
3035
3036 e->inuse = 0;
3037 e->next = NULL;
3038 if( !memtbl_unused )
3039 memtbl_unused = e;
3040 else {
3041 for(e2=memtbl_unused; e2->next; e2 = e2->next )
3042 ;
3043 e2->next = e;
3044 }
3045 if( m_is_secure(p+EXTRA_ALIGN+4) )
3046 secmem_free(p);
3047 else {
3048 memset(p,'f', e->user_n+5);
3049 free(p);
3050 }
3051 }
3052
3053 static void
3054 dump_entry(struct memtbl_entry *e )
3055 {
3056 unsigned n = e - memtbl;
3057
3058 fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n",
3059 n, e->inuse?'a':'u', e->count, e->user_p, e->user_n,
3060 e->info->info, e->info->count );
3061
3062
3063 }
3064
3065
3066 static void
3067 dump_table_at_exit( void)
3068 {
3069 if( DBG_MEMSTAT )
3070 dump_table();
3071 }
3072
3073 static void
3074 dump_table( void)
3075 {
3076 unsigned n;
3077 struct memtbl_entry *e;
3078 ulong sum = 0, chunks =0;
3079
3080 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
3081 if(e->inuse) {
3082 dump_entry(e);
3083 sum += e->user_n;
3084 chunks++;
3085 }
3086 }
3087 fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n",
3088 sum, chunks );
3089 }
3090
3091
3092 static void
3093 check_allmem( const char *info )
3094 {
3095 unsigned n;
3096 struct memtbl_entry *e;
3097
3098 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
3099 if( e->inuse ) {
3100 check_mem(e->user_p-4-EXTRA_ALIGN, info);
3101 }
3102 }
3103 }
3104
3105 #endif /* M_DEBUG */
3106
3107 #if defined(M_DEBUG) || defined(M_GUARD)
3108 static void
3109 membug( const char *fmt, ... )
3110 {
3111 va_list arg_ptr ;
3112
3113 fprintf(stderr, "\nMemory Error: " ) ;
3114 va_start( arg_ptr, fmt ) ;
3115 vfprintf(stderr,fmt,arg_ptr) ;
3116 va_end(arg_ptr);
3117 fflush(stderr);
3118 #ifdef M_DEBUG
3119 if( DBG_MEMSTAT )
3120 dump_table();
3121 #endif
3122 abort();
3123 }
3124 #endif
3125
3126 void
3127 m_print_stats( const char *prefix )
3128 {
3129 #ifdef M_DEBUG
3130 unsigned n;
3131 struct memtbl_entry *e;
3132 ulong sum = 0, chunks =0;
3133
3134 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
3135 if(e->inuse) {
3136 sum += e->user_n;
3137 chunks++;
3138 }
3139 }
3140
3141 log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n",
3142 prefix? prefix:"", prefix? ": ":"", sum, chunks );
3143 #elif defined(M_GUARD)
3144 log_debug( "%s%smemstat: %8ld bytes\n",
3145 prefix? prefix:"", prefix? ": ":"", used_memory );
3146 #endif
3147 }
3148
3149 void
3150 m_dump_table( const char *prefix )
3151 {
3152 #ifdef M_DEBUG
3153 fprintf(stderr,"Memory-Table-Dump: %s\n", prefix);
3154 dump_table();
3155 #endif
3156 m_print_stats( prefix );
3157 }
3158
3159
3160 static void
3161 out_of_core(size_t n, int secure)
3162 {
3163 log_error ("out of %s memory while allocating %u bytes\n",
3164 secure? "secure":"" ,(unsigned)n );
3165 if (secure) {
3166 /*secmem_dump_stats ();*/
3167 log_info ("(this may be caused by too many secret keys used "
3168 "simultaneously or due to excessive large key sizes)\n");
3169 }
3170 exit(2);
3171 }
3172
3173 /****************
3174 * Allocate memory of size n.
3175 * This function gives up if we do not have enough memory
3176 */
3177 void *
3178 FNAMEXM(alloc)( size_t n FNAMEPRT )
3179 {
3180 char *p;
3181
3182 #ifdef M_GUARD
3183 if(!n)
3184 out_of_core(n,0); /* should never happen */
3185 if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
3186 out_of_core(n,0);
3187 store_len(p,n,0);
3188 used_memory += n;
3189 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
3190 return p+EXTRA_ALIGN+4;
3191 #else
3192 /* mallocing zero bytes is undefined by ISO-C, so we better make
3193 sure that it won't happen */
3194 if (!n)
3195 n = 1;
3196 if( !(p = malloc( n )) )
3197 out_of_core(n,0);
3198 return p;
3199 #endif
3200 }
3201
3202 /* Allocate memory of size n. This function returns NULL if we do not
3203 have enough memory. */
3204 void *
3205 FNAMEX(trymalloc)(size_t n FNAMEPRT)
3206 {
3207 #ifdef M_GUARD
3208 char *p;
3209
3210 if (!n)
3211 n = 1;
3212 p = malloc (n + EXTRA_ALIGN+5);
3213 if (!p)
3214 return NULL;
3215 store_len(p,n,0);
3216 used_memory += n;
3217 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
3218 return p+EXTRA_ALIGN+4;
3219 #else
3220 /* Mallocing zero bytes is undefined by ISO-C, so we better make
3221 sure that it won't happen. */
3222 return malloc (n? n: 1);
3223 #endif
3224 }
3225
3226 /****************
3227 * Allocate memory of size n from the secure memory pool.
3228 * This function gives up if we do not have enough memory
3229 */
3230 void *
3231 FNAMEXM(alloc_secure)( size_t n FNAMEPRT )
3232 {
3233 char *p;
3234
3235 #ifdef M_GUARD
3236 if(!n)
3237 out_of_core(n,1); /* should never happen */
3238 if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
3239 out_of_core(n,1);
3240 store_len(p,n,1);
3241 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
3242 return p+EXTRA_ALIGN+4;
3243 #else
3244 /* mallocing zero bytes is undefined by ISO-C, so we better make
3245 sure that it won't happen */
3246 if (!n)
3247 n = 1;
3248 if( !(p = secmem_malloc( n )) )
3249 out_of_core(n,1);
3250 return p;
3251 #endif
3252 }
3253
3254 void *
3255 FNAMEXM(alloc_clear)( size_t n FNAMEPRT )
3256 {
3257 void *p;
3258 p = FNAMEXM(alloc)( n FNAMEARG );
3259 memset(p, 0, n );
3260 return p;
3261 }
3262
3263 void *
3264 FNAMEXM(alloc_secure_clear)( size_t n FNAMEPRT)
3265 {
3266 void *p;
3267 p = FNAMEXM(alloc_secure)( n FNAMEARG );
3268 memset(p, 0, n );
3269 return p;
3270 }
3271
3272
3273 /****************
3274 * realloc and clear the old space
3275 */
3276 void *
3277 FNAMEX(realloc)( void *a, size_t n FNAMEPRT )
3278 {
3279 void *b;
3280
3281 #ifdef M_GUARD
3282 if( a ) {
3283 #error "--enable-m-guard does not currently work"
3284 unsigned char *p = a;
3285 size_t len = m_size(a);
3286
3287 if( len >= n ) /* we don't shrink for now */
3288 return a;
3289 if( p[-1] == MAGIC_SEC_BYTE )
3290 b = FNAME(alloc_secure_clear)(n FNAMEARG);
3291 else
3292 b = FNAME(alloc_clear)(n FNAMEARG);
3293 FNAME(check)(NULL FNAMEARG);
3294 memcpy(b, a, len );
3295 FNAME(free)(p FNAMEARG);
3296 }
3297 else
3298 b = FNAME(alloc)(n FNAMEARG);
3299 #else
3300 if( m_is_secure(a) ) {
3301 if( !(b = secmexrealloc( a, n )) )
3302 out_of_core(n,1);
3303 }
3304 else {
3305 if( !(b = realloc( a, n )) )
3306 out_of_core(n,0);
3307 }
3308 #endif
3309
3310 return b;
3311 }
3312
3313
3314
3315 /****************
3316 * Free a pointer
3317 */
3318 void
3319 FNAMEX(free)( void *a FNAMEPRT )
3320 {
3321 byte *p = a;
3322
3323 if( !p )
3324 return;
3325 #ifdef M_DEBUG
3326 free_entry(p-EXTRA_ALIGN-4, info);
3327 #elif defined M_GUARD
3328 m_check(p);
3329 if( m_is_secure(a) )
3330 secmem_free(p-EXTRA_ALIGN-4);
3331 else {
3332 used_memory -= m_size(a);
3333 free(p-EXTRA_ALIGN-4);
3334 }
3335 #else
3336 if( m_is_secure(a) )
3337 secmem_free(p);
3338 else
3339 free(p);
3340 #endif
3341 }
3342
3343
3344 void
3345 FNAME(check)( const void *a FNAMEPRT )
3346 {
3347 #ifdef M_GUARD
3348 const byte *p = a;
3349
3350 #ifdef M_DEBUG
3351 if( p )
3352 check_mem(p-EXTRA_ALIGN-4, info);
3353 else
3354 check_allmem(info);
3355 #else
3356 if( !p )
3357 return;
3358 if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
3359 membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
3360 else if( p[m_size(p)] != MAGIC_END_BYTE )
3361 membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
3362 #endif
3363 #endif
3364 }
3365
3366
3367 size_t
3368 m_size( const void *a )
3369 {
3370 #ifndef M_GUARD
3371 log_debug("dummy m_size called\n");
3372 return 0;
3373 #else
3374 const byte *p = a;
3375 size_t n;
3376
3377 #ifdef M_DEBUG
3378 n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n;
3379 #else
3380 n = ((byte*)p)[-4];
3381 n |= ((byte*)p)[-3] << 8;
3382 n |= ((byte*)p)[-2] << 16;
3383 #endif
3384 return n;
3385 #endif
3386 }
3387
3388
3389 char *
3390 FNAMEX(strdup)( const char *a FNAMEPRT )
3391 {
3392 size_t n = strlen(a);
3393 char *p = FNAMEXM(alloc)(n+1 FNAMEARG);
3394 strcpy(p, a);
3395 return p;
3396 }
3397
3398 char *
3399 FNAMEX(trystrdup)(const char *a FNAMEPRT)
3400 {
3401 size_t n = strlen (a);
3402 char *p = FNAMEX(trymalloc)(n+1 FNAMEARG);
3403 if (p)
3404 strcpy (p, a);
3405 return p;
3406 }
3407
3408
3409 /* Wrapper around xmalloc_clear to take the usual 2 arguments of a
3410 calloc style function. */
3411 void *
3412 xcalloc (size_t n, size_t m)
3413 {
3414 size_t nbytes;
3415
3416 nbytes = n * m;
3417 if (m && nbytes / m != n)
3418 out_of_core (nbytes, 0);
3419 return xmalloc_clear (nbytes);
3420 }
3421
3422 /* Wrapper around xmalloc_csecure_lear to take the usual 2 arguments
3423 of a calloc style function. */
3424 void *
3425 xcalloc_secure (size_t n, size_t m)
3426 {
3427 size_t nbytes;
3428
3429 nbytes = n * m;
3430 if (m && nbytes / m != n)
3431 out_of_core (nbytes, 1);
3432 return xmalloc_secure_clear (nbytes);
3433 }