[OpenWrt-Devel] [PATCH] openssl: Fix longer booting times by unblocking getrandom

Petr Štetiar ynezz at true.cz
Fri Mar 15 08:28:39 EDT 2019


While testing simple firmware image for x86/64 in QEMU I've discovered
some weird behavior today. This image contains simple package with
simple init script to bootstrap the device UCI configuration from
network server. This init script uses uclient-fetch and libustream-openssl.

This image was booting fine until today, usually finished booting under
10s, but today it was booting much slowly, boot times were in range from
60s to a few minutes. I was also unable to power off the QEMU with
poweroff command.

I've found out, that it's all happening because of uclient-fetch being
blocked in getrandom syscall, leading for example to following:

 root at OpenWrt:~# time uclient-fetch
 ^CCommand terminated by signal 2
 real	8m 31.08s

The problem passes away after `random: crng init done` hits
the system log, but this step can take ages in some cases (usually when there
are more processes calling getrandom in parallel), but I couldn't get it
under 60s on my QEMU machine. I've similar weird reports from users on
MIPS devices as well.

 [   13.786576] random: fast init done
 ...
 [  653.153740] random: crng init done

I've bisected the problem down to the following commit (reverting it
fixed the problem):

  # first bad commit: [d872d00b2f] openssl: update to version 1.1.1a

So this patch tries to fix this issue by making getrandom syscall
nonblocking, and also removes possible usage of getentropy libc call,
which in case of musl libc results again in use of getrandom syscall in
blocking mode.

I've also added new config option just in case someone would prefer to
have probably safer but much slower boot times on some devices.

Fixes: d872d00b2f ("openssl: update to version 1.1.1a")
Reviewed-by: Eneas U de Queiroz <cote2004-github at yahoo.com>
Signed-off-by: Petr Štetiar <ynezz at true.cz>
---
 package/libs/openssl/Config.in                     | 12 ++++++
 package/libs/openssl/Makefile                      |  7 +++-
 .../openssl/patches/150-unblock-getrandom.patch    | 45 ++++++++++++++++++++++
 3 files changed, 63 insertions(+), 1 deletion(-)
 create mode 100644 package/libs/openssl/patches/150-unblock-getrandom.patch

diff --git a/package/libs/openssl/Config.in b/package/libs/openssl/Config.in
index ecb9eea..0809afa 100644
--- a/package/libs/openssl/Config.in
+++ b/package/libs/openssl/Config.in
@@ -70,6 +70,18 @@ config OPENSSL_WITH_ERROR_MESSAGES
 		This option aids debugging, but increases package size and
 		memory usage.
 
+config OPENSSL_BLOCKING_GETRANDOM
+	bool
+	prompt "Enable back getrandom in blocking mode"
+	help
+		Enable back the default (upstream) blocking behavior.  By default, when
+		reading from the random source, getrandom() blocks if no random bytes are
+		available, and when reading from the urandom source, it blocks if the entropy
+		pool has not yet been initialized.
+
+		Please note, that turning this option on may affect the boot time, which can
+		in some cases take minutes.
+
 comment "Protocol Support"
 
 config OPENSSL_WITH_TLS13
diff --git a/package/libs/openssl/Makefile b/package/libs/openssl/Makefile
index 56e95af..6e7a603 100644
--- a/package/libs/openssl/Makefile
+++ b/package/libs/openssl/Makefile
@@ -11,7 +11,7 @@ PKG_NAME:=openssl
 PKG_BASE:=1.1.1
 PKG_BUGFIX:=b
 PKG_VERSION:=$(PKG_BASE)$(PKG_BUGFIX)
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 PKG_USE_MIPS16:=0
 ENGINES_DIR=engines-1.1
 
@@ -30,6 +30,7 @@ PKG_LICENSE:=OpenSSL
 PKG_LICENSE_FILES:=LICENSE
 PKG_CPE_ID:=cpe:/a:openssl:openssl
 PKG_CONFIG_DEPENDS:= \
+	CONFIG_OPENSSL_BLOCKING_GETRANDOM \
 	CONFIG_OPENSSL_ENGINE \
 	CONFIG_OPENSSL_ENGINE_BUILTIN \
 	CONFIG_OPENSSL_ENGINE_BUILTIN_AFALG \
@@ -327,6 +328,10 @@ ifdef CONFIG_i386
   endif
 endif
 
+ifdef CONFIG_OPENSSL_BLOCKING_GETRANDOM
+  OPENSSL_OPTIONS += -DOPENSSL_BLOCKING_GETRANDOM
+endif
+
 OPENSSL_TARGET:=linux-$(call qstrip,$(CONFIG_ARCH))-openwrt
 
 STAMP_CONFIGURED := $(STAMP_CONFIGURED)_$(shell echo $(OPENSSL_OPTIONS) | mkhash md5)
diff --git a/package/libs/openssl/patches/150-unblock-getrandom.patch b/package/libs/openssl/patches/150-unblock-getrandom.patch
new file mode 100644
index 0000000..f74abaa
--- /dev/null
+++ b/package/libs/openssl/patches/150-unblock-getrandom.patch
@@ -0,0 +1,45 @@
+--- a/crypto/rand/rand_unix.c
++++ b/crypto/rand/rand_unix.c
+@@ -20,6 +20,7 @@
+ #include "internal/dso.h"
+ #if defined(__linux)
+ # include <sys/syscall.h>
++# include <sys/random.h>
+ #endif
+ #if defined(__FreeBSD__)
+ # include <sys/types.h>
+@@ -292,7 +293,8 @@ static ssize_t syscall_random(void *buf,
+      */
+ 
+     /*
+-     * Do runtime detection to find getentropy().
++     * Do runtime detection to find getentropy(). Please note, that at least
++     * on musl libc (version 1.2.21) getentropy() uses getrandom() in blocking mode.
+      *
+      * Known OSs that should support this:
+      * - Darwin since 16 (OSX 10.12, IOS 10.0).
+@@ -301,6 +303,7 @@ static ssize_t syscall_random(void *buf,
+      * - Linux since 3.17 with glibc 2.25
+      * - FreeBSD since 12.0 (1200061)
+      */
++#  if defined(OPENSSL_BLOCKING_GETRANDOM)
+ #  if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
+     extern int getentropy(void *buffer, size_t length) __attribute__((weak));
+ 
+@@ -322,10 +325,15 @@ static ssize_t syscall_random(void *buf,
+     if (p_getentropy.p != NULL)
+         return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;
+ #  endif
++#  endif /* defined(OPENSSL_BLOCKING_GETRANDOM) */
+ 
+     /* Linux supports this since version 3.17 */
+ #  if defined(__linux) && defined(SYS_getrandom)
+-    return syscall(SYS_getrandom, buf, buflen, 0);
++    unsigned int flags = 0;
++#  if !defined(OPENSSL_BLOCKING_GETRANDOM)
++    flags = GRND_NONBLOCK;
++#  endif
++    return syscall(SYS_getrandom, buf, buflen, flags);
+ #  elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
+     return sysctl_random(buf, buflen);
+ #  else
-- 
1.9.1


_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list