]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
simplified fork detection
authorNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 26 Jun 2015 07:08:20 +0000 (09:08 +0200)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Fri, 26 Jun 2015 07:08:20 +0000 (09:08 +0200)
lib/atfork.c
lib/atfork.h
lib/nettle/rnd-fips.c
lib/nettle/rnd.c
lib/pkcs11.c

index dec8d2cb2cd9c7be3e0d50f2d2ee20468209e8c6..793de391cfc14430a8b07c6f151c4daa0167802c 100644 (file)
 #include <sys/types.h>
 #include <atfork.h>
 
-#ifndef _WIN32
-
-# if defined(HAVE___REGISTER_ATFORK) || defined(HAVE_PTHREAD_ATFORK)
-#  define HAVE_ATFORK
-# endif
+unsigned int gnutls_forkid = 0;
 
-/* The maximum number of users of the API */
-# define MAX_VALS 6
-
-static unsigned int * fvals[MAX_VALS];
-static unsigned int fvals_size = 0;
+#ifndef _WIN32
 
 # ifdef HAVE_ATFORK
 static void fork_handler(void)
 {
-       unsigned i;
-       for (i=0;i<fvals_size;i++)
-               *fvals[i] = 1;
+       gnutls_forkid++;
 }
 # endif
 
-static void set_val_on_fork(unsigned int *val, unsigned int def)
-{
-       if (fvals_size >= MAX_VALS)
-               abort(); /* internal error */
-       *val = def;
-       fvals[fvals_size++] = val;
-}
-
-void _gnutls_fork_set_val(unsigned int *val)
-{
-# ifdef HAVE_ATFORK
-       set_val_on_fork(val, 0);
-# else
-       set_val_on_fork(val, getpid());
-# endif
-}
-
 # if defined(HAVE_PTHREAD_ATFORK)
 
 #  include <pthread.h>
@@ -93,9 +66,22 @@ int _gnutls_register_fork_handler(void)
 
 # else
 
+unsigned int _gnutls_get_forkid(void)
+{
+       return getpid();
+}
+
+int _gnutls_detect_fork(unsigned int forkid)
+{
+       if (getpid() == forkid)
+               return 0;
+       return 1;
+}
+
 /* we have to detect fork manually */
 int _gnutls_register_fork_handler(void)
 {
+       gnutls_forkid = getpid();
        return 0;
 }
 
index dfb682bd90ac10d39571d0e9b73b82ed0f7d7ccf..c8768877ff862ae6bcb4f14c40db61393825b5f6 100644 (file)
  */
 
 #ifndef ATFORK_H
-#define ATFORK_H
+# define ATFORK_H
 
 #include <config.h>
 #include <gnutls_int.h>
 
+extern unsigned int gnutls_forkid;
+
+#if defined(HAVE___REGISTER_ATFORK) || defined(HAVE_PTHREAD_ATFORK)
+# define HAVE_ATFORK
+#endif
+
 #ifndef _WIN32
 
 /* API */
 int _gnutls_register_fork_handler(void); /* global init */
 
-/* Each user of the API that needs to be notified registers
- * a pointer to an int */
-void _gnutls_fork_set_val(unsigned int *val);
-
-/* 
- * Each user, calls this function with the integer registered
- * to check whether a fork is detected
- *
- * unsigned _gnutls_fork_detected(unsigned int *v);
- */
-
-# if defined(HAVE___REGISTER_ATFORK) || defined(HAVE_PTHREAD_ATFORK)
-inline static
-unsigned _gnutls_fork_detected(unsigned int *v)
+# if defined(HAVE_ATFORK)
+inline static int _gnutls_detect_fork(unsigned int forkid)
 {
-       if (*v != 0) {
-               *v = 0;
-               return 1;
-       }
-       return 0;
+       if (forkid == gnutls_forkid)
+               return 0;
+       return 1;
 }
-# else
-#  include <unistd.h>
 
-inline static
-unsigned _gnutls_fork_detected(unsigned int *v)
+inline static unsigned int _gnutls_get_forkid(void)
 {
-       if (getpid() != (pid_t)*v) {
-               *v = getpid();
-               return 1;
-       }
-       return 0;
+       return gnutls_forkid;
 }
-
+# else
+int _gnutls_detect_fork(unsigned int forkid);
+unsigned int _gnutls_get_forkid(void);
 # endif
 
-#else /* _WIN32 */
-# define _gnutls_fork_set_val(x) 0
-# define _gnutls_register_fork_handler() 0
-# define _gnutls_fork_detected(x) 0
+#else
+
+# define _gnutls_detect_fork(x) 0
+# define _gnutls_get_forkid() 0
+
 #endif
 
 #endif
index 33c23e678cddee8dbda7704cb4da6f24f2ebde12..8e31f73895a9bbec472291bbd5c33c72a5afa836 100644 (file)
@@ -48,7 +48,7 @@ struct fips_ctx {
        struct drbg_aes_ctx nonce_context;
        struct drbg_aes_ctx normal_context;
        struct drbg_aes_ctx strong_context;
-       unsigned int dfork;
+       unsigned int forkid;
 };
 
 static int _rngfips_ctx_reinit(struct fips_ctx *fctx);
