]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/smartall.c
6f77db113ff41cbae1c2337a78884ca5090b278b
[bacula/bacula] / bacula / src / lib / smartall.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5    Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6
7    The original author of Bacula is Kern Sibbald, with contributions
8    from many others, a complete list can be found in the file AUTHORS.
9
10    You may use this file and others of this release according to the
11    license defined in the LICENSE file, which includes the Affero General
12    Public License, v3.0 ("AGPLv3") and some additional permissions and
13    terms pursuant to its AGPLv3 Section 7.
14
15    This notice must be preserved when any source code is 
16    conveyed and/or propagated.
17
18    Bacula(R) is a registered trademark of Kern Sibbald.
19 */
20 /*
21
22                          S M A R T A L L O C
23                         Smart Memory Allocator
24
25         Evolved   over   several  years,  starting  with  the  initial
26         SMARTALLOC code for AutoSketch in 1986, guided  by  the  Blind
27         Watchbreaker,  John  Walker.  Isolated in this general-purpose
28         form in  September  of  1989.   Updated  with  be  more  POSIX
29         compliant  and  to  include Web-friendly HTML documentation in
30         October  of  1998  by  the  same  culprit.    For   additional
31         information and the current version visit the Web page:
32
33                   http://www.fourmilab.ch/smartall/
34
35 */
36
37 #define LOCKMGR_COMPLIANT
38
39 #include "bacula.h"
40 /* Use the real routines here */
41 #undef realloc
42 #undef calloc
43 #undef malloc
44 #undef free
45
46 /* We normally turn off debugging here.
47  *  If you want it, simply #ifdef all the
48  *  following off.
49  */
50 #ifdef no_debug_xxxxx
51 #undef Dmsg1
52 #undef Dmsg2
53 #undef Dmsg3
54 #undef Dmsg4
55 #define Dmsg1(l,f,a1)
56 #define Dmsg2(l,f,a1,a2)
57 #define Dmsg3(l,f,a1,a2,a3)
58 #define Dmsg4(l,f,a1,a2,a3,a4)
59 #endif
60
61
62 uint64_t sm_max_bytes = 0;
63 uint64_t sm_bytes = 0;
64 uint32_t sm_max_buffers = 0;
65 uint32_t sm_buffers = 0;
66
67 #ifdef SMARTALLOC
68
69 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
70
71 extern char my_name[];                /* daemon name */
72
73 #define EOS      '\0'              /* End of string sentinel */
74 #define sm_min(a, b) ((a) < (b) ? (a) : (b))
75
76 /*  Queue data structures  */
77
78 /*  Memory allocation control structures and storage.  */
79
80 struct abufhead {
81    struct b_queue abq;         /* Links on allocated queue */
82    uint32_t ablen;             /* Buffer length in bytes */
83    const char *abfname;        /* File name pointer */
84    uint32_t ablineno;          /* Line number of allocation */
85    bool abin_use;              /* set when malloced and cleared when free */
86 };
87
88 static struct b_queue abqueue = {    /* Allocated buffer queue */
89    &abqueue, &abqueue
90 };
91
92
93 static bool bufimode = false;   /* Buffers not tracked when True */
94
95 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
96
97
98 /*  SMALLOC  --  Allocate buffer, enqueing on the orphaned buffer
99                  tracking list.  */
100
101 static void *smalloc(const char *fname, int lineno, unsigned int nbytes)
102 {
103    char *buf;
104
105    /* Note:  Unix  MALLOC  actually  permits  a zero length to be
106       passed and allocates a valid block with  zero  user  bytes.
107       Such  a  block  can  later  be expanded with realloc().  We
108       disallow this based on the belief that it's better to  make
109       a  special case and allocate one byte in the rare case this
110       is desired than to miss all the erroneous occurrences where
111       buffer length calculation code results in a zero.  */
112
113    ASSERT(nbytes > 0);
114
115    nbytes += HEAD_SIZE + 1;
116    if ((buf = (char *)malloc(nbytes)) != NULL) {
117       struct abufhead *head = (struct abufhead *)buf;
118       P(mutex);
119       /* Enqueue buffer on allocated list */
120       qinsert(&abqueue, (struct b_queue *) buf);
121       head->ablen = nbytes;
122       head->abfname = bufimode ? NULL : fname;
123       head->ablineno = (uint32_t)lineno;
124       head->abin_use = true;
125       /* Emplace end-clobber detector at end of buffer */
126       buf[nbytes - 1] = (uint8_t)((((intptr_t) buf) & 0xFF) ^ 0xC5);
127       buf += HEAD_SIZE;  /* Increment to user data start */
128       if (++sm_buffers > sm_max_buffers) {
129          sm_max_buffers = sm_buffers;
130       }
131       sm_bytes += nbytes;
132       if (sm_bytes > sm_max_bytes) {
133          sm_max_bytes = sm_bytes;
134       }
135       V(mutex);
136    } else {
137       Emsg0(M_ABORT, 0, _("Out of memory\n"));
138    }
139    Dmsg4(DT_MEMORY|1050, "smalloc %d at %p from %s:%d\n", nbytes, buf, fname, lineno);
140 #if    SMALLOC_SANITY_CHECK > 0
141    if (sm_bytes > SMALLOC_SANITY_CHECK) {
142       Emsg0(M_ABORT, 0, _("Too much memory used."));
143    }
144 #endif
145    return (void *)buf;
146 }
147
148 /*  SM_NEW_OWNER -- Update the File and line number for a buffer
149                     This is to accomodate mem_pool. */
150
151 void sm_new_owner(const char *fname, int lineno, char *buf)
152 {
153    buf -= HEAD_SIZE;  /* Decrement to header */
154    P(mutex);
155    ((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
156    ((struct abufhead *)buf)->ablineno = (uint32_t) lineno;
157    ((struct abufhead *)buf)->abin_use = true;
158    V(mutex);
159    return;
160 }
161
162 /*  SM_FREE  --  Update free pool availability.  FREE is never called
163                  except  through  this interface or by actuallyfree().
164                  free(x)  is  defined  to  generate  a  call  to  this
165                  routine.  */
166
167 void sm_free(const char *file, int line, void *fp)
168 {
169    char *cp = (char *) fp;
170    struct b_queue *qp;
171    uint32_t lineno = line;
172
173    if (cp == NULL) {
174       Emsg2(M_ABORT, 0, _("Attempt to free NULL called from %s:%d\n"), file, lineno);
175    }
176
177    cp -= HEAD_SIZE;
178    qp = (struct b_queue *)cp;
179    struct abufhead *head = (struct abufhead *)cp;
180
181    P(mutex);
182    Dmsg4(DT_MEMORY|1050, "sm_free %d at %p from %s:%d\n",
183          head->ablen, fp,
184          get_basename(head->abfname), head->ablineno);
185
186    if (!head->abin_use) {
187       V(mutex);
188       Emsg2(M_ABORT, 0, _("in-use bit not set: double free from %s:%d\n"), file, lineno);
189    }
190    head->abin_use = false;
191
192    /* The following assertions will catch virtually every release
193       of an address which isn't an allocated buffer. */
194    if (qp->qnext->qprev != qp) {
195       V(mutex);
196       Emsg2(M_ABORT, 0, _("qp->qnext->qprev != qp called from %s:%d\n"), file, lineno);
197    }
198    if (qp->qprev->qnext != qp) {
199       V(mutex);
200       Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, lineno);
201    }
202
203    /* The following assertion detects storing off the  end  of  the
204       allocated  space in the buffer by comparing the end of buffer
205       checksum with the address of the buffer.  */
206
207    if (((unsigned char *)cp)[head->ablen - 1] != ((((intptr_t) cp) & 0xFF) ^ 0xC5)) {
208       V(mutex);
209       Emsg6(M_ABORT, 0, _("Overrun buffer: len=%d addr=%p allocated: %s:%d called from %s:%d\n"),
210          head->ablen, fp, get_basename(head->abfname), head->ablineno, file, line);
211    }
212    if (sm_buffers > 0) {
213       sm_buffers--;
214       sm_bytes -= head->ablen;
215    }
216
217    qdchain(qp);
218    V(mutex);
219
220    /* Now we wipe the contents of  the  just-released  buffer  with
221       "designer  garbage"  (Duff  Kurland's  phrase) of alternating
222       bits.  This is intended to ruin the day for any miscreant who
223       attempts to access data through a pointer into storage that's
224       been previously released.
225
226       Modified, kes May, 2007 to not zap the header. This allows us
227       to check the in_use bit and detect doubly freed buffers.
228    */
229
230    memset(cp+HEAD_SIZE, 0xAA, (int)(head->ablen - HEAD_SIZE));
231
232    free(cp);
233 }
234
235 /*  SM_MALLOC  --  Allocate buffer.  NULL is returned if no memory
236                    was available.  */
237
238 void *sm_malloc(const char *fname, int lineno, unsigned int nbytes)
239 {
240    void *buf;
241
242    if ((buf = smalloc(fname, lineno, nbytes)) != NULL) {
243
244       /* To catch sloppy code that assumes  buffers  obtained  from
245          malloc()  are  zeroed,  we  preset  the buffer contents to
246          "designer garbage" consisting of alternating bits.  */
247
248       memset(buf, 0x55, (int) nbytes);
249    } else {
250       Emsg0(M_ABORT, 0, _("Out of memory\n"));
251    }
252    return buf;
253 }
254
255 /*  SM_CALLOC  --  Allocate an array and clear it to zero.  */
256
257 void *sm_calloc(const char *fname, int lineno,
258                 unsigned int nelem, unsigned int elsize)
259 {
260    void *buf;
261
262    if ((buf = smalloc(fname, lineno, nelem * elsize)) != NULL) {
263       memset(buf, 0, (int) (nelem * elsize));
264    } else {
265       Emsg0(M_ABORT, 0, _("Out of memory\n"));
266    }
267    return buf;
268 }
269
270 /*  SM_REALLOC  --  Adjust the size of a  previously  allocated  buffer.
271                     Note  that  the trick of "resurrecting" a previously
272                     freed buffer with realloc() is NOT supported by this
273                     function.   Further, because of the need to maintain
274                     our control storage, SM_REALLOC must always allocate
275                     a  new  block  and  copy  the data in the old block.
276                     This may result in programs which make heavy use  of
277                     realloc() running much slower than normally.  */
278
279 void *sm_realloc(const char *fname, int lineno, void *ptr, unsigned int size)
280 {
281    unsigned osize;
282    void *buf;
283    char *cp = (char *) ptr;
284
285    Dmsg4(DT_MEMORY|1050, "sm_realloc %s:%d %p %d\n", get_basename(fname), (uint32_t)lineno, ptr, size);
286    if (size <= 0) {
287       e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size);
288    }
289
290    /*  If  the  old  block  pointer  is  NULL, treat realloc() as a
291       malloc().  SVID is silent  on  this,  but  many  C  libraries
292       permit this.  */
293    if (ptr == NULL) {
294       return sm_malloc(fname, lineno, size);
295    }
296
297    /* If the old and new sizes are the same, be a nice guy and just
298       return the buffer passed in.  */
299    cp -= HEAD_SIZE;
300    struct abufhead *head = (struct abufhead *)cp;
301    osize = head->ablen - (HEAD_SIZE + 1);
302    if (size == osize) {
303       return ptr;
304    }
305
306    /* Sizes differ.  Allocate a new buffer of the  requested  size.
307       If  we  can't  obtain  such a buffer, act as defined in SVID:
308       return NULL from  realloc()  and  leave  the  buffer  in  PTR
309       intact.  */
310
311 // sm_buffers--;
312 // sm_bytes -= head->ablen;
313
314    if ((buf = smalloc(fname, lineno, size)) != NULL) {
315       memcpy(buf, ptr, (int)sm_min(size, osize));
316       /* If the new buffer is larger than the old, fill the balance
317          of it with "designer garbage". */
318       if (size > osize) {
319          memset(((char *) buf) + osize, 0x55, (int) (size - osize));
320       }
321
322       /* All done.  Free and dechain the original buffer. */
323       sm_free(fname, lineno, ptr);
324    }
325    Dmsg4(DT_MEMORY|1060, _("sm_realloc %d at %p from %s:%d\n"), size, buf, get_basename(fname), (uint32_t)lineno);
326    return buf;
327 }
328
329 /*  ACTUALLYMALLOC  --  Call the system malloc() function to obtain
330                         storage which will eventually be released
331                         by system or library routines not compiled
332                         using SMARTALLOC.  */
333
334 void *actuallymalloc(unsigned int size)
335 {
336    return malloc(size);
337 }
338
339 /*  ACTUALLYCALLOC  --  Call the system calloc() function to obtain
340                         storage which will eventually be released
341                         by system or library routines not compiled
342                         using SMARTALLOC.  */
343
344 void *actuallycalloc(unsigned int nelem, unsigned int elsize)
345 {
346    return calloc(nelem, elsize);
347 }
348
349 /*  ACTUALLYREALLOC  --  Call the system realloc() function to obtain
350                          storage which will eventually be released
351                          by system or library routines not compiled
352                          using SMARTALLOC.  */
353
354 void *actuallyrealloc(void *ptr, unsigned int size)
355 {
356    Dmsg2(DT_MEMORY|1040, "Actuallyrealloc %p %d\n", ptr, size);
357    return realloc(ptr, size);
358 }
359
360 /*  ACTUALLYFREE  --  Interface to system free() function to release
361                       buffers allocated by low-level routines. */
362
363 void actuallyfree(void *cp)
364 {
365    free(cp);
366 }
367
368 /*  SM_DUMP  --  Print orphaned buffers (and dump them if BUFDUMP is
369  *               True).
370  */
371 void sm_dump(bool bufdump, bool in_use)
372 {
373    struct abufhead *ap;
374
375    P(mutex);
376
377    ap = (struct abufhead *)abqueue.qnext;
378
379    while (ap != (struct abufhead *) &abqueue) {
380
381       if ((ap == NULL) ||
382           (ap->abq.qnext->qprev != (struct b_queue *) ap) ||
383           (ap->abq.qprev->qnext != (struct b_queue *) ap)) {
384          Pmsg1(0, _(
385             "\nOrphaned buffers exist.  Dump terminated following\n"
386             "  discovery of bad links in chain of orphaned buffers.\n"
387             "  Buffer address with bad links: %p\n"), ap);
388          break;
389       }
390
391       if (ap->abfname != NULL) {
392          char errmsg[500];
393          uint32_t memsize = ap->ablen - (HEAD_SIZE + 1);
394          char *cp = ((char *)ap) + HEAD_SIZE;
395
396          Pmsg6(0, "%s buffer: %s %d bytes at %p from %s:%d\n",
397             in_use?"In use":"Orphaned",
398             my_name, memsize, cp, get_basename(ap->abfname), ap->ablineno);
399          if (bufdump) {
400             char buf[20];
401             unsigned llen = 0;
402
403             errmsg[0] = EOS;
404             while (memsize) {
405                if (llen >= 16) {
406                   bstrncat(errmsg, "\n", sizeof(errmsg));
407                   llen = 0;
408                   Pmsg1(0, "%s", errmsg);
409                   errmsg[0] = EOS;
410                }
411                bsnprintf(buf, sizeof(buf), " %02X",
412                   (*cp++) & 0xFF);
413                bstrncat(errmsg, buf, sizeof(errmsg));
414                llen++;
415                memsize--;
416             }
417             Pmsg1(0, "%s\n", errmsg);
418          }
419       }
420       ap = (struct abufhead *) ap->abq.qnext;
421    }
422    V(mutex);
423 }
424
425 #undef sm_check
426 /*  SM_CHECK --  Check the buffers and dump if any damage exists. */
427 void sm_check(const char *fname, int lineno, bool bufdump)
428 {
429    if (!sm_check_rtn(fname, lineno, bufdump)) {
430       Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"),
431             get_basename(fname), (uint32_t)lineno);
432    }
433 }
434
435 #undef sm_check_rtn
436 /*  SM_CHECK_RTN -- Check the buffers and return 1 if OK otherwise 0 */
437 int sm_check_rtn(const char *fname, int lineno, bool bufdump)
438 {
439    struct abufhead *ap;
440    int bad, badbuf = 0;
441
442    P(mutex);
443    ap = (struct abufhead *) abqueue.qnext;
444    while (ap != (struct abufhead *)&abqueue) {
445       bad = 0;
446       if (ap != NULL) {
447          if (ap->abq.qnext->qprev != (struct b_queue *)ap) {
448             bad = 0x1;
449          }
450          if (ap->abq.qprev->qnext != (struct b_queue *)ap) {
451             bad |= 0x2;
452          }
453          if (((unsigned char *) ap)[((struct abufhead *)ap)->ablen - 1] !=
454               ((((intptr_t) ap) & 0xFF) ^ 0xC5)) {
455             bad |= 0x4;
456          }
457       } else {
458          bad = 0x8;
459       }
460       badbuf |= bad;
461       if (bad) {
462          Pmsg2(0,
463             _("\nDamaged buffers found at %s:%d\n"), get_basename(fname), (uint32_t)lineno);
464
465          if (bad & 0x1) {
466             Pmsg0(0,  _("  discovery of bad prev link.\n"));
467          }
468          if (bad & 0x2) {
469             Pmsg0(0, _("  discovery of bad next link.\n"));
470          }
471          if (bad & 0x4) {
472             Pmsg0(0, _("  discovery of data overrun.\n"));
473          }
474          if (bad & 0x8) {
475             Pmsg0(0, _("  NULL pointer.\n"));
476          }
477
478          if (!ap) {
479             goto get_out;
480          }
481          Pmsg1(0, _("  Buffer address: %p\n"), ap);
482
483          if (ap->abfname != NULL) {
484             uint32_t memsize = ap->ablen - (HEAD_SIZE + 1);
485             char errmsg[80];
486
487             Pmsg4(0,
488               _("Damaged buffer:  %6u bytes allocated at line %d of %s %s\n"),
489                memsize, ap->ablineno, my_name, get_basename(ap->abfname)
490             );
491             if (bufdump) {
492                unsigned llen = 0;
493                char *cp = ((char *) ap) + HEAD_SIZE;
494
495                errmsg[0] = EOS;
496                while (memsize) {
497                   if (llen >= 16) {
498                      strcat(errmsg, "\n");
499                      llen = 0;
500                      Pmsg1(0, "%s", errmsg);
501                      errmsg[0] = EOS;
502                   }
503                   if (*cp < 0x20) {
504                      sprintf(errmsg + strlen(errmsg), " %02X",
505                         (*cp++) & 0xFF);
506                   } else {
507                      sprintf(errmsg + strlen(errmsg), " %c ",
508                         (*cp++) & 0xFF);
509                   }
510                   llen++;
511                   memsize--;
512                }
513                Pmsg1(0, "%s\n", errmsg);
514             }
515          }
516       }
517       ap = (struct abufhead *)ap->abq.qnext;
518    }
519 get_out:
520    V(mutex);
521    return badbuf ? 0 : 1;
522 }
523
524
525 /*  SM_STATIC  --  Orphaned buffer detection can be disabled  (for  such
526                    items  as buffers allocated during initialisation) by
527                    calling   sm_static(1).    Normal   orphaned   buffer
528                    detection  can be re-enabled with sm_static(0).  Note
529                    that all the other safeguards still apply to  buffers
530                    allocated  when  sm_static(1)  mode is in effect.  */
531
532 void sm_static(bool mode)
533 {
534    bufimode = mode;
535 }
536
537 /*
538  * Here we overload C++'s global new and delete operators
539  *  so that the memory is allocated through smartalloc.
540  */
541
542 #ifdef xxx
543 void * operator new(size_t size)
544 {
545 // Dmsg1(000, "new called %d\n", size);
546    return sm_malloc(__FILE__, __LINE__, size);
547 }
548
549 void operator delete(void *buf)
550 {
551 // Dmsg1(000, "free called %p\n", buf);
552    sm_free(__FILE__, __LINE__, buf);
553 }
554 #endif
555
556 #endif