source: trunk/src/sh_mem.c@ 139

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

Detect availability of recursive mutexes on Linux.

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#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 /*
259 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MMEM,
260 file, line);
261 */
262 eblock = 0;
263 }
264 /* use _exit() rather than exit() - we malloc() in atexit() functions
265 */
266 _exit (42);
267 }
268
269 /* --- Set check bytes. ---
270 */
271 theAddress = ((char *) the_realAddress + SH_MEMMULT);
272
273 memset(the_realAddress, CHECKBYTE, SH_MEMMULT);
274 memset(theAddress, CHECKBYTE, size + 1);
275 memset(theAddress, 0, 1);
276
277 ++Alloc_Count;
278 ++Now_Alloc_Count;
279
280 if (Max_Alloc_Count < Now_Alloc_Count)
281 Max_Alloc_Count = Now_Alloc_Count;
282
283#ifdef MEM_DETAILS
284 if (size <= 32)
285 {
286 ++now_upto_032;
287 ++tot_upto_032;
288 if (now_upto_032 > max_upto_032) max_upto_032 = now_upto_032;
289 }
290 else if (size <= 64)
291 {
292 ++now_upto_064;
293 ++tot_upto_064;
294 if (now_upto_064 > max_upto_064) max_upto_064 = now_upto_064;
295 }
296 else if (size <= 128)
297 {
298 ++now_upto_128;
299 ++tot_upto_128;
300 if (now_upto_128 > max_upto_128) max_upto_128 = now_upto_128;
301 }
302 else if (size <= 256)
303 {
304 ++now_upto_256;
305 ++tot_upto_256;
306 if (now_upto_256 > max_upto_256) max_upto_256 = now_upto_256;
307 }
308 else if (size <= 512)
309 {
310 ++now_upto_512;
311 ++tot_upto_512;
312 if (now_upto_512 > max_upto_512) max_upto_512 = now_upto_512;
313 }
314 else if (size <= 1024)
315 {
316 ++now_upto_1024;
317 ++tot_upto_1024;
318 if (now_upto_1024 > max_upto_1024) max_upto_1024 = now_upto_1024;
319 }
320 else if (size <= 4096)
321 {
322 ++now_upto_4096;
323 ++tot_upto_4096;
324 if (now_upto_4096 > max_upto_4096) max_upto_4096 = now_upto_4096;
325 }
326 else
327 {
328 ++now_upto_inf;
329 ++tot_upto_inf;
330 if (now_upto_inf > max_upto_inf) max_upto_inf = now_upto_inf;
331
332 fprintf(stderr, "\n___BIGSIZE___");
333 fprintf(stderr, " %6d -> %16s %10d \n", size, file, line);
334 fprintf(stderr, "\n");
335
336 }
337#endif
338
339 Mem_Current += size;
340 Mem_Max = ( (Mem_Current > Mem_Max) ? Mem_Current : Mem_Max);
341
342 this = (memlist_t *) malloc (sizeof(memlist_t));
343
344 if ( this == NULL)
345 {
346 if (eblock == 0)
347 {
348 eblock = 1;
349 (void) safe_logger(0, 0, NULL);
350 /*
351 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MMEM,
352 file, line);
353 */
354 eblock = 0;
355 }
356 _exit(42);
357 }
358 else
359 {
360 /* make list entry */
361
362 this->real_address = the_realAddress;
363 this->address = theAddress;
364 this->size = size;
365 this->line = line;
366 sl_strlcpy(this->file, file, 20);
367
368 this->next = memlist;
369 memlist = this;
370 }
371
372 SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
373 SL_RETURN( theAddress, _("sh_mem_malloc"));
374}
375
376
377void sh_mem_free (void * a, char * file, int line)
378{
379 memlist_t * this = memlist;
380 memlist_t * before = memlist;
381 unsigned long size = 0;
382
383 SL_ENTER(_("sh_mem_free"));
384
385 SH_MUTEX_RECURSIVE_INIT(mutex_mem);
386 SH_MUTEX_RECURSIVE_LOCK(mutex_mem);
387 if ( a == NULL )
388 {
389 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MNULL,
390 file, line);
391 goto out;
392 }
393
394 /* -- Find record. --
395 */
396 while (this != NULL)
397 {
398 if (this->address == a)
399 break;
400 before = this;
401 this = this->next;
402 }
403
404 if (this == NULL)
405 {
406 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MREC,
407 file, line);
408 goto out;
409 }
410 else
411 {
412 a = this->real_address;
413
414 if ( this->address[this->size] != CHECKBYTE )
415 {
416 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MOVER,
417 this->file, this->line, file, line);
418 }
419 if ( this->real_address[SH_MEMMULT-1] != CHECKBYTE )
420 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MUNDER,
421 this->file, this->line, file, line);
422
423 size = this->size;
424
425 if (this == memlist)
426 memlist = this->next;
427 else
428 before->next = this->next;
429 }
430
431 free(a);
432 if (this)
433 free(this);
434 ++Free_Count;
435 --Now_Alloc_Count;
436
437#ifdef MEM_DETAILS
438 if (size <= 32)
439 --now_upto_032;
440 else if (size <= 64)
441 --now_upto_064;
442 else if (size <= 128)
443 --now_upto_128;
444 else if (size <= 256)
445 --now_upto_256;
446 else if (size <= 512)
447 --now_upto_512;
448 else if (size <= 1024)
449 --now_upto_1024;
450 else if (size <= 4096)
451 --now_upto_4096;
452 else
453 --now_upto_inf;
454#endif
455
456 Mem_Current -= size;
457 out:
458 SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
459 SL_RET0(_("sh_mem_free"));
460}
461
462#else
463
464void sh_mem_free (void * a)
465{
466 SL_ENTER(_("sh_mem_free"));
467
468 if (a)
469 {
470 free(a);
471 }
472 else
473 {
474 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MNULL);
475 }
476 SL_RET0(_("sh_mem_free"));
477}
478
479void * sh_mem_malloc (size_t size)
480{
481 void * theAddress;
482
483 SL_ENTER(_("sh_mem_malloc"));
484
485 theAddress = malloc(size);
486
487 if ( theAddress == NULL )
488 {
489 if (eblock == 0)
490 {
491 eblock = 1;
492 (void) safe_logger(0, 0, NULL);
493 /*
494 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MMEM);
495 */
496 eblock = 0;
497 }
498 /* use _exit() rather than exit() - we malloc() in atexit()
499 */
500 _exit (42);
501 }
502 /* memset (theAddress, 0, 1); *//* needs testing */
503
504 SL_RETURN( theAddress, _("sh_mem_malloc"));
505}
506#endif
Note: See TracBrowser for help on using the repository browser.