Obsolete option --no-sig-create-check.
[gnupg.git] / util / secmem.c
index 91cd3eb..553175b 100644 (file)
@@ -1,11 +1,12 @@
 /* secmem.c  - memory allocation from a secure heap
- *     Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ *                    2007 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
  * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * GnuPG is distributed in the hope that it will be useful,
@@ -14,8 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include "util.h"
 #include "i18n.h"
 
+/* MinGW doesn't seem to prototype getpagesize, though it does have
+   it. */
+#if !HAVE_DECL_GETPAGESIZE
+int getpagesize(void);
+#endif
+
 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
 #define MAP_ANONYMOUS MAP_ANON
 #endif
@@ -88,8 +94,8 @@ print_warn(void)
   if (!no_warning)
     {
       log_info(_("WARNING: using insecure memory!\n"));
-      log_info(_("please see http://www.gnupg.org/faq.html "
-                "for more information\n"));
+      log_info(_("please see http://www.gnupg.org/documentation/faqs.html"
+                " for more information\n"));
     }
 }
 
@@ -183,7 +189,11 @@ lock_pool( void *p, size_t n )
             && errno != ENOMEM
 #endif
          )
-           log_error("can't lock memory: %s\n", strerror(err));
+#ifdef __VMS
+           log_warning ("can't lock memory: %s\n", strerror(err));
+#else
+           log_error ("can't lock memory: %s\n", strerror(err));
+#endif
        show_warning = 1;
     }
 
@@ -211,6 +221,7 @@ lock_pool( void *p, size_t n )
 static void
 init_pool( size_t n)
 {
+    long int pgsize_val;
     size_t pgsize;
 
     poolsize = n;
@@ -218,11 +229,15 @@ init_pool( size_t n)
     if( disable_secmem )
        log_bug("secure memory is disabled");
 
-#ifdef HAVE_GETPAGESIZE
-    pgsize = getpagesize();
+#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
+    pgsize_val = sysconf (_SC_PAGESIZE);
+#elif defined(HAVE_GETPAGESIZE)
+    pgsize_val = getpagesize ();
 #else
-    pgsize = 4096;
+    pgsize_val = -1;
 #endif
+    pgsize = (pgsize_val != -1 && pgsize_val > 0)? pgsize_val : 4096;
+
 
 #ifdef HAVE_MMAP
     poolsize = (poolsize + pgsize -1 ) & ~(pgsize-1);
@@ -240,6 +255,7 @@ init_pool( size_t n)
        else {
            pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
                                      MAP_PRIVATE, fd, 0);
+           close (fd);
        }
     }
 #endif
@@ -297,7 +313,8 @@ secmem_get_flags(void)
     return flags;
 }
 
-void
+/* Returns 1 if memory was locked, 0 if not. */
+int
 secmem_init( size_t n )
 {
     if( !n ) {
@@ -326,6 +343,8 @@ secmem_init( size_t n )
        else
            log_error("Oops, secure memory pool already initialized\n");
     }
+
+    return !show_warning;
 }
 
 
@@ -346,7 +365,10 @@ secmem_malloc( size_t size )
        print_warn();
     }
 
-    /* blocks are always a multiple of 32 */
+    /* Blocks are always a multiple of 32.  Note that we allocate an
+       extra of the size of an entire MEMBLOCK.  This is required
+       becuase we do not only need the SIZE info but also extra space
+       to chain up unused memory blocks.  */
     size += sizeof(MEMBLOCK);
     size = ((size + 31) / 32) * 32;
 
@@ -387,7 +409,7 @@ secmem_malloc( size_t size )
 
 
 void *
-secmem_realloc( void *p, size_t newsize )
+secmexrealloc( void *p, size_t newsize )
 {
     MEMBLOCK *mb;
     size_t size;
@@ -395,8 +417,12 @@ secmem_realloc( void *p, size_t newsize )
 
     mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.aligned.c));
     size = mb->size;
-    if( newsize < size )
-       return p; /* it is easier not to shrink the memory */
+    if (size < sizeof(MEMBLOCK))
+      log_bug ("secure memory corrupted at block %p\n", (void *)mb);
+    size -= ((size_t) &((MEMBLOCK*)0)->u.aligned.c);
+
+    if( newsize <= size )
+       return p; /* It is easier not to shrink the memory.  */
     a = secmem_malloc( newsize );
     if ( a ) {
         memcpy(a, p, size);
@@ -431,10 +457,27 @@ secmem_free( void *a )
     cur_alloced -= size;
 }
 
+
+/* Check whether P points into the pool.  */
+static int
+ptr_into_pool_p (const void *p)
+{
+  /* We need to convert pointers to addresses.  This is required by
+     C-99 6.5.8 to avoid undefined behaviour.  Using size_t is at
+     least only implementation defined.  See also
+     http://lists.gnupg.org/pipermail/gcrypt-devel/2007-February/001102.html
+  */
+  size_t p_addr = (size_t)p;
+  size_t pool_addr = (size_t)pool;
+
+  return p_addr >= pool_addr && p_addr <  pool_addr+poolsize;
+}
+
+
 int
 m_is_secure( const void *p )
 {
-    return p >= pool && p < (void*)((char*)pool+poolsize);
+  return pool_okay && ptr_into_pool_p (p);
 }