diff options
| -rw-r--r-- | src/gcrypt-testapi.h | 1 | ||||
| -rw-r--r-- | src/global.c | 5 | ||||
| -rw-r--r-- | src/secmem.c | 40 | ||||
| -rw-r--r-- | src/secmem.h | 2 | ||||
| -rw-r--r-- | tests/Makefile.am | 2 | ||||
| -rw-r--r-- | tests/t-secmem.c | 141 |
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; +} |
