[git] GPG-ERROR - branch, gniibe/secmem, created. libgpg-error-1.32-14-gc6b7bbe
by NIIBE Yutaka
cvs at cvs.gnupg.org
Thu Sep 6 03:18:38 CEST 2018
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Error codes used by GnuPG et al.".
The branch, gniibe/secmem has been created
at c6b7bbe9136854bfb4f7d7a0f384dd41d9f6945d (commit)
- Log -----------------------------------------------------------------
commit c6b7bbe9136854bfb4f7d7a0f384dd41d9f6945d
Author: NIIBE Yutaka <gniibe at fsij.org>
Date: Thu Sep 6 10:03:22 2018 +0900
secmem: Export symbols and the interface.
* src/Makefile.am (libgpg_error_la_SOURCES): Add secmem.c and secmem.h.
* src/gpg-error.def.in: Add secmem symbols.
* src/gpg-error.vers: Likewise.
* src/gpg-error.h.in: Add secmem functions and macros.
* src/secmem.h: Move internal prototypes to ...
* src/gpgrt-int.h: ... here.
* src/visibility.c: Add external functions.
* src/visibility.h: Declare secmem functions.
diff --git a/src/Makefile.am b/src/Makefile.am
index fcfbb83..294bc27 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -187,6 +187,7 @@ libgpg_error_la_SOURCES = gettext.h $(arch_sources) \
estream.c estream-printf.c estream-printf.h \
strsource.c strerror.c code-to-errno.c code-from-errno.c \
visibility.c visibility.h \
+ secmem.c secmem.h \
sysutils.c \
syscall-clamp.c \
logging.c \
diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in
index 67bb12e..f4f3668 100644
--- a/src/gpg-error.def.in
+++ b/src/gpg-error.def.in
@@ -218,5 +218,15 @@ EXPORTS
gpgrt_b64enc_write @167
gpgrt_b64enc_finish @168
+ gpgrt_secmem_init @169
+ gpgrt_secmem_term @170
+ gpgrt_secmem_malloc @171
+ gpgrt_secmem_realloc @172
+ gpgrt_secmem_free @173
+ gpgrt_secmem_dump_stats @174
+ gpgrt_secmem_set_auto_expand @175
+ gpgrt_secmem_set_flags @176
+ gpgrt_secmem_get_flags @177
+ gpgrt_private_is_secure @178
;; end of file with public symbols for Windows.
diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in
index 8bcafcc..46d4ea7 100644
--- a/src/gpg-error.h.in
+++ b/src/gpg-error.h.in
@@ -1270,7 +1270,28 @@ const char *gpgrt_strusage (int level);
void gpgrt_set_strusage (const char *(*f)(int));
void gpgrt_set_usage_outfnc (int (*f)(int, const char *));
void gpgrt_set_fixed_string_mapper (const char *(*f)(const char*));
+
+/*
+ * secmem functions.
+ */
+/* Flags for _gpgrt_secmem_{set,get}_flags. */
+#define GPGRT_SECMEM_FLAG_NO_WARNING (1 << 0)
+#define GPGRT_SECMEM_FLAG_SUSPEND_WARNING (1 << 1)
+#define GPGRT_SECMEM_FLAG_NOT_LOCKED (1 << 2)
+#define GPGRT_SECMEM_FLAG_NO_MLOCK (1 << 3)
+#define GPGRT_SECMEM_FLAG_NO_PRIV_DROP (1 << 4)
+
+void gpgrt_secmem_init (size_t npool);
+void gpgrt_secmem_term (void);
+void *gpgrt_secmem_malloc (size_t size, int xhint) GPGRT_ATTR_MALLOC;
+void *gpgrt_secmem_realloc (void *a, size_t newsize, int xhint);
+int gpgrt_secmem_free (void *a);
+void gpgrt_secmem_dump_stats (int extended);
+void gpgrt_secmem_set_auto_expand (unsigned int chunksize);
+void gpgrt_secmem_set_flags (unsigned flags);
+unsigned gpgrt_secmem_get_flags (void);
+int gpgrt_private_is_secure (const void *p);
#ifdef __cplusplus
diff --git a/src/gpg-error.vers b/src/gpg-error.vers
index 201b784..4e58300 100644
--- a/src/gpg-error.vers
+++ b/src/gpg-error.vers
@@ -190,6 +190,16 @@ GPG_ERROR_1.0 {
gpgrt_b64enc_write;
gpgrt_b64enc_finish;
+ gpgrt_secmem_init;
+ gpgrt_secmem_term;
+ gpgrt_secmem_malloc;
+ gpgrt_secmem_realloc;
+ gpgrt_secmem_free;
+ gpgrt_secmem_dump_stats;
+ gpgrt_secmem_set_auto_expand;
+ gpgrt_secmem_set_flags;
+ gpgrt_secmem_get_flags;
+ gpgrt_private_is_secure;
local:
*;
diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h
index 34e494c..2cc3a4c 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -742,6 +742,19 @@ void _gpgrt_set_usage_outfnc (int (*fnc)(int, const char *));
void _gpgrt_set_fixed_string_mapper (const char *(*f)(const char*));
+/*
+ * Local prototypes for secmem.
+ */
+void _gpgrt_secmem_init (size_t npool);
+void _gpgrt_secmem_term (void);
+void *_gpgrt_secmem_malloc (size_t size, int xhint) GPGRT_ATTR_MALLOC;
+void *_gpgrt_secmem_realloc (void *a, size_t newsize, int xhint);
+int _gpgrt_secmem_free (void *a);
+void _gpgrt_secmem_dump_stats (int extended);
+void _gpgrt_secmem_set_auto_expand (unsigned int chunksize);
+void _gpgrt_secmem_set_flags (unsigned flags);
+unsigned _gpgrt_secmem_get_flags (void);
+int _gpgrt_private_is_secure (const void *p);
/*
* Internal platform abstraction functions (sysutils.c)
diff --git a/src/secmem.h b/src/secmem.h
index cdab761..31b2b9b 100644
--- a/src/secmem.h
+++ b/src/secmem.h
@@ -23,24 +23,6 @@
#ifndef G10_SECMEM_H
#define G10_SECMEM_H 1
-void _gpgrt_secmem_init (size_t npool);
-void _gpgrt_secmem_term (void);
-void *_gpgrt_secmem_malloc (size_t size, int xhint) GPGRT_ATTR_MALLOC;
-void *_gpgrt_secmem_realloc (void *a, size_t newsize, int xhint);
-int _gpgrt_secmem_free (void *a);
-void _gpgrt_secmem_dump_stats (int extended);
-void _gpgrt_secmem_set_auto_expand (unsigned int chunksize);
-void _gpgrt_secmem_set_flags (unsigned flags);
-unsigned _gpgrt_secmem_get_flags(void);
-int _gpgrt_private_is_secure (const void *p);
-
-/* Flags for _gpgrt_secmem_{set,get}_flags. */
-#define GPGRT_SECMEM_FLAG_NO_WARNING (1 << 0)
-#define GPGRT_SECMEM_FLAG_SUSPEND_WARNING (1 << 1)
-#define GPGRT_SECMEM_FLAG_NOT_LOCKED (1 << 2)
-#define GPGRT_SECMEM_FLAG_NO_MLOCK (1 << 3)
-#define GPGRT_SECMEM_FLAG_NO_PRIV_DROP (1 << 4)
-
#if __GNUC__ >= 3
#define LIKELY( expr ) __builtin_expect( !!(expr), 1 )
#define UNLIKELY( expr ) __builtin_expect( !!(expr), 0 )
diff --git a/src/visibility.c b/src/visibility.c
index 6f8bb24..e11dc98 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1122,6 +1122,65 @@ gpgrt_set_fixed_string_mapper (const char *(*f)(const char*))
}
+void
+gpgrt_secmem_init (size_t n)
+{
+ _gpgrt_secmem_init (n);
+}
+
+void
+gpgrt_secmem_term (void)
+{
+ _gpgrt_secmem_term ();
+}
+
+void *
+gpgrt_secmem_malloc (size_t size, int xhint)
+{
+ return _gpgrt_secmem_malloc (size, xhint);
+}
+
+void *
+gpgrt_secmem_realloc (void *a, size_t newsize, int xhint)
+{
+ return _gpgrt_secmem_realloc (a, newsize, xhint);
+}
+
+int
+gpgrt_secmem_free (void *a)
+{
+ return _gpgrt_secmem_free (a);
+}
+
+void
+gpgrt_secmem_dump_stats (int extended)
+{
+ _gpgrt_secmem_dump_stats (extended);
+}
+
+void
+gpgrt_secmem_set_auto_expand (unsigned int chunksize)
+{
+ _gpgrt_secmem_set_auto_expand (chunksize);
+}
+
+void
+gpgrt_secmem_set_flags (unsigned flags)
+{
+ _gpgrt_secmem_set_flags (flags);
+}
+
+unsigned
+gpgrt_secmem_get_flags (void)
+{
+ return _gpgrt_secmem_get_flags ();
+}
+
+int
+gpgrt_private_is_secure (const void *p)
+{
+ return _gpgrt_private_is_secure (p);
+}
/* For consistency reasons we use function wrappers also for Windows
* specific function despite that they are technically not needed. */
diff --git a/src/visibility.h b/src/visibility.h
index cfa32e5..47ade34 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -209,6 +209,17 @@ MARK_VISIBLE (gpgrt_set_strusage)
MARK_VISIBLE (gpgrt_set_fixed_string_mapper);
MARK_VISIBLE (gpgrt_set_usage_outfnc);
+MARK_VISIBLE (gpgrt_secmem_init);
+MARK_VISIBLE (gpgrt_secmem_term);
+MARK_VISIBLE (gpgrt_secmem_malloc);
+MARK_VISIBLE (gpgrt_secmem_realloc);
+MARK_VISIBLE (gpgrt_secmem_free);
+MARK_VISIBLE (gpgrt_secmem_dump_stats);
+MARK_VISIBLE (gpgrt_secmem_set_auto_expand);
+MARK_VISIBLE (gpgrt_secmem_set_flags);
+MARK_VISIBLE (gpgrt_secmem_get_flags);
+MARK_VISIBLE (gpgrt_private_is_secure);
+
#undef MARK_VISIBLE
#else /*!_GPGRT_INCL_BY_VISIBILITY_C*/
@@ -379,6 +390,17 @@ MARK_VISIBLE (gpgrt_set_usage_outfnc);
#define gpgrt_set_usage_outfnc _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_set_fixed_string_mapper _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_secmem_init _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_secmem_term _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_secmem_malloc _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_secmem_realloc _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_secmem_free _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_secmem_dump_stats _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_secmem_set_auto_expand _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_secmem_set_flags _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_secmem_get_flags _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_private_is_secure _gpgrt_USE_UNDERSCORED_FUNCTION
+
/* Windows specific functions. */
#define gpgrt_w32_reg_query_string _gpgrt_USE_UNDERSCORED_FUNCTION
commit c03cc0015612a1f626fe79faeeea7a5e28a68935
Author: NIIBE Yutaka <gniibe at fsij.org>
Date: Thu Sep 6 09:30:40 2018 +0900
Copy definitions from libgcrypt/src/g10lib.h.
* src/secmem.c (PROPERLY_ALIGNED_TYPE): Move to ...
* src/semem.h (PROPERLY_ALIGNED_TYPE): ... here.
* src/semem.h (LIKELY, UNLIKELY): Copy definitions
from libgcrypt/src/g10lib.h.
(wipememory2, wipememory)
(fast_wipememory2_unaligned_head, fast_wipememory2): Likewise.
(FASTWIPE_T, FASTWIPE_MULT): Use uint64_t and ULL of C99.
diff --git a/src/secmem.c b/src/secmem.c
index dd1d3cc..7645093 100644
--- a/src/secmem.c
+++ b/src/secmem.c
@@ -44,17 +44,6 @@
#include "gpgrt-int.h"
#include "secmem.h"
-typedef union
-{
- int a;
- short b;
- char c[1];
- long d;
- uint64_t e;
- float f;
- double g;
-} PROPERLY_ALIGNED_TYPE;
-
#if defined (MAP_ANON) && ! defined (MAP_ANONYMOUS)
#define MAP_ANONYMOUS MAP_ANON
#endif
diff --git a/src/secmem.h b/src/secmem.h
index 8f0a938..cdab761 100644
--- a/src/secmem.h
+++ b/src/secmem.h
@@ -41,4 +41,78 @@ int _gpgrt_private_is_secure (const void *p);
#define GPGRT_SECMEM_FLAG_NO_MLOCK (1 << 3)
#define GPGRT_SECMEM_FLAG_NO_PRIV_DROP (1 << 4)
+#if __GNUC__ >= 3
+#define LIKELY( expr ) __builtin_expect( !!(expr), 1 )
+#define UNLIKELY( expr ) __builtin_expect( !!(expr), 0 )
+#else
+#define LIKELY( expr ) (!!(expr))
+#define UNLIKELY( expr ) (!!(expr))
+#endif
+
+typedef union
+{
+ int a;
+ short b;
+ char c[1];
+ long d;
+ uint64_t e;
+ float f;
+ double g;
+} PROPERLY_ALIGNED_TYPE;
+
+/* To avoid that a compiler optimizes certain memset calls away, these
+ macros may be used instead. */
+#define wipememory2(_ptr,_set,_len) do { \
+ volatile char *_vptr=(volatile char *)(_ptr); \
+ size_t _vlen=(_len); \
+ unsigned char _vset=(_set); \
+ fast_wipememory2(_vptr,_vset,_vlen); \
+ while(_vlen) { *_vptr=(_vset); _vptr++; _vlen--; } \
+ } while(0)
+#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
+
+#define FASTWIPE_T uint64_t
+#define FASTWIPE_MULT (0x0101010101010101ULL)
+
+/* Following architectures can handle unaligned accesses fast. */
+#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \
+ defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \
+ defined(HAVE_GCC_ATTRIBUTE_MAY_ALIAS) && \
+ (defined(__i386__) || defined(__x86_64__) || \
+ defined(__powerpc__) || defined(__powerpc64__) || \
+ (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \
+ defined(__aarch64__))
+#define fast_wipememory2_unaligned_head(_ptr,_set,_len) /*do nothing*/
+typedef struct fast_wipememory_s
+{
+ FASTWIPE_T a;
+} __attribute__((packed, aligned(1), may_alias)) fast_wipememory_t;
+#else
+#define fast_wipememory2_unaligned_head(_vptr,_vset,_vlen) do { \
+ while(UNLIKELY((size_t)(_vptr)&(sizeof(FASTWIPE_T)-1)) && _vlen) \
+ { *_vptr=(_vset); _vptr++; _vlen--; } \
+ } while(0)
+typedef struct fast_wipememory_s
+{
+ FASTWIPE_T a;
+} fast_wipememory_t;
+#endif
+
+/* fast_wipememory2 may leave tail bytes unhandled, in which case tail bytes
+ are handled by wipememory2. */
+#define fast_wipememory2(_vptr,_vset,_vlen) do { \
+ FASTWIPE_T _vset_long = _vset; \
+ fast_wipememory2_unaligned_head(_vptr,_vset,_vlen); \
+ if (_vlen < sizeof(FASTWIPE_T)) \
+ break; \
+ _vset_long *= FASTWIPE_MULT; \
+ do { \
+ volatile fast_wipememory_t *_vptr_long = \
+ (volatile void *)_vptr; \
+ _vptr_long->a = _vset_long; \
+ _vlen -= sizeof(FASTWIPE_T); \
+ _vptr += sizeof(FASTWIPE_T); \
+ } while (_vlen >= sizeof(FASTWIPE_T)); \
+ } while (0)
+
#endif /* G10_SECMEM_H */
commit 74dfa426d682906adb2679ad8e4a4824d3cd27e4
Author: NIIBE Yutaka <gniibe at fsij.org>
Date: Thu Sep 6 09:22:24 2018 +0900
Remove fips_mode support originally available in libgcrypt.
* _gpgrt_secmem_malloc_internal: Remove fips_mode() call and its
handling.
diff --git a/src/secmem.c b/src/secmem.c
index ad82dfb..dd1d3cc 100644
--- a/src/secmem.c
+++ b/src/secmem.c
@@ -619,12 +619,6 @@ _gpgrt_secmem_malloc_internal (size_t size, int xhint)
return NULL;
}
}
- if (not_locked && fips_mode ())
- {
- _gpgrt_log_info (_("secure memory pool is not locked while in FIPS mode\n"));
- _gpg_err_set_errno (ENOMEM);
- return NULL;
- }
if (show_warning && !suspend_warning)
{
show_warning = 0;
@@ -642,9 +636,8 @@ _gpgrt_secmem_malloc_internal (size_t size, int xhint)
}
/* If we are called from xmalloc style function resort to the
- * overflow pools to return memory. We don't do this in FIPS mode,
- * though. */
- if ((xhint || auto_expand) && !fips_mode ())
+ * overflow pools to return memory. */
+ if ((xhint || auto_expand))
{
for (pool = pool->next; pool; pool = pool->next)
{
commit 26bf6d0ab3f4b2a502d063ea3c02ebf57561097a
Author: NIIBE Yutaka <gniibe at fsij.org>
Date: Thu Sep 6 09:15:49 2018 +0900
secmem.c migration into gpgrt.
* src/secmem.c: Include gpgrt-int.h instead of g10lib.h.
(PROPERLY_ALIGNED_TYPE): Define here with uint64_t. Originally in
libgcrypt/src/types.h.
(SECMEM_LOCK, SECMEM_UNLOCK): Use _gpgrt_* functions, instead.
(*): Use _gpg_err_set_errno instead (underscore version).
(*): Use _gpgrt_log_* functions instead (underscore version).
diff --git a/src/secmem.c b/src/secmem.c
index da5bd57..ad82dfb 100644
--- a/src/secmem.c
+++ b/src/secmem.c
@@ -30,6 +30,7 @@
#include <stdarg.h>
#include <unistd.h>
#include <stddef.h>
+#include <stdint.h>
#if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
#include <sys/mman.h>
@@ -40,9 +41,20 @@
#endif
#endif
-#include "g10lib.h"
+#include "gpgrt-int.h"
#include "secmem.h"
+typedef union
+{
+ int a;
+ short b;
+ char c[1];
+ long d;
+ uint64_t e;
+ float f;
+ double g;
+} PROPERLY_ALIGNED_TYPE;
+
#if defined (MAP_ANON) && ! defined (MAP_ANONYMOUS)
#define MAP_ANONYMOUS MAP_ANON
#endif
@@ -109,8 +121,8 @@ static unsigned int auto_expand;
GPGRT_LOCK_DEFINE (secmem_lock);
/* Convenient macros. */
-#define SECMEM_LOCK gpgrt_lock_lock (&secmem_lock)
-#define SECMEM_UNLOCK gpgrt_lock_unlock (&secmem_lock)
+#define SECMEM_LOCK _gpgrt_lock_lock (&secmem_lock)
+#define SECMEM_UNLOCK _gpgrt_lock_unlock (&secmem_lock)
/* The size of the memblock structure; this does not include the
memory that is available to the user. */
@@ -241,7 +253,7 @@ mb_get_new (pooldesc_t *pool, memblock_t *block, size_t size)
if (! ptr_into_pool_p (pool, mb))
{
- gpg_err_set_errno (ENOMEM);
+ _gpg_err_set_errno (ENOMEM);
mb = NULL;
}
@@ -253,7 +265,7 @@ static void
print_warn (void)
{
if (!no_warning)
- log_info (_("Warning: using insecure memory!\n"));
+ _gpgrt_log_info (_("Warning: using insecure memory!\n"));
}
@@ -298,7 +310,7 @@ lock_pool_pages (void *p, size_t n)
&& err != ENOMEM
#endif
)
- log_error ("can't lock memory: %s\n", strerror (err));
+ _gpgrt_log_error ("can't lock memory: %s\n", strerror (err));
show_warning = 1;
not_locked = 1;
}
@@ -340,7 +352,7 @@ lock_pool_pages (void *p, size_t n)
/* Check that we really dropped the privs.
* Note: setuid(0) should always fail */
if (setuid (uid) || getuid () != geteuid () || !setuid (0))
- log_fatal ("failed to reset uid: %s\n", strerror (errno));
+ _gpgrt_log_fatal ("failed to reset uid: %s\n", strerror (errno));
}
}
@@ -357,7 +369,7 @@ lock_pool_pages (void *p, size_t n)
&& err != ENOMEM
#endif
)
- log_error ("can't lock memory: %s\n", strerror (err));
+ _gpgrt_log_error ("can't lock memory: %s\n", strerror (err));
show_warning = 1;
not_locked = 1;
}
@@ -384,7 +396,7 @@ lock_pool_pages (void *p, size_t n)
(void)p;
(void)n;
if (!no_mlock)
- log_info ("Please note that you don't have secure memory on this system\n");
+ _gpgrt_log_info ("Please note that you don't have secure memory on this system\n");
#endif
}
@@ -397,7 +409,7 @@ init_pool (pooldesc_t *pool, size_t n)
pool->size = n;
if (disable_secmem)
- log_bug ("secure memory is disabled");
+ _gpgrt_log_bug ("secure memory is disabled");
#if HAVE_MMAP
@@ -425,7 +437,7 @@ init_pool (pooldesc_t *pool, size_t n)
fd = open ("/dev/zero", O_RDWR);
if (fd == -1)
{
- log_error ("can't open /dev/zero: %s\n", strerror (errno));
+ _gpgrt_log_error ("can't open /dev/zero: %s\n", strerror (errno));
pool->mem = (void *) -1;
}
else
@@ -437,8 +449,8 @@ init_pool (pooldesc_t *pool, size_t n)
}
# endif
if (pool->mem == (void *) -1)
- log_info ("can't mmap pool of %u bytes: %s - using malloc\n",
- (unsigned) pool->size, strerror (errno));
+ _gpgrt_log_info ("can't mmap pool of %u bytes: %s - using malloc\n",
+ (unsigned) pool->size, strerror (errno));
else
{
pool->is_mmapped = 1;
@@ -451,8 +463,8 @@ init_pool (pooldesc_t *pool, size_t n)
{
pool->mem = malloc (pool->size);
if (!pool->mem)
- log_fatal ("can't allocate memory pool of %u bytes\n",
- (unsigned) pool->size);
+ _gpgrt_log_fatal ("can't allocate memory pool of %u bytes\n",
+ (unsigned) pool->size);
else
pool->okay = 1;
}
@@ -552,7 +564,7 @@ _gpgrt_secmem_init_internal (size_t n)
if (uid != geteuid ())
{
if (setuid (uid) || getuid () != geteuid () || !setuid (0))
- log_fatal ("failed to drop setuid\n");
+ _gpgrt_log_fatal ("failed to drop setuid\n");
}
#endif
}
@@ -566,7 +578,7 @@ _gpgrt_secmem_init_internal (size_t n)
lock_pool_pages (pool->mem, n);
}
else
- log_error ("Oops, secure memory pool already initialized\n");
+ _gpgrt_log_error ("Oops, secure memory pool already initialized\n");
}
}
@@ -601,16 +613,16 @@ _gpgrt_secmem_malloc_internal (size_t size, int xhint)
_gpgrt_secmem_init_internal (STANDARD_POOL_SIZE);
if (!pool->okay)
{
- log_info (_("operation is not possible without "
- "initialized secure memory\n"));
- gpg_err_set_errno (ENOMEM);
+ _gpgrt_log_info (_("operation is not possible without "
+ "initialized secure memory\n"));
+ _gpg_err_set_errno (ENOMEM);
return NULL;
}
}
if (not_locked && fips_mode ())
{
- log_info (_("secure memory pool is not locked while in FIPS mode\n"));
- gpg_err_set_errno (ENOMEM);
+ _gpgrt_log_info (_("secure memory pool is not locked while in FIPS mode\n"));
+ _gpg_err_set_errno (ENOMEM);
return NULL;
}
if (show_warning && !suspend_warning)
@@ -872,21 +884,21 @@ _gpgrt_secmem_dump_stats (int extended)
if (!extended)
{
if (pool->okay)
- log_info ("%-13s %u/%lu bytes in %u blocks\n",
- pool == &mainpool? "secmem usage:":"",
- pool->cur_alloced, (unsigned long)pool->size,
- pool->cur_blocks);
+ _gpgrt_log_info ("%-13s %u/%lu bytes in %u blocks\n",
+ pool == &mainpool? "secmem usage:":"",
+ pool->cur_alloced, (unsigned long)pool->size,
+ pool->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 %d %s block %i size %i\n",
- poolno,
- (mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
- i,
- mb->size);
+ _gpgrt_log_info ("SECMEM: pool %d %s block %i size %i\n",
+ poolno,
+ (mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
+ i,
+ mb->size);
}
}
SECMEM_UNLOCK;
commit 6930b723a1941b4dece6caa754a89add362418b3
Author: NIIBE Yutaka <gniibe at fsij.org>
Date: Thu Sep 6 08:53:07 2018 +0900
Remove _gpgrt_secmem_module_init.
diff --git a/src/secmem.c b/src/secmem.c
index 8b5d803..da5bd57 100644
--- a/src/secmem.c
+++ b/src/secmem.c
@@ -587,14 +587,6 @@ _gpgrt_secmem_init (size_t n)
}
-gpgrt_err_code_t
-_gpgrt_secmem_module_init ()
-{
- /* Not anymore needed. */
- return 0;
-}
-
-
static void *
_gpgrt_secmem_malloc_internal (size_t size, int xhint)
{
commit 25e0253fdaa8d47795ed7f5895202413afd90b28
Author: NIIBE Yutaka <gniibe at fsij.org>
Date: Thu Sep 6 08:52:14 2018 +0900
Change gcry -> gpgrt_.
diff --git a/src/secmem.c b/src/secmem.c
index 532fbde..8b5d803 100644
--- a/src/secmem.c
+++ b/src/secmem.c
@@ -467,7 +467,7 @@ init_pool (pooldesc_t *pool, size_t n)
/* Enable overflow pool allocation in all cases. CHUNKSIZE is a hint
* on how large to allocate overflow pools. */
void
-_gcry_secmem_set_auto_expand (unsigned int chunksize)
+_gpgrt_secmem_set_auto_expand (unsigned int chunksize)
{
/* Round up to a multiple of the STANDARD_POOL_SIZE. */
chunksize = ((chunksize + (2*STANDARD_POOL_SIZE) - 1)
@@ -482,17 +482,17 @@ _gcry_secmem_set_auto_expand (unsigned int chunksize)
void
-_gcry_secmem_set_flags (unsigned flags)
+_gpgrt_secmem_set_flags (unsigned flags)
{
int was_susp;
SECMEM_LOCK;
was_susp = suspend_warning;
- no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING;
- suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING;
- no_mlock = flags & GCRY_SECMEM_FLAG_NO_MLOCK;
- no_priv_drop = flags & GCRY_SECMEM_FLAG_NO_PRIV_DROP;
+ no_warning = flags & GPGRT_SECMEM_FLAG_NO_WARNING;
+ suspend_warning = flags & GPGRT_SECMEM_FLAG_SUSPEND_WARNING;
+ no_mlock = flags & GPGRT_SECMEM_FLAG_NO_MLOCK;
+ no_priv_drop = flags & GPGRT_SECMEM_FLAG_NO_PRIV_DROP;
/* and now issue the warning if it is not longer suspended */
if (was_susp && !suspend_warning && show_warning)
@@ -505,17 +505,17 @@ _gcry_secmem_set_flags (unsigned flags)
}
unsigned int
-_gcry_secmem_get_flags (void)
+_gpgrt_secmem_get_flags (void)
{
unsigned flags;
SECMEM_LOCK;
- flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0;
- flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0;
- flags |= not_locked ? GCRY_SECMEM_FLAG_NOT_LOCKED : 0;
- flags |= no_mlock ? GCRY_SECMEM_FLAG_NO_MLOCK : 0;
- flags |= no_priv_drop ? GCRY_SECMEM_FLAG_NO_PRIV_DROP : 0;
+ flags = no_warning ? GPGRT_SECMEM_FLAG_NO_WARNING : 0;
+ flags |= suspend_warning ? GPGRT_SECMEM_FLAG_SUSPEND_WARNING : 0;
+ flags |= not_locked ? GPGRT_SECMEM_FLAG_NOT_LOCKED : 0;
+ flags |= no_mlock ? GPGRT_SECMEM_FLAG_NO_MLOCK : 0;
+ flags |= no_priv_drop ? GPGRT_SECMEM_FLAG_NO_PRIV_DROP : 0;
SECMEM_UNLOCK;
@@ -526,7 +526,7 @@ _gcry_secmem_get_flags (void)
/* This function initializes the main memory pool MAINPOOL. Itis
* expected to be called with the secmem lock held. */
static void
-_gcry_secmem_init_internal (size_t n)
+_gpgrt_secmem_init_internal (size_t n)
{
pooldesc_t *pool;
@@ -577,18 +577,18 @@ _gcry_secmem_init_internal (size_t n)
order to prevent page-outs of the data. Furthermore allocated
secure memory will be wiped out when released. */
void
-_gcry_secmem_init (size_t n)
+_gpgrt_secmem_init (size_t n)
{
SECMEM_LOCK;
- _gcry_secmem_init_internal (n);
+ _gpgrt_secmem_init_internal (n);
SECMEM_UNLOCK;
}
-gcry_err_code_t
-_gcry_secmem_module_init ()
+gpgrt_err_code_t
+_gpgrt_secmem_module_init ()
{
/* Not anymore needed. */
return 0;
@@ -596,7 +596,7 @@ _gcry_secmem_module_init ()
static void *
-_gcry_secmem_malloc_internal (size_t size, int xhint)
+_gpgrt_secmem_malloc_internal (size_t size, int xhint)
{
pooldesc_t *pool;
memblock_t *mb;
@@ -606,7 +606,7 @@ _gcry_secmem_malloc_internal (size_t size, int xhint)
if (!pool->okay)
{
/* Try to initialize the pool if the user forgot about it. */
- _gcry_secmem_init_internal (STANDARD_POOL_SIZE);
+ _gpgrt_secmem_init_internal (STANDARD_POOL_SIZE);
if (!pool->okay)
{
log_info (_("operation is not possible without "
@@ -669,7 +669,7 @@ _gcry_secmem_malloc_internal (size_t size, int xhint)
pool->okay = 1;
- /* Take care: in _gcry_private_is_secure we do not lock and thus
+ /* Take care: in _gpgrt_private_is_secure we do not lock and thus
* we assume that the second assignment below is atomic. */
pool->next = mainpool.next;
mainpool.next = pool;
@@ -695,19 +695,19 @@ _gcry_secmem_malloc_internal (size_t size, int xhint)
/* Allocate a block from the secmem of SIZE. With XHINT set assume
* that the caller is a xmalloc style function. */
void *
-_gcry_secmem_malloc (size_t size, int xhint)
+_gpgrt_secmem_malloc (size_t size, int xhint)
{
void *p;
SECMEM_LOCK;
- p = _gcry_secmem_malloc_internal (size, xhint);
+ p = _gpgrt_secmem_malloc_internal (size, xhint);
SECMEM_UNLOCK;
return p;
}
static int
-_gcry_secmem_free_internal (void *a)
+_gpgrt_secmem_free_internal (void *a)
{
pooldesc_t *pool;
memblock_t *mb;
@@ -746,7 +746,7 @@ _gcry_secmem_free_internal (void *a)
/* Wipe out and release memory. Returns true if this function
* actually released A. */
int
-_gcry_secmem_free (void *a)
+_gpgrt_secmem_free (void *a)
{
int mine;
@@ -754,14 +754,14 @@ _gcry_secmem_free (void *a)
return 1; /* Tell caller that we handled it. */
SECMEM_LOCK;
- mine = _gcry_secmem_free_internal (a);
+ mine = _gpgrt_secmem_free_internal (a);
SECMEM_UNLOCK;
return mine;
}
static void *
-_gcry_secmem_realloc_internal (void *p, size_t newsize, int xhint)
+_gpgrt_secmem_realloc_internal (void *p, size_t newsize, int xhint)
{
memblock_t *mb;
size_t size;
@@ -777,12 +777,12 @@ _gcry_secmem_realloc_internal (void *p, size_t newsize, int xhint)
}
else
{
- a = _gcry_secmem_malloc_internal (newsize, xhint);
+ a = _gpgrt_secmem_malloc_internal (newsize, xhint);
if (a)
{
memcpy (a, p, size);
memset ((char *) a + size, 0, newsize - size);
- _gcry_secmem_free_internal (p);
+ _gpgrt_secmem_free_internal (p);
}
}
@@ -793,12 +793,12 @@ _gcry_secmem_realloc_internal (void *p, size_t newsize, int xhint)
/* Realloc memory. With XHINT set assume that the caller is a xmalloc
* style function. */
void *
-_gcry_secmem_realloc (void *p, size_t newsize, int xhint)
+_gpgrt_secmem_realloc (void *p, size_t newsize, int xhint)
{
void *a;
SECMEM_LOCK;
- a = _gcry_secmem_realloc_internal (p, newsize, xhint);
+ a = _gpgrt_secmem_realloc_internal (p, newsize, xhint);
SECMEM_UNLOCK;
return a;
@@ -807,12 +807,12 @@ _gcry_secmem_realloc (void *p, size_t newsize, int xhint)
/* Return true if P points into the secure memory areas. */
int
-_gcry_private_is_secure (const void *p)
+_gpgrt_private_is_secure (const void *p)
{
pooldesc_t *pool;
/* We do no lock here because once a pool is allocatred it will not
- * be removed anymore (except for gcry_secmem_term). Further,
+ * be removed anymore (except for gpgrt_secmem_term). Further,
* adding a new pool to the list should be atomic. */
for (pool = &mainpool; pool; pool = pool->next)
if (pool->okay && ptr_into_pool_p (pool, p))
@@ -831,7 +831,7 @@ _gcry_private_is_secure (const void *p)
* there is no chance to get the secure memory cleaned.
*/
void
-_gcry_secmem_term ()
+_gpgrt_secmem_term ()
{
pooldesc_t *pool, *next;
@@ -867,7 +867,7 @@ _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 (int extended)
+_gpgrt_secmem_dump_stats (int extended)
{
pooldesc_t *pool;
memblock_t *mb;
diff --git a/src/secmem.h b/src/secmem.h
index 3a0af2a..8f0a938 100644
--- a/src/secmem.h
+++ b/src/secmem.h
@@ -23,22 +23,22 @@
#ifndef G10_SECMEM_H
#define G10_SECMEM_H 1
-void _gcry_secmem_init (size_t npool);
-void _gcry_secmem_term (void);
-void *_gcry_secmem_malloc (size_t size, int xhint) _GCRY_GCC_ATTR_MALLOC;
-void *_gcry_secmem_realloc (void *a, size_t newsize, int xhint);
-int _gcry_secmem_free (void *a);
-void _gcry_secmem_dump_stats (int extended);
-void _gcry_secmem_set_auto_expand (unsigned int chunksize);
-void _gcry_secmem_set_flags (unsigned flags);
-unsigned _gcry_secmem_get_flags(void);
-int _gcry_private_is_secure (const void *p);
+void _gpgrt_secmem_init (size_t npool);
+void _gpgrt_secmem_term (void);
+void *_gpgrt_secmem_malloc (size_t size, int xhint) GPGRT_ATTR_MALLOC;
+void *_gpgrt_secmem_realloc (void *a, size_t newsize, int xhint);
+int _gpgrt_secmem_free (void *a);
+void _gpgrt_secmem_dump_stats (int extended);
+void _gpgrt_secmem_set_auto_expand (unsigned int chunksize);
+void _gpgrt_secmem_set_flags (unsigned flags);
+unsigned _gpgrt_secmem_get_flags(void);
+int _gpgrt_private_is_secure (const void *p);
-/* Flags for _gcry_secmem_{set,get}_flags. */
-#define GCRY_SECMEM_FLAG_NO_WARNING (1 << 0)
-#define GCRY_SECMEM_FLAG_SUSPEND_WARNING (1 << 1)
-#define GCRY_SECMEM_FLAG_NOT_LOCKED (1 << 2)
-#define GCRY_SECMEM_FLAG_NO_MLOCK (1 << 3)
-#define GCRY_SECMEM_FLAG_NO_PRIV_DROP (1 << 4)
+/* Flags for _gpgrt_secmem_{set,get}_flags. */
+#define GPGRT_SECMEM_FLAG_NO_WARNING (1 << 0)
+#define GPGRT_SECMEM_FLAG_SUSPEND_WARNING (1 << 1)
+#define GPGRT_SECMEM_FLAG_NOT_LOCKED (1 << 2)
+#define GPGRT_SECMEM_FLAG_NO_MLOCK (1 << 3)
+#define GPGRT_SECMEM_FLAG_NO_PRIV_DROP (1 << 4)
#endif /* G10_SECMEM_H */
commit ed813b1dfb33f8c441b72a47ec0d8938f529c0f8
Author: NIIBE Yutaka <gniibe at fsij.org>
Date: Thu Sep 6 08:49:54 2018 +0900
Fix copyright notices.
diff --git a/src/secmem.c b/src/secmem.c
index 79c135f..532fbde 100644
--- a/src/secmem.c
+++ b/src/secmem.c
@@ -3,20 +3,23 @@
* 2003, 2007 Free Software Foundation, Inc.
* Copyright (C) 2013, 2016 g10 Code GmbH
*
- * This file is part of Libgcrypt.
+ * This file is part of Libgpg-error.
*
- * 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
+ * Libgpg-error 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.
+ * Libgpg-error 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/>.
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1+
+ *
+ * This file was originally a part of libgcrypt.
*/
#include <config.h>
diff --git a/src/secmem.h b/src/secmem.h
index 8ad6ef1..3a0af2a 100644
--- a/src/secmem.h
+++ b/src/secmem.h
@@ -1,21 +1,23 @@
/* secmem.h - internal definitions for secmem
* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
*
- * This file is part of Libgcrypt.
+ * This file is part of Libgpg-error.
*
- * 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
+ * Libgpg-error 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.
+ * Libgpg-error 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * License along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1+
+ *
+ * This file was originally a part of libgcrypt.
*/
#ifndef G10_SECMEM_H
commit ed924cebb5115212f6315f16630b6b7f1460e98b
Author: NIIBE Yutaka <gniibe at fsij.org>
Date: Thu Sep 6 08:43:51 2018 +0900
Add src/secmem.{c,h} from libgcrypt master.
diff --git a/src/secmem.c b/src/secmem.c
new file mode 100644
index 0000000..79c135f
--- /dev/null
+++ b/src/secmem.c
@@ -0,0 +1,898 @@
+/* secmem.c - memory allocation from a secure heap
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002,
+ * 2003, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2013, 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/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <stddef.h>
+
+#if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#ifdef USE_CAPABILITIES
+#include <sys/capability.h>
+#endif
+#endif
+
+#include "g10lib.h"
+#include "secmem.h"
+
+#if defined (MAP_ANON) && ! defined (MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#define MINIMUM_POOL_SIZE 16384
+#define STANDARD_POOL_SIZE 32768
+#define DEFAULT_PAGE_SIZE 4096
+
+typedef struct memblock
+{
+ unsigned size; /* Size of the memory available to the
+ user. */
+ int flags; /* See below. */
+ PROPERLY_ALIGNED_TYPE aligned;
+} memblock_t;
+
+/* This flag specifies that the memory block is in use. */
+#define MB_FLAG_ACTIVE (1 << 0)
+
+/* An object describing a memory pool. */
+typedef struct pooldesc_s
+{
+ /* A link to the next pool. This is used to connect the overflow
+ * pools. */
+ struct pooldesc_s *next;
+
+ /* A memory buffer used as allocation pool. */
+ void *mem;
+
+ /* The allocated size of MEM. */
+ size_t size;
+
+ /* Flag indicating that this memory pool is ready for use. May be
+ * checked in an atexit function. */
+ volatile int okay;
+
+ /* Flag indicating whether MEM is mmapped. */
+ volatile int is_mmapped;
+
+ /* The number of allocated bytes and the number of used blocks in
+ * this pool. */
+ unsigned int cur_alloced, cur_blocks;
+} pooldesc_t;
+
+
+/* The pool of secure memory. This is the head of a linked list with
+ * the first element being the standard mlock-ed pool and the
+ * following elements being the overflow pools. */
+static pooldesc_t mainpool;
+
+
+/* A couple of flags with some being set early. */
+static int disable_secmem;
+static int show_warning;
+static int not_locked;
+static int no_warning;
+static int suspend_warning;
+static int no_mlock;
+static int no_priv_drop;
+static unsigned int auto_expand;
+
+
+/* Lock protecting accesses to the memory pools. */
+GPGRT_LOCK_DEFINE (secmem_lock);
+
+/* Convenient macros. */
+#define SECMEM_LOCK gpgrt_lock_lock (&secmem_lock)
+#define SECMEM_UNLOCK gpgrt_lock_unlock (&secmem_lock)
+
+/* The size of the memblock structure; this does not include the
+ memory that is available to the user. */
+#define BLOCK_HEAD_SIZE \
+ offsetof (memblock_t, aligned)
+
+/* Convert an address into the according memory block structure. */
+#define ADDR_TO_BLOCK(addr) \
+ (memblock_t *) (void *) ((char *) addr - BLOCK_HEAD_SIZE)
+
+/* Check whether P points into POOL. */
+static inline int
+ptr_into_pool_p (pooldesc_t *pool, const void *p)
+{
+ /* We need to convert pointers to addresses. This is required by
+ C-99 6.5.8 to avoid undefined behaviour. See also
+ http://lists.gnupg.org/pipermail/gcrypt-devel/2007-February/001102.html
+ */
+ uintptr_t p_addr = (uintptr_t)p;
+ uintptr_t pool_addr = (uintptr_t)pool->mem;
+
+ return p_addr >= pool_addr && p_addr < pool_addr + pool->size;
+}
+
+/* Update the stats. */
+static void
+stats_update (pooldesc_t *pool, size_t add, size_t sub)
+{
+ if (add)
+ {
+ pool->cur_alloced += add;
+ pool->cur_blocks++;
+ }
+ if (sub)
+ {
+ pool->cur_alloced -= sub;
+ pool->cur_blocks--;
+ }
+}
+
+/* Return the block following MB or NULL, if MB is the last block. */
+static memblock_t *
+mb_get_next (pooldesc_t *pool, memblock_t *mb)
+{
+ memblock_t *mb_next;
+
+ mb_next = (memblock_t *) (void *) ((char *) mb + BLOCK_HEAD_SIZE + mb->size);
+
+ if (! ptr_into_pool_p (pool, mb_next))
+ mb_next = NULL;
+
+ return mb_next;
+}
+
+/* Return the block preceding MB or NULL, if MB is the first
+ block. */
+static memblock_t *
+mb_get_prev (pooldesc_t *pool, memblock_t *mb)
+{
+ memblock_t *mb_prev, *mb_next;
+
+ if (mb == pool->mem)
+ mb_prev = NULL;
+ else
+ {
+ mb_prev = (memblock_t *) pool->mem;
+ while (1)
+ {
+ mb_next = mb_get_next (pool, mb_prev);
+ if (mb_next == mb)
+ break;
+ else
+ mb_prev = mb_next;
+ }
+ }
+
+ return mb_prev;
+}
+
+/* If the preceding block of MB and/or the following block of MB
+ exist and are not active, merge them to form a bigger block. */
+static void
+mb_merge (pooldesc_t *pool, memblock_t *mb)
+{
+ memblock_t *mb_prev, *mb_next;
+
+ mb_prev = mb_get_prev (pool, mb);
+ mb_next = mb_get_next (pool, mb);
+
+ if (mb_prev && (! (mb_prev->flags & MB_FLAG_ACTIVE)))
+ {
+ mb_prev->size += BLOCK_HEAD_SIZE + mb->size;
+ mb = mb_prev;
+ }
+ if (mb_next && (! (mb_next->flags & MB_FLAG_ACTIVE)))
+ mb->size += BLOCK_HEAD_SIZE + mb_next->size;
+}
+
+/* Return a new block, which can hold SIZE bytes. */
+static memblock_t *
+mb_get_new (pooldesc_t *pool, memblock_t *block, size_t size)
+{
+ memblock_t *mb, *mb_split;
+
+ for (mb = block; ptr_into_pool_p (pool, mb); mb = mb_get_next (pool, mb))
+ if (! (mb->flags & MB_FLAG_ACTIVE) && mb->size >= size)
+ {
+ /* Found a free block. */
+ mb->flags |= MB_FLAG_ACTIVE;
+
+ if (mb->size - size > BLOCK_HEAD_SIZE)
+ {
+ /* Split block. */
+
+ mb_split = (memblock_t *) (void *) (((char *) mb) + BLOCK_HEAD_SIZE
+ + size);
+ mb_split->size = mb->size - size - BLOCK_HEAD_SIZE;
+ mb_split->flags = 0;
+
+ mb->size = size;
+
+ mb_merge (pool, mb_split);
+
+ }
+
+ break;
+ }
+
+ if (! ptr_into_pool_p (pool, mb))
+ {
+ gpg_err_set_errno (ENOMEM);
+ mb = NULL;
+ }
+
+ return mb;
+}
+
+/* Print a warning message. */
+static void
+print_warn (void)
+{
+ if (!no_warning)
+ log_info (_("Warning: using insecure memory!\n"));
+}
+
+
+/* Lock the memory pages of pool P of size N into core and drop
+ * privileges. */
+static void
+lock_pool_pages (void *p, size_t n)
+{
+#if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK)
+ int err;
+
+ {
+ cap_t cap;
+
+ if (!no_priv_drop)
+ {
+ cap = cap_from_text ("cap_ipc_lock+ep");
+ cap_set_proc (cap);
+ cap_free (cap);
+ }
+ err = no_mlock? 0 : mlock (p, n);
+ if (err && errno)
+ err = errno;
+ if (!no_priv_drop)
+ {
+ cap = cap_from_text ("cap_ipc_lock+p");
+ cap_set_proc (cap);
+ cap_free(cap);
+ }
+ }
+
+ if (err)
+ {
+ if (err != EPERM
+#ifdef EAGAIN /* BSD and also Linux may return EAGAIN */
+ && err != EAGAIN
+#endif
+#ifdef ENOSYS /* Some SCOs return this (function not implemented) */
+ && err != ENOSYS
+#endif
+#ifdef ENOMEM /* Linux might return this. */
+ && err != ENOMEM
+#endif
+ )
+ log_error ("can't lock memory: %s\n", strerror (err));
+ show_warning = 1;
+ not_locked = 1;
+ }
+
+#elif defined(HAVE_MLOCK)
+ uid_t uid;
+ int err;
+
+ uid = getuid ();
+
+#ifdef HAVE_BROKEN_MLOCK
+ /* Under HP/UX mlock segfaults if called by non-root. Note, we have
+ noch checked whether mlock does really work under AIX where we
+ also detected a broken nlock. Note further, that using plock ()
+ is not a good idea under AIX. */
+ if (uid)
+ {
+ errno = EPERM;
+ err = errno;
+ }
+ else
+ {
+ err = no_mlock? 0 : mlock (p, n);
+ if (err && errno)
+ err = errno;
+ }
+#else /* !HAVE_BROKEN_MLOCK */
+ err = no_mlock? 0 : mlock (p, n);
+ if (err && errno)
+ err = errno;
+#endif /* !HAVE_BROKEN_MLOCK */
+
+ /* Test whether we are running setuid(0). */
+ if (uid && ! geteuid ())
+ {
+ /* Yes, we are. */
+ if (!no_priv_drop)
+ {
+ /* Check that we really dropped the privs.
+ * Note: setuid(0) should always fail */
+ if (setuid (uid) || getuid () != geteuid () || !setuid (0))
+ log_fatal ("failed to reset uid: %s\n", strerror (errno));
+ }
+ }
+
+ if (err)
+ {
+ if (err != EPERM
+#ifdef EAGAIN /* BSD and also Linux may return this. */
+ && err != EAGAIN
+#endif
+#ifdef ENOSYS /* Some SCOs return this (function not implemented). */
+ && err != ENOSYS
+#endif
+#ifdef ENOMEM /* Linux might return this. */
+ && err != ENOMEM
+#endif
+ )
+ log_error ("can't lock memory: %s\n", strerror (err));
+ show_warning = 1;
+ not_locked = 1;
+ }
+
+#elif defined ( __QNX__ )
+ /* QNX does not page at all, so the whole secure memory stuff does
+ * not make much sense. However it is still of use because it
+ * wipes out the memory on a free().
+ * Therefore it is sufficient to suppress the warning. */
+ (void)p;
+ (void)n;
+#elif defined (HAVE_DOSISH_SYSTEM) || defined (__CYGWIN__)
+ /* It does not make sense to print such a warning, given the fact that
+ * this whole Windows !@#$% and their user base are inherently insecure. */
+ (void)p;
+ (void)n;
+#elif defined (__riscos__)
+ /* No virtual memory on RISC OS, so no pages are swapped to disc,
+ * besides we don't have mmap, so we don't use it! ;-)
+ * But don't complain, as explained above. */
+ (void)p;
+ (void)n;
+#else
+ (void)p;
+ (void)n;
+ if (!no_mlock)
+ log_info ("Please note that you don't have secure memory on this system\n");
+#endif
+}
+
+/* Initialize POOL. */
+static void
+init_pool (pooldesc_t *pool, size_t n)
+{
+ memblock_t *mb;
+
+ pool->size = n;
+
+ if (disable_secmem)
+ log_bug ("secure memory is disabled");
+
+
+#if HAVE_MMAP
+ {
+ size_t pgsize;
+ long int pgsize_val;
+
+# if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
+ pgsize_val = sysconf (_SC_PAGESIZE);
+# elif defined(HAVE_GETPAGESIZE)
+ pgsize_val = getpagesize ();
+# else
+ pgsize_val = -1;
+# endif
+ pgsize = (pgsize_val > 0)? pgsize_val:DEFAULT_PAGE_SIZE;
+
+ pool->size = (pool->size + pgsize - 1) & ~(pgsize - 1);
+# ifdef MAP_ANONYMOUS
+ pool->mem = mmap (0, pool->size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+# else /* map /dev/zero instead */
+ {
+ int fd;
+
+ fd = open ("/dev/zero", O_RDWR);
+ if (fd == -1)
+ {
+ log_error ("can't open /dev/zero: %s\n", strerror (errno));
+ pool->mem = (void *) -1;
+ }
+ else
+ {
+ pool->mem = mmap (0, pool->size,
+ (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);
+ close (fd);
+ }
+ }
+# endif
+ if (pool->mem == (void *) -1)
+ log_info ("can't mmap pool of %u bytes: %s - using malloc\n",
+ (unsigned) pool->size, strerror (errno));
+ else
+ {
+ pool->is_mmapped = 1;
+ pool->okay = 1;
+ }
+ }
+#endif /*HAVE_MMAP*/
+
+ if (!pool->okay)
+ {
+ pool->mem = malloc (pool->size);
+ if (!pool->mem)
+ log_fatal ("can't allocate memory pool of %u bytes\n",
+ (unsigned) pool->size);
+ else
+ pool->okay = 1;
+ }
+
+ /* Initialize first memory block. */
+ mb = (memblock_t *) pool->mem;
+ mb->size = pool->size - BLOCK_HEAD_SIZE;
+ mb->flags = 0;
+}
+
+
+/* Enable overflow pool allocation in all cases. CHUNKSIZE is a hint
+ * on how large to allocate overflow pools. */
+void
+_gcry_secmem_set_auto_expand (unsigned int chunksize)
+{
+ /* Round up to a multiple of the STANDARD_POOL_SIZE. */
+ chunksize = ((chunksize + (2*STANDARD_POOL_SIZE) - 1)
+ / STANDARD_POOL_SIZE ) * STANDARD_POOL_SIZE;
+ if (chunksize < STANDARD_POOL_SIZE) /* In case of overflow. */
+ chunksize = STANDARD_POOL_SIZE;
+
+ SECMEM_LOCK;
+ auto_expand = chunksize;
+ SECMEM_UNLOCK;
+}
+
+
+void
+_gcry_secmem_set_flags (unsigned flags)
+{
+ int was_susp;
+
+ SECMEM_LOCK;
+
+ was_susp = suspend_warning;
+ no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING;
+ suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING;
+ no_mlock = flags & GCRY_SECMEM_FLAG_NO_MLOCK;
+ no_priv_drop = flags & GCRY_SECMEM_FLAG_NO_PRIV_DROP;
+
+ /* and now issue the warning if it is not longer suspended */
+ if (was_susp && !suspend_warning && show_warning)
+ {
+ show_warning = 0;
+ print_warn ();
+ }
+
+ SECMEM_UNLOCK;
+}
+
+unsigned int
+_gcry_secmem_get_flags (void)
+{
+ unsigned flags;
+
+ SECMEM_LOCK;
+
+ flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0;
+ flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0;
+ flags |= not_locked ? GCRY_SECMEM_FLAG_NOT_LOCKED : 0;
+ flags |= no_mlock ? GCRY_SECMEM_FLAG_NO_MLOCK : 0;
+ flags |= no_priv_drop ? GCRY_SECMEM_FLAG_NO_PRIV_DROP : 0;
+
+ SECMEM_UNLOCK;
+
+ return flags;
+}
+
+
+/* This function initializes the main memory pool MAINPOOL. Itis
+ * expected to be called with the secmem lock held. */
+static void
+_gcry_secmem_init_internal (size_t n)
+{
+ pooldesc_t *pool;
+
+ pool = &mainpool;
+ if (!n)
+ {
+#ifdef USE_CAPABILITIES
+ /* drop all capabilities */
+ if (!no_priv_drop)
+ {
+ cap_t cap;
+
+ cap = cap_from_text ("all-eip");
+ cap_set_proc (cap);
+ cap_free (cap);
+ }
+
+#elif !defined(HAVE_DOSISH_SYSTEM)
+ uid_t uid;
+
+ disable_secmem = 1;
+ uid = getuid ();
+ if (uid != geteuid ())
+ {
+ if (setuid (uid) || getuid () != geteuid () || !setuid (0))
+ log_fatal ("failed to drop setuid\n");
+ }
+#endif
+ }
+ else
+ {
+ if (n < MINIMUM_POOL_SIZE)
+ n = MINIMUM_POOL_SIZE;
+ if (! pool->okay)
+ {
+ init_pool (pool, n);
+ lock_pool_pages (pool->mem, n);
+ }
+ else
+ log_error ("Oops, secure memory pool already initialized\n");
+ }
+}
+
+
+
+/* Initialize the secure memory system. If running with the necessary
+ privileges, the secure memory pool will be locked into the core in
+ order to prevent page-outs of the data. Furthermore allocated
+ secure memory will be wiped out when released. */
+void
+_gcry_secmem_init (size_t n)
+{
+ SECMEM_LOCK;
+
+ _gcry_secmem_init_internal (n);
+
+ SECMEM_UNLOCK;
+}
+
+
+gcry_err_code_t
+_gcry_secmem_module_init ()
+{
+ /* Not anymore needed. */
+ return 0;
+}
+
+
+static void *
+_gcry_secmem_malloc_internal (size_t size, int xhint)
+{
+ pooldesc_t *pool;
+ memblock_t *mb;
+
+ pool = &mainpool;
+
+ if (!pool->okay)
+ {
+ /* Try to initialize the pool if the user forgot about it. */
+ _gcry_secmem_init_internal (STANDARD_POOL_SIZE);
+ if (!pool->okay)
+ {
+ log_info (_("operation is not possible without "
+ "initialized secure memory\n"));
+ gpg_err_set_errno (ENOMEM);
+ return NULL;
+ }
+ }
+ if (not_locked && fips_mode ())
+ {
+ log_info (_("secure memory pool is not locked while in FIPS mode\n"));
+ gpg_err_set_errno (ENOMEM);
+ return NULL;
+ }
+ if (show_warning && !suspend_warning)
+ {
+ show_warning = 0;
+ print_warn ();
+ }
+
+ /* Blocks are always a multiple of 32. */
+ size = ((size + 31) / 32) * 32;
+
+ mb = mb_get_new (pool, (memblock_t *) pool->mem, size);
+ if (mb)
+ {
+ stats_update (pool, mb->size, 0);
+ return &mb->aligned.c;
+ }
+
+ /* If we are called from xmalloc style function resort to the
+ * overflow pools to return memory. We don't do this in FIPS mode,
+ * though. */
+ if ((xhint || auto_expand) && !fips_mode ())
+ {
+ for (pool = pool->next; pool; pool = pool->next)
+ {
+ mb = mb_get_new (pool, (memblock_t *) pool->mem, size);
+ if (mb)
+ {
+ stats_update (pool, mb->size, 0);
+ return &mb->aligned.c;
+ }
+ }
+ /* Allocate a new overflow pool. We put a new pool right after
+ * the mainpool so that the next allocation will happen in that
+ * pool and not in one of the older pools. When this new pool
+ * gets full we will try to find space in the older pools. */
+ pool = calloc (1, sizeof *pool);
+ if (!pool)
+ return NULL; /* Not enough memory for a new pool descriptor. */
+ pool->size = auto_expand? auto_expand : STANDARD_POOL_SIZE;
+ pool->mem = malloc (pool->size);
+ if (!pool->mem)
+ return NULL; /* Not enough memory available for a new pool. */
+ /* Initialize first memory block. */
+ mb = (memblock_t *) pool->mem;
+ mb->size = pool->size - BLOCK_HEAD_SIZE;
+ mb->flags = 0;
+
+ pool->okay = 1;
+
+ /* Take care: in _gcry_private_is_secure we do not lock and thus
+ * we assume that the second assignment below is atomic. */
+ pool->next = mainpool.next;
+ mainpool.next = pool;
+
+ /* After the first time we allocated an overflow pool, print a
+ * warning. */
+ if (!pool->next)
+ print_warn ();
+
+ /* Allocate. */
+ mb = mb_get_new (pool, (memblock_t *) pool->mem, size);
+ if (mb)
+ {
+ stats_update (pool, mb->size, 0);
+ return &mb->aligned.c;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* Allocate a block from the secmem of SIZE. With XHINT set assume
+ * that the caller is a xmalloc style function. */
+void *
+_gcry_secmem_malloc (size_t size, int xhint)
+{
+ void *p;
+
+ SECMEM_LOCK;
+ p = _gcry_secmem_malloc_internal (size, xhint);
+ SECMEM_UNLOCK;
+
+ return p;
+}
+
+static int
+_gcry_secmem_free_internal (void *a)
+{
+ pooldesc_t *pool;
+ memblock_t *mb;
+ int size;
+
+ for (pool = &mainpool; pool; pool = pool->next)
+ if (pool->okay && ptr_into_pool_p (pool, a))
+ break;
+ if (!pool)
+ return 0; /* A does not belong to use. */
+
+ mb = ADDR_TO_BLOCK (a);
+ size = mb->size;
+
+ /* This does not make much sense: probably this memory is held in the
+ * cache. We do it anyway: */
+#define MB_WIPE_OUT(byte) \
+ wipememory2 (((char *) mb + BLOCK_HEAD_SIZE), (byte), size);
+
+ MB_WIPE_OUT (0xff);
+ MB_WIPE_OUT (0xaa);
+ MB_WIPE_OUT (0x55);
+ MB_WIPE_OUT (0x00);
+
+ /* Update stats. */
+ stats_update (pool, 0, size);
+
+ mb->flags &= ~MB_FLAG_ACTIVE;
+
+ mb_merge (pool, mb);
+
+ return 1; /* Freed. */
+}
+
+
+/* Wipe out and release memory. Returns true if this function
+ * actually released A. */
+int
+_gcry_secmem_free (void *a)
+{
+ int mine;
+
+ if (!a)
+ return 1; /* Tell caller that we handled it. */
+
+ SECMEM_LOCK;
+ mine = _gcry_secmem_free_internal (a);
+ SECMEM_UNLOCK;
+ return mine;
+}
+
+
+static void *
+_gcry_secmem_realloc_internal (void *p, size_t newsize, int xhint)
+{
+ memblock_t *mb;
+ size_t size;
+ void *a;
+
+ mb = (memblock_t *) (void *) ((char *) p
+ - ((size_t) &((memblock_t *) 0)->aligned.c));
+ size = mb->size;
+ if (newsize < size)
+ {
+ /* It is easier to not shrink the memory. */
+ a = p;
+ }
+ else
+ {
+ a = _gcry_secmem_malloc_internal (newsize, xhint);
+ if (a)
+ {
+ memcpy (a, p, size);
+ memset ((char *) a + size, 0, newsize - size);
+ _gcry_secmem_free_internal (p);
+ }
+ }
+
+ return a;
+}
+
+
+/* Realloc memory. With XHINT set assume that the caller is a xmalloc
+ * style function. */
+void *
+_gcry_secmem_realloc (void *p, size_t newsize, int xhint)
+{
+ void *a;
+
+ SECMEM_LOCK;
+ a = _gcry_secmem_realloc_internal (p, newsize, xhint);
+ SECMEM_UNLOCK;
+
+ return a;
+}
+
+
+/* Return true if P points into the secure memory areas. */
+int
+_gcry_private_is_secure (const void *p)
+{
+ pooldesc_t *pool;
+
+ /* We do no lock here because once a pool is allocatred it will not
+ * be removed anymore (except for gcry_secmem_term). Further,
+ * adding a new pool to the list should be atomic. */
+ for (pool = &mainpool; pool; pool = pool->next)
+ if (pool->okay && ptr_into_pool_p (pool, p))
+ return 1;
+
+ return 0;
+}
+
+
+/****************
+ * Warning: This code might be called by an interrupt handler
+ * and frankly, there should really be such a handler,
+ * to make sure that the memory is wiped out.
+ * We hope that the OS wipes out mlocked memory after
+ * receiving a SIGKILL - it really should do so, otherwise
+ * there is no chance to get the secure memory cleaned.
+ */
+void
+_gcry_secmem_term ()
+{
+ pooldesc_t *pool, *next;
+
+ for (pool = &mainpool; pool; pool = next)
+ {
+ next = pool->next;
+ if (!pool->okay)
+ continue;
+
+ wipememory2 (pool->mem, 0xff, pool->size);
+ wipememory2 (pool->mem, 0xaa, pool->size);
+ wipememory2 (pool->mem, 0x55, pool->size);
+ wipememory2 (pool->mem, 0x00, pool->size);
+ if (0)
+ ;
+#if HAVE_MMAP
+ else if (pool->is_mmapped)
+ munmap (pool->mem, pool->size);
+#endif
+ else
+ free (pool->mem);
+ pool->mem = NULL;
+ pool->okay = 0;
+ pool->size = 0;
+ if (pool != &mainpool)
+ free (pool);
+ }
+ mainpool.next = NULL;
+ not_locked = 0;
+}
+
+
+/* Print stats of the secmem allocator. With EXTENDED passwed as true
+ * a detiled listing is returned (used for testing). */
+void
+_gcry_secmem_dump_stats (int extended)
+{
+ pooldesc_t *pool;
+ memblock_t *mb;
+ int i, poolno;
+
+ SECMEM_LOCK;
+
+ for (pool = &mainpool, poolno = 0; pool; pool = pool->next, poolno++)
+ {
+ if (!extended)
+ {
+ if (pool->okay)
+ log_info ("%-13s %u/%lu bytes in %u blocks\n",
+ pool == &mainpool? "secmem usage:":"",
+ pool->cur_alloced, (unsigned long)pool->size,
+ pool->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 %d %s block %i size %i\n",
+ poolno,
+ (mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
+ i,
+ mb->size);
+ }
+ }
+ SECMEM_UNLOCK;
+}
diff --git a/src/secmem.h b/src/secmem.h
new file mode 100644
index 0000000..8ad6ef1
--- /dev/null
+++ b/src/secmem.h
@@ -0,0 +1,42 @@
+/* secmem.h - internal definitions for secmem
+ * Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef G10_SECMEM_H
+#define G10_SECMEM_H 1
+
+void _gcry_secmem_init (size_t npool);
+void _gcry_secmem_term (void);
+void *_gcry_secmem_malloc (size_t size, int xhint) _GCRY_GCC_ATTR_MALLOC;
+void *_gcry_secmem_realloc (void *a, size_t newsize, int xhint);
+int _gcry_secmem_free (void *a);
+void _gcry_secmem_dump_stats (int extended);
+void _gcry_secmem_set_auto_expand (unsigned int chunksize);
+void _gcry_secmem_set_flags (unsigned flags);
+unsigned _gcry_secmem_get_flags(void);
+int _gcry_private_is_secure (const void *p);
+
+/* Flags for _gcry_secmem_{set,get}_flags. */
+#define GCRY_SECMEM_FLAG_NO_WARNING (1 << 0)
+#define GCRY_SECMEM_FLAG_SUSPEND_WARNING (1 << 1)
+#define GCRY_SECMEM_FLAG_NOT_LOCKED (1 << 2)
+#define GCRY_SECMEM_FLAG_NO_MLOCK (1 << 3)
+#define GCRY_SECMEM_FLAG_NO_PRIV_DROP (1 << 4)
+
+#endif /* G10_SECMEM_H */
-----------------------------------------------------------------------
hooks/post-receive
--
Error codes used by GnuPG et al.
http://git.gnupg.org
More information about the Gnupg-commits
mailing list