source: trunk/src/sh_mem.c

Last change on this file was 579, checked in by katerina, 18 months ago

Fix for ticket #467 (memleak).

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