Hi All, Le ven. 15 mars 2019 à 09:29, Petr Štetiar <yn...@true.cz> a écrit : > > 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@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.
Just a side note, on first boot we save a random seed using getrandom() https://github.com/openwrt/openwrt/blob/master/package/base-files/files/etc/init.d/urandom_seed https://github.com/openwrt/openwrt/blob/master/package/base-files/files/sbin/urandom_seed And we restore it in preinit https://github.com/openwrt/openwrt/blob/master/package/base-files/files/lib/preinit/81_urandom_seed So even if kernel PRNG is considered not initialized, in reality it is, so starting from second boot we are ~ok I'm not sure if we block on getrandom to generate ssh keys (and any other keys) on first boot though Regards Etienne > > Fixes: d872d00b2f ("openssl: update to version 1.1.1a") > Reviewed-by: Eneas U de Queiroz <cote2004-git...@yahoo.com> > Signed-off-by: Petr Štetiar <yn...@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@lists.openwrt.org > https://lists.openwrt.org/mailman/listinfo/openwrt-devel _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel