All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] panic: flush unsafe consoles before reboot and kdump
@ 2026-11-02 18:14 Breno Leitao
  2026-11-02 18:14 ` [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic Breno Leitao
  2026-11-02 18:14 ` [PATCH 2/2] crash: Flush unsafe consoles before machine_crash_shutdown() Breno Leitao
  0 siblings, 2 replies; 8+ messages in thread
From: Breno Leitao @ 2026-11-02 18:14 UTC (permalink / raw)
  To: Petr Mladek, John Ogness, Kiryl Shutsemau
  Cc: linux-kernel, printk, gustavold, samuelcrossley, ryan.roberts,
	brads, x86, Breno Leitao, kernel-team, stable

Since netconsole moved to NBCON, its messages are lost when the
machine reboots after a panic or boots a crash kernel. netconsole is
a CON_NBCON_ATOMIC_UNSAFE console, and those are only flushed at the
very end of panic(), after both.

Ryan reported this [1], and the fix is based on Petr's suggestions
[2][3]. Patch 1 flushes the unsafe consoles from printk() on the
panic CPU. Patch 2 also flushes them in __crash_kexec(), for an oops
that goes straight to kdump: on x86 that path prints nothing once the
CPU has become the panic CPU.

Tested on x86 with netconsole sending to a receiver: panic reboot,
kdump from sysrq and kdump from an oops all deliver the report, and
the crash kernel boots. Under virtme-ng that is 21 of 21 runs,
against 0 of 21 without the series. On a bare-metal host each case
was run once, and an unpatched kernel delivered nothing in all
three. arm64 is untested.

One case is left open. A printk() inside machine_crash_shutdown()
now also reaches netconsole. On x86 that only happens on errors, but
on a TDX guest tdx_kexec_finish() can pr_err() after it has unmapped
the shared memory a virtio-net netconsole uses. Stopping the printk()
flush once __crash_kexec() has flushed would close it, but would also
drop "Starting crashdump kernel..." and "Bye!" from netconsole on
arm64.

[1] https://lore.kernel.org/all/20260915100140.3631650-1-ryan.roberts@arm.com/
[2] https://lore.kernel.org/all/auNaD8LELWok3LOF@pathway/
[3] https://lore.kernel.org/all/auhl3cdwrHt4Vw7U@pathway/

Signed-off-by: Breno Leitao <leitao@debian.org>
---
Breno Leitao (2):
      printk: nbcon: Flush unsafe consoles from printk() in panic
      crash: Flush unsafe consoles before machine_crash_shutdown()

 include/linux/console.h |  7 ++++---
 include/linux/printk.h  |  5 +++++
 kernel/crash_core.c     |  1 +
 kernel/printk/nbcon.c   | 38 ++++++++++++++++++++++++++++++++------
 4 files changed, 42 insertions(+), 9 deletions(-)
---
base-commit: a39c950806213f6861d00f90729acaaa21f2d95a
change-id: 20261030-panic_unsafe_flush-62939c2c28e7

Best regards,
--  
Breno Leitao <leitao@debian.org>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic
  2026-11-02 18:14 [PATCH 0/2] panic: flush unsafe consoles before reboot and kdump Breno Leitao
@ 2026-11-02 18:14 ` Breno Leitao
  2026-11-02 18:29   ` sashiko-bot
  2026-11-05 14:34   ` John Ogness
  2026-11-02 18:14 ` [PATCH 2/2] crash: Flush unsafe consoles before machine_crash_shutdown() Breno Leitao
  1 sibling, 2 replies; 8+ messages in thread
From: Breno Leitao @ 2026-11-02 18:14 UTC (permalink / raw)
  To: Petr Mladek, John Ogness, Kiryl Shutsemau
  Cc: linux-kernel, printk, gustavold, samuelcrossley, ryan.roberts,
	brads, x86, Breno Leitao, kernel-team, stable

netconsole registers with CON_NBCON_ATOMIC_UNSAFE since commit
7eab73b18630 ("netconsole: convert to NBCON console infrastructure"), so
its write_atomic() only runs from nbcon_atomic_flush_unsafe(). vpanic()
calls that right before its final busy loop, after emergency_restart()
and after __crash_kexec().

A panic that reboots (panic_timeout != 0) or boots a crash kernel
therefore never reaches the netconsole target. Before the conversion,
netconsole was a legacy console and printk() wrote each panic message to
it as it was printed.

