All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Theodore Tso <tytso@mit.edu>,
	Dominik Brodowski <linux@dominikbrodowski.net>,
	"Jason A. Donenfeld" <Jason@zx2c4.com>
Subject: [PATCH 5.18 31/47] random: remove ratelimiting for in-kernel unseeded randomness
Date: Fri, 27 May 2022 10:50:11 +0200	[thread overview]
Message-ID: <20220527084806.597924164@linuxfoundation.org> (raw)
In-Reply-To: <20220527084801.223648383@linuxfoundation.org>

From: "Jason A. Donenfeld" <Jason@zx2c4.com>

commit cc1e127bfa95b5fb2f9307e7168bf8b2b45b4c5e upstream.

The CONFIG_WARN_ALL_UNSEEDED_RANDOM debug option controls whether the
kernel warns about all unseeded randomness or just the first instance.
There's some complicated rate limiting and comparison to the previous
caller, such that even with CONFIG_WARN_ALL_UNSEEDED_RANDOM enabled,
developers still don't see all the messages or even an accurate count of
how many were missed. This is the result of basically parallel
mechanisms aimed at accomplishing more or less the same thing, added at
different points in random.c history, which sort of compete with the
first-instance-only limiting we have now.

It turns out, however, that nobody cares about the first unseeded
randomness instance of in-kernel users. The same first user has been
there for ages now, and nobody is doing anything about it. It isn't even
clear that anybody _can_ do anything about it. Most places that can do
something about it have switched over to using get_random_bytes_wait()
or wait_for_random_bytes(), which is the right thing to do, but there is
still much code that needs randomness sometimes during init, and as a
geeneral rule, if you're not using one of the _wait functions or the
readiness notifier callback, you're bound to be doing it wrong just
based on that fact alone.

So warning about this same first user that can't easily change is simply
not an effective mechanism for anything at all. Users can't do anything
about it, as the Kconfig text points out -- the problem isn't in
userspace code -- and kernel developers don't or more often can't react
to it.

Instead, show the warning for all instances when CONFIG_WARN_ALL_UNSEEDED_RANDOM
is set, so that developers can debug things need be, or if it isn't set,
don't show a warning at all.

At the same time, CONFIG_WARN_ALL_UNSEEDED_RANDOM now implies setting
random.ratelimit_disable=1 on by default, since if you care about one
you probably care about the other too. And we can clean up usage around
the related urandom_warning ratelimiter as well (whose behavior isn't
changing), so that it properly counts missed messages after the 10
message threshold is reached.

Cc: Theodore Ts'o <tytso@mit.edu>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/char/random.c |   61 ++++++++++++++------------------------------------
 lib/Kconfig.debug     |    3 --
 2 files changed, 19 insertions(+), 45 deletions(-)

--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -86,11 +86,10 @@ static DEFINE_SPINLOCK(random_ready_chai
 static RAW_NOTIFIER_HEAD(random_ready_chain);
 
 /* Control how we warn userspace. */
-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 int ratelimit_disable __read_mostly;
+static int ratelimit_disable __read_mostly =
+	IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM);
 module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
 MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
 
@@ -181,27 +180,15 @@ static void process_random_ready_list(vo
 	spin_unlock_irqrestore(&random_ready_chain_lock, flags);
 }
 
-#define warn_unseeded_randomness(previous) \
-	_warn_unseeded_randomness(__func__, (void *)_RET_IP_, (previous))
+#define warn_unseeded_randomness() \
+	_warn_unseeded_randomness(__func__, (void *)_RET_IP_)
 
-static void _warn_unseeded_randomness(const char *func_name, void *caller, void **previous)
+static void _warn_unseeded_randomness(const char *func_name, void *caller)
 {
-#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
-	const bool print_once = false;
-#else
-	static bool print_once __read_mostly;
-#endif
-
-	if (print_once || crng_ready() ||
-	    (previous && (caller == READ_ONCE(*previous))))
+	if (!IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) || crng_ready())
 		return;
-	WRITE_ONCE(*previous, caller);
-#ifndef CONFIG_WARN_ALL_UNSEEDED_RANDOM
-	print_once = true;
-#endif
-	if (__ratelimit(&unseeded_warning))
-		printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n",
-				func_name, caller, crng_init);
+	printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n",
+			func_name, caller, crng_init);
 }
 
 
