mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 16:30:02 -04:00
printk: Fix possible console use-after-free
When emitting a record via legacy printing, it is possible that a handover
to another legacy printing context occurs. When a context has performed a
handover, the console SRCU read lock is released and the pointer to the
console struct might now be invalid. Therefore, after calling
nbcon_legacy_emit_next_record() or console_emit_next_record(), it is
necessary to check if a handover occurred _before_ further @con usage.
Sashiko pointed out that console_flush_one_record() was not doing this.
In console_flush_one_record(), after emitting a record, move the further
usage of @con after the handover check.
Fixes: c158834b22 ("printk: nbcon: Use nbcon consoles in console_flush_all()")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/lkml/20260630170903.099D61F000E9@smtp.kernel.org
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Link: https://patch.msgid.link/20260703141521.202813-1-john.ogness@linutronix.de
Signed-off-by: Petr Mladek <pmladek@suse.com>
This commit is contained in:
@@ -3264,10 +3264,8 @@ static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *
|
||||
if (flags & CON_NBCON) {
|
||||
progress = nbcon_legacy_emit_next_record(con, handover, cookie,
|
||||
!do_cond_resched);
|
||||
printk_seq = nbcon_seq_read(con);
|
||||
} else {
|
||||
progress = console_emit_next_record(con, handover, cookie);
|
||||
printk_seq = con->seq;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3277,6 +3275,15 @@ static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *
|
||||
if (*handover)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* @con can be used here now that it is certain that this
|
||||
* context is still holding the SRCU read lock.
|
||||
*/
|
||||
if (flags & CON_NBCON)
|
||||
printk_seq = nbcon_seq_read(con);
|
||||
else
|
||||
printk_seq = con->seq;
|
||||
|
||||
/* Track the next of the highest seq flushed. */
|
||||
if (printk_seq > *next_seq)
|
||||
*next_seq = printk_seq;
|
||||
|
||||
Reference in New Issue
Block a user