Flush the unsafe consoles from nbcon_atomic_flush_pending() as well,
right after the safe ones, when it runs on the panic CPU with
oops_in_progress set. Every printk() on the panic CPU then reaches
netconsole again, "Rebooting in" included.

An unsafe write_atomic() that hangs now stops the panic CPU at the first
message, before the other consoles print the rest and before the reboot
or the crash kernel. Getting the messages out is worth that.

Fixes: 187de7c212e5 ("printk: nbcon: Allow unsafe write_atomic() for panic")
Reported-by: Ryan Roberts <ryan.roberts@arm.com>
Closes: https://lore.kernel.org/all/20260915100140.3631650-1-ryan.roberts@arm.com/
Suggested-by: Petr Mladek <pmladek@suse.com>
Cc: stable@vger.kernel.org
Signed-off-by: Breno Leitao <leitao@debian.org>
---
 include/linux/console.h |  7 ++++---
 kernel/printk/nbcon.c   | 24 ++++++++++++++++++------
 2 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/include/linux/console.h b/include/linux/console.h
index cb8be9ea4a767b..934fe72978b0e5 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -183,7 +183,8 @@ static inline void con_debug_leave(void) { }
  * @CON_NBCON:		Console can operate outside of the legacy style console_lock
  *			constraints.
  * @CON_NBCON_ATOMIC_UNSAFE: The write_atomic() callback is not safe and is
- *			therefore only used by nbcon_atomic_flush_unsafe().
+ *			therefore only used in panic, when unsafe takeovers
+ *			are allowed.
  */
 enum cons_flags {
 	CON_PRINTBUFFER		= BIT(0),
@@ -246,8 +247,8 @@ static_assert(sizeof(struct nbcon_state) <= sizeof(int));
  * @NBCON_PRIO_MAX:		The number of priority levels
  *
  * A higher priority context can takeover the console when it is
- * in the safe state. The final attempt to flush consoles in panic()
- * can be allowed to do so even in an unsafe state (Hope and pray).
+ * in the safe state. The panic CPU can be allowed to do so even in
+ * an unsafe state (Hope and pray).
  */
 enum nbcon_prio {
 	NBCON_PRIO_NONE = 0,
diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
index 5f8afaca886650..19fa9f79cac3cb 100644
--- a/kernel/printk/nbcon.c
+++ b/kernel/printk/nbcon.c
@@ -84,8 +84,8 @@
  *        b) Gives up console ownership by clearing the 'prio' field.
  *
  *   3) Unsafe hostile takeover allows to take over the lock even when the
- *      console is an unsafe state. It is used only in panic() by the final
- *      attempt to flush consoles in a try and hope mode.
+ *      console is an unsafe state. It is used only on the panic CPU, in a
+ *      try and hope mode.
  *
  *      Note that separate record buffers are used in panic(). As a result,
  *      the messages can be read and formatted without any risk even after
@@ -543,7 +543,7 @@ static int nbcon_context_try_acquire_handover(struct nbcon_context *ctxt,
  * Acquire the console even in the unsafe state.
  *
  * It can be permitted by setting the 'allow_unsafe_takeover' field only
- * by the final attempt to flush messages in panic().
+ * on the panic CPU.
  *
  * Return:	0 on success. -EPERM when not allowed by the context.
  */
@@ -1653,8 +1653,9 @@ static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq)
  * __nbcon_atomic_flush_pending - Flush all nbcon consoles using their
  *					write_atomic() callback
  * @stop_seq:			Flush up until this record
+ * @unsafe_only:		Flush only the CON_NBCON_ATOMIC_UNSAFE consoles
  */
-static void __nbcon_atomic_flush_pending(u64 stop_seq)
+static void __nbcon_atomic_flush_pending(u64 stop_seq, bool unsafe_only)
 {
 	struct console *con;
 	int cookie;
@@ -1666,6 +1667,9 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq)
 		if (!(flags & CON_NBCON))
 			continue;
 
+		if (unsafe_only && !(flags & CON_NBCON_ATOMIC_UNSAFE))
+			continue;
+
 		if (!console_is_usable(con, flags, true))
 			continue;
 
