File libgcrypt-check-re-open-dev_random-after-fork.patch of Package libgcrypt.15117
From 319f55e6e5793c59f1ba4cfe481b562bca42194d Mon Sep 17 00:00:00 2001
From: Werner Koch <wk@gnupg.org>
Date: Fri, 26 Oct 2018 13:22:16 +0200
Subject: [PATCH] random: Make sure to re-open /dev/random after a fork
* random/rndlinux.c (_gcry_rndlinux_gather_random): Detect fork and
re-open devices.
--
This mitigates about ill-behaving software which has closed the
standard fds but later dups them to /dev/null.
GnuPG-bug-id: 3491
Signed-off-by: Werner Koch <wk@gnupg.org>
---
random/rndlinux.c | 33 +++++++++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)
Index: libgcrypt-1.8.2/random/rndlinux.c
===================================================================
--- libgcrypt-1.8.2.orig/random/rndlinux.c
+++ libgcrypt-1.8.2/random/rndlinux.c
@@ -108,9 +108,10 @@ open_device (const char *name, int retry
/* Note that the caller needs to make sure that this function is only
- called by one thread at a time. The function returns 0 on success
- or true on failure (in which case the caller will signal a fatal
- error). */
+ * called by one thread at a time. The function returns 0 on success
+ * or true on failure (in which case the caller will signal a fatal
+ * error). This function should be entered only by one thread at a
+ * time. */
int
_gcry_rndlinux_gather_random (void (*add)(const void*, size_t,
enum random_origins),
@@ -122,6 +123,11 @@ _gcry_rndlinux_gather_random (void (*add
static int fd_configured = -1;
static int only_urandom = -1;
static unsigned char ever_opened;
+ static volatile pid_t my_pid; /* The volatile is there to make sure
+ * the compiler does not optimize the
+ * code away in case the getpid
+ * function is badly attributed. */
+ volatile pid_t apid;
int fd;
int n;
byte buffer[768];
@@ -135,13 +141,13 @@ _gcry_rndlinux_gather_random (void (*add
* use only urandom. */
if (only_urandom == -1)
{
+ my_pid = getpid ();
if ((_gcry_random_read_conf () & RANDOM_CONF_ONLY_URANDOM))
only_urandom = 1;
else
only_urandom = 0;
}
-
if (!add)
{
/* Special mode to close the descriptors. */
@@ -163,6 +169,25 @@ _gcry_rndlinux_gather_random (void (*add
return 0;
}
+ /* Detect a fork and close the devices so that we don't use the old
+ * file descriptors. Note that open_device will be called in retry
+ * mode if the devices was opened by the parent process. */
+ apid = getpid ();
+ if (my_pid != apid)
+ {
+ if (fd_random != -1)
+ {
+ close (fd_random);
+ fd_random = -1;
+ }
+ if (fd_urandom != -1)
+ {
+ close (fd_urandom);
+ fd_urandom = -1;
+ }
+ my_pid = apid;
+ }
+
/* First read from a hardware source. However let it account only
for up to 50% (or 25% for RDRAND) of the requested bytes. */