diff mbox series

eudev: backport patch to fix udevd hanging while trying to access /dev/urandom

Message ID 20250113233140.40499-1-hiagofranco@gmail.com
State New
Headers show
Series eudev: backport patch to fix udevd hanging while trying to access /dev/urandom | expand

Commit Message

Hiago De Franco Jan. 13, 2025, 11:31 p.m. UTC
From: Hiago De Franco <hiago.franco@toradex.com>

Linux kernel commit 48bff1053c17 ("random: opportunistically initialize
on /dev/urandom reads") introduced a change where /dev/urandom blocks if
the random pool is insufficiently initialized during hardware boot. This
behavior causes /dev/urandom reads to hang for approximately 5 seconds,
delaying the boot process with eudev init script (when it calls udevd).

This issue has already been solved upstream, therefore backport the
upstream patch to fix this.

Signed-off-by: Hiago De Franco <hiago.franco@toradex.com>
---
 ...nc-dev_urandom-implementation-to-sys.patch | 138 ++++++++++++++++++
 meta/recipes-core/udev/eudev_3.2.14.bb        |   1 +
 2 files changed, 139 insertions(+)
 create mode 100644 meta/recipes-core/udev/eudev/0001-random-util.c-sync-dev_urandom-implementation-to-sys.patch
diff mbox series

Patch

diff --git a/meta/recipes-core/udev/eudev/0001-random-util.c-sync-dev_urandom-implementation-to-sys.patch b/meta/recipes-core/udev/eudev/0001-random-util.c-sync-dev_urandom-implementation-to-sys.patch
new file mode 100644
index 000000000000..668aa731aca1
--- /dev/null
+++ b/meta/recipes-core/udev/eudev/0001-random-util.c-sync-dev_urandom-implementation-to-sys.patch
@@ -0,0 +1,138 @@ 
+From 95c871b7b912f39539777ac222ef7f8798bb0225 Mon Sep 17 00:00:00 2001
+From: Masahisa Kojima <kojima.masahisa@socionext.com>
+Date: Thu, 25 Apr 2024 17:23:10 +0900
+Subject: [PATCH] random-util.c: sync dev_urandom implementation to
+ systemd-udev
+
+Current dev_urandom() assumes that reading /dev/urandom
+will never block regardless if the random pool is fully
+initialized or not.
+This assumption is no longer applicable since linux kerrnel
+enforces the /dev/urandom entropy initialization from
+v5.18-rc2 with the commit:
+48bff1053c17 ("random: opportunistically initialize on /dev/urandom reads").
+
+With this, when we use the linux v5.18-rc2 or later,
+dev_urandom() will block if enough random pool is not supplied.
+It causes the boot delay, typically 1024msec(4msec * 256 = 1024msec)
+delay to fill the 256 bits entropy for the case CONFIG_HZ=250.
+
+To prevent this boot delay, this commit syncs dev_urandom()
+implementation to the systemd-udev.
+The systemd-udev implementation of reading /dev/urandom is as follows.
+ - Try to get random with calling getrandom(GRND_INSECURE)
+ - If kernel does not support GRND_INSECURE, fallback to GRND_NONBLOCK
+ - If enough entropy is not supplied, fallback to reading /dev/urandom,
+   this will block when the kernel version is v5.18-rc2 or later
+
+With this modification, dev_urandom() tries not to block
+as much as possible.
+
+This modification still keeps the backword compatibility,
+dev_random() will never block if the commit(48bff1053c17) is not
+applied to the linux kernel, the behavior is same as before
+in this case.
+
+Upstream-Status: Backport [a49a3aaa460add6ae7ea208b4cac630e56fe1180]
+Signed-off-by: Masahisa Kojima <kojima.masahisa@socionext.com>
+---
+ src/shared/missing.h     |  4 +++
+ src/shared/random-util.c | 70 ++++++++++++++++++----------------------
+ 2 files changed, 35 insertions(+), 39 deletions(-)
+
+diff --git a/src/shared/missing.h b/src/shared/missing.h
+index 1967840cdbf3..1caec0f9207c 100644
+--- a/src/shared/missing.h
++++ b/src/shared/missing.h
+@@ -79,6 +79,10 @@ static inline int getrandom(void *buffer, size_t count, unsigned flags) {
+ #define GRND_RANDOM 0x0002
+ #endif
+ 
++#ifndef GRND_INSECURE
++#define GRND_INSECURE 0x0004
++#endif
++
+ #ifndef BTRFS_IOCTL_MAGIC
+ #define BTRFS_IOCTL_MAGIC 0x94
+ #endif
+diff --git a/src/shared/random-util.c b/src/shared/random-util.c
+index 01a28c8ef4e9..852b00e4ce2b 100644
+--- a/src/shared/random-util.c
++++ b/src/shared/random-util.c
+@@ -31,45 +31,37 @@
+ #include "util.h"
+ 
+ int dev_urandom(void *p, size_t n) {
+-        static int have_syscall = -1;
+-
+-        _cleanup_close_ int fd = -1;
+-        int r;
+-
+-        /* Gathers some randomness from the kernel. This call will
+-         * never block, and will always return some data from the
+-         * kernel, regardless if the random pool is fully initialized
+-         * or not. It thus makes no guarantee for the quality of the
+-         * returned entropy, but is good enough for or usual usecases
+-         * of seeding the hash functions for hashtable */
+-
+-        /* Use the getrandom() syscall unless we know we don't have
+-         * it, or when the requested size is too large for it. */
+-        if (have_syscall != 0 || (size_t) (int) n != n) {
+-                r = getrandom(p, n, GRND_NONBLOCK);
+-                if (r == (int) n) {
+-                        have_syscall = true;
+-                        return 0;
+-                }
+-
+-                if (r < 0) {
+-                        if (errno == ENOSYS)
+-                                /* we lack the syscall, continue with
+-                                 * reading from /dev/urandom */
+-                                have_syscall = false;
+-                        else if (errno == EAGAIN)
+-                                /* not enough entropy for now. Let's
+-                                 * remember to use the syscall the
+-                                 * next time, again, but also read
+-                                 * from /dev/urandom for now, which
+-                                 * doesn't care about the current
+-                                 * amount of entropy.  */
+-                                have_syscall = true;
+-                        else
+-                                return -errno;
+-                } else
+-                        /* too short read? */
+-                        return -ENODATA;
++        static bool have_getrandom = true, have_grndinsecure = true;
++        _cleanup_close_ int fd = -EBADF;
++
++        if (n == 0)
++                return 0;
++
++        for (;;) {
++                ssize_t l;
++
++                if (!have_getrandom)
++                        break;
++
++                l = getrandom(p, n, have_grndinsecure ? GRND_INSECURE : GRND_NONBLOCK);
++                if (l > 0) {
++                        if ((size_t) l == n)
++                                return 0; /* Done reading, success. */
++                        p = (uint8_t *) p + l;
++                        n -= l;
++                        continue; /* Interrupted by a signal; keep going. */
++                } else if (l == 0)
++                        break; /* Weird, so fallback to /dev/urandom. */
++                else if (errno == ENOSYS) {
++                        have_getrandom = false;
++                        break; /* No syscall, so fallback to /dev/urandom. */
++                } else if (errno == EINVAL && have_grndinsecure) {
++                        have_grndinsecure = false;
++                        continue; /* No GRND_INSECURE; fallback to GRND_NONBLOCK. */
++                } else if (errno == EAGAIN && !have_grndinsecure)
++                        break; /* Will block, but no GRND_INSECURE, so fallback to /dev/urandom. */
++
++                break; /* Unexpected, so just give up and fallback to /dev/urandom. */
+         }
+ 
+         fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
diff --git a/meta/recipes-core/udev/eudev_3.2.14.bb b/meta/recipes-core/udev/eudev_3.2.14.bb
index 0e5610f77c2d..b3e7d092c58d 100644
--- a/meta/recipes-core/udev/eudev_3.2.14.bb
+++ b/meta/recipes-core/udev/eudev_3.2.14.bb
@@ -13,6 +13,7 @@  SRC_URI = "${GITHUB_BASE_URI}/download/v${PV}/${BP}.tar.gz \
            file://netifnames.patch \
            file://init \
            file://local.rules \
+           file://0001-random-util.c-sync-dev_urandom-implementation-to-sys.patch \
            "
 
 SRC_URI[sha256sum] = "8da4319102f24abbf7fff5ce9c416af848df163b29590e666d334cc1927f006f"