@@ -1688,7 +1692,15 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq)
  */
 void nbcon_atomic_flush_pending(void)
 {
-	__nbcon_atomic_flush_pending(prb_next_reserve_seq(prb));
+	u64 stop_seq = prb_next_reserve_seq(prb);
+
+	__nbcon_atomic_flush_pending(stop_seq, false);
+
+	if (panic_on_this_cpu() && oops_in_progress) {
+		panic_nbcon_allow_unsafe_takeover = true;
+		__nbcon_atomic_flush_pending(stop_seq, true);
+		panic_nbcon_allow_unsafe_takeover = false;
+	}
 }
 
 /**
@@ -1701,7 +1713,7 @@ void nbcon_atomic_flush_pending(void)
 void nbcon_atomic_flush_unsafe(void)
 {
 	panic_nbcon_allow_unsafe_takeover = true;
-	__nbcon_atomic_flush_pending(prb_next_reserve_seq(prb));
+	__nbcon_atomic_flush_pending(prb_next_reserve_seq(prb), false);
 	panic_nbcon_allow_unsafe_takeover = false;
 }
 

-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] crash: Flush unsafe consoles before machine_crash_shutdown()
  2026-11-02 18:14 [PATCH 0/2] panic: flush unsafe consoles before reboot and kdump Breno Leitao
  2026-11-02 18:14 ` [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic Breno Leitao
@ 2026-11-02 18:14 ` Breno Leitao
  2026-11-02 18:51   ` sashiko-bot
  1 sibling, 1 reply; 8+ messages in thread
From: Breno Leitao @ 2026-11-02 18:14 UTC (permalink / raw)
  To: Petr Mladek, John Ogness, Kiryl Shutsemau
  Cc: linux-kernel, printk, gustavold, samuelcrossley, ryan.roberts,
	brads, x86, Breno Leitao, kernel-team, stable

On x86, an oops that goes to kdump never reaches netconsole. oops_end()
calls crash_kexec() after the oops is printed, before this CPU becomes
the panic CPU, so printk() skips the unsafe consoles for the whole
report. Unless something fails, nothing else is printed on the panic CPU
before machine_kexec().

Add nbcon_atomic_unsafe_only_flush(), which flushes only the
CON_NBCON_ATOMIC_UNSAFE consoles and allows unsafe takeovers on them.
Call it in __crash_kexec() before machine_crash_shutdown() tears down
what they may need, such as the shared memory of a TDX guest. As with
the legacy console, the other CPUs are still running at that point,
unless crash_kexec_post_notifiers is set.

When kdump comes from panic(), printk() has already flushed the unsafe
consoles and the call finds nothing pending.

Fixes: 187de7c212e5 ("printk: nbcon: Allow unsafe write_atomic() for panic")
Suggested-by: John Ogness <john.ogness@linutronix.de>
Suggested-by: Petr Mladek <pmladek@suse.com>
Cc: stable@vger.kernel.org
Signed-off-by: Breno Leitao <leitao@debian.org>
---
 include/linux/printk.h |  5 +++++
 kernel/crash_core.c    |  1 +
 kernel/printk/nbcon.c  | 14 ++++++++++++++
 3 files changed, 20 insertions(+)

diff --git a/include/linux/printk.h b/include/linux/printk.h
index f594c1266bfd41..95da3904c0d30e 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -208,6 +208,7 @@ void printk_legacy_allow_panic_sync(void);
 extern bool nbcon_device_try_acquire(struct console *con);
 extern void nbcon_device_release(struct console *con);
 void nbcon_atomic_flush_unsafe(void);
+void nbcon_atomic_unsafe_only_flush(void);
 bool pr_flush(int timeout_ms, bool reset_on_progress);
 #else
 static inline __printf(1, 0)
@@ -322,6 +323,10 @@ static inline void nbcon_atomic_flush_unsafe(void)
 {
 }
 
+static inline void nbcon_atomic_unsafe_only_flush(void)
+{
+}
+
 static inline bool pr_flush(int timeout_ms, bool reset_on_progress)
 {
 	return true;
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
index d0bd2d0cf8990b..6580eaa86685a9 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -140,6 +140,7 @@ void __noclone __crash_kexec(struct pt_regs *regs)
 
 			crash_setup_regs(&fixed_regs, regs);
 			crash_save_vmcoreinfo();
+			nbcon_atomic_unsafe_only_flush();
 			machine_crash_shutdown(&fixed_regs);
 			crash_cma_clear_pending_dma();
 			machine_kexec(kexec_crash_image);
diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
index 19fa9f79cac3cb..c22175a33ce17e 100644
--- a/kernel/printk/nbcon.c
+++ b/kernel/printk/nbcon.c
@@ -1717,6 +1717,20 @@ void nbcon_atomic_flush_unsafe(void)
 	panic_nbcon_allow_unsafe_takeover = false;
 }
 
+/**
+ * nbcon_atomic_unsafe_only_flush - Flush only the CON_NBCON_ATOMIC_UNSAFE
+ *	consoles, allowing unsafe hostile takeovers
+ *
+ * Like nbcon_atomic_flush_unsafe(), but consoles with a safe write_atomic()
+ * are left alone. Only effective on the panic CPU.
+ */
+void nbcon_atomic_unsafe_only_flush(void)
+{
+	panic_nbcon_allow_unsafe_takeover = true;
+	__nbcon_atomic_flush_pending(prb_next_reserve_seq(prb), true);
+	panic_nbcon_allow_unsafe_takeover = false;
+}
+
 /**
  * nbcon_cpu_emergency_enter - Enter an emergency section where printk()
  *				messages for that CPU are flushed directly

-- 
2.53.0-Meta


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic
  2026-11-02 18:14 ` [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic Breno Leitao
@ 2026-11-02 18:29   ` sashiko-bot
  2026-11-02 18:54     ` Breno Leitao
  2026-11-05 14:34   ` John Ogness
  1 sibling, 1 reply; 8+ messages in thread
From: sashiko-bot @ 2026-11-02 18:29 UTC (permalink / raw)
  To: Breno Leitao, Petr Mladek, John Ogness, Kiryl Shutsemau
  Cc: printk, gustavold, samuelcrossley, ryan.roberts, brads, x86,
	kernel-team

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] printk: nbcon: nested printk() in nbcon_atomic_flush_pending() corrupts state
--

commit 8683fa106aa2304e041764eca5971a98495ef1b9
Author: Breno Leitao <leitao@debian.org>

printk: nbcon: Flush unsafe consoles from printk() in panic

This commit flushes CON_NBCON_ATOMIC_UNSAFE consoles from
nbcon_atomic_flush_pending() when running on the panic CPU with
oops_in_progress set, so that panic messages reach netconsole before a
panic reboot or crash kexec.

> diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
> index 5f8afaca88665..19fa9f79cac3c 100644
> --- a/kernel/printk/nbcon.c
> +++ b/kernel/printk/nbcon.c

[ ... ]

> @@ -1688,7 +1692,15 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq)
>   */
>  void nbcon_atomic_flush_pending(void)
>  {
> -	__nbcon_atomic_flush_pending(prb_next_reserve_seq(prb));
> +	u64 stop_seq = prb_next_reserve_seq(prb);
> +
> +	__nbcon_atomic_flush_pending(stop_seq, false);
> +
> +	if (panic_on_this_cpu() && oops_in_progress) {
> +		panic_nbcon_allow_unsafe_takeover = true;
> +		__nbcon_atomic_flush_pending(stop_seq, true);
> +		panic_nbcon_allow_unsafe_takeover = false;
> +	}
>  }

