source: trunk/src/sh_mem.c@ 579

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

Fix for ticket #467 (memleak).

File size: 10.8 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 thesignal, int method, char * details);
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
75#ifdef HAVE_PTHREAD
76SH_MUTEX_RECURSIVE(mutex_mem);
77#endif
78
79/* define MEM_LOG to enable this */
80/* #define MEM_LOG 1 */
81#ifdef MEM_LOG
82void sh_mem_dump ()
83{
84 memlist_t * this = memlist;
85 FILE * fd;
86 static unsigned int nr = 0;
87 char filename[256];
88
89 snprintf(filename, sizeof(filename), "sh_mem_dump.%04u.%lu", nr, (unsigned long) sh.pid);
90
91 SH_MUTEX_RECURSIVE_INIT(mutex_mem);
92 SH_MUTEX_RECURSIVE_LOCK(mutex_mem);
93
94 fd = fopen(filename, "w");
95 if (!fd)
96 {
97 perror(filename);
98 _exit(EXIT_FAILURE);
99 }
100
101 while (this != NULL)
102 {
103 fprintf (fd, "## %20s %5d %ld\n", this->file, this->line, this->size);
104 fprintf (fd, "%10p %8ld\n", (void *)this->address, this->size);
105 this = this->next;
106 }
107 sl_fclose(FIL__, __LINE__, fd);
108
109 SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
110 ++nr;
111 /* _exit(EXIT_SUCCESS); */
112 return;
113}
114#else
115void sh_mem_dump ()
116{
117 return;
118}
119#endif
120
121memlist_t ** sh_dummy_114_merrlist;
122
123void sh_mem_stat ()
124{
125 memlist_t * this;
126 memlist_t * merrlist = NULL;
127
128 SL_ENTER(_("sh_mem_stat"));
129
130 sh_dummy_114_merrlist = (memlist_t **) &merrlist;
131
132 if (Alloc_Count == Free_Count)
133 {
134 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MSTAMP,
135 Mem_Max, Mem_Current);
136 SL_RET0(_("sh_mem_stat"));
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
144 SH_MUTEX_RECURSIVE_INIT(mutex_mem);
145 SH_MUTEX_RECURSIVE_LOCK(mutex_mem);
146
147 this = memlist;
148
149 while (this != NULL)
150 {
151 memlist_t * merr = calloc(1,sizeof(memlist_t));
152
153 memcpy(merr, this, sizeof(memlist_t));
154 merr->next = merrlist;
155 merrlist = merr;
156
157 this = this->next;
158 }
159
160 SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
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
172 SL_RET0(_("sh_mem_stat"));
173}
174
175memlist_t ** sh_dummy_168_merrlist;
176
177void sh_mem_check ()
178{
179 memlist_t * this;
180 memlist_t * merrlist = NULL;
181 memlist_t * merr;
182 long nerr = 0;
183
184 SL_ENTER(_("sh_mem_check"));
185
186 sh_dummy_168_merrlist = (memlist_t **) &merrlist;
187
188 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MSTAMP,
189 Mem_Max, Mem_Current);
190
191 SH_MUTEX_RECURSIVE_INIT(mutex_mem);
192 SH_MUTEX_RECURSIVE_LOCK(mutex_mem);
193
194 this = memlist;
195
196 while (this != NULL)
197 {
198 if ( this->address == NULL )
199 {
200 merr = calloc (1,sizeof(memlist_t));
201
202 memcpy(merr, this, sizeof(memlist_t));
203 merr->size = 2;
204
205 merr->next = merrlist;
206 merrlist = merr;
207 ++nerr;
208 }
209 else
210 {
211 if ( this->address[this->size] != CHECKBYTE )
212 {
213 merr = calloc(1, sizeof(memlist_t));
214
215 memcpy(merr, this, sizeof(memlist_t));
216 merr->size = 1;
217
218 merr->next = merrlist;
219 merrlist = merr;
220 ++nerr;
221 }
222 if ( this->real_address[SH_MEMMULT-1] != CHECKBYTE )
223 {
224 merr = calloc(1, sizeof(memlist_t));
225
226 memcpy(merr, this, sizeof(memlist_t));
227 merr->size = 0;
228
229 merr->next = merrlist;
230 merrlist = merr;
231 ++nerr;
232 }
233 }
234 this = this->next;
235 }
236
237
238 SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
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);
255 SH_ABORT;
256 _exit (EXIT_FAILURE);
257 }
258
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
270 SH_MUTEX_RECURSIVE_INIT(mutex_mem);
271 SH_MUTEX_RECURSIVE_LOCK(mutex_mem);
272
273 the_realAddress = calloc(1,size + 2 * SH_MEMMULT);
274
275 if ( the_realAddress == NULL )
276 {
277 (void) safe_logger (0, 0, NULL);
278
279 /* use _exit() rather than exit() - we malloc() in atexit() functions
280 */
281 _exit (EXIT_FAILURE);
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
301 this = calloc(1,sizeof(memlist_t));
302
303 if ( this == NULL)
304 {
305 (void) safe_logger(0, 0, NULL);
306
307 _exit(EXIT_FAILURE);
308 }
309 else
310 {
311 /* make list entry */
312
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);
318
319 this->next = memlist;
320 memlist = this;
321 }
322
323 SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
324 SL_RETURN( theAddress, _("sh_mem_malloc"));
325}
326
327void ** sh_mem_dummy_a;
328memlist_t ** sh_mem_merr_3;
329
330void sh_mem_free (void * aa, char * file, int line)
331{
332 memlist_t * this;
333 memlist_t * before;
334 memlist_t * merr;
335 memlist_t * merrlist = NULL;
336 unsigned long size = 0;
337 void * a;
338 volatile int flag = 0;
339
340 SL_ENTER(_("sh_mem_free"));
341
342 a = aa;
343 sh_mem_dummy_a = &a;
344 sh_mem_merr_3 = (memlist_t **) &merrlist;
345
346
347 if ( a == NULL )
348 {
349 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MNULL,
350 file, line, FIL__, __LINE__);
351 SH_ABORT;
352 _exit (EXIT_FAILURE);
353 SL_RET0(_("sh_mem_free"));
354 }
355
356 SH_MUTEX_RECURSIVE_INIT(mutex_mem);
357 SH_MUTEX_RECURSIVE_LOCK(mutex_mem);
358
359 this = memlist;
360 before = memlist;
361
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 {
374 flag = 1;
375 goto out;
376 }
377 else
378 {
379 a = this->real_address;
380
381 if ( this->address[this->size] != CHECKBYTE )
382 {
383 merr = calloc(1, sizeof(memlist_t));
384
385 memcpy(merr, this, sizeof(memlist_t));
386 merr->size = 1;
387
388 merr->next = merrlist;
389 merrlist = merr;
390 }
391
392 if ( this->real_address[SH_MEMMULT-1] != CHECKBYTE )
393 {
394 merr = calloc(1,sizeof(memlist_t));
395
396 memcpy(merr, this, sizeof(memlist_t));
397 merr->size = 0;
398
399 merr->next = merrlist;
400 merrlist = merr;
401 }
402
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)
413 free(this);
414
415 ++Free_Count;
416 --Now_Alloc_Count;
417
418 Mem_Current -= size;
419 out:
420 ; /* label at end of compound statement */
421 SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
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);
435 SH_ABORT;
436 _exit (EXIT_FAILURE);
437 }
438
439 if (flag != 0)
440 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_MREC,
441 file, line);
442
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 SH_ABORT;
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
470 theAddress = calloc(1,size);
471
472 if ( theAddress != NULL )
473 {
474 SL_RETURN( theAddress, _("sh_mem_malloc"));
475 }
476 else
477 {
478 (void) safe_logger(0, 0, NULL);
479
480 /* use _exit() rather than exit() - we malloc() in atexit()
481 */
482 SH_ABORT;
483 _exit (EXIT_FAILURE);
484 }
485}
486#endif
Note: See TracBrowser for help on using the repository browser.