summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gcrypt-testapi.h1
-rw-r--r--src/global.c5
-rw-r--r--src/secmem.c40
-rw-r--r--src/secmem.h2
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/t-secmem.c141
6 files changed, 168 insertions, 23 deletions
diff --git a/src/gcrypt-testapi.h b/src/gcrypt-testapi.h
index 23d38008..0417754f 100644
--- a/src/gcrypt-testapi.h
+++ b/src/gcrypt-testapi.h
@@ -31,6 +31,7 @@
#define PRIV_CTL_RUN_EXTRNG_TEST 59
#define PRIV_CTL_DEINIT_EXTRNG_TEST 60
#define PRIV_CTL_EXTERNAL_LOCK_TEST 61
+#define PRIV_CTL_DUMP_SECMEM_STATS 62
#define EXTERNAL_LOCK_TEST_INIT 30111
#define EXTERNAL_LOCK_TEST_LOCK 30112
diff --git a/src/global.c b/src/global.c
index 8e54efe6..be112b77 100644
--- a/src/global.c
+++ b/src/global.c
@@ -380,7 +380,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
break;
case GCRYCTL_DUMP_SECMEM_STATS:
- _gcry_secmem_dump_stats ();
+ _gcry_secmem_dump_stats (0);
break;
case GCRYCTL_DROP_PRIVS:
@@ -613,7 +613,8 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
case PRIV_CTL_EXTERNAL_LOCK_TEST: /* Run external lock test */
rc = external_lock_test (va_arg (arg_ptr, int));
break;
- case 62: /* RFU */
+ case PRIV_CTL_DUMP_SECMEM_STATS:
+ _gcry_secmem_dump_stats (1);
break;
#if _GCRY_GCC_VERSION >= 40600
# pragma GCC diagnostic pop
diff --git a/src/secmem.c b/src/secmem.c
index 1f92f176..54bbda11 100644
--- a/src/secmem.c
+++ b/src/secmem.c
@@ -751,33 +751,35 @@ _gcry_secmem_term ()
}
+/* Print stats of the secmem allocator. With EXTENDED passwed as true
+ * a detiled listing is returned (used for testing). */
void
-_gcry_secmem_dump_stats ()
+_gcry_secmem_dump_stats (int extended)
{
pooldesc_t *pool;
-
-#if 1
- SECMEM_LOCK;
-
- pool = &mainpool;
- if (pool->okay)
- log_info ("secmem usage: %u/%lu bytes in %u blocks\n",
- cur_alloced, (unsigned long)pool->size, cur_blocks);
- SECMEM_UNLOCK;
-#else
memblock_t *mb;
int i;
SECMEM_LOCK;
pool = &mainpool;
- for (i = 0, mb = (memblock_t *) pool->mem;
- ptr_into_pool_p (pool, mb);
- mb = mb_get_next (pool, mb), i++)
- log_info ("SECMEM: [%s] block: %i; size: %i\n",
- (mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
- i,
- mb->size);
+ if (!extended)
+ {
+ if (pool->okay)
+ log_info ("secmem usage: %u/%lu bytes in %u blocks\n",
+ cur_alloced, (unsigned long)pool->size, cur_blocks);
+ }
+ else
+ {
+ for (i = 0, mb = (memblock_t *) pool->mem;
+ ptr_into_pool_p (pool, mb);
+ mb = mb_get_next (pool, mb), i++)
+ log_info ("SECMEM: pool %p %s block %i size %i\n",
+ pool,
+ (mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
+ i,
+ mb->size);
+ }
+
SECMEM_UNLOCK;
-#endif
}
diff --git a/src/secmem.h b/src/secmem.h
index 3577381c..764bfebc 100644
--- a/src/secmem.h
+++ b/src/secmem.h
@@ -26,7 +26,7 @@ void _gcry_secmem_term (void);
void *_gcry_secmem_malloc (size_t size) _GCRY_GCC_ATTR_MALLOC;
void *_gcry_secmem_realloc (void *a, size_t newsize);
void _gcry_secmem_free (void *a);
-void _gcry_secmem_dump_stats (void);
+void _gcry_secmem_dump_stats (int extended);
void _gcry_secmem_set_flags (unsigned flags);
unsigned _gcry_secmem_get_flags(void);
int _gcry_private_is_secure (const void *p);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d462f306..374e72e7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -19,7 +19,7 @@
## Process this file with automake to produce Makefile.in
tests_bin = \
- version mpitests t-sexp t-convert \
+ version t-secmem mpitests t-sexp t-convert \
t-mpi-bit t-mpi-point curves t-lock \
prime basic keygen pubkey hmac hashtest t-kdf keygrip \
fips186-dsa aeswrap pkcs1v2 random dsa-rfc6979 t-ed25519 t-cv25519
diff --git a/tests/t-secmem.c b/tests/t-secmem.c
new file mode 100644
index 00000000..b464d02d
--- /dev/null
+++ b/tests/t-secmem.c
@@ -0,0 +1,141 @@
+/* t-secmem.c - Test the secmem memory allocator
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define PGMNAME "t-secmem"
+
+#include "t-common.h"
+#include "../src/gcrypt-testapi.h"
+
+
+static void
+test_secmem (void)
+{
+ void *a[28];
+ void *b;
+ int i;
+
+ memset (a, 0, sizeof a);
+
+ /* Allocating 28*512=14k should work in the default 16k pool even
+ * with extrem alignment requirements. */
+ for (i=0; i < DIM(a); i++)
+ a[i] = gcry_xmalloc_secure (512);
+
+ /* Allocating another 2k should fail for the default 16k pool. */
+ b = gcry_malloc_secure (2048);
+ if (b)
+ fail ("allocation did not fail as expected\n");
+
+ for (i=0; i < DIM(a); i++)
+ xfree (a[i]);
+ xfree (b);
+}
+
+
+/* This function is called when we ran out of core and there is no way
+ * to return that error to the caller (xmalloc or mpi allocation). */
+static int
+outofcore_handler (void *opaque, size_t req_n, unsigned int flags)
+{
+ static int been_here; /* Used to protect against recursive calls. */
+
+ (void)opaque;
+
+ /* Protect against a second call. */
+ if (been_here)
+ return 0; /* Let libgcrypt call its own fatal error handler. */
+ been_here = 1;
+
+ info ("outofcore handler invoked");
+ gcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
+ fail ("out of core%s while allocating %lu bytes",
+ (flags & 1)?" in secure memory":"", (unsigned long)req_n);
+
+ die ("stopped");
+ /*NOTREACHED*/
+ return 0;
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+
+ if (argc)
+ { argc--; argv++; }
+
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ {
+ fputs ("usage: " PGMNAME " [options]\n"
+ "Options:\n"
+ " --verbose print timings etc.\n"
+ " --debug flyswatter\n"
+ , stdout);
+ exit (0);
+ }
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose++;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--debug"))
+ {
+ verbose += 2;
+ debug++;
+ argc--; argv++;
+ }
+ else if (!strncmp (*argv, "--", 2))
+ die ("unknown option '%s'", *argv);
+ }
+
+ if (!gcry_check_version (GCRYPT_VERSION))
+ die ("version mismatch; pgm=%s, library=%s\n",
+ GCRYPT_VERSION, gcry_check_version (NULL));
+ if (debug)
+ gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
+ gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+ gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
+ gcry_set_outofcore_handler (outofcore_handler, NULL);
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+
+ test_secmem ();
+
+ if (verbose)
+ gcry_control (PRIV_CTL_DUMP_SECMEM_STATS, 0 , 0);
+ info ("All tests completed. Errors: %d\n", errorcount);
+ return !!errorcount;
+}