[Severity: Medium]
Can a nested printk() or WARN() inside an unsafe console's write_atomic()
callback re-enter nbcon_atomic_flush_pending() and corrupt the outer flush?

Previously, CON_NBCON_ATOMIC_UNSAFE consoles were only flushed from
nbcon_atomic_flush_unsafe() at the end of vpanic() after suppress_printk
was set, so any nested printk() returned immediately in vprintk_emit().

With this change, CON_NBCON_ATOMIC_UNSAFE callbacks run during vpanic()
while suppress_printk is still 0. In netconsole, write_atomic() calls into
netpoll, skb allocation, and network driver paths that can trigger a nested
printk() or WARN(), such as netcons_skb_pop() in drivers/net/netconsole.c:

	if (!in_nmi())
		net_warn_ratelimited("netconsole: dropping message, requested skb len %d exceeds pool buffer size %zu on %s\n",
				     len, (size_t)MAX_SKB_SIZE,
				     nt->np.dev->name);

Because vprintk_store() exits printk_enter_irqsave() before vprintk_emit()
calls nbcon_atomic_flush_pending(), a nested printk() synchronously
re-enters nbcon_atomic_flush_pending():

  vprintk_emit()
    nbcon_atomic_flush_pending()
      panic_nbcon_allow_unsafe_takeover = true;
      __nbcon_atomic_flush_pending(stop_seq, true)
        nbcon_atomic_flush_pending_con()
          con->write_atomic()
            printk() / WARN()
              vprintk_emit()
                nbcon_atomic_flush_pending()

