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