Put blocking calls into Libgpg-error's system call clamp.
authorWerner Koch <wk@gnupg.org>
Sat, 12 Nov 2016 10:34:49 +0000 (11:34 +0100)
committerWerner Koch <wk@gnupg.org>
Sat, 12 Nov 2016 10:34:49 +0000 (11:34 +0100)
* src/gcrypt.h.in (GCRYCTL_REINIT_SYSCALL_CLAMP): New.
* configure.ac: Require Libgpg-error 1.25.  Set version number to
1.8.0.
* src/gcrypt-int.h: Remove error code emulation.
* src/global.c (pre_syscall_func, post_syscall_func): New.
(global_init): Call gpgrt_get_syscall_clamp.
(_gcry_vcontrol) <GCRYCTL_REINIT_SYSCALL_CLAMP>: Ditto.
(_gcry_pre_syscall, _gcry_post_syscall): New.
* random/rndlinux.c (_gcry_rndlinux_gather_random): Use the new
functions.

Signed-off-by: Werner Koch <wk@gnupg.org>
NEWS
configure.ac
doc/gcrypt.texi
random/rndlinux.c
src/g10lib.h
src/gcrypt-int.h
src/gcrypt.h.in
src/global.c

diff --git a/NEWS b/NEWS
index cdf1ef4..0aaf863 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,24 @@
-Noteworthy changes in version 1.7.4 (unreleased)  [C21/A1/R_]
+Noteworthy changes in version 1.8.0 (unreleased)  [C21/A1/R_]
 ------------------------------------------------
 
+ * New interfaces:
+
+   - GCRYCTL_REINIT_SYSCALL_CLAMP allows to init nPth after Libgcrypt.
+
+ * Internal changes:
+
+   - Libgpg-error 1.25 is now required.  This avoids stalling of nPth
+     threads due to contention on internal Libgcrypt locks (e.g. the
+     random pool lock).
+
+   - The system call clamp of libgpg-error is now used to wrap the
+     blocking read of /dev/random.  This allows other nPth threads to
+     run while Libgcrypt is gathering entropy.
+
+
+ * Interface changes relative to the 1.6.0 release:
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   GCRYCTL_REINIT_SYSCALL_CLAMP    NEW macro.
 
 Noteworthy changes in version 1.7.3 (2016-08-17)  [C21/A1/R3]
 ------------------------------------------------
index 7bbf4bd..17ff407 100644 (file)
@@ -29,8 +29,8 @@ min_automake_version="1.14"
 # commit and push so that the git magic is able to work.  See below
 # for the LT versions.
 m4_define(mym4_version_major, [1])
-m4_define(mym4_version_minor, [7])
-m4_define(mym4_version_micro, [4])
+m4_define(mym4_version_minor, [8])
+m4_define(mym4_version_micro, [0])
 
 # Below is m4 magic to extract and compute the revision number, the
 # decimalized short revision number, a beta version string, and a flag
@@ -67,7 +67,7 @@ LIBGCRYPT_CONFIG_API_VERSION=1
 
 # If you change the required gpg-error version, please remove
 # unnecessary error code defines in src/gcrypt-int.h.
-NEED_GPG_ERROR_VERSION=1.13
+NEED_GPG_ERROR_VERSION=1.25
 
 PACKAGE=$PACKAGE_NAME
 VERSION=$PACKAGE_VERSION
index c2c39ad..933d22d 100644 (file)
@@ -905,6 +905,21 @@ detection code might be run if the feature has been disabled.  This
 command must be used at initialization time; i.e. before calling
 @code{gcry_check_version}.
 
+@item GCRYCTL_REINIT_SYSCALL_CLAMP; Arguments: none
+
+Libgcrypt wraps blocking system calls with two functions calls
+(``system call clamp'') to give user land threading libraries a hook
+for re-scheduling.  This works by reading the system call clamp from
+Libgpg-error at initialization time.  However sometimes Libgcrypt
+needs to be initialized before the user land threading systems and at
+that point the system call clamp has not been registered with
+Libgpg-error and in turn Libgcrypt would not use them.  The control
+code can be used to tell Libgcrypt that a system call clamp has now
+been registered with Libgpg-error and advised it to read the clamp
+again.  Obviously this control code may only be used before a second
+thread is started in a process.
+
+
 @end table
 
 @end deftypefun
index 2b563bf..562149a 100644 (file)
@@ -220,7 +220,10 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
           FD_SET(fd, &rfds);
           tv.tv_sec = delay;
           tv.tv_usec = delay? 0 : 100000;
