source: trunk/src/sh_mem.c @ 481

Last change on this file since 481 was 481, checked in by katerina, 6 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

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