source: trunk/src/sh_mem.c @ 139

Last change on this file since 139 was 139, checked in by rainer, 12 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.