LCOV - code coverage report
Current view: top level - src - secmem.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 135 213 63.4 %
Date: 2016-11-29 14:56:30 Functions: 18 22 81.8 %

          Line data    Source code
       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 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             : /* The pool of secure memory.  */
      63             : static void *pool;
      64             : 
      65             : /* Size of POOL in bytes.  */
      66             : static size_t pool_size;
      67             : 
      68             : /* True, if the memory pool is ready for use.  May be checked in an
      69             :    atexit function.  */
      70             : static volatile int pool_okay;
      71             : 
      72             : /* True, if the memory pool is mmapped.  */
      73             : static volatile int pool_is_mmapped;
      74             : 
      75             : /* FIXME?  */
      76             : static int disable_secmem;
      77             : static int show_warning;
      78             : static int not_locked;
      79             : static int no_warning;
      80             : static int suspend_warning;
      81             : static int no_mlock;
      82             : static int no_priv_drop;
      83             : 
      84             : /* Stats.  */
      85             : static unsigned int cur_alloced, cur_blocks;
      86             : 
      87             : /* Lock protecting accesses to the memory pool.  */
      88             : GPGRT_LOCK_DEFINE (secmem_lock);
      89             : 
      90             : /* Convenient macros.  */
      91             : #define SECMEM_LOCK   gpgrt_lock_lock   (&secmem_lock)
      92             : #define SECMEM_UNLOCK gpgrt_lock_unlock (&secmem_lock)
      93             : 
      94             : /* The size of the memblock structure; this does not include the
      95             :    memory that is available to the user.  */
      96             : #define BLOCK_HEAD_SIZE \
      97             :   offsetof (memblock_t, aligned)
      98             : 
      99             : /* Convert an address into the according memory block structure.  */
     100             : #define ADDR_TO_BLOCK(addr) \
     101             :   (memblock_t *) (void *) ((char *) addr - BLOCK_HEAD_SIZE)
     102             : 
     103             : /* Check whether P points into the pool.  */
     104             : static int
     105        1091 : ptr_into_pool_p (const void *p)
     106             : {
     107             :   /* We need to convert pointers to addresses.  This is required by
     108             :      C-99 6.5.8 to avoid undefined behaviour.  See also
     109             :      http://lists.gnupg.org/pipermail/gcrypt-devel/2007-February/001102.html
     110             :   */
     111        1091 :   uintptr_t p_addr    = (uintptr_t)p;
     112        1091 :   uintptr_t pool_addr = (uintptr_t)pool;
     113             : 
     114        1091 :   return p_addr >= pool_addr && p_addr <  pool_addr + pool_size;
     115             : }
     116             : 
     117             : /* Update the stats.  */
     118             : static void
     119           5 : stats_update (size_t add, size_t sub)
     120             : {
     121           5 :   if (add)
     122             :     {
     123           3 :       cur_alloced += add;
     124           3 :       cur_blocks++;
     125             :     }
     126           5 :   if (sub)
     127             :     {
     128           2 :       cur_alloced -= sub;
     129           2 :       cur_blocks--;
     130             :     }
     131           5 : }
     132             : 
     133             : /* Return the block following MB or NULL, if MB is the last block.  */
     134             : static memblock_t *
     135          14 : mb_get_next (memblock_t *mb)
     136             : {
     137             :   memblock_t *mb_next;
     138             : 
     139          14 :   mb_next = (memblock_t *) (void *) ((char *) mb + BLOCK_HEAD_SIZE + mb->size);
     140             : 
     141          14 :   if (! ptr_into_pool_p (mb_next))
     142           3 :     mb_next = NULL;
     143             : 
     144          14 :   return mb_next;
     145             : }
     146             : 
     147             : /* Return the block preceding MB or NULL, if MB is the first
     148             :    block.  */
     149             : static memblock_t *
     150           5 : mb_get_prev (memblock_t *mb)
     151             : {
     152             :   memblock_t *mb_prev, *mb_next;
     153             : 
     154           5 :   if (mb == pool)
     155           0 :     mb_prev = NULL;
     156             :   else
     157             :     {
     158           5 :       mb_prev = (memblock_t *) pool;
     159             :       while (1)
     160             :         {
     161           7 :           mb_next = mb_get_next (mb_prev);
     162           7 :           if (mb_next == mb)
     163           5 :             break;
     164             :           else
     165           2 :             mb_prev = mb_next;
     166           2 :         }
     167             :     }
     168             : 
     169           5 :   return mb_prev;
     170             : }
     171             : 
     172             : /* If the preceding block of MB and/or the following block of MB
     173             :    exist and are not active, merge them to form a bigger block.  */
     174             : static void
     175           5 : mb_merge (memblock_t *mb)
     176             : {
     177             :   memblock_t *mb_prev, *mb_next;
     178             : 
     179           5 :   mb_prev = mb_get_prev (mb);
     180           5 :   mb_next = mb_get_next (mb);
     181             : 
     182           5 :   if (mb_prev && (! (mb_prev->flags & MB_FLAG_ACTIVE)))
     183             :     {
     184           0 :       mb_prev->size += BLOCK_HEAD_SIZE + mb->size;
     185           0 :       mb = mb_prev;
     186             :     }
     187           5 :   if (mb_next && (! (mb_next->flags & MB_FLAG_ACTIVE)))
     188           2 :     mb->size += BLOCK_HEAD_SIZE + mb_next->size;
     189           5 : }
     190             : 
     191             : /* Return a new block, which can hold SIZE bytes.  */
     192             : static memblock_t *
     193           3 : mb_get_new (memblock_t *block, size_t size)
     194             : {
     195             :   memblock_t *mb, *mb_split;
     196             : 
     197           5 :   for (mb = block; ptr_into_pool_p (mb); mb = mb_get_next (mb))
     198           5 :     if (! (mb->flags & MB_FLAG_ACTIVE) && mb->size >= size)
     199             :       {
     200             :         /* Found a free block.  */
     201           3 :         mb->flags |= MB_FLAG_ACTIVE;
     202             : 
     203           3 :         if (mb->size - size > BLOCK_HEAD_SIZE)
     204             :           {
     205             :             /* Split block.  */
     206             : 
     207           3 :             mb_split = (memblock_t *) (void *) (((char *) mb) + BLOCK_HEAD_SIZE
     208           3 :                                                 + size);
     209           3 :             mb_split->size = mb->size - size - BLOCK_HEAD_SIZE;
     210           3 :             mb_split->flags = 0;
     211             : 
     212           3 :             mb->size = size;
     213             : 
     214           3 :             mb_merge (mb_split);
     215             : 
     216             :           }
     217             : 
     218           3 :         break;
     219             :       }
     220             : 
     221           3 :   if (! ptr_into_pool_p (mb))
     222             :     {
     223           0 :       gpg_err_set_errno (ENOMEM);
     224           0 :       mb = NULL;
     225             :     }
     226             : 
     227           3 :   return mb;
     228             : }
     229             : 
     230             : /* Print a warning message.  */
     231             : static void
     232           0 : print_warn (void)
     233             : {
     234           0 :   if (!no_warning)
     235           0 :     log_info (_("Warning: using insecure memory!\n"));
     236           0 : }
     237             : 
     238             : /* Lock the memory pages into core and drop privileges.  */
     239             : static void
     240           1 : lock_pool (void *p, size_t n)
     241             : {
     242             : #if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK)
     243             :   int err;
     244             : 
     245             :   {
     246             :     cap_t cap;
     247             : 
     248             :     if (!no_priv_drop)
     249             :       {
     250             :         cap = cap_from_text ("cap_ipc_lock+ep");
     251             :         cap_set_proc (cap);
     252             :         cap_free (cap);
     253             :       }
     254             :     err = no_mlock? 0 : mlock (p, n);
     255             :     if (err && errno)
     256             :       err = errno;
     257             :     if (!no_priv_drop)
     258             :       {
     259             :         cap = cap_from_text ("cap_ipc_lock+p");
     260             :         cap_set_proc (cap);
     261             :         cap_free(cap);
     262             :       }
     263             :   }
     264             : 
     265             :   if (err)
     266             :     {
     267             :       if (errno != EPERM
     268             : #ifdef EAGAIN   /* OpenBSD returns this */
     269             :           && errno != EAGAIN
     270             : #endif
     271             : #ifdef ENOSYS   /* Some SCOs return this (function not implemented) */
     272             :           && errno != ENOSYS
     273             : #endif
     274             : #ifdef ENOMEM  /* Linux might return this. */
     275             :             && errno != ENOMEM
     276             : #endif
     277             :           )
     278             :         log_error ("can't lock memory: %s\n", strerror (err));
     279             :       show_warning = 1;
     280             :       not_locked = 1;
     281             :     }
     282             : 
     283             : #elif defined(HAVE_MLOCK)
     284             :   uid_t uid;
     285             :   int err;
     286             : 
     287           1 :   uid = getuid ();
     288             : 
     289             : #ifdef HAVE_BROKEN_MLOCK
     290             :   /* Under HP/UX mlock segfaults if called by non-root.  Note, we have
     291             :      noch checked whether mlock does really work under AIX where we
     292             :      also detected a broken nlock.  Note further, that using plock ()
     293             :      is not a good idea under AIX. */
     294             :   if (uid)
     295             :     {
     296             :       errno = EPERM;
     297             :       err = errno;
     298             :     }
     299             :   else
     300             :     {
     301             :       err = no_mlock? 0 : mlock (p, n);
     302             :       if (err && errno)
     303             :         err = errno;
     304             :     }
     305             : #else /* !HAVE_BROKEN_MLOCK */
     306           1 :   err = no_mlock? 0 : mlock (p, n);
     307           1 :   if (err && errno)
     308           0 :     err = errno;
     309             : #endif /* !HAVE_BROKEN_MLOCK */
     310             : 
     311             :   /* Test whether we are running setuid(0).  */
     312           1 :   if (uid && ! geteuid ())
     313             :     {
     314             :       /* Yes, we are.  */
     315           0 :       if (!no_priv_drop)
     316             :         {
     317             :           /* Check that we really dropped the privs.
     318             :            * Note: setuid(0) should always fail */
     319           0 :           if (setuid (uid) || getuid () != geteuid () || !setuid (0))
     320           0 :             log_fatal ("failed to reset uid: %s\n", strerror (errno));
     321             :         }
     322             :     }
     323             : 
     324           1 :   if (err)
     325             :     {
     326           0 :       if (errno != EPERM
     327             : #ifdef EAGAIN   /* OpenBSD returns this. */
     328           0 :           && errno != EAGAIN
     329             : #endif
     330             : #ifdef ENOSYS   /* Some SCOs return this (function not implemented). */
     331           0 :           && errno != ENOSYS
     332             : #endif
     333             : #ifdef ENOMEM  /* Linux might return this. */
     334           0 :             && errno != ENOMEM
     335             : #endif
     336             :           )
     337           0 :         log_error ("can't lock memory: %s\n", strerror (err));
     338           0 :       show_warning = 1;
     339           0 :       not_locked = 1;
     340             :     }
     341             : 
     342             : #elif defined ( __QNX__ )
     343             :   /* QNX does not page at all, so the whole secure memory stuff does
     344             :    * not make much sense.  However it is still of use because it
     345             :    * wipes out the memory on a free().
     346             :    * Therefore it is sufficient to suppress the warning.  */
     347             :   (void)p;
     348             :   (void)n;
     349             : #elif defined (HAVE_DOSISH_SYSTEM) || defined (__CYGWIN__)
     350             :     /* It does not make sense to print such a warning, given the fact that
     351             :      * this whole Windows !@#$% and their user base are inherently insecure. */
     352             :   (void)p;
     353             :   (void)n;
     354             : #elif defined (__riscos__)
     355             :     /* No virtual memory on RISC OS, so no pages are swapped to disc,
     356             :      * besides we don't have mmap, so we don't use it! ;-)
     357             :      * But don't complain, as explained above.  */
     358             :   (void)p;
     359             :   (void)n;
     360             : #else
     361             :   (void)p;
     362             :   (void)n;
     363             :   if (!no_mlock)
     364             :     log_info ("Please note that you don't have secure memory on this system\n");
     365             : #endif
     366           1 : }
     367             : 
     368             : /* Initialize POOL.  */
     369             : static void
     370           1 : init_pool (size_t n)
     371             : {
     372             :   memblock_t *mb;
     373             : 
     374           1 :   pool_size = n;
     375             : 
     376           1 :   if (disable_secmem)
     377           0 :     log_bug ("secure memory is disabled");
     378             : 
     379             : 
     380             : #if HAVE_MMAP
     381             :   {
     382             :     size_t pgsize;
     383             :     long int pgsize_val;
     384             : 
     385             : # if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
     386           1 :     pgsize_val = sysconf (_SC_PAGESIZE);
     387             : # elif defined(HAVE_GETPAGESIZE)
     388             :     pgsize_val = getpagesize ();
     389             : # else
     390             :     pgsize_val = -1;
     391             : # endif
     392           1 :     pgsize = (pgsize_val != -1 && pgsize_val > 0)? pgsize_val:DEFAULT_PAGE_SIZE;
     393             : 
     394           1 :     pool_size = (pool_size + pgsize - 1) & ~(pgsize - 1);
     395             : # ifdef MAP_ANONYMOUS
     396           1 :     pool = mmap (0, pool_size, PROT_READ | PROT_WRITE,
     397             :                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     398             : # else /* map /dev/zero instead */
     399             :     {
     400             :       int fd;
     401             : 
     402             :       fd = open ("/dev/zero", O_RDWR);
     403             :       if (fd == -1)
     404             :         {
     405             :           log_error ("can't open /dev/zero: %s\n", strerror (errno));
     406             :           pool = (void *) -1;
     407             :         }
     408             :       else
     409             :         {
     410             :           pool = mmap (0, pool_size,
     411             :                        (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);
     412             :           close (fd);
     413             :         }
     414             :     }
     415             : # endif
     416           1 :     if (pool == (void *) -1)
     417           0 :       log_info ("can't mmap pool of %u bytes: %s - using malloc\n",
     418           0 :                 (unsigned) pool_size, strerror (errno));
     419             :     else
     420             :       {
     421           1 :         pool_is_mmapped = 1;
     422           1 :         pool_okay = 1;
     423             :       }
     424             :   }
     425             : #endif /*HAVE_MMAP*/
     426             : 
     427           1 :   if (!pool_okay)
     428             :     {
     429           0 :       pool = malloc (pool_size);
     430           0 :       if (!pool)
     431           0 :         log_fatal ("can't allocate memory pool of %u bytes\n",
     432             :                    (unsigned) pool_size);
     433             :       else
     434           0 :         pool_okay = 1;
     435             :     }
     436             : 
     437             :   /* Initialize first memory block.  */
     438           1 :   mb = (memblock_t *) pool;
     439           1 :   mb->size = pool_size;
     440           1 :   mb->flags = 0;
     441           1 : }
     442             : 
     443             : void
     444           1 : _gcry_secmem_set_flags (unsigned flags)
     445             : {
     446             :   int was_susp;
     447             : 
     448           1 :   SECMEM_LOCK;
     449             : 
     450           1 :   was_susp = suspend_warning;
     451           1 :   no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING;
     452           1 :   suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING;
     453           1 :   no_mlock      = flags & GCRY_SECMEM_FLAG_NO_MLOCK;
     454           1 :   no_priv_drop = flags & GCRY_SECMEM_FLAG_NO_PRIV_DROP;
     455             : 
     456             :   /* and now issue the warning if it is not longer suspended */
     457           1 :   if (was_susp && !suspend_warning && show_warning)
     458             :     {
     459           0 :       show_warning = 0;
     460           0 :       print_warn ();
     461             :     }
     462             : 
     463           1 :   SECMEM_UNLOCK;
     464           1 : }
     465             : 
     466             : unsigned int
     467           2 : _gcry_secmem_get_flags (void)
     468             : {
     469             :   unsigned flags;
     470             : 
     471           2 :   SECMEM_LOCK;
     472             : 
     473           2 :   flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0;
     474           2 :   flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0;
     475           2 :   flags |= not_locked ? GCRY_SECMEM_FLAG_NOT_LOCKED : 0;
     476           2 :   flags |= no_mlock ? GCRY_SECMEM_FLAG_NO_MLOCK : 0;
     477           2 :   flags |= no_priv_drop ? GCRY_SECMEM_FLAG_NO_PRIV_DROP : 0;
     478             : 
     479           2 :   SECMEM_UNLOCK;
     480             : 
     481           2 :   return flags;
     482             : }
     483             : 
     484             : 
     485             : /* See _gcry_secmem_init.  This function is expected to be called with
     486             :    the secmem lock held. */
     487             : static void
     488           1 : secmem_init (size_t n)
     489             : {
     490           1 :   if (!n)
     491             :     {
     492             : #ifdef USE_CAPABILITIES
     493             :       /* drop all capabilities */
     494             :       if (!no_priv_drop)
     495             :         {
     496             :           cap_t cap;
     497             : 
     498             :           cap = cap_from_text ("all-eip");
     499             :           cap_set_proc (cap);
     500             :           cap_free (cap);
     501             :         }
     502             : 
     503             : #elif !defined(HAVE_DOSISH_SYSTEM)
     504             :       uid_t uid;
     505             : 
     506           0 :       disable_secmem = 1;
     507           0 :       uid = getuid ();
     508           0 :       if (uid != geteuid ())
     509             :         {
     510           0 :           if (setuid (uid) || getuid () != geteuid () || !setuid (0))
     511           0 :             log_fatal ("failed to drop setuid\n");
     512             :         }
     513             : #endif
     514             :     }
     515             :   else
     516             :     {
     517           1 :       if (n < MINIMUM_POOL_SIZE)
     518           0 :         n = MINIMUM_POOL_SIZE;
     519           1 :       if (! pool_okay)
     520             :         {
     521           1 :           init_pool (n);
     522           1 :           lock_pool (pool, n);
     523             :         }
     524             :       else
     525           0 :         log_error ("Oops, secure memory pool already initialized\n");
     526             :     }
     527           1 : }
     528             : 
     529             : 
     530             : 
     531             : /* Initialize the secure memory system.  If running with the necessary
     532             :    privileges, the secure memory pool will be locked into the core in
     533             :    order to prevent page-outs of the data.  Furthermore allocated
     534             :    secure memory will be wiped out when released.  */
     535             : void
     536           1 : _gcry_secmem_init (size_t n)
     537             : {
     538           1 :   SECMEM_LOCK;
     539             : 
     540           1 :   secmem_init (n);
     541             : 
     542           1 :   SECMEM_UNLOCK;
     543           1 : }
     544             : 
     545             : 
     546             : gcry_err_code_t
     547          32 : _gcry_secmem_module_init ()
     548             : {
     549             :   /* Not anymore needed.  */
     550          32 :   return 0;
     551             : }
     552             : 
     553             : 
     554             : static void *
     555           3 : _gcry_secmem_malloc_internal (size_t size)
     556             : {
     557             :   memblock_t *mb;
     558             : 
     559           3 :   if (!pool_okay)
     560             :     {
     561             :       /* Try to initialize the pool if the user forgot about it.  */
     562           0 :       secmem_init (STANDARD_POOL_SIZE);
     563           0 :       if (!pool_okay)
     564             :         {
     565           0 :           log_info (_("operation is not possible without "
     566             :                       "initialized secure memory\n"));
     567           0 :           gpg_err_set_errno (ENOMEM);
     568           0 :           return NULL;
     569             :         }
     570             :     }
     571           3 :   if (not_locked && fips_mode ())
     572             :     {
     573           0 :       log_info (_("secure memory pool is not locked while in FIPS mode\n"));
     574           0 :       gpg_err_set_errno (ENOMEM);
     575           0 :       return NULL;
     576             :     }
     577           3 :   if (show_warning && !suspend_warning)
     578             :     {
     579           0 :       show_warning = 0;
     580           0 :       print_warn ();
     581             :     }
     582             : 
     583             :   /* Blocks are always a multiple of 32. */
     584           3 :   size = ((size + 31) / 32) * 32;
     585             : 
     586           3 :   mb = mb_get_new ((memblock_t *) pool, size);
     587           3 :   if (mb)
     588           3 :     stats_update (size, 0);
     589             : 
     590           3 :   return mb ? &mb->aligned.c : NULL;
     591             : }
     592             : 
     593             : void *
     594           3 : _gcry_secmem_malloc (size_t size)
     595             : {
     596             :   void *p;
     597             : 
     598           3 :   SECMEM_LOCK;
     599           3 :   p = _gcry_secmem_malloc_internal (size);
     600           3 :   SECMEM_UNLOCK;
     601             : 
     602           3 :   return p;
     603             : }
     604             : 
     605             : static void
     606           2 : _gcry_secmem_free_internal (void *a)
     607             : {
     608             :   memblock_t *mb;
     609             :   int size;
     610             : 
     611           2 :   if (!a)
     612           2 :     return;
     613             : 
     614           2 :   mb = ADDR_TO_BLOCK (a);
     615           2 :   size = mb->size;
     616             : 
     617             :   /* This does not make much sense: probably this memory is held in the
     618             :    * cache. We do it anyway: */
     619             : #define MB_WIPE_OUT(byte) \
     620             :   wipememory2 (((char *) mb + BLOCK_HEAD_SIZE), (byte), size);
     621             : 
     622           2 :   MB_WIPE_OUT (0xff);
     623           2 :   MB_WIPE_OUT (0xaa);
     624           2 :   MB_WIPE_OUT (0x55);
     625           2 :   MB_WIPE_OUT (0x00);
     626             : 
     627           2 :   stats_update (0, size);
     628             : 
     629           2 :   mb->flags &= ~MB_FLAG_ACTIVE;
     630             : 
     631             :   /* Update stats.  */
     632             : 
     633           2 :   mb_merge (mb);
     634             : }
     635             : 
     636             : /* Wipe out and release memory.  */
     637             : void
     638           2 : _gcry_secmem_free (void *a)
     639             : {
     640           2 :   SECMEM_LOCK;
     641           2 :   _gcry_secmem_free_internal (a);
     642           2 :   SECMEM_UNLOCK;
     643           2 : }
     644             : 
     645             : /* Realloc memory.  */
     646             : void *
     647           0 : _gcry_secmem_realloc (void *p, size_t newsize)
     648             : {
     649             :   memblock_t *mb;
     650             :   size_t size;
     651             :   void *a;
     652             : 
     653           0 :   SECMEM_LOCK;
     654             : 
     655           0 :   mb = (memblock_t *) (void *) ((char *) p
     656             :                                 - ((size_t) &((memblock_t *) 0)->aligned.c));
     657           0 :   size = mb->size;
     658           0 :   if (newsize < size)
     659             :     {
     660             :       /* It is easier to not shrink the memory.  */
     661           0 :       a = p;
     662             :     }
     663             :   else
     664             :     {
     665           0 :       a = _gcry_secmem_malloc_internal (newsize);
     666           0 :       if (a)
     667             :         {
     668           0 :           memcpy (a, p, size);
     669           0 :           memset ((char *) a + size, 0, newsize - size);
     670           0 :           _gcry_secmem_free_internal (p);
     671             :         }
     672             :     }
     673             : 
     674           0 :   SECMEM_UNLOCK;
     675             : 
     676           0 :   return a;
     677             : }
     678             : 
     679             : 
     680             : /* Return true if P points into the secure memory area.  */
     681             : int
     682    89507575 : _gcry_private_is_secure (const void *p)
     683             : {
     684    89507575 :   return pool_okay && ptr_into_pool_p (p);
     685             : }
     686             : 
     687             : 
     688             : /****************
     689             :  * Warning:  This code might be called by an interrupt handler
     690             :  *           and frankly, there should really be such a handler,
     691             :  *           to make sure that the memory is wiped out.
     692             :  *           We hope that the OS wipes out mlocked memory after
     693             :  *           receiving a SIGKILL - it really should do so, otherwise
     694             :  *           there is no chance to get the secure memory cleaned.
     695             :  */
     696             : void
     697           0 : _gcry_secmem_term ()
     698             : {
     699           0 :   if (!pool_okay)
     700           0 :     return;
     701             : 
     702           0 :   wipememory2 (pool, 0xff, pool_size);
     703           0 :   wipememory2 (pool, 0xaa, pool_size);
     704           0 :   wipememory2 (pool, 0x55, pool_size);
     705           0 :   wipememory2 (pool, 0x00, pool_size);
     706             : #if HAVE_MMAP
     707           0 :   if (pool_is_mmapped)
     708           0 :     munmap (pool, pool_size);
     709             : #endif
     710           0 :   pool = NULL;
     711           0 :   pool_okay = 0;
     712           0 :   pool_size = 0;
     713           0 :   not_locked = 0;
     714             : }
     715             : 
     716             : 
     717             : void
     718           0 : _gcry_secmem_dump_stats ()
     719             : {
     720             : #if 1
     721           0 :   SECMEM_LOCK;
     722             : 
     723           0 :  if (pool_okay)
     724           0 :     log_info ("secmem usage: %u/%lu bytes in %u blocks\n",
     725             :               cur_alloced, (unsigned long)pool_size, cur_blocks);
     726           0 :   SECMEM_UNLOCK;
     727             : #else
     728             :   memblock_t *mb;
     729             :   int i;
     730             : 
     731             :   SECMEM_LOCK;
     732             : 
     733             :   for (i = 0, mb = (memblock_t *) pool;
     734             :        ptr_into_pool_p (mb);
     735             :        mb = mb_get_next (mb), i++)
     736             :     log_info ("SECMEM: [%s] block: %i; size: %i\n",
     737             :               (mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
     738             :               i,
     739             :               mb->size);
     740             :   SECMEM_UNLOCK;
     741             : #endif
     742           0 : }

Generated by: LCOV version 1.11