3e091d88f47d2b6f5cc26d0c82f4793985a364c5
[libgcrypt.git] / src / secmem.c
1 /* secmem.c  -  memory allocation from a secure heap
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3  *               2003, 2007 Free Software Foundation, Inc.
4  * Copyright (C) 2013, 2016 g10 Code GmbH
5  *
6  * This file is part of Libgcrypt.
7  *
8  * Libgcrypt is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser general Public License as
10  * published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * Libgcrypt is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <stdarg.h>
28 #include <unistd.h>
29 #include <stddef.h>
30
31 #if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
32 #include <sys/mman.h>
33 #include <sys/types.h>
34 #include <fcntl.h>
35 #ifdef USE_CAPABILITIES
36 #include <sys/capability.h>
37 #endif
38 #endif
39
40 #include "g10lib.h"
41 #include "secmem.h"
42
43 #if defined (MAP_ANON) && ! defined (MAP_ANONYMOUS)
44 #define MAP_ANONYMOUS MAP_ANON
45 #endif
46
47 #define MINIMUM_POOL_SIZE 16384
48 #define STANDARD_POOL_SIZE 32768
49 #define DEFAULT_PAGE_SIZE 4096
50
51 typedef struct memblock
52 {
53   unsigned size;                /* Size of the memory available to the
54                                    user.  */
55   int flags;                    /* See below.  */
56   PROPERLY_ALIGNED_TYPE aligned;
57 } memblock_t;
58
59 /* This flag specifies that the memory block is in use.  */
60 #define MB_FLAG_ACTIVE (1 << 0)
61
62 /* An object describing a memory pool.  */
63 typedef struct pooldesc_s
64 {
65   /* A link to the next pool.  This is used to connect the overflow
66    * pools.  */
67   struct pooldesc_s *next;
68
69   /* A memory buffer used as allocation pool.  */
70   void *mem;
71
72   /* The allocated size of MEM. */
73   size_t size;
74
75   /* Flag indicating that this memory pool is ready for use.  May be
76    * checked in an atexit function.  */
77   volatile int okay;
78
79   /* Flag indicating whether MEM is mmapped.  */
80   volatile int is_mmapped;
81
82   /* The number of allocated bytes and the number of used blocks in
83    * this pool.  */
84   unsigned int cur_alloced, cur_blocks;
85 } pooldesc_t;
86
87
88 /* The pool of secure memory.  This is the head of a linked list with
89  * the first element being the standard mlock-ed pool and the
90  * following elements being the overflow pools. */
91 static pooldesc_t mainpool;
92
93
94 /* A couple of flags with some being set early.  */
95 static int disable_secmem;
96 static int show_warning;
97 static int not_locked;
98 static int no_warning;
99 static int suspend_warning;
100 static int no_mlock;
101 static int no_priv_drop;
102 static unsigned int auto_expand;
103
104
105 /* Lock protecting accesses to the memory pools.  */
106 GPGRT_LOCK_DEFINE (secmem_lock);
107
108 /* Convenient macros.  */
109 #define SECMEM_LOCK   gpgrt_lock_lock   (&secmem_lock)
110 #define SECMEM_UNLOCK gpgrt_lock_unlock (&secmem_lock)
111
112 /* The size of the memblock structure; this does not include the
113    memory that is available to the user.  */
114 #define BLOCK_HEAD_SIZE \
115   offsetof (memblock_t, aligned)
116
117 /* Convert an address into the according memory block structure.  */
118 #define ADDR_TO_BLOCK(addr) \
119   (memblock_t *) (void *) ((char *) addr - BLOCK_HEAD_SIZE)
120
121 /* Check whether P points into POOL.  */
122 static inline int
123 ptr_into_pool_p (pooldesc_t *pool, const void *p)
124 {
125   /* We need to convert pointers to addresses.  This is required by
126      C-99 6.5.8 to avoid undefined behaviour.  See also
127      http://lists.gnupg.org/pipermail/gcrypt-devel/2007-February/001102.html
128   */
129   uintptr_t p_addr    = (uintptr_t)p;
130   uintptr_t pool_addr = (uintptr_t)pool->mem;
131
132   return p_addr >= pool_addr && p_addr <  pool_addr + pool->size;
133 }
134
135 /* Update the stats.  */
136 static void
137 stats_update (pooldesc_t *pool, size_t add, size_t sub)
138 {
139   if (add)
140     {
141       pool->cur_alloced += add;
142       pool->cur_blocks++;
143     }
144   if (sub)
145     {
146       pool->cur_alloced -= sub;
147       pool->cur_blocks--;
148     }
149 }
150
151 /* Return the block following MB or NULL, if MB is the last block.  */
152 static memblock_t *
153 mb_get_next (pooldesc_t *pool, memblock_t *mb)
154 {
155   memblock_t *mb_next;
156
157   mb_next = (memblock_t *) (void *) ((char *) mb + BLOCK_HEAD_SIZE + mb->size);
158
159   if (! ptr_into_pool_p (pool, mb_next))
160     mb_next = NULL;
161
162   return mb_next;
163 }
164
165 /* Return the block preceding MB or NULL, if MB is the first
166    block.  */
167 static memblock_t *
168 mb_get_prev (pooldesc_t *pool, memblock_t *mb)
169 {
170   memblock_t *mb_prev, *mb_next;
171
172   if (mb == pool->mem)
173     mb_prev = NULL;
174   else
175     {
176       mb_prev = (memblock_t *) pool->mem;
177       while (1)
178         {
179           mb_next = mb_get_next (pool, mb_prev);
180           if (mb_next == mb)
181             break;
182           else
183             mb_prev = mb_next;
184         }
185     }
186
187   return mb_prev;
188 }
189
190 /* If the preceding block of MB and/or the following block of MB
191    exist and are not active, merge them to form a bigger block.  */
192 static void
193 mb_merge (pooldesc_t *pool, memblock_t *mb)
194 {
195   memblock_t *mb_prev, *mb_next;
196
197   mb_prev = mb_get_prev (pool, mb);
198   mb_next = mb_get_next (pool, mb);
199
200   if (mb_prev && (! (mb_prev->flags & MB_FLAG_ACTIVE)))
201     {
202       mb_prev->size += BLOCK_HEAD_SIZE + mb->size;
203       mb = mb_prev;
204     }
205   if (mb_next && (! (mb_next->flags & MB_FLAG_ACTIVE)))
206     mb->size += BLOCK_HEAD_SIZE + mb_next->size;
207 }
208
209 /* Return a new block, which can hold SIZE bytes.  */
210 static memblock_t *
211 mb_get_new (pooldesc_t *pool, memblock_t *block, size_t size)
212 {
213   memblock_t *mb, *mb_split;
214
215   for (mb = block; ptr_into_pool_p (pool, mb); mb = mb_get_next (pool, mb))
216     if (! (mb->flags & MB_FLAG_ACTIVE) && mb->size >= size)
217       {
218         /* Found a free block.  */
219         mb->flags |= MB_FLAG_ACTIVE;
220
221         if (mb->size - size > BLOCK_HEAD_SIZE)
222           {
223             /* Split block.  */
224
225             mb_split = (memblock_t *) (void *) (((char *) mb) + BLOCK_HEAD_SIZE
226                                                 + size);
227             mb_split->size = mb->size - size - BLOCK_HEAD_SIZE;
228             mb_split->flags = 0;
229
230             mb->size = size;
231
232             mb_merge (pool, mb_split);
233
234           }
235
236         break;
237       }
238
239   if (! ptr_into_pool_p (pool, mb))
240     {
241       gpg_err_set_errno (ENOMEM);
242       mb = NULL;
243     }
244
245   return mb;
246 }
247
248 /* Print a warning message.  */
249 static void
250 print_warn (void)
251 {
252   if (!no_warning)
253     log_info (_("Warning: using insecure memory!\n"));
254 }
255
256
257 /* Lock the memory pages of pool P of size N into core and drop
258  * privileges.  */
259 static void
260 lock_pool_pages (void *p, size_t n)
261 {
262 #if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK)
263   int err;
264
265   {
266     cap_t cap;
267
268     if (!no_priv_drop)
269       {
270         cap = cap_from_text ("cap_ipc_lock+ep");
271         cap_set_proc (cap);
272         cap_free (cap);
273       }
274     err = no_mlock? 0 : mlock (p, n);
275     if (err && errno)
276       err = errno;
277     if (!no_priv_drop)
278       {
279         cap = cap_from_text ("cap_ipc_lock+p");
280         cap_set_proc (cap);
281         cap_free(cap);
282       }
283   }
284
285   if (err)
286     {
287       if (err != EPERM
288 #ifdef EAGAIN   /* BSD and also Linux may return EAGAIN */
289           && err != EAGAIN
290 #endif
291 #ifdef ENOSYS   /* Some SCOs return this (function not implemented) */
292           && err != ENOSYS
293 #endif
294 #ifdef ENOMEM  /* Linux might return this. */
295             && err != ENOMEM
296 #endif
297           )
298         log_error ("can't lock memory: %s\n", strerror (err));
299       show_warning = 1;
300       not_locked = 1;
301     }
302
303 #elif defined(HAVE_MLOCK)
304   uid_t uid;
305   int err;
306
307   uid = getuid ();
308
309 #ifdef HAVE_BROKEN_MLOCK
310   /* Under HP/UX mlock segfaults if called by non-root.  Note, we have
311      noch checked whether mlock does really work under AIX where we
312      also detected a broken nlock.  Note further, that using plock ()
313      is not a good idea under AIX. */
314   if (uid)
315     {
316       errno = EPERM;
317       err = errno;
318     }
319   else
320     {
321       err = no_mlock? 0 : mlock (p, n);
322       if (err && errno)
323         err = errno;
324     }
325 #else /* !HAVE_BROKEN_MLOCK */
326   err = no_mlock? 0 : mlock (p, n);
327   if (err && errno)
328     err = errno;
329 #endif /* !HAVE_BROKEN_MLOCK */
330
331   /* Test whether we are running setuid(0).  */
332   if (uid && ! geteuid ())
333     {
334       /* Yes, we are.  */
335       if (!no_priv_drop)
336         {
337           /* Check that we really dropped the privs.
338            * Note: setuid(0) should always fail */
339           if (setuid (uid) || getuid () != geteuid () || !setuid (0))
340             log_fatal ("failed to reset uid: %s\n", strerror (errno));
341         }
342     }
343
344   if (err)
345     {
346       if (err != EPERM
347 #ifdef EAGAIN   /* BSD and also Linux may return this. */
348           && err != EAGAIN
349 #endif
350 #ifdef ENOSYS   /* Some SCOs return this (function not implemented). */
351           && err != ENOSYS
352 #endif
353 #ifdef ENOMEM  /* Linux might return this. */
354             && err != ENOMEM
355 #endif
356           )
357         log_error ("can't lock memory: %s\n", strerror (err));
358       show_warning = 1;
359       not_locked = 1;
360     }
361
362 #elif defined ( __QNX__ )
363   /* QNX does not page at all, so the whole secure memory stuff does
364    * not make much sense.  However it is still of use because it
365    * wipes out the memory on a free().
366    * Therefore it is sufficient to suppress the warning.  */
367   (void)p;
368   (void)n;
369 #elif defined (HAVE_DOSISH_SYSTEM) || defined (__CYGWIN__)
370     /* It does not make sense to print such a warning, given the fact that
371      * this whole Windows !@#$% and their user base are inherently insecure. */
372   (void)p;
373   (void)n;
374 #elif defined (__riscos__)
375     /* No virtual memory on RISC OS, so no pages are swapped to disc,
376      * besides we don't have mmap, so we don't use it! ;-)
377      * But don't complain, as explained above.  */
378   (void)p;
379   (void)n;
380 #else
381   (void)p;
382   (void)n;
383   if (!no_mlock)
384     log_info ("Please note that you don't have secure memory on this system\n");
385 #endif
386 }
387
388 /* Initialize POOL.  */
389 static void
390 init_pool (pooldesc_t *pool, size_t n)
391 {
392   memblock_t *mb;
393
394   pool->size = n;
395
396   if (disable_secmem)
397     log_bug ("secure memory is disabled");
398
399
400 #if HAVE_MMAP
401   {
402     size_t pgsize;
403     long int pgsize_val;
404
405 # if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
406     pgsize_val = sysconf (_SC_PAGESIZE);
407 # elif defined(HAVE_GETPAGESIZE)
408     pgsize_val = getpagesize ();
409 # else
410     pgsize_val = -1;
411 # endif
412     pgsize = (pgsize_val > 0)? pgsize_val:DEFAULT_PAGE_SIZE;
413
414     pool->size = (pool->size + pgsize - 1) & ~(pgsize - 1);
415 # ifdef MAP_ANONYMOUS
416     pool->mem = mmap (0, pool->size, PROT_READ | PROT_WRITE,
417                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
418 # else /* map /dev/zero instead */
419     {
420       int fd;
421
422       fd = open ("/dev/zero", O_RDWR);
423       if (fd == -1)
424         {
425           log_error ("can't open /dev/zero: %s\n", strerror (errno));
426           pool->mem = (void *) -1;
427         }
428       else
429         {
430           pool->mem = mmap (0, pool->size,
431                            (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);
432           close (fd);
433         }
434     }
435 # endif
436     if (pool->mem == (void *) -1)
437       log_info ("can't mmap pool of %u bytes: %s - using malloc\n",
438                 (unsigned) pool->size, strerror (errno));
439     else
440       {
441         pool->is_mmapped = 1;
442         pool->okay = 1;
443       }
444   }
445 #endif /*HAVE_MMAP*/
446
447   if (!pool->okay)
448     {
449       pool->mem = malloc (pool->size);
450       if (!pool->mem)
451         log_fatal ("can't allocate memory pool of %u bytes\n",
452                    (unsigned) pool->size);
453       else
454         pool->okay = 1;
455     }
456
457   /* Initialize first memory block.  */
458   mb = (memblock_t *) pool->mem;
459   mb->size = pool->size - BLOCK_HEAD_SIZE;
460   mb->flags = 0;
461 }
462
463
464 /* Enable overflow pool allocation in all cases.  CHUNKSIZE is a hint
465  * on how large to allocate overflow pools.  */
466 void
467 _gcry_secmem_set_auto_expand (unsigned int chunksize)
468 {
469   /* Round up to a multiple of the STANDARD_POOL_SIZE.  */
470   chunksize = ((chunksize + (2*STANDARD_POOL_SIZE) - 1)
471                / STANDARD_POOL_SIZE ) * STANDARD_POOL_SIZE;
472   if (chunksize < STANDARD_POOL_SIZE) /* In case of overflow.  */
473     chunksize = STANDARD_POOL_SIZE;
474
475   SECMEM_LOCK;
476   auto_expand = chunksize;
477   SECMEM_UNLOCK;
478 }
479
480
481 void
482 _gcry_secmem_set_flags (unsigned flags)
483 {
484   int was_susp;
485
486   SECMEM_LOCK;
487
488   was_susp = suspend_warning;
489   no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING;
490   suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING;
491   no_mlock      = flags & GCRY_SECMEM_FLAG_NO_MLOCK;
492   no_priv_drop = flags & GCRY_SECMEM_FLAG_NO_PRIV_DROP;
493
494   /* and now issue the warning if it is not longer suspended */
495   if (was_susp && !suspend_warning && show_warning)
496     {
497       show_warning = 0;
498       print_warn ();
499     }
500
501   SECMEM_UNLOCK;
502 }
503
504 unsigned int
505 _gcry_secmem_get_flags (void)
506 {
507   unsigned flags;
508
509   SECMEM_LOCK;
510
511   flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0;
512   flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0;
513   flags |= not_locked ? GCRY_SECMEM_FLAG_NOT_LOCKED : 0;
514   flags |= no_mlock ? GCRY_SECMEM_FLAG_NO_MLOCK : 0;
515   flags |= no_priv_drop ? GCRY_SECMEM_FLAG_NO_PRIV_DROP : 0;
516
517   SECMEM_UNLOCK;
518
519   return flags;
520 }
521
522
523 /* This function initializes the main memory pool MAINPOOL.  Itis
524  * expected to be called with the secmem lock held.  */
525 static void
526 _gcry_secmem_init_internal (size_t n)
527 {
528   pooldesc_t *pool;
529
530   pool = &mainpool;
531   if (!n)
532     {
533 #ifdef USE_CAPABILITIES
534       /* drop all capabilities */
535       if (!no_priv_drop)
536         {
537           cap_t cap;
538
539           cap = cap_from_text ("all-eip");
540           cap_set_proc (cap);
541           cap_free (cap);
542         }
543
544 #elif !defined(HAVE_DOSISH_SYSTEM)
545       uid_t uid;
546
547       disable_secmem = 1;
548       uid = getuid ();
549       if (uid != geteuid ())
550         {
551           if (setuid (uid) || getuid () != geteuid () || !setuid (0))
552             log_fatal ("failed to drop setuid\n");
553         }
554 #endif
555     }
556   else
557     {
558       if (n < MINIMUM_POOL_SIZE)
559         n = MINIMUM_POOL_SIZE;
560       if (! pool->okay)
561         {
562           init_pool (pool, n);
563           lock_pool_pages (pool->mem, n);
564         }
565       else
566         log_error ("Oops, secure memory pool already initialized\n");
567     }
568 }
569
570
571
572 /* Initialize the secure memory system.  If running with the necessary
573    privileges, the secure memory pool will be locked into the core in
574    order to prevent page-outs of the data.  Furthermore allocated
575    secure memory will be wiped out when released.  */
576 void
577 _gcry_secmem_init (size_t n)
578 {
579   SECMEM_LOCK;
580
581   _gcry_secmem_init_internal (n);
582
583   SECMEM_UNLOCK;
584 }
585
586
587 gcry_err_code_t
588 _gcry_secmem_module_init ()
589 {
590   /* Not anymore needed.  */
591   return 0;
592 }
593
594
595 static void *
596 _gcry_secmem_malloc_internal (size_t size, int xhint)
597 {
598   pooldesc_t *pool;
599   memblock_t *mb;
600
601   pool = &mainpool;
602
603   if (!pool->okay)
604     {
605       /* Try to initialize the pool if the user forgot about it.  */
606       _gcry_secmem_init_internal (STANDARD_POOL_SIZE);
607       if (!pool->okay)
608         {
609           log_info (_("operation is not possible without "
610                       "initialized secure memory\n"));
611           gpg_err_set_errno (ENOMEM);
612           return NULL;
613         }
614     }
615   if (not_locked && fips_mode ())
616     {
617       log_info (_("secure memory pool is not locked while in FIPS mode\n"));
618       gpg_err_set_errno (ENOMEM);
619       return NULL;
620     }
621   if (show_warning && !suspend_warning)
622     {
623       show_warning = 0;
624       print_warn ();
625     }
626
627   /* Blocks are always a multiple of 32. */
628   size = ((size + 31) / 32) * 32;
629
630   mb = mb_get_new (pool, (memblock_t *) pool->mem, size);
631   if (mb)
632     {
633       stats_update (pool, mb->size, 0);
634       return &mb->aligned.c;
635     }
636
637   /* If we are called from xmalloc style function resort to the
638    * overflow pools to return memory.  We don't do this in FIPS mode,
639    * though. */
640   if ((xhint || auto_expand) && !fips_mode ())
641     {
642       for (pool = pool->next; pool; pool = pool->next)
643         {
644           mb = mb_get_new (pool, (memblock_t *) pool->mem, size);
645           if (mb)
646             {
647               stats_update (pool, mb->size, 0);
648               return &mb->aligned.c;
649             }
650         }
651       /* Allocate a new overflow pool.  We put a new pool right after
652        * the mainpool so that the next allocation will happen in that
653        * pool and not in one of the older pools.  When this new pool
654        * gets full we will try to find space in the older pools.  */
655       pool = calloc (1, sizeof *pool);
656       if (!pool)
657         return NULL;  /* Not enough memory for a new pool descriptor.  */
658       pool->size = auto_expand? auto_expand : STANDARD_POOL_SIZE;
659       pool->mem = malloc (pool->size);
660       if (!pool->mem)
661         {
662           free (pool);
663           return NULL; /* Not enough memory available for a new pool.  */
664         }
665       /* Initialize first memory block.  */
666       mb = (memblock_t *) pool->mem;
667       mb->size = pool->size - BLOCK_HEAD_SIZE;
668       mb->flags = 0;
669
670       pool->okay = 1;
671
672       /* Take care: in _gcry_private_is_secure we do not lock and thus
673        * we assume that the second assignment below is atomic.  */
674       pool->next = mainpool.next;
675       mainpool.next = pool;
676
677       /* After the first time we allocated an overflow pool, print a
678        * warning.  */
679       if (!pool->next)
680         print_warn ();
681
682       /* Allocate.  */
683       mb = mb_get_new (pool, (memblock_t *) pool->mem, size);
684       if (mb)
685         {
686           stats_update (pool, mb->size, 0);
687           return &mb->aligned.c;
688         }
689     }
690
691   return NULL;
692 }
693
694
695 /* Allocate a block from the secmem of SIZE.  With XHINT set assume
696  * that the caller is a xmalloc style function.  */
697 void *
698 _gcry_secmem_malloc (size_t size, int xhint)
699 {
700   void *p;
701
702   SECMEM_LOCK;
703   p = _gcry_secmem_malloc_internal (size, xhint);
704   SECMEM_UNLOCK;
705
706   return p;
707 }
708
709 static int
710 _gcry_secmem_free_internal (void *a)
711 {
712   pooldesc_t *pool;
713   memblock_t *mb;
714   int size;
715
716   for (pool = &mainpool; pool; pool = pool->next)
717     if (pool->okay && ptr_into_pool_p (pool, a))
718       break;
719   if (!pool)
720     return 0; /* A does not belong to use.  */
721
722   mb = ADDR_TO_BLOCK (a);
723   size = mb->size;
724
725   /* This does not make much sense: probably this memory is held in the
726    * cache. We do it anyway: */
727 #define MB_WIPE_OUT(byte) \
728   wipememory2 (((char *) mb + BLOCK_HEAD_SIZE), (byte), size);
729
730   MB_WIPE_OUT (0xff);
731   MB_WIPE_OUT (0xaa);
732   MB_WIPE_OUT (0x55);
733   MB_WIPE_OUT (0x00);
734
735   /* Update stats.  */
736   stats_update (pool, 0, size);
737
738   mb->flags &= ~MB_FLAG_ACTIVE;
739
740   mb_merge (pool, mb);
741
742   return 1; /* Freed.  */
743 }
744
745
746 /* Wipe out and release memory.  Returns true if this function
747  * actually released A.  */
748 int
749 _gcry_secmem_free (void *a)
750 {
751   int mine;
752
753   if (!a)
754     return 1; /* Tell caller that we handled it.  */
755
756   SECMEM_LOCK;
757   mine = _gcry_secmem_free_internal (a);
758   SECMEM_UNLOCK;
759   return mine;
760 }
761
762
763 static void *
764 _gcry_secmem_realloc_internal (void *p, size_t newsize, int xhint)
765 {
766   memblock_t *mb;
767   size_t size;
768   void *a;
769
770   mb = (memblock_t *) (void *) ((char *) p
771                                 - ((size_t) &((memblock_t *) 0)->aligned.c));
772   size = mb->size;
773   if (newsize < size)
774     {
775       /* It is easier to not shrink the memory.  */
776       a = p;
777     }
778   else
779     {
780       a = _gcry_secmem_malloc_internal (newsize, xhint);
781       if (a)
782         {
783           memcpy (a, p, size);
784           memset ((char *) a + size, 0, newsize - size);
785           _gcry_secmem_free_internal (p);
786         }
787     }
788
789   return a;
790 }
791
792
793 /* Realloc memory.  With XHINT set assume that the caller is a xmalloc
794  * style function.  */
795 void *
796 _gcry_secmem_realloc (void *p, size_t newsize, int xhint)
797 {
798   void *a;
799
800   SECMEM_LOCK;
801   a = _gcry_secmem_realloc_internal (p, newsize, xhint);
802   SECMEM_UNLOCK;
803
804   return a;
805 }
806
807
808 /* Return true if P points into the secure memory areas.  */
809 int
810 _gcry_private_is_secure (const void *p)
811 {
812   pooldesc_t *pool;
813
814   /* We do no lock here because once a pool is allocatred it will not
815    * be removed anymore (except for gcry_secmem_term).  Further,
816    * adding a new pool to the list should be atomic.  */
817   for (pool = &mainpool; pool; pool = pool->next)
818     if (pool->okay && ptr_into_pool_p (pool, p))
819       return 1;
820
821   return 0;
822 }
823
824
825 /****************
826  * Warning:  This code might be called by an interrupt handler
827  *           and frankly, there should really be such a handler,
828  *           to make sure that the memory is wiped out.
829  *           We hope that the OS wipes out mlocked memory after
830  *           receiving a SIGKILL - it really should do so, otherwise
831  *           there is no chance to get the secure memory cleaned.
832  */
833 void
834 _gcry_secmem_term ()
835 {
836   pooldesc_t *pool, *next;
837
838   for (pool = &mainpool; pool; pool = next)
839     {
840       next = pool->next;
841       if (!pool->okay)
842         continue;
843
844       wipememory2 (pool->mem, 0xff, pool->size);
845       wipememory2 (pool->mem, 0xaa, pool->size);
846       wipememory2 (pool->mem, 0x55, pool->size);
847       wipememory2 (pool->mem, 0x00, pool->size);
848       if (0)
849         ;
850 #if HAVE_MMAP
851       else if (pool->is_mmapped)
852         munmap (pool->mem, pool->size);
853 #endif
854       else
855         free (pool->mem);
856       pool->mem = NULL;
857       pool->okay = 0;
858       pool->size = 0;
859       if (pool != &mainpool)
860         free (pool);
861     }
862   mainpool.next = NULL;
863   not_locked = 0;
864 }
865
866
867 /* Print stats of the secmem allocator.  With EXTENDED passwed as true
868  * a detiled listing is returned (used for testing).  */
869 void
870 _gcry_secmem_dump_stats (int extended)
871 {
872   pooldesc_t *pool;
873   memblock_t *mb;
874   int i, poolno;
875
876   SECMEM_LOCK;
877
878   for (pool = &mainpool, poolno = 0; pool; pool = pool->next, poolno++)
879     {
880       if (!extended)
881         {
882           if (pool->okay)
883             log_info ("%-13s %u/%lu bytes in %u blocks\n",
884                       pool == &mainpool? "secmem usage:":"",
885                       pool->cur_alloced, (unsigned long)pool->size,
886                       pool->cur_blocks);
887         }
888       else
889         {
890           for (i = 0, mb = (memblock_t *) pool->mem;
891                ptr_into_pool_p (pool, mb);
892                mb = mb_get_next (pool, mb), i++)
893             log_info ("SECMEM: pool %d %s block %i size %i\n",
894                       poolno,
895                       (mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
896                       i,
897                       mb->size);
898         }
899     }
900   SECMEM_UNLOCK;
901 }