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