source: trunk/src/sh_mem.c@ 141

Last change on this file since 141 was 140, checked in by rainer, 17 years ago

Utility function for threaded modules.

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