When that happens:

1. In kernel/printk/nbcon.c:nbcon_context_try_acquire(), all nbcon consoles
on the panic CPU share the single static panic_nbcon_pbufs instance:

	if (panic_on_this_cpu())
		ctxt->pbufs = &panic_nbcon_pbufs;
	else
		ctxt->pbufs = con->pbufs;

Flushing any other nbcon console during the nested call overwrites
panic_nbcon_pbufs.outbuf while the outer write_atomic() callback is still
reading from wctxt->outbuf (for example across UDP fragments or multiple
netconsole targets).

2. The nested nbcon_atomic_flush_pending() runs its first pass
__nbcon_atomic_flush_pending(stop_seq, false) while
panic_nbcon_allow_unsafe_takeover is still true from the outer call,
allowing unsafe hostile takeovers on safe nbcon consoles and treating
CON_NBCON_ATOMIC_UNSAFE consoles as usable during the first pass.

3. When the nested nbcon_atomic_flush_pending() finishes, it resets
panic_nbcon_allow_unsafe_takeover to false. The outer flush then skips any
remaining CON_NBCON_ATOMIC_UNSAFE consoles in __nbcon_atomic_flush_pending()
because console_is_usable() sees nbcon_allow_unsafe_takeover() as false,
and the retry loop in nbcon_atomic_flush_pending_con():

	printk_get_console_flush_type(&ft);
	if (!ft.nbcon_offload &&
	    prb_read_valid(prb, nbcon_seq_read(con), NULL)) {
		stop_seq = prb_next_reserve_seq(prb);
		goto again;
	}

runs with allow_unsafe_takeover set to false.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261102-panic_unsafe_flush-v1-0-12d1e22fd6d8@debian.org?part=1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] crash: Flush unsafe consoles before machine_crash_shutdown()
  2026-11-02 18:14 ` [PATCH 2/2] crash: Flush unsafe consoles before machine_crash_shutdown() Breno Leitao
@ 2026-11-02 18:51   ` sashiko-bot
  0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-11-02 18:51 UTC (permalink / raw)
  To: Breno Leitao, Petr Mladek, John Ogness, Kiryl Shutsemau
  Cc: printk, gustavold, samuelcrossley, ryan.roberts, brads, x86,
	kernel-team

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] printk: nbcon: re-entrant printk() in unsafe flush corrupts state and buffer
- [Medium] crash: interrupts and preemption enabled in __crash_kexec() console flush
--

commit 96308e7b9265481420ed9a4a2c3bd4f84534b26f
Author: Breno Leitao <leitao@debian.org>

crash: Flush unsafe consoles before machine_crash_shutdown()

This patch adds nbcon_atomic_unsafe_only_flush() to flush
CON_NBCON_ATOMIC_UNSAFE consoles with unsafe hostile takeovers enabled, and
calls it in __crash_kexec() before machine_crash_shutdown() so oops reports
reach consoles such as netconsole before kdump tears down device state.

> diff --git a/kernel/crash_core.c b/kernel/crash_core.c
> index d0bd2d0cf8990..6580eaa86685a 100644
> --- a/kernel/crash_core.c
> +++ b/kernel/crash_core.c
> @@ -140,6 +140,7 @@ void __noclone __crash_kexec(struct pt_regs *regs)
>  
>  			crash_setup_regs(&fixed_regs, regs);
>  			crash_save_vmcoreinfo();
> +			nbcon_atomic_unsafe_only_flush();

[Severity: Medium]
Can calling nbcon_atomic_unsafe_only_flush() here before local interrupts
and preemption are disabled cause problems if an interrupt fires between
emitted records on panic_cpu?

Unlike vpanic(), which disables local interrupts and preemption before
calling panic_try_start(), crash_kexec() sets panic_cpu via
panic_try_start() without disabling interrupts or preemption, and local
interrupts are only disabled later inside machine_crash_shutdown().

Several architecture oops paths release die_lock and re-enable or restore
local interrupts before calling crash_kexec(regs), such as:

arch/powerpc/kernel/traps.c:oops_end()
arch/loongarch/kernel/traps.c:die()
arch/mips/kernel/traps.c:die()
arch/sh/kernel/traps.c:die()

crash_kexec() can also be invoked as a KF_DESTRUCTIVE BPF kfunc with
interrupts and preemption enabled.

