source: trunk/src/sh_mem.c@ 135

Last change on this file since 135 was 134, checked in by rainer, 17 years ago

More thread-safety changes.

File size: 11.9 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <sys/types.h>
27#include <unistd.h>
28
29
30#ifdef HAVE_MEMORY_H
31#include <memory.h>
32#endif
33
34#define SH_REAL_SET
35
36#include "samhain.h"
37#include "sh_error.h"
38#include "sh_utils.h"
39#include "sh_mem.h"
40#include "sh_pthread.h"
41
42extern int safe_logger (int signal, int method, char * details);
43
44#undef FIL__
45#define FIL__ _("sh_mem.c")
46static int eblock = 0;
47
48#ifdef MEM_DEBUG
49
50#define CHECKBYTE 0x7F
51
52/* Memory alignment; should be 16 bytes on 64 bit machines.
53 * -> 32 bytes overhead/allocation
54 */
55#define SH_MEMMULT 16
56
57
58typedef struct mem_struct {
59 struct mem_struct *next; /* link to next struct */
60 char * real_address; /* address assigned */
61 char * address; /* address returned */
62 unsigned long size; /* size allocated */
63 char file[20]; /* Allocation file name */
64 int line; /* Allocation line number */
65} memlist_t;
66
67memlist_t * memlist = NULL;
68
69int Free_Count = 0, Alloc_Count = 0;
70int Now_Alloc_Count = 0, Max_Alloc_Count = 0;
71unsigned long Mem_Current = 0, Mem_Max = 0;
72
73#if 0
74#define MEM_DETAILS
75#endif
76
77#ifdef MEM_DETAILS
78int max_upto_032 = 0;
79int max_upto_064 = 0;
80int max_upto_128 = 0;
81int max_upto_256 = 0;
82int max_upto_512 = 0;
83int max_upto_1024 = 0;
84int max_upto_4096 = 0;
85int max_upto_inf = 0;
86
87int now_upto_032 = 0;
88int now_upto_064 = 0;
89int now_upto_128 = 0;
90int now_upto_256 = 0;
91int now_upto_512 = 0;
92int now_upto_1024 = 0;
93int now_upto_4096 = 0;
94int now_upto_inf = 0;
95
96int tot_upto_032 = 0;
97int tot_upto_064 = 0;
98int tot_upto_128 = 0;
99int tot_upto_256 = 0;
100int tot_upto_512 = 0;
101int tot_upto_1024 = 0;
102int tot_upto_4096 = 0;
103int tot_upto_inf = 0;
104#endif
105
106#ifdef HAVE_PTHREAD
107static pthread_once_t mem_is_initialized = PTHREAD_ONCE_INIT;
108static pthread_mutex_t mutex_mem;
109
110static int initialize_mem(void)
111{
112 pthread_mutexattr_t mta;
113 pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
114 pthread_mutex_init(&mutex_mem, &mta);
115 pthread_mutexattr_destroy(&mta);
116 return 0;
117}
118#define MEM_MUTEX_INIT (void) pthread_once(&mem_is_initialized, initialize_mem)
119#else
120#define MEM_MUTEX_INIT ((void)0)
121#endif
122
123#ifdef MEM_LOG
124void sh_mem_dump ()
125{
126 memlist_t * this = memlist;
127
128
129 FILE * fd;
130
131 MEM_MUTEX_INIT;
132 SH_MUTEX_LOCK(mutex_mem);
133
134 fd = fopen(MEM_LOG, "w");
135
136 while (this != NULL)
137 {
138 fprintf (fd, "%20s %5d %ld\n", this->file, this->line, this->size);
139 this = this->next;
140 }
141 fclose(fd);
142 SH_MUTEX_UNLOCK(mutex_mem);
143 return;
144}
145#else
146void sh_mem_dump ()
147{
148 return;
149}
150#endif
151
152void sh_mem_stat ()
153{
154 memlist_t * this;
155
156
157 SL_ENTER(_("sh_mem_stat"));
158
159 MEM_MUTEX_INIT;
160 SH_MUTEX_LOCK(mutex_mem);
161
162 if (Alloc_Count == Free_Count)
163 {
164 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MSTAMP,
165 Mem_Max, Mem_Current);
166 goto out;
167 }
168
169 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0, MSG_MSTAMP2,
170 Alloc_Count, Free_Count, Max_Alloc_Count);
171 sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0, MSG_MSTAMP,
172 Mem_Max, Mem_Current);
173
174#ifdef MEM_DETAILS
175 fprintf(stderr, "\n");
176 fprintf(stderr, "__SIZE_____TOTAL___MAXIMUM___\n");
177 fprintf(stderr, " 32 %6d %6d\n", tot_upto_032, max_upto_032);
178 fprintf(stderr, " 64 %6d %6d\n", tot_upto_064, max_upto_064);
179 fprintf(stderr, " 128 %6d %6d\n", tot_upto_128, max_upto_128);
180 fprintf(stderr, " 256 %6d %6d\n", tot_upto_256, max_upto_256);
181 fprintf(stderr, " 512 %6d %6d\n", tot_upto_512, max_upto_512);
182 fprintf(stderr, " 1024 %6d %6d\n", tot_upto_1024, max_upto_1024);
183 fprintf(stderr, " 4096 %6d %6d\n", tot_upto_4096, max_upto_4096);
184 fprintf(stderr, " inf %6d %6d\n", tot_upto_inf, max_upto_inf);
185 fprintf(stderr, "\n");
186#endif
187
188 this = memlist;
189
190 while (this != NULL)
191 {
192 sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_NOTFREE,
193 this->size, this->file, this->line);
194 this = this->next;
195 }
196 out:
197 SH_MUTEX_UNLOCK(mutex_mem);
198 SL_RET0(_("sh_mem_stat"));
199}
200
201void sh_mem_check ()
202{
203 memlist_t * this;
204 long nerr = 0;
205
206 SL_ENTER(_("sh_mem_check"));
207
208 MEM_MUTEX_INIT;
209 SH_MUTEX_LOCK(mutex_mem);
210 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MSTAMP,
211 Mem_Max, Mem_Current);
212
213 this = memlist;
214
215 while (this != NULL)
216 {
217 if ( this->address == NULL )
218 {
219 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MNULL);
220 ++nerr;
221 }
222 else
223 {
224 if ( this->address[this->size] != CHECKBYTE )
225 {
226 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MOVER,
227 this->file, this->line, FIL__, __LINE__);
228 ++nerr;
229 }
230 if ( this->real_address[SH_MEMMULT-1] != CHECKBYTE )
231 {
232 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MUNDER,
233 this->file, this->line, FIL__, __LINE__);
234 ++nerr;
235 }
236 }
237 this = this->next;
238 }
239
240 /* if (nerr > 0) abort(); */
241
242 SH_MUTEX_UNLOCK(mutex_mem);
243 SL_RET0(_("sh_mem_check"));
244}
245
246void * sh_mem_malloc (size_t size, char * file, int line)
247{
248 void * the_realAddress;
249 void * theAddress;
250 memlist_t * this;
251
252 SL_ENTER(_("sh_mem_malloc"));
253
254 MEM_MUTEX_INIT;
255 SH_MUTEX_LOCK(mutex_mem);
256 the_realAddress = malloc(size + 2 * SH_MEMMULT);
257
258 if ( the_realAddress == NULL )
259 {
260 if (eblock == 0)
261 {
262 eblock = 1;
263 (void) safe_logger (0, 0, NULL);
264 /*
265 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MMEM,
266 file, line);
267 */
268 eblock = 0;
269 }
270 /* use _exit() rather than exit() - we malloc() in atexit() functions
271 */
272 _exit (42);
273 }
274
275 /* --- Set check bytes. ---
276 */
277 theAddress = ((char *) the_realAddress + SH_MEMMULT);
278
279 memset(the_realAddress, CHECKBYTE, SH_MEMMULT);
280 memset(theAddress, CHECKBYTE, size + 1);
281 memset(theAddress, 0, 1);
282
283 ++Alloc_Count;
284 ++Now_Alloc_Count;
285
286 if (Max_Alloc_Count < Now_Alloc_Count)
287 Max_Alloc_Count = Now_Alloc_Count;
288
289#ifdef MEM_DETAILS
290 if (size <= 32)
291 {
292 ++now_upto_032;
293 ++tot_upto_032;
294 if (now_upto_032 > max_upto_032) max_upto_032 = now_upto_032;
295 }
296 else if (size <= 64)
297 {
298 ++now_upto_064;
299 ++tot_upto_064;
300 if (now_upto_064 > max_upto_064) max_upto_064 = now_upto_064;
301 }
302 else if (size <= 128)
303 {
304 ++now_upto_128;
305 ++tot_upto_128;
306 if (now_upto_128 > max_upto_128) max_upto_128 = now_upto_128;
307 }
308 else if (size <= 256)
309 {
310 ++now_upto_256;
311 ++tot_upto_256;
312 if (now_upto_256 > max_upto_256) max_upto_256 = now_upto_256;
313 }
314 else if (size <= 512)
315 {
316 ++now_upto_512;
317 ++tot_upto_512;
318 if (now_upto_512 > max_upto_512) max_upto_512 = now_upto_512;
319 }
320 else if (size <= 1024)
321 {
322 ++now_upto_1024;
323 ++tot_upto_1024;
324 if (now_upto_1024 > max_upto_1024) max_upto_1024 = now_upto_1024;
325 }
326 else if (size <= 4096)
327 {
328 ++now_upto_4096;
329 ++tot_upto_4096;
330 if (now_upto_4096 > max_upto_4096) max_upto_4096 = now_upto_4096;
331 }
332 else
333 {
334 ++now_upto_inf;
335 ++tot_upto_inf;
336 if (now_upto_inf > max_upto_inf) max_upto_inf = now_upto_inf;
337
338 fprintf(stderr, "\n___BIGSIZE___");
339 fprintf(stderr, " %6d -> %16s %10d \n", size, file, line);
340 fprintf(stderr, "\n");
341
342 }
343#endif
344
345 Mem_Current += size;
346 Mem_Max = ( (Mem_Current > Mem_Max) ? Mem_Current : Mem_Max);
347
348 this = (memlist_t *) malloc (sizeof(memlist_t));
349
350 if ( this == NULL)
351 {
352 if (eblock == 0)
353 {
354 eblock = 1;
355 (void) safe_logger(0, 0, NULL);
356 /*
357 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MMEM,
358 file, line);
359 */
360 eblock = 0;
361 }
362 _exit(42);
363 }
364
365 /* make list entry */
366
367 this->real_address = the_realAddress;
368 this->address = theAddress;
369 this->size = size;
370 this->line = line;
371 sl_strlcpy(this->file, file, 20);
372
373 this->next = memlist;
374 memlist = this;
375
376 SH_MUTEX_UNLOCK(mutex_mem);
377 SL_RETURN( theAddress, _("sh_mem_malloc"));
378}
379
380
381void sh_mem_free (void * a, char * file, int line)
382{
383 memlist_t * this = memlist;
384 memlist_t * before = memlist;
385 unsigned long size = 0;
386
387 SL_ENTER(_("sh_mem_free"));
388
389 MEM_MUTEX_INIT;
390 SH_MUTEX_LOCK(mutex_mem);
391 if ( a == NULL )
392 {
393 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MNULL,
394 file, line);
395 goto out;
396 }
397
398 /* -- Find record. --
399 */
400 while (this != NULL)
401 {
402 if (this->address == a)
403 break;
404 before = this;
405 this = this->next;
406 }
407
408 if (this == NULL)
409 {
410 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MREC,
411 file, line);
412 goto out;
413 }
414 else
415 {
416 a = this->real_address;
417
418 if ( this->address[this->size] != CHECKBYTE )
419 {
420 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MOVER,
421 this->file, this->line, file, line);
422 }
423 if ( this->real_address[SH_MEMMULT-1] != CHECKBYTE )
424 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MUNDER,
425 this->file, this->line, file, line);
426
427 size = this->size;
428
429 if (this == memlist)
430 memlist = this->next;
431 else
432 before->next = this->next;
433 }
434
435 free(a);
436 if (this)
437 free(this);
438 ++Free_Count;
439 --Now_Alloc_Count;
440
441#ifdef MEM_DETAILS
442 if (size <= 32)
443 --now_upto_032;
444 else if (size <= 64)
445 --now_upto_064;
446 else if (size <= 128)
447 --now_upto_128;
448 else if (size <= 256)
449 --now_upto_256;
450 else if (size <= 512)
451 --now_upto_512;
452 else if (size <= 1024)
453 --now_upto_1024;
454 else if (size <= 4096)
455 --now_upto_4096;
456 else
457 --now_upto_inf;
458#endif
459
460 Mem_Current -= size;
461 out:
462 SH_MUTEX_UNLOCK(mutex_mem);
463 SL_RET0(_("sh_mem_free"));
464}
465
466#else
467
468void sh_mem_free (void * a)
469{
470 SL_ENTER(_("sh_mem_free"));
471
472 if (a)
473 {
474 free(a);
475 }
476 else
477 {
478 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MNULL);
479 }
480 SL_RET0(_("sh_mem_free"));
481}
482
483void * sh_mem_malloc (size_t size)
484{
485 void * theAddress;
486
487 SL_ENTER(_("sh_mem_malloc"));
488
489 theAddress = malloc(size);
490
491 if ( theAddress == NULL )
492 {
493 if (eblock == 0)
494 {
495 eblock = 1;
496 (void) safe_logger(0, 0, NULL);
497 /*
498 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MMEM);
499 */
500 eblock = 0;
501 }
502 /* use _exit() rather than exit() - we malloc() in atexit()
503 */
504 _exit (42);
505 }
506 /* memset (theAddress, 0, 1); *//* needs testing */
507
508 SL_RETURN( theAddress, _("sh_mem_malloc"));
509}
510#endif
Note: See TracBrowser for help on using the repository browser.