lib/vsprintf: Initialize vsprintf's pointer hash once the random core is ready.
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Tue, 27 Sep 2022 10:49:12 +0000 (12:49 +0200)
committerPetr Mladek <pmladek@suse.com>
Thu, 29 Sep 2022 11:44:51 +0000 (13:44 +0200)
commit6f0ac3b52a9075b7291a72fb338d08491c1f0a64
tree3be12d01fcba74e5726e3abccd60db287b3e4a72
parente4279b599863dd1aa71fb8e35bffa943545bbaeb
lib/vsprintf: Initialize vsprintf's pointer hash once the random core is ready.

The printk code invokes vnsprintf in order to compute the complete
string before adding it into its buffer. This happens in an IRQ-off
region which leads to a warning on PREEMPT_RT in the random code if the
format strings contains a %p for pointer printing. This happens because
the random core acquires locks which become sleeping locks on PREEMPT_RT
which must not be acquired with disabled interrupts and or preemption
disabled.
By default the pointers are hashed which requires a random value on the
first invocation (either by printk or another user which comes first.

One could argue that there is no need for printk to disable interrupts
during the vsprintf() invocation which would fix the just mentioned
problem. However printk itself can be invoked in a context with
disabled interrupts which would lead to the very same problem.

Move the initialization of ptr_key into a worker and schedule it from
subsys_initcall(). This happens early but after the workqueue subsystem
is ready. Use get_random_bytes() to retrieve the random value if the RNG
core is ready, otherwise schedule a worker in two seconds and try again.

Another advantage is that it removes a lock from the vsprintf() code path.
It prevents a possible deadlock when printk("%p", ptr) is called under
the lock taken in get_random_bytes().

Reported-by: Mike Galbraith <efault@gmx.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Jason A. Donenfeld <Jason@zx2c4.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
[pmladek@suse.com: Added a note about the it prevented a possible deadlock in printk().]
Signed-off-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20220927104912.622645-3-bigeasy@linutronix.de
lib/vsprintf.c