@@ -60,7 +60,7 @@ static int get_random(struct drbg_aes_ctx *ctx, struct fips_ctx *fctx,
 {
        int ret;
 
-       if ( _gnutls_fork_detected(&fctx->dfork) != 0) {
+       if ( _gnutls_detect_fork(fctx->forkid) != 0) {
                ret = _rngfips_ctx_reinit(fctx);
                if (ret < 0)
                        return gnutls_assert_val(ret);
@@ -135,7 +135,8 @@ static int _rngfips_ctx_init(struct fips_ctx *fctx)
        if (ret < 0)
                return gnutls_assert_val(ret);
 
-       _gnutls_fork_set_val(&fctx->dfork);
+       fctx->forkid = _gnutls_get_forkid();
+
        return 0;
 }
 
@@ -158,6 +159,8 @@ static int _rngfips_ctx_reinit(struct fips_ctx *fctx)
        if (ret < 0)
                return gnutls_assert_val(ret);
 
+       fctx->forkid = _gnutls_get_forkid();
+
        return 0;
 }
 
index d4dbdc144fcb9126742ac6666a6365218b266092..8ac30a8d95fe9fedf11a63612d78137328426951 100644 (file)
@@ -54,7 +54,7 @@ struct nonce_ctx_st {
        struct salsa20_ctx ctx;
        unsigned int counter;
        void *mutex;
-       unsigned int dfork;
+       unsigned int forkid;
 };
 
 struct rnd_ctx_st {
@@ -64,7 +64,7 @@ struct rnd_ctx_st {
        time_t trivia_previous_time;
        time_t trivia_time_count;
        void *mutex;
-       unsigned dfork; /* detect fork() */
+       unsigned forkid;
 };
 
 static struct rnd_ctx_st rnd_ctx;
@@ -178,7 +178,7 @@ static int nonce_rng_init(struct nonce_ctx_st *ctx,
                 * from the old key */
                salsa20r12_crypt(&ctx->ctx, nonce_key_size, nonce_key, nonce_key);
        } else {
-               _gnutls_fork_set_val(&ctx->dfork);
+               ctx->forkid = _gnutls_get_forkid();
 
                /* when initializing read the IV from the system randomness source */
                ret = _rnd_get_system_entropy(iv, sizeof(iv));
@@ -229,7 +229,7 @@ static int wrap_nettle_rnd_init(void **ctx)
 
        _rnd_get_event(&event);
 
-       _gnutls_fork_set_val(&rnd_ctx.dfork);
+       rnd_ctx.forkid = _gnutls_get_forkid();
 
        ret = do_device_source(&rnd_ctx, 1, &event);
        if (ret < 0) {
@@ -278,7 +278,7 @@ wrap_nettle_rnd_nonce(void *_ctx, void *data, size_t datasize)
 
        RND_LOCK(&nonce_ctx);
 
-       if (_gnutls_fork_detected(&nonce_ctx.dfork)) {
+       if (_gnutls_detect_fork(nonce_ctx.forkid)) {
                reseed = 1;
        }
 
@@ -295,6 +295,8 @@ wrap_nettle_rnd_nonce(void *_ctx, void *data, size_t datasize)
                        gnutls_assert();
                        goto cleanup;
                }
+
+               nonce_ctx.forkid = _gnutls_get_forkid();
        }
 
        salsa20r12_crypt(&nonce_ctx.ctx, datasize, data, data);
@@ -322,7 +324,7 @@ wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize)
 
        RND_LOCK(&rnd_ctx);
 
-       if (_gnutls_fork_detected(&rnd_ctx.dfork)) {    /* fork() detected */
+       if (_gnutls_detect_fork(rnd_ctx.forkid)) {      /* fork() detected */
                memset(&rnd_ctx.device_last_read, 0, sizeof(rnd_ctx.device_last_read));
                reseed = 1;
        }
@@ -340,8 +342,10 @@ wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize)
                goto cleanup;
        }
 
-       if (reseed != 0)
+       if (reseed != 0) {
                yarrow256_slow_reseed(&rnd_ctx.yctx);
+               rnd_ctx.forkid = _gnutls_get_forkid();
+       }
 
        yarrow256_random(&rnd_ctx.yctx, datasize, data);
        ret = 0;
index dadfd57fff4344e462f752c6d7e2926b8ba376c0..cf361dfd3134307ba1eac4103cc8e5e757b29a86 100644 (file)
@@ -100,7 +100,7 @@ struct find_cert_st {
 static struct gnutls_pkcs11_provider_st providers[MAX_PROVIDERS];
 static unsigned int active_providers = 0;
 static unsigned int providers_initialized = 0;
-static unsigned int dfork = 0;
+static unsigned int pkcs11_forkid = 0;
 
 gnutls_pkcs11_token_callback_t _gnutls_token_func;
 void *_gnutls_token_data;
@@ -256,7 +256,7 @@ int _gnutls_pkcs11_check_init(void)
        if (providers_initialized != 0) {
                ret = 0;
 
-               if (_gnutls_fork_detected(&dfork)) {
+               if (_gnutls_detect_fork(pkcs11_forkid)) {
                        /* if we are initialized but a fork is detected */
                        ret = gnutls_pkcs11_reinit();
                        if (ret == 0)
@@ -761,7 +761,7 @@ gnutls_pkcs11_init(unsigned int flags, const char *deprecated_config_file)
        }
        init++;
 
-       _gnutls_fork_set_val(&dfork);
+       pkcs11_forkid = _gnutls_get_forkid();
 
        p11_kit_pin_register_callback(P11_KIT_PIN_FALLBACK,
                                      p11_kit_pin_file_callback, NULL,
@@ -807,7 +807,7 @@ int gnutls_pkcs11_reinit(void)
        ck_rv_t rv;
 
        /* make sure that we don't call more than once after a fork */
-       if (_gnutls_fork_detected(&dfork) == 0)
+       if (_gnutls_detect_fork(pkcs11_forkid) == 0)
                return 0;
 
        for (i = 0; i < active_providers; i++) {
@@ -826,6 +826,8 @@ int gnutls_pkcs11_reinit(void)
                }
        }
 
+       pkcs11_forkid = _gnutls_get_forkid();
+
        return 0;
 }