lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20190914122500.GA1425@darwi-home-pc>
Date:   Sat, 14 Sep 2019 14:25:00 +0200
From:   "Ahmed S. Darwish" <darwish.07@...il.com>
To:     Linus Torvalds <torvalds@...ux-foundation.org>
Cc:     "Theodore Y. Ts'o" <tytso@....edu>,
        Michael Kerrisk <mtk.manpages@...il.com>,
        Andreas Dilger <adilger.kernel@...ger.ca>,
        Jan Kara <jack@...e.cz>, Ray Strode <rstrode@...hat.com>,
        William Jon McCann <mccann@....edu>,
        "Alexander E. Patrakov" <patrakov@...il.com>,
        zhangjs <zachary@...shancloud.com>, linux-ext4@...r.kernel.org,
        lkml <linux-kernel@...r.kernel.org>
Subject: [PATCH RFC] random: getrandom(2): don't block on non-initialized
 entropy pool

getrandom() has been created as a new and more secure interface for
pseudorandom data requests.  Unlike /dev/urandom, it unconditionally
blocks until the entropy pool has been properly initialized.

While getrandom() has no guaranteed upper bound for its waiting time,
user-space has been abusing it by issuing the syscall, from shared
libraries no less, during the main system boot sequence.

Thus, on certain setups where there is no hwrng (embedded), or the
hwrng is not trusted by some users (intel RDRAND), or sometimes it's
just broken (amd RDRAND), the system boot can be *reliably* blocked.

The issue is further exaggerated by recent file-system optimizations,
e.g. b03755ad6f33 (ext4: make __ext4_get_inode_loc plug), which
merges directory lookup code inode table IO, and thus minimizes the
number of disk interrupts and entropy during boot. After that commit,
a blocked boot can be reliably reproduced on a Thinkpad E480 laptop
with standard ArchLinux user-space.

Thus, don't trust user-space on calling getrandom() from the right
context. Just never block, and return -EINVAL if entropy is not yet
available.

Link: https://lkml.kernel.org/r/CAHk-=wjyH910+JRBdZf_Y9G54c1M=LBF8NKXB6vJcm9XjLnRfg@mail.gmail.com
Link: https://lkml.kernel.org/r/20190912034421.GA2085@darwi-home-pc
Link: https://lkml.kernel.org/r/20190911173624.GI2740@mit.edu
Link: https://lkml.kernel.org/r/20180514003034.GI14763@thunk.org

Suggested-by: Linus Torvalds <torvalds@...ux-foundation.org>
Signed-off-by: Ahmed S. Darwish <darwish.07@...il.com>
---

Notes:
    This feels very risky at the very end of -rc8, so only sending
    this as an RFC. The system of course reliably boots with this,
    and the log, as expected, powerfully warns all callers:

    $ dmesg | grep random
    [0.236472] random: get_random_bytes called from start_kernel+0x30f/0x4d7 with crng_init=0
    [0.680263] random: fast init done
    [2.500346] random: lvm: uninitialized urandom read (4 bytes read)
    [2.595125] random: systemd-random-: invalid getrandom request (512 bytes): crng not ready
    [2.595126] random: systemd-random-: uninitialized urandom read (512 bytes read)
    [3.427699] random: dbus-daemon: uninitialized urandom read (12 bytes read)
    [3.979425] urandom_read: 1 callbacks suppressed
    [3.979426] random: polkitd: uninitialized urandom read (8 bytes read)
    [3.979726] random: polkitd: uninitialized urandom read (8 bytes read)
    [3.979752] random: polkitd: uninitialized urandom read (8 bytes read)
    [4.473398] random: gnome-session-b: invalid getrandom request (16 bytes): crng not ready
    [4.473404] random: gnome-session-b: invalid getrandom request (16 bytes): crng not ready
    [4.473409] random: gnome-session-b: invalid getrandom request (16 bytes): crng not ready
    [5.265636] random: crng init done
    [5.265649] random: 3 urandom warning(s) missed due to ratelimiting
    [5.265652] random: 1 getrandom warning(s) missed due to ratelimiting

 drivers/char/random.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 4a50ee2c230d..309dc5ddf370 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -511,6 +511,8 @@ static struct ratelimit_state unseeded_warning =
 	RATELIMIT_STATE_INIT("warn_unseeded_randomness", HZ, 3);
 static struct ratelimit_state urandom_warning =
 	RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3);
+static struct ratelimit_state getrandom_warning =
+	RATELIMIT_STATE_INIT("warn_getrandom_notavail", HZ, 3);

 static int ratelimit_disable __read_mostly;

@@ -1053,6 +1055,12 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
 				  urandom_warning.missed);
 			urandom_warning.missed = 0;
 		}
+		if (getrandom_warning.missed) {
+			pr_notice("random: %d getrandom warning(s) missed "
+				  "due to ratelimiting\n",
+				  getrandom_warning.missed);
+			getrandom_warning.missed = 0;
+		}
 	}
 }

@@ -1915,6 +1923,7 @@ int __init rand_initialize(void)
 	crng_global_init_time = jiffies;
 	if (ratelimit_disable) {
 		urandom_warning.interval = 0;
+		getrandom_warning.interval = 0;
 		unseeded_warning.interval = 0;
 	}
 	return 0;
@@ -2138,8 +2147,6 @@ const struct file_operations urandom_fops = {
 SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
 		unsigned int, flags)
 {
-	int ret;
-
 	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
 		return -EINVAL;

@@ -2152,9 +2159,13 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
 	if (!crng_ready()) {
 		if (flags & GRND_NONBLOCK)
 			return -EAGAIN;
-		ret = wait_for_random_bytes();
-		if (unlikely(ret))
-			return ret;
+
+		if (__ratelimit(&getrandom_warning))
+			pr_notice("random: %s: invalid getrandom request "
+				  "(%zd bytes): crng not ready",
+				  current->comm, count);
+
+		return -EINVAL;
 	}
 	return urandom_read(NULL, buf, count, NULL);
 }
--
2.23.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