@@ -454,9 +441,7 @@ static void _get_random_bytes(void *buf,
  */
 void get_random_bytes(void *buf, size_t nbytes)
 {
-	static void *previous;
-
-	warn_unseeded_randomness(&previous);
+	warn_unseeded_randomness();
 	_get_random_bytes(buf, nbytes);
 }
 EXPORT_SYMBOL(get_random_bytes);
@@ -552,10 +537,9 @@ u64 get_random_u64(void)
 	u64 ret;
 	unsigned long flags;
 	struct batched_entropy *batch;
-	static void *previous;
 	unsigned long next_gen;
 
-	warn_unseeded_randomness(&previous);
+	warn_unseeded_randomness();
 
 	if  (!crng_ready()) {
 		_get_random_bytes(&ret, sizeof(ret));
@@ -591,10 +575,9 @@ u32 get_random_u32(void)
 	u32 ret;
 	unsigned long flags;
 	struct batched_entropy *batch;
-	static void *previous;
 	unsigned long next_gen;
 
-	warn_unseeded_randomness(&previous);
+	warn_unseeded_randomness();
 
 	if  (!crng_ready()) {
 		_get_random_bytes(&ret, sizeof(ret));
@@ -821,16 +804,9 @@ static void credit_init_bits(size_t nbit
 		wake_up_interruptible(&crng_init_wait);
 		kill_fasync(&fasync, SIGIO, POLL_IN);
 		pr_notice("crng init done\n");
-		if (unseeded_warning.missed) {
-			pr_notice("%d get_random_xx warning(s) missed due to ratelimiting\n",
-				  unseeded_warning.missed);
-			unseeded_warning.missed = 0;
-		}
-		if (urandom_warning.missed) {
+		if (urandom_warning.missed)
 			pr_notice("%d urandom warning(s) missed due to ratelimiting\n",
 				  urandom_warning.missed);
-			urandom_warning.missed = 0;
-		}
 	} else if (orig < POOL_EARLY_BITS && new >= POOL_EARLY_BITS) {
 		spin_lock_irqsave(&base_crng.lock, flags);
 		/* Check if crng_init is CRNG_EMPTY, to avoid race with crng_reseed(). */
@@ -948,10 +924,6 @@ int __init rand_initialize(void)
 	else if (arch_init && trust_cpu)
 		credit_init_bits(BLAKE2S_BLOCK_SIZE * 8);
 
-	if (ratelimit_disable) {
-		urandom_warning.interval = 0;
-		unseeded_warning.interval = 0;
-	}
 	return 0;
 }
 
@@ -1438,11 +1410,14 @@ static ssize_t urandom_read(struct file
 	if (!crng_ready())
 		try_to_generate_entropy();
 
-	if (!crng_ready() && maxwarn > 0) {
-		maxwarn--;
-		if (__ratelimit(&urandom_warning))
+	if (!crng_ready()) {
+		if (!ratelimit_disable && maxwarn <= 0)
+			++urandom_warning.missed;
+		else if (ratelimit_disable || __ratelimit(&urandom_warning)) {
+			--maxwarn;
 			pr_notice("%s: uninitialized urandom read (%zd bytes read)\n",
 				  current->comm, nbytes);
+		}
 	}
 
 	return get_random_bytes_user(buf, nbytes);
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1616,8 +1616,7 @@ config WARN_ALL_UNSEEDED_RANDOM
 	  so architecture maintainers really need to do what they can
 	  to get the CRNG seeded sooner after the system is booted.
 	  However, since users cannot do anything actionable to
-	  address this, by default the kernel will issue only a single
-	  warning for the first use of unseeded randomness.
+	  address this, by default this option is disabled.
 
 	  Say Y here if you want to receive warnings for all uses of
 	  unseeded randomness.  This will be of use primarily for



  parent reply	other threads:[~2022-05-27  8:56 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-27  8:49 [PATCH 5.18 00/47] 5.18.1-rc1 review Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 01/47] lockdown: also lock down previous kgdb use Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 02/47] HID: amd_sfh: Add support for sensor discovery Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 03/47] random: fix sysctl documentation nits Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 04/47] init: call time_init() before rand_initialize() Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 05/47] ia64: define get_cycles macro for arch-override Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 06/47] s390: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 07/47] parisc: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 08/47] alpha: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 09/47] powerpc: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 10/47] timekeeping: Add raw clock fallback for random_get_entropy() Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 11/47] m68k: use fallback for random_get_entropy() instead of zero Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 12/47] riscv: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 13/47] mips: use fallback for random_get_entropy() instead of just c0 random Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 14/47] arm: use fallback for random_get_entropy() instead of zero Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 15/47] nios2: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 16/47] x86/tsc: Use " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 17/47] um: use " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 18/47] sparc: " Greg Kroah-Hartman
2022-05-27  8:49 ` [PATCH 5.18 19/47] xtensa: " Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 20/47] random: insist on random_get_entropy() existing in order to simplify Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 21/47] random: do not use batches when !crng_ready() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 22/47] random: use first 128 bits of input as fast init Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 23/47] random: do not pretend to handle premature next security model Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 24/47] random: order timer entropy functions below interrupt functions Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 25/47] random: do not use input pool from hard IRQs Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 26/47] random: help compiler out with fast_mix() by using simpler arguments Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 27/47] siphash: use one source of truth for siphash permutations Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 28/47] random: use symbolic constants for crng_init states Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 29/47] random: avoid initializing twice in credit race Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 30/47] random: move initialization out of reseeding hot path Greg Kroah-Hartman
2022-05-27  8:50 ` Greg Kroah-Hartman [this message]
2022-05-27  8:50 ` [PATCH 5.18 32/47] random: use proper jiffies comparison macro Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 33/47] random: handle latent entropy and command line from random_init() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 34/47] random: credit architectural init the exact amount Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 35/47] random: use static branch for crng_ready() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 36/47] random: remove extern from functions in header Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 37/47] random: use proper return types on get_random_{int,long}_wait() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 38/47] random: make consistent use of buf and len Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 39/47] random: move initialization functions out of hot pages Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 40/47] random: move randomize_page() into mm where it belongs Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 41/47] random: unify batched entropy implementations Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 42/47] random: convert to using fops->read_iter() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 43/47] random: convert to using fops->write_iter() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 44/47] random: wire up fops->splice_{read,write}_iter() Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 45/47] random: check for signals after page of pool writes Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 46/47] ACPI: sysfs: Fix BERT error region memory mapping Greg Kroah-Hartman
2022-05-27  8:50 ` [PATCH 5.18 47/47] ALSA: ctxfi: Add SB046x PCI ID Greg Kroah-Hartman
2022-05-27 22:40 ` [PATCH 5.18 00/47] 5.18.1-rc1 review Guenter Roeck
2022-05-28  1:53 ` Justin Forbes
2022-05-28  2:24 ` Ron Economos
2022-05-28  2:50 ` Bagas Sanjaya
2022-05-28 11:16 ` Naresh Kamboju
2022-05-28 13:39 ` Rudi Heitbaum
2022-05-29  2:48 ` Fox Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220527084806.597924164@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=Jason@zx2c4.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@dominikbrodowski.net \
    --cc=stable@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.