When nbcon_atomic_unsafe_only_flush() flushes a multi-record oops report,
__nbcon_atomic_flush_pending_con() uses scoped_guard(irqsave) around each
individual record, restoring the caller's enabled interrupt state at the end
of every iteration:

kernel/printk/nbcon.c:__nbcon_atomic_flush_pending_con() {
	...
	while (nbcon_seq_read(con) < stop_seq) {
		scoped_guard(irqsave) {
			if (!nbcon_context_try_acquire(ctxt, false))
				return -EPERM;
			if (!nbcon_emit_next_record(&wctxt, true))
				return -EAGAIN;
			nbcon_context_release(ctxt);
		}
	}
	...
}

If a hardware interrupt fires between records while preemption is enabled,
could the crashing task be preempted and migrated off panic_cpu mid-flush?
Once on another CPU, panic_on_this_cpu() becomes false and
panic_on_other_cpu() becomes true, causing nbcon_context_try_acquire_direct()
to fail with -EPERM and machine_crash_shutdown() to execute on a different
CPU than panic_cpu.

Even without migration, if an interrupt handler on panic_cpu calls printk()
while panic_nbcon_allow_unsafe_takeover is true, it will re-enter
nbcon_atomic_flush_pending(), allowing hostile takeovers on safe consoles and
clearing panic_nbcon_allow_unsafe_takeover before returning to the interrupted
flush; or if the interrupt handler calls panic(), vpanic() on panic_cpu will
fail kexec_trylock() because __crash_kexec() already holds kexec_lock.

> diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
> index 19fa9f79cac3c..c22175a33ce17 100644
> --- a/kernel/printk/nbcon.c
> +++ b/kernel/printk/nbcon.c
> @@ -1717,6 +1717,20 @@ void nbcon_atomic_flush_unsafe(void)
>  	panic_nbcon_allow_unsafe_takeover = false;
>  }
>  
> +/**
> + * nbcon_atomic_unsafe_only_flush - Flush only the CON_NBCON_ATOMIC_UNSAFE
> + *	consoles, allowing unsafe hostile takeovers
> + *
> + * Like nbcon_atomic_flush_unsafe(), but consoles with a safe write_atomic()
> + * are left alone. Only effective on the panic CPU.
> + */
> +void nbcon_atomic_unsafe_only_flush(void)
> +{
> +	panic_nbcon_allow_unsafe_takeover = true;
> +	__nbcon_atomic_flush_pending(prb_next_reserve_seq(prb), true);
> +	panic_nbcon_allow_unsafe_takeover = false;
> +}

[Severity: Medium]
What happens if a CON_NBCON_ATOMIC_UNSAFE console's write_atomic() callback
triggers a nested printk() or WARN() while nbcon_atomic_unsafe_only_flush()
is running?

In __crash_kexec(), suppress_printk is 0 and oops_in_progress is still 1 from
oops_begin(). During the flush:

__crash_kexec()
  nbcon_atomic_unsafe_only_flush()
    panic_nbcon_allow_unsafe_takeover = true;
    __nbcon_atomic_flush_pending(stop_seq, true)
      nbcon_atomic_flush_pending_con()
        nbcon_emit_next_record()
          con->write_atomic() (e.g. netconsole -> netpoll / NIC driver)
            printk() / WARN_ONCE()
              vprintk_emit()
                nbcon_atomic_flush_pending()

When vprintk_emit() calls nbcon_atomic_flush_pending(), it runs:

kernel/printk/nbcon.c:nbcon_atomic_flush_pending() {
	u64 stop_seq = prb_next_reserve_seq(prb);

	__nbcon_atomic_flush_pending(stop_seq, false);

	if (panic_on_this_cpu() && oops_in_progress) {
		panic_nbcon_allow_unsafe_takeover = true;
		__nbcon_atomic_flush_pending(stop_seq, true);
		panic_nbcon_allow_unsafe_takeover = false;
	}
}

Because panic_nbcon_allow_unsafe_takeover is already true on entry to the
nested nbcon_atomic_flush_pending(), doesn't this cause three issues?

1. The initial __nbcon_atomic_flush_pending(stop_seq, false) runs with
panic_nbcon_allow_unsafe_takeover set to true, allowing unsafe hostile
takeovers on safe consoles while other CPUs are still running in
__crash_kexec().

