diff options
| author | Hiago De Franco <hiago.franco@toradex.com> | 2025-01-13 20:31:40 -0300 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2025-01-21 12:07:56 +0000 |
| commit | e330214c2c4c16a0ce6e872db42b08e093a6de1d (patch) | |
| tree | ed25736d35155584ba22361df922ebe87bd6b1d2 | |
| parent | 15d005ccbfad08c76cc523ca3f438ae5ce50cfa2 (diff) | |
| download | poky-e330214c2c4c16a0ce6e872db42b08e093a6de1d.tar.gz | |
eudev: backport patch to fix udevd hanging while trying to access /dev/urandom
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.
(From OE-Core rev: cd5f630581f3e38645a92ad75b496bce92b679cb)
Signed-off-by: Hiago De Franco <hiago.franco@toradex.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -rw-r--r-- | meta/recipes-core/udev/eudev/0001-random-util.c-sync-dev_urandom-implementation-to-sys.patch | 138 | ||||
| -rw-r--r-- | meta/recipes-core/udev/eudev_3.2.14.bb | 1 |
2 files changed, 139 insertions, 0 deletions
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 0000000000..668aa731ac --- /dev/null +++ b/meta/recipes-core/udev/eudev/0001-random-util.c-sync-dev_urandom-implementation-to-sys.patch | |||
| @@ -0,0 +1,138 @@ | |||
| 1 | From 95c871b7b912f39539777ac222ef7f8798bb0225 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Masahisa Kojima <kojima.masahisa@socionext.com> | ||
| 3 | Date: Thu, 25 Apr 2024 17:23:10 +0900 | ||
| 4 | Subject: [PATCH] random-util.c: sync dev_urandom implementation to | ||
| 5 | systemd-udev | ||
| 6 | |||
| 7 | Current dev_urandom() assumes that reading /dev/urandom | ||
| 8 | will never block regardless if the random pool is fully | ||
| 9 | initialized or not. | ||
| 10 | This assumption is no longer applicable since linux kerrnel | ||
| 11 | enforces the /dev/urandom entropy initialization from | ||
| 12 | v5.18-rc2 with the commit: | ||
| 13 | 48bff1053c17 ("random: opportunistically initialize on /dev/urandom reads"). | ||
| 14 | |||
| 15 | With this, when we use the linux v5.18-rc2 or later, | ||
| 16 | dev_urandom() will block if enough random pool is not supplied. | ||
| 17 | It causes the boot delay, typically 1024msec(4msec * 256 = 1024msec) | ||
| 18 | delay to fill the 256 bits entropy for the case CONFIG_HZ=250. | ||
| 19 | |||
| 20 | To prevent this boot delay, this commit syncs dev_urandom() | ||
| 21 | implementation to the systemd-udev. | ||
| 22 | The systemd-udev implementation of reading /dev/urandom is as follows. | ||
| 23 | - Try to get random with calling getrandom(GRND_INSECURE) | ||
| 24 | - If kernel does not support GRND_INSECURE, fallback to GRND_NONBLOCK | ||
| 25 | - If enough entropy is not supplied, fallback to reading /dev/urandom, | ||
| 26 | this will block when the kernel version is v5.18-rc2 or later | ||
| 27 | |||
| 28 | With this modification, dev_urandom() tries not to block | ||
| 29 | as much as possible. | ||
| 30 | |||
| 31 | This modification still keeps the backword compatibility, | ||
| 32 | dev_random() will never block if the commit(48bff1053c17) is not | ||
| 33 | applied to the linux kernel, the behavior is same as before | ||
| 34 | in this case. | ||
| 35 | |||
| 36 | Upstream-Status: Backport [a49a3aaa460add6ae7ea208b4cac630e56fe1180] | ||
| 37 | Signed-off-by: Masahisa Kojima <kojima.masahisa@socionext.com> | ||
| 38 | --- | ||
| 39 | src/shared/missing.h | 4 +++ | ||
| 40 | src/shared/random-util.c | 70 ++++++++++++++++++---------------------- | ||
| 41 | 2 files changed, 35 insertions(+), 39 deletions(-) | ||
| 42 | |||
| 43 | diff --git a/src/shared/missing.h b/src/shared/missing.h | ||
| 44 | index 1967840cdbf3..1caec0f9207c 100644 | ||
| 45 | --- a/src/shared/missing.h | ||
| 46 | +++ b/src/shared/missing.h | ||
| 47 | @@ -79,6 +79,10 @@ static inline int getrandom(void *buffer, size_t count, unsigned flags) { | ||
| 48 | #define GRND_RANDOM 0x0002 | ||
| 49 | #endif | ||
| 50 | |||
| 51 | +#ifndef GRND_INSECURE | ||
| 52 | +#define GRND_INSECURE 0x0004 | ||
| 53 | +#endif | ||
| 54 | + | ||
| 55 | #ifndef BTRFS_IOCTL_MAGIC | ||
| 56 | #define BTRFS_IOCTL_MAGIC 0x94 | ||
| 57 | #endif | ||
| 58 | diff --git a/src/shared/random-util.c b/src/shared/random-util.c | ||
| 59 | index 01a28c8ef4e9..852b00e4ce2b 100644 | ||
| 60 | --- a/src/shared/random-util.c | ||
| 61 | +++ b/src/shared/random-util.c | ||
| 62 | @@ -31,45 +31,37 @@ | ||
| 63 | #include "util.h" | ||
| 64 | |||
| 65 | int dev_urandom(void *p, size_t n) { | ||
| 66 | - static int have_syscall = -1; | ||
| 67 | - | ||
| 68 | - _cleanup_close_ int fd = -1; | ||
| 69 | - int r; | ||
| 70 | - | ||
| 71 | - /* Gathers some randomness from the kernel. This call will | ||
| 72 | - * never block, and will always return some data from the | ||
| 73 | - * kernel, regardless if the random pool is fully initialized | ||
| 74 | - * or not. It thus makes no guarantee for the quality of the | ||
| 75 | - * returned entropy, but is good enough for or usual usecases | ||
| 76 | - * of seeding the hash functions for hashtable */ | ||
| 77 | - | ||
| 78 | - /* Use the getrandom() syscall unless we know we don't have | ||
| 79 | - * it, or when the requested size is too large for it. */ | ||
| 80 | - if (have_syscall != 0 || (size_t) (int) n != n) { | ||
| 81 | - r = getrandom(p, n, GRND_NONBLOCK); | ||
| 82 | - if (r == (int) n) { | ||
| 83 | - have_syscall = true; | ||
| 84 | - return 0; | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - if (r < 0) { | ||
| 88 | - if (errno == ENOSYS) | ||
| 89 | - /* we lack the syscall, continue with | ||
| 90 | - * reading from /dev/urandom */ | ||
| 91 | - have_syscall = false; | ||
| 92 | - else if (errno == EAGAIN) | ||
| 93 | - /* not enough entropy for now. Let's | ||
| 94 | - * remember to use the syscall the | ||
| 95 | - * next time, again, but also read | ||
| 96 | - * from /dev/urandom for now, which | ||
| 97 | - * doesn't care about the current | ||
| 98 | - * amount of entropy. */ | ||
| 99 | - have_syscall = true; | ||
| 100 | - else | ||
| 101 | - return -errno; | ||
| 102 | - } else | ||
| 103 | - /* too short read? */ | ||
| 104 | - return -ENODATA; | ||
| 105 | + static bool have_getrandom = true, have_grndinsecure = true; | ||
| 106 | + _cleanup_close_ int fd = -EBADF; | ||
| 107 | + | ||
| 108 | + if (n == 0) | ||
| 109 | + return 0; | ||
| 110 | + | ||
| 111 | + for (;;) { | ||
| 112 | + ssize_t l; | ||
| 113 | + | ||
| 114 | + if (!have_getrandom) | ||
| 115 | + break; | ||
| 116 | + | ||
| 117 | + l = getrandom(p, n, have_grndinsecure ? GRND_INSECURE : GRND_NONBLOCK); | ||
| 118 | + if (l > 0) { | ||
| 119 | + if ((size_t) l == n) | ||
| 120 | + return 0; /* Done reading, success. */ | ||
| 121 | + p = (uint8_t *) p + l; | ||
| 122 | + n -= l; | ||
| 123 | + continue; /* Interrupted by a signal; keep going. */ | ||
| 124 | + } else if (l == 0) | ||
| 125 | + break; /* Weird, so fallback to /dev/urandom. */ | ||
| 126 | + else if (errno == ENOSYS) { | ||
| 127 | + have_getrandom = false; | ||
| 128 | + break; /* No syscall, so fallback to /dev/urandom. */ | ||
| 129 | + } else if (errno == EINVAL && have_grndinsecure) { | ||
| 130 | + have_grndinsecure = false; | ||
| 131 | + continue; /* No GRND_INSECURE; fallback to GRND_NONBLOCK. */ | ||
| 132 | + } else if (errno == EAGAIN && !have_grndinsecure) | ||
| 133 | + break; /* Will block, but no GRND_INSECURE, so fallback to /dev/urandom. */ | ||
| 134 | + | ||
| 135 | + break; /* Unexpected, so just give up and fallback to /dev/urandom. */ | ||
| 136 | } | ||
| 137 | |||
| 138 | 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 0e5610f77c..b3e7d092c5 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 \ | |||
| 13 | file://netifnames.patch \ | 13 | file://netifnames.patch \ |
| 14 | file://init \ | 14 | file://init \ |
| 15 | file://local.rules \ | 15 | file://local.rules \ |
| 16 | file://0001-random-util.c-sync-dev_urandom-implementation-to-sys.patch \ | ||
| 16 | " | 17 | " |
| 17 | 18 | ||
| 18 | SRC_URI[sha256sum] = "8da4319102f24abbf7fff5ce9c416af848df163b29590e666d334cc1927f006f" | 19 | SRC_URI[sha256sum] = "8da4319102f24abbf7fff5ce9c416af848df163b29590e666d334cc1927f006f" |
