mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Breno Leitao <leitao@debian.org>
To: Petr Mladek <pmladek@suse.com>
Cc: John Ogness <john.ogness@linutronix.de>,
	 Ryan Roberts <ryan.roberts@arm.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	 Steven Rostedt <rostedt@goodmis.org>,
	Sergey Senozhatsky <senozhatsky@chromium.org>,
	 Rio <rioo.tsukatsukii@gmail.com>,
	linux-kernel@vger.kernel.org
Subject: Re: [RFC PATCH v1] panic: Flush unsafe consoles before panic reboot
Date: Fri, 30 Oct 2026 10:56:35 -0700	[thread overview]
Message-ID: <auTaBZlNbpm3jgvb@gmail.com> (raw)
In-Reply-To: <auNaD8LELWok3LOF@pathway>

On Thu, Oct 29, 2026 at 03:37:03PM +0100, Petr Mladek wrote:
> Another question is where to call it. I guess the it should be called
> in two code paths:
> 
>    + __crash_kexec() likely after stopping other CPUs
> 
>     + console_flush_on_panic() after flushing safe nbcon consoles
> 	the safe way

What about something like:


commit de57403441b601af01d92bc03bf0625338d39c80
Author: Breno Leitao <leitao@debian.org>
Date:   Fri Oct 30 10:08:01 2026 -0700

    panic: flush unsafe consoles before reboot and kdump
    
    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. Neither does an oops that
    goes to kdump through crash_kexec(), which skips vpanic() entirely.
    Before the conversion, netconsole was a legacy console, flushed by
    console_flush_on_panic() ahead of the reboot.
    
    Add nbcon_atomic_unsafe_only_flush(), which flushes only the
    CON_NBCON_ATOMIC_UNSAFE consoles and allows unsafe takeovers on them.
    Call it on the panic CPU once the other CPUs are stopped, leaving the
    consoles with a safe write_atomic() alone.
    
    In vpanic() it runs after the safe flush, when
    panic_other_cpus_shutdown() has stopped the other CPUs. In
    __crash_kexec() it runs after crash_smp_send_stop() and before
    machine_crash_shutdown(), the order panic() already uses with
    crash_kexec_post_notifiers.
    
    The call does not go into console_flush_on_panic(), because kgdb_panic()
    calls that before the other CPUs are stopped. It does not go after
    machine_crash_shutdown() either: on TDX guests tdx_kexec_finish() zaps
    the shared PTEs there, and netconsole on a virtio NIC would touch that
    memory.
    
    A write_atomic() that hangs now keeps the machine from rebooting or from
    reaching the crash kernel.
    
    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: 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>

diff --git a/include/linux/console.h b/include/linux/console.h
index cb8be9ea4a767b..ebfa259633761a 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 by nbcon_atomic_flush_unsafe() and
+ *			nbcon_atomic_unsafe_only_flush().
  */
 enum cons_flags {
 	CON_PRINTBUFFER		= BIT(0),
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..d00a8ce5cb618c 100644
--- a/kernel/crash_core.c
+++ b/kernel/crash_core.c
@@ -140,6 +140,13 @@ void __noclone __crash_kexec(struct pt_regs *regs)
 
 			crash_setup_regs(&fixed_regs, regs);
 			crash_save_vmcoreinfo();
+			/*
+			 * Flush the unsafe consoles with the other CPUs
+			 * stopped, before machine_crash_shutdown() tears
+			 * down what they may need.
+			 */
+			crash_smp_send_stop();
+			nbcon_atomic_unsafe_only_flush();
 			machine_crash_shutdown(&fixed_regs);
 			crash_cma_clear_pending_dma();
 			machine_kexec(kexec_crash_image);
diff --git a/kernel/panic.c b/kernel/panic.c
index 91e48d33b7dbbd..e14b1b60828130 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -723,6 +723,9 @@ void vpanic(const char *fmt, va_list args)
 		panic_console_replay)
 		console_flush_on_panic(CONSOLE_REPLAY_ALL);
 
+	/* The other CPUs are stopped, flush the unsafe consoles too.
h /tmp/puf_post.sh kerneltest001.31.atn1 6791 atn1a &); (sh
/tmp/puf_post.sh kerneltest005.19.atn2 6792 atn2a &)
/
+	nbcon_atomic_unsafe_only_flush();
+
 	if (!panic_blink)
 		panic_blink = no_blink;
 
diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
index 5f8afaca886650..a43143eca1a015 100644
--- a/kernel/printk/nbcon.c
+++ b/kernel/printk/nbcon.c
@@ -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,7 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq)
  */
 void nbcon_atomic_flush_pending(void)
 {
-	__nbcon_atomic_flush_pending(prb_next_reserve_seq(prb));
+	__nbcon_atomic_flush_pending(prb_next_reserve_seq(prb), false);
 }
 
 /**
@@ -1701,7 +1705,21 @@ 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;
+}
+
+/**
+ * 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. Meant for the panic CPU once the other CPUs are stopped.
+ */
+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;
 }
 

      reply	other threads:[~2026-10-30 17:56 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-15 10:01 Ryan Roberts
2026-09-15 10:06 ` Ryan Roberts
2026-09-15 18:49   ` Bradley Morgan
2026-09-16  7:44     ` Ryan Roberts
2026-09-16 14:58       ` Bradley Morgan
2026-09-16 13:08 ` Petr Mladek
2026-10-22 20:35   ` Gustavo Luiz Duarte
2026-10-23  7:57   ` John Ogness
2026-10-23 10:36     ` Petr Mladek
2026-10-27 16:12       ` Breno Leitao
2026-10-27 17:43         ` Breno Leitao
2026-10-27 18:01           ` John Ogness
2026-10-28 11:24             ` Breno Leitao
2026-10-28 10:52     ` Breno Leitao
2026-10-28 14:37       ` John Ogness
2026-10-28 21:15         ` Breno Leitao
2026-10-29  9:20           ` John Ogness
2026-10-29 10:58             ` Breno Leitao
2026-10-29 13:53               ` John Ogness
2026-10-29 14:37                 ` Petr Mladek
2026-10-30 17:56                   ` Breno Leitao [this message]

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=auTaBZlNbpm3jgvb@gmail.com \
    --to=leitao@debian.org \
    --cc=akpm@linux-foundation.org \
    --cc=john.ogness@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pmladek@suse.com \
    --cc=rioo.tsukatsukii@gmail.com \
    --cc=rostedt@goodmis.org \
    --cc=ryan.roberts@arm.com \
    --cc=senozhatsky@chromium.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®