2. In nbcon_context_try_acquire(), every nbcon console acquired on the panic
CPU shares the single static panic_nbcon_pbufs buffer:

	if (panic_on_this_cpu())
		ctxt->pbufs = &panic_nbcon_pbufs;
	else
		ctxt->pbufs = con->pbufs;

When the nested flush acquires any other nbcon console and calls
nbcon_emit_next_record(), it formats into panic_nbcon_pbufs.outbuf,
overwriting wctxt->outbuf while the outer con->write_atomic() callback (such
as netconsole splitting a message across UDP fragments or iterating over
multiple targets) is still reading from it.

3. When the nested nbcon_atomic_flush_pending() finishes, it resets
panic_nbcon_allow_unsafe_takeover to false before returning to the outer
flush, so any remaining CON_NBCON_ATOMIC_UNSAFE consoles in the outer
nbcon_atomic_unsafe_only_flush() loop will no longer have
panic_nbcon_allow_unsafe_takeover enabled.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261102-panic_unsafe_flush-v1-0-12d1e22fd6d8@debian.org?part=2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic
  2026-11-02 18:29   ` sashiko-bot
@ 2026-11-02 18:54     ` Breno Leitao
  0 siblings, 0 replies; 8+ messages in thread
From: Breno Leitao @ 2026-11-02 18:54 UTC (permalink / raw)
  To: sashiko-reviews
  Cc: Petr Mladek, John Ogness, Kiryl Shutsemau, printk, gustavold,
	samuelcrossley, ryan.roberts, brads, x86, kernel-team

On Mon, Nov 02, 2026 at 06:29:46PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] printk: nbcon: nested printk() in nbcon_atomic_flush_pending() corrupts state
> --
> 
> commit 8683fa106aa2304e041764eca5971a98495ef1b9
> Author: Breno Leitao <leitao@debian.org>
> 
> printk: nbcon: Flush unsafe consoles from printk() in panic
> 
> This commit flushes CON_NBCON_ATOMIC_UNSAFE consoles from
> nbcon_atomic_flush_pending() when running on the panic CPU with
> oops_in_progress set, so that panic messages reach netconsole before a
> panic reboot or crash kexec.
> 
> > diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
> > index 5f8afaca88665..19fa9f79cac3c 100644
> > --- a/kernel/printk/nbcon.c
> > +++ b/kernel/printk/nbcon.c
> 
> [ ... ]
> 
> > @@ -1688,7 +1692,15 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq)
> >   */
> >  void nbcon_atomic_flush_pending(void)
> >  {
> > -	__nbcon_atomic_flush_pending(prb_next_reserve_seq(prb));
> > +	u64 stop_seq = prb_next_reserve_seq(prb);
> > +
> > +	__nbcon_atomic_flush_pending(stop_seq, false);
> > +
> > +	if (panic_on_this_cpu() && oops_in_progress) {
> > +		panic_nbcon_allow_unsafe_takeover = true;
> > +		__nbcon_atomic_flush_pending(stop_seq, true);
> > +		panic_nbcon_allow_unsafe_takeover = false;
> > +	}
> >  }
> 
> [Severity: Medium]
> Can a nested printk() or WARN() inside an unsafe console's write_atomic()
> callback re-enter nbcon_atomic_flush_pending() and corrupt the outer flush?

Maybe we want to make panic_nbcon_allow_unsafe_takeover a counter
instead o boolean, and increment and decrement it instead of true/false?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic
  2026-11-02 18:14 ` [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic Breno Leitao
  2026-11-02 18:29   ` sashiko-bot
@ 2026-11-05 14:34   ` John Ogness
  2026-11-05 15:37     ` Breno Leitao
  1 sibling, 1 reply; 8+ messages in thread
From: John Ogness @ 2026-11-05 14:34 UTC (permalink / raw)
  To: Breno Leitao, Petr Mladek, Kiryl Shutsemau
  Cc: linux-kernel, printk, gustavold, samuelcrossley, ryan.roberts,
	brads, x86, Breno Leitao, kernel-team, stable

