linux/init
Sergey Senozhatsky ab6f762f0f printk: queue wake_up_klogd irq_work only if per-CPU areas are ready
printk_deferred(), similarly to printk_safe/printk_nmi, does not
immediately attempt to print a new message on the consoles, avoiding
calls into non-reentrant kernel paths, e.g. scheduler or timekeeping,
which potentially can deadlock the system.

Those printk() flavors, instead, rely on per-CPU flush irq_work to print
messages from safer contexts.  For same reasons (recursive scheduler or
timekeeping calls) printk() uses per-CPU irq_work in order to wake up
user space syslog/kmsg readers.

However, only printk_safe/printk_nmi do make sure that per-CPU areas
have been initialised and that it's safe to modify per-CPU irq_work.
This means that, for instance, should printk_deferred() be invoked "too
early", that is before per-CPU areas are initialised, printk_deferred()
will perform illegal per-CPU access.

Lech Perczak [0] reports that after commit 1b710b1b10 ("char/random:
silence a lockdep splat with printk()") user-space syslog/kmsg readers
are not able to read new kernel messages.

The reason is printk_deferred() being called too early (as was pointed
out by Petr and John).

Fix printk_deferred() and do not queue per-CPU irq_work before per-CPU
areas are initialized.

Link: https://lore.kernel.org/lkml/aa0732c6-5c4e-8a8b-a1c1-75ebe3dca05b@camlintechnologies.com/
Reported-by: Lech Perczak <l.perczak@camlintechnologies.com>
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Tested-by: Jann Horn <jannh@google.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Theodore Ts'o <tytso@mit.edu>
Cc: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-04-10 13:18:57 -07:00
..
calibrate.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
do_mounts_initrd.c init: unify opening /dev/console as stdin/stdout/stderr 2019-12-12 18:58:24 +01:00
do_mounts_md.c init/: remove ineffective sparse disabling 2018-08-22 10:52:49 -07:00
do_mounts_rd.c init/: remove ineffective sparse disabling 2018-08-22 10:52:49 -07:00
do_mounts.c block: remove __bdevname 2020-03-24 07:57:07 -06:00
do_mounts.h fs: add do_mknodat() helper and ksys_mknod() wrapper; remove in-kernel calls to syscall 2018-04-02 20:15:56 +02:00
init_task.c exec: Add exec_update_mutex to replace cred_guard_mutex 2020-03-25 10:03:36 -05:00
initramfs.c arm64: use generic free_initrd_mem() 2019-10-16 13:55:25 +01:00
Kconfig arm64 fixes: 2020-04-09 11:04:16 -07:00
main.c printk: queue wake_up_klogd irq_work only if per-CPU areas are ready 2020-04-10 13:18:57 -07:00
Makefile Kbuild: Handle PREEMPT_RT for version string and magic 2019-08-14 01:10:42 +09:00
noinitramfs.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 167 2019-05-30 11:26:39 -07:00
version.c treewide: Add SPDX license identifier for missed files 2019-05-21 10:50:45 +02:00