summaryrefslogtreecommitdiff
path: root/recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch
diff options
context:
space:
mode:
authorMax Krummenacher <max.krummenacher@toradex.com>2016-12-30 15:48:19 +0100
committerMax Krummenacher <max.krummenacher@toradex.com>2017-01-11 20:18:11 +0100
commita4c62af62750a8c33ed1b8bee7d2f8b8d707d3cc (patch)
tree4d47bdb191b4fcbc48034e7fbb92ea57b6123011 /recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch
parentdc4caf1f337ea524a786a7c956af71e3934fe4c1 (diff)
gnutls: backport split initialization in preinit and init
From https://bugzilla.redhat.com/show_bug.cgi?id=1387141: Description of problem: GnuTLS initializes its random generator on the library constructor. That has the side effect that applications which load early on boot process may block for significant time even when they wouldn't otherwise use the random generator. connmand is hit by the above issue. Backport the relevant patches. Signed-off-by: Max Krummenacher <max.krummenacher@toradex.com> Acked-by: Stefan Agner <stefan.agner@toradex.com>
Diffstat (limited to 'recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch')
-rw-r--r--recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch261
1 files changed, 261 insertions, 0 deletions
diff --git a/recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch b/recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch
new file mode 100644
index 0000000..29bcf5f
--- /dev/null
+++ b/recipes-support/gnutls/gnutls-3.5.3/0002-rng-split-initialization-in-preinit-and-init.patch
@@ -0,0 +1,261 @@
+From 834e8fc03cb27ae437a2044cfaf265752c3e6a26 Mon Sep 17 00:00:00 2001
+From: Nikos Mavrogiannopoulos <nmav@redhat.com>
+Date: Fri, 14 Oct 2016 14:16:51 +0200
+Subject: [PATCH 2/3] rng: split initialization in preinit and init
+
+This makes gnutls to initialize its random generator on the
+first call to gnutls_rnd(). That prevents blocking due to
+getrandom() on a constructor; that change allows to use gnutls-linked
+applications even in early boot in systems where getrandom() blocks
+waiting for entropy.
+
+Upstream-Status: Backport
+
+diff --git a/configure.ac b/configure.ac
+index 0ba2230..f842e26 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -186,6 +186,7 @@ AM_SUBST_NOTMAKE([DEFINE_IOVEC_T])
+
+ dnl Need netinet/tcp.h for TCP_FASTOPEN
+ AC_CHECK_HEADERS([netinet/tcp.h])
++AC_CHECK_HEADERS([stdatomic.h])
+
+ AC_ARG_ENABLE(padlock,
+ AS_HELP_STRING([--disable-padlock], [unconditionally disable padlock acceleration]),
+diff --git a/lib/global.c b/lib/global.c
+index d75cea8..bdc3c1f 100644
+--- a/lib/global.c
++++ b/lib/global.c
+@@ -304,7 +304,7 @@ static int _gnutls_global_init(unsigned constructor)
+ }
+
+ /* Initialize the random generator */
+- ret = _gnutls_rnd_init();
++ ret = _gnutls_rnd_preinit();
+ if (ret < 0) {
+ gnutls_assert();
+ goto out;
+diff --git a/lib/locks.h b/lib/locks.h
+index 5807754..b1efbb5 100644
+--- a/lib/locks.h
++++ b/lib/locks.h
+@@ -27,6 +27,10 @@
+ #include "gnutls_int.h"
+ #include <system.h>
+
++#ifdef HAVE_STDATOMIC_H
++# include <stdatomic.h>
++#endif
++
+ extern mutex_init_func gnutls_mutex_init;
+ extern mutex_deinit_func gnutls_mutex_deinit;
+ extern mutex_lock_func gnutls_mutex_lock;
+diff --git a/lib/nettle/rnd-fips.c b/lib/nettle/rnd-fips.c
+index 59795a9..0807701 100644
+--- a/lib/nettle/rnd-fips.c
++++ b/lib/nettle/rnd-fips.c
+@@ -172,10 +172,6 @@ static int _rngfips_init(void **_ctx)
+ struct fips_ctx *ctx;
+ int ret;
+
+- ret = _rnd_system_entropy_init();
+- if (ret < 0)
+- return gnutls_assert_val(ret);
+-
+ ctx = gnutls_calloc(1, sizeof(*ctx));
+ if (ctx == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c
+index 39b99e1..c4fbc48 100644
+--- a/lib/nettle/rnd.c
++++ b/lib/nettle/rnd.c
+@@ -218,12 +218,6 @@ static int wrap_nettle_rnd_init(void **ctx)
+ return ret;
+ }
+
+- ret = _rnd_system_entropy_init();
+- if (ret < 0) {
+- gnutls_assert();
+- return ret;
+- }
+-
+ /* initialize the main RNG */
+ yarrow256_init(&rnd_ctx.yctx, SOURCES, rnd_ctx.ysources);
+
+diff --git a/lib/random.c b/lib/random.c
+index d7f18f2..977d7aa 100644
+--- a/lib/random.c
++++ b/lib/random.c
+@@ -26,30 +26,80 @@
+ #include "gnutls_int.h"
+ #include "errors.h"
+ #include <random.h>
++#include "locks.h"
+ #include <fips.h>
+
+ void *gnutls_rnd_ctx;
++GNUTLS_STATIC_MUTEX(gnutls_rnd_init_mutex);
+
+-int _gnutls_rnd_init(void)
++#ifdef HAVE_STDATOMIC_H
++static atomic_uint rnd_initialized = 0;
++
++inline static int _gnutls_rnd_init(void)
++{
++ if (unlikely(!rnd_initialized)) {
++ if (_gnutls_rnd_ops.init == NULL) {
++ rnd_initialized = 1;
++ return 0;
++ }
++
++ GNUTLS_STATIC_MUTEX_LOCK(gnutls_rnd_init_mutex);
++ if (!rnd_initialized) {
++ if (_gnutls_rnd_ops.init(&gnutls_rnd_ctx) < 0) {
++ gnutls_assert();
++ GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex);
++ return GNUTLS_E_RANDOM_FAILED;
++ }
++ rnd_initialized = 1;
++ }
++ GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex);
++ }
++ return 0;
++}
++#else
++static unsigned rnd_initialized = 0;
++
++inline static int _gnutls_rnd_init(void)
++{
++ GNUTLS_STATIC_MUTEX_LOCK(gnutls_rnd_init_mutex);
++ if (unlikely(!rnd_initialized)) {
++ if (_gnutls_rnd_ops.init == NULL) {
++ rnd_initialized = 1;
++ GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex);
++ return 0;
++ }
++
++ if (_gnutls_rnd_ops.init(&gnutls_rnd_ctx) < 0) {
++ gnutls_assert();
++ GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex);
++ return GNUTLS_E_RANDOM_FAILED;
++ }
++ rnd_initialized = 1;
++ }
++ GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_init_mutex);
++ return 0;
++}
++#endif
++
++int _gnutls_rnd_preinit(void)
+ {
++ int ret;
++
+ #ifdef ENABLE_FIPS140
+ /* The FIPS140 random generator is only enabled when we are compiled
+ * with FIPS support, _and_ the system requires FIPS140.
+ */
+ if (_gnutls_fips_mode_enabled() == 1) {
+- int ret;
+-
+ ret = gnutls_crypto_rnd_register(100, &_gnutls_fips_rnd_ops);
+ if (ret < 0)
+ return ret;
+ }
+ #endif
+
+- if (_gnutls_rnd_ops.init != NULL) {
+- if (_gnutls_rnd_ops.init(&gnutls_rnd_ctx) < 0) {
+- gnutls_assert();
+- return GNUTLS_E_RANDOM_FAILED;
+- }
++ ret = _rnd_system_entropy_init();
++ if (ret < 0) {
++ gnutls_assert();
++ return GNUTLS_E_RANDOM_FAILED;
+ }
+
+ return 0;
+@@ -57,9 +107,12 @@ int _gnutls_rnd_init(void)
+
+ void _gnutls_rnd_deinit(void)
+ {
+- if (_gnutls_rnd_ops.deinit != NULL) {
++ if (rnd_initialized && _gnutls_rnd_ops.deinit != NULL) {
+ _gnutls_rnd_ops.deinit(gnutls_rnd_ctx);
+ }
++ rnd_initialized = 0;
++
++ _rnd_system_entropy_deinit();
+
+ return;
+ }
+@@ -81,8 +134,17 @@ void _gnutls_rnd_deinit(void)
+ **/
+ int gnutls_rnd(gnutls_rnd_level_t level, void *data, size_t len)
+ {
++ int ret;
+ FAIL_IF_LIB_ERROR;
+- return _gnutls_rnd(level, data, len);
++
++ if (unlikely((ret=_gnutls_rnd_init()) < 0))
++ return gnutls_assert_val(ret);
++
++ if (likely(len > 0)) {
++ return _gnutls_rnd_ops.rnd(gnutls_rnd_ctx, level, data,
++ len);
++ }
++ return 0;
+ }
+
+ /**
+@@ -98,5 +160,6 @@ int gnutls_rnd(gnutls_rnd_level_t level, void *data, size_t len)
+ **/
+ void gnutls_rnd_refresh(void)
+ {
+- _gnutls_rnd_refresh();
++ if (rnd_initialized && _gnutls_rnd_ops.rnd_refresh)
++ _gnutls_rnd_ops.rnd_refresh(gnutls_rnd_ctx);
+ }
+diff --git a/lib/random.h b/lib/random.h
+index 1538ec8..2ef7bc4 100644
+--- a/lib/random.h
++++ b/lib/random.h
+@@ -31,31 +31,15 @@ extern int crypto_rnd_prio;
+ extern void *gnutls_rnd_ctx;
+ extern gnutls_crypto_rnd_st _gnutls_rnd_ops;
+
+-inline static int
+-_gnutls_rnd(gnutls_rnd_level_t level, void *data, size_t len)
+-{
+- if (len > 0) {
+- return _gnutls_rnd_ops.rnd(gnutls_rnd_ctx, level, data,
+- len);
+- }
+- return 0;
+-}
+-
+-inline static void _gnutls_rnd_refresh(void)
+-{
+- _gnutls_rnd_ops.rnd_refresh(gnutls_rnd_ctx);
+-}
++#define _gnutls_rnd gnutls_rnd
++#define _gnutls_rnd_refresh gnutls_rnd_refresh
+
+ void _gnutls_rnd_deinit(void);
+-int _gnutls_rnd_init(void);
++int _gnutls_rnd_preinit(void);
+
+ inline static int _gnutls_rnd_check(void)
+ {
+ return _rnd_system_entropy_check();
+ }
+
+-#ifndef _WIN32
+-extern int _gnutls_urandom_fd;
+-#endif
+-
+ #endif
+--
+2.6.6
+