On 2026-11-02, Breno Leitao <leitao@debian.org> wrote:
> --- a/kernel/printk/nbcon.c
> +++ b/kernel/printk/nbcon.c
> @@ -1688,7 +1692,15 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq)
>   */
>  void nbcon_atomic_flush_pending(void)
>  {
> -	__nbcon_atomic_flush_pending(prb_next_reserve_seq(prb));
> +	u64 stop_seq = prb_next_reserve_seq(prb);
> +
> +	__nbcon_atomic_flush_pending(stop_seq, false);
> +
> +	if (panic_on_this_cpu() && oops_in_progress) {
> +		panic_nbcon_allow_unsafe_takeover = true;
> +		__nbcon_atomic_flush_pending(stop_seq, true);
> +		panic_nbcon_allow_unsafe_takeover = false;
> +	}
>  }
>  
>  /**

This part of the patch gave me some ideas. First, I like the idea of
putting the policy handling code inside
nbcon_atomic_flush_pending(). This keeps the code outside of
kernel/printk fairly simple:

1. In emergency sections, printk() is calling
nbcon_atomic_flush_pending(), which always skips
CON_NBCON_ATOMIC_UNSAFE.

2. During panic, printk() is calling nbcon_atomic_flush_pending(), which
via policy could include CON_NBCON_ATOMIC_UNSAFE (in a 2nd internal
loop, after all safe atomic consoles are attempted).

3. After kthreads are shutdown, printk() is calling
nbcon_atomic_flush_pending(), which via policy could include
CON_NBCON_ATOMIC_UNSAFE (in a 2nd internal loop, after all safe atomic
consoles are attempted).

For the above situations, no new flushing calls are needed. But there is
another scenario for CON_NBCON_ATOMIC_UNSAFE (and unsafe printing in
general):

4. If the kernel ends in a way other than the final panic() loop, (for
example kexec, sysrq-r, panic+reboot), the above scenarios do not allow
unsafe printing. For the related code points we could call
nbcon_atomic_flush_unsafe() and it could handle the policy of unsafe
flushing depending on the context, which would allow
CON_NBCON_ATOMIC_UNSAFE to flush here as well.

The unsafe policy flags could be something like:

PANIC_PRINTK
- panic: all printk() calls during panic
- checked in nbcon_atomic_flush_pending() of #2
- if ((policy & PANIC_PRINTK) && panic_in_progress())

NORMAL_FLUSH
- non-panic: atomic flush calls: shutdown, reboot, kexec
- checked in nbcon_atomic_flush_pending() of #3
- checked in nbcon_atomic_flush_unsafe() of #4
- if ((policy & NORMAL_FLUSH) && !panic_in_progress())

PANIC_FLUSH
- panic: unsafe atomic flush calls: reboot, kexec
- checked in nbcon_atomic_flush_unsafe() of #4
- if ((policy & PANIC_FLUSH) && panic_in_progress())

Netconsole originally wanted by default:

    .policy = NORMAL_FLUSH | PANIC_FLUSH,

But this last series shows that netconsole actually wants:

    .policy = NORMAL_FLUSH | PANIC_FLUSH | PANIC_PRINTK,

These are slightly different policies. But as long as printk supports
all 3 policy flags, we do not care which policies are chosen.

I am happy to code up a full implementation if you think this has merit
or you want to see the patch to decide.

John

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic
  2026-11-05 14:34   ` John Ogness
@ 2026-11-05 15:37     ` Breno Leitao
  0 siblings, 0 replies; 8+ messages in thread
From: Breno Leitao @ 2026-11-05 15:37 UTC (permalink / raw)
  To: John Ogness
  Cc: Petr Mladek, Kiryl Shutsemau, linux-kernel, printk, gustavold,
	samuelcrossley, ryan.roberts, brads, x86, kernel-team, stable

On Thu, Nov 05, 2026 at 03:40:33PM +0106, John Ogness wrote:
> I am happy to code up a full implementation if you think this has merit
> or you want to see the patch to decide.

Yes, please go ahead. I was only trying to move quickly and close the
netconsole lack of messages gap we have right now, but if you can take
this over, you are much better placed than I am in this area.

Thanks,
--breno

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-11-05 15:37 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-02 18:14 [PATCH 0/2] panic: flush unsafe consoles before reboot and kdump Breno Leitao
2026-11-02 18:14 ` [PATCH 1/2] printk: nbcon: Flush unsafe consoles from printk() in panic Breno Leitao
2026-11-02 18:29   ` sashiko-bot
2026-11-02 18:54     ` Breno Leitao
2026-11-05 14:34   ` John Ogness
2026-11-05 15:37     ` Breno Leitao
2026-11-02 18:14 ` [PATCH 2/2] crash: Flush unsafe consoles before machine_crash_shutdown() Breno Leitao
2026-11-02 18:51   ` sashiko-bot

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.