-          if ( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) )
+          _gcry_pre_syscall ();
+          rc = select (fd+1, &rfds, NULL, NULL, &tv);
+          _gcry_post_syscall ();
+          if (!rc)
             {
               any_need_entropy = 1;
               delay = 3; /* Use 3 seconds henceforth.  */
@@ -256,8 +259,10 @@ _gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
               nbytes = length < sizeof(buffer)? length : sizeof(buffer);
               if (nbytes > 256)
                 nbytes = 256;
+              _gcry_pre_syscall ();
               ret = syscall (__NR_getrandom,
                              (void*)buffer, (size_t)nbytes, (unsigned int)0);
+              _gcry_post_syscall ();
             }
           while (ret == -1 && errno == EINTR);
           if (ret == -1 && errno == ENOSYS)
index 444c868..d4e3fef 100644 (file)
@@ -93,7 +93,9 @@
 /*-- src/global.c -*/
 int _gcry_global_is_operational (void);
 gcry_err_code_t _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr);
-void  _gcry_check_heap (const void *a);
+void _gcry_check_heap (const void *a);
+void _gcry_pre_syscall (void);
+void _gcry_post_syscall (void);
 int _gcry_get_debug_flag (unsigned int mask);
 
 /* Malloc functions and common wrapper macros.  */
index d367307..729f54a 100644 (file)
 #include "types.h"
 
 /* These error codes are used but not defined in the required
-   libgpg-error 1.11.  Define them here. */
-#if GPG_ERROR_VERSION_NUMBER < 0x010c00  /* 1.12 */
-# define GPG_ERR_NO_CRYPT_CTX      191
-# define GPG_ERR_WRONG_CRYPT_CTX    192
-# define GPG_ERR_BAD_CRYPT_CTX     193
-# define GPG_ERR_CRYPT_CTX_CONFLICT 194
-# define GPG_ERR_BROKEN_PUBKEY      195
-# define GPG_ERR_BROKEN_SECKEY      196
-#endif
+ * libgpg-error N.MM.  Define them here.  [None right now.] */
 
-#if GPG_ERROR_VERSION_NUMBER < 0x010d00  /* 1.13 */
-# define GPG_ERR_MAC_ALGO           197
-#endif
 
 \f
 /* Context used with elliptic curve functions.  */
index 02b8772..f896a78 100644 (file)
@@ -331,7 +331,8 @@ enum gcry_ctl_cmds
     GCRYCTL_SET_SBOX = 73,
     GCRYCTL_DRBG_REINIT = 74,
     GCRYCTL_SET_TAGLEN = 75,
-    GCRYCTL_GET_TAGLEN = 76
+    GCRYCTL_GET_TAGLEN = 76,
+    GCRYCTL_REINIT_SYSCALL_CLAMP = 77
   };
 
 /* Perform various operations defined by CMD. */
index 8669a46..8e54efe 100644 (file)
@@ -56,6 +56,15 @@ static int force_fips_mode;
 /* Controlled by global_init().  */
 static int any_init_done;
 
+/*
+ * Functions called before and after blocking syscalls.
+ * Initialized by global_init and used via
+ * _gcry_pre_syscall and _gcry_post_syscall.
+ */
+static void (*pre_syscall_func)(void);
+static void (*post_syscall_func)(void);
+
+
 /* Memory management. */
 
 static gcry_handler_alloc_t alloc_func;
@@ -89,6 +98,10 @@ global_init (void)
   /* Tell the random module that we have seen an init call.  */
   _gcry_set_preferred_rng_type (0);
 
+  /* Get the system call clamp functions.  */
+  if (!pre_syscall_func)
+    gpgrt_get_syscall_clamp (&pre_syscall_func, &post_syscall_func);
+
   /* See whether the system is in FIPS mode.  This needs to come as
      early as possible but after ATH has been initialized.  */
   _gcry_initialize_fips_mode (force_fips_mode);
@@ -673,6 +686,11 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       }
       break;
 
+    case GCRYCTL_REINIT_SYSCALL_CLAMP:
+      if (!pre_syscall_func)
+        gpgrt_get_syscall_clamp (&pre_syscall_func, &post_syscall_func);
+      break;
+
     default:
       _gcry_set_preferred_rng_type (0);
       rc = GPG_ERR_INV_OP;
@@ -1059,6 +1077,24 @@ _gcry_xstrdup (const char *string)
 }
 
 
+/* Used before blocking system calls.  */
+void
+_gcry_pre_syscall (void)
+{
+  if (pre_syscall_func)
+    pre_syscall_func ();
+}
+
+
+/* Used after blocking system calls.  */
+void
+_gcry_post_syscall (void)
+{
+  if (post_syscall_func)
+    post_syscall_func ();
+}
+
+
 int
 _gcry_get_debug_flag (unsigned int mask)
 {