@@ -1437,6 +1437,26 @@ enum nbcon_prio nbcon_get_default_prio(void)
14371437 return NBCON_PRIO_NORMAL ;
14381438}
14391439
1440+ /*
1441+ * Track if it is allowed to perform unsafe hostile takeovers of console
1442+ * ownership. When true, console drivers might perform unsafe actions while
1443+ * printing. It is externally available via nbcon_allow_unsafe_takeover().
1444+ */
1445+ static bool panic_nbcon_allow_unsafe_takeover ;
1446+
1447+ /**
1448+ * nbcon_allow_unsafe_takeover - Check if unsafe console takeovers are allowed
1449+ *
1450+ * Return: True, when it is permitted to perform unsafe console printing
1451+ *
1452+ * This is also used by console_is_usable() to determine if it is allowed to
1453+ * call write_atomic() callbacks flagged as unsafe (CON_NBCON_ATOMIC_UNSAFE).
1454+ */
1455+ bool nbcon_allow_unsafe_takeover (void )
1456+ {
1457+ return panic_on_this_cpu () && panic_nbcon_allow_unsafe_takeover ;
1458+ }
1459+
14401460/**
14411461 * nbcon_legacy_emit_next_record - Print one record for an nbcon console
14421462 * in legacy contexts
@@ -1507,7 +1527,6 @@ bool nbcon_legacy_emit_next_record(struct console *con, bool *handover,
15071527 * write_atomic() callback
15081528 * @con: The nbcon console to flush
15091529 * @stop_seq: Flush up until this record
1510- * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers
15111530 *
15121531 * Return: 0 if @con was flushed up to @stop_seq Otherwise, error code on
15131532 * failure.
@@ -1526,8 +1545,7 @@ bool nbcon_legacy_emit_next_record(struct console *con, bool *handover,
15261545 * returned, it cannot be expected that the unfinalized record will become
15271546 * available.
15281547 */
1529- static int __nbcon_atomic_flush_pending_con (struct console * con , u64 stop_seq ,
1530- bool allow_unsafe_takeover )
1548+ static int __nbcon_atomic_flush_pending_con (struct console * con , u64 stop_seq )
15311549{
15321550 struct nbcon_write_context wctxt = { };
15331551 struct nbcon_context * ctxt = & ACCESS_PRIVATE (& wctxt , ctxt );
@@ -1536,7 +1554,7 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq,
15361554 ctxt -> console = con ;
15371555 ctxt -> spinwait_max_us = 2000 ;
15381556 ctxt -> prio = nbcon_get_default_prio ();
1539- ctxt -> allow_unsafe_takeover = allow_unsafe_takeover ;
1557+ ctxt -> allow_unsafe_takeover = nbcon_allow_unsafe_takeover () ;
15401558
15411559 while (nbcon_seq_read (con ) < stop_seq ) {
15421560 if (!nbcon_context_try_acquire (ctxt , false))
@@ -1568,15 +1586,13 @@ static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq,
15681586 * write_atomic() callback
15691587 * @con: The nbcon console to flush
15701588 * @stop_seq: Flush up until this record
1571- * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers
15721589 *
15731590 * This will stop flushing before @stop_seq if another context has ownership.
15741591 * That context is then responsible for the flushing. Likewise, if new records
15751592 * are added while this context was flushing and there is no other context
15761593 * to handle the printing, this context must also flush those records.
15771594 */
1578- static void nbcon_atomic_flush_pending_con (struct console * con , u64 stop_seq ,
1579- bool allow_unsafe_takeover )
1595+ static void nbcon_atomic_flush_pending_con (struct console * con , u64 stop_seq )
15801596{
15811597 struct console_flush_type ft ;
15821598 unsigned long flags ;
@@ -1591,7 +1607,7 @@ static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq,
15911607 */
15921608 local_irq_save (flags );
15931609
1594- err = __nbcon_atomic_flush_pending_con (con , stop_seq , allow_unsafe_takeover );
1610+ err = __nbcon_atomic_flush_pending_con (con , stop_seq );
15951611
15961612 local_irq_restore (flags );
15971613
@@ -1623,9 +1639,8 @@ static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq,
16231639 * __nbcon_atomic_flush_pending - Flush all nbcon consoles using their
16241640 * write_atomic() callback
16251641 * @stop_seq: Flush up until this record
1626- * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers
16271642 */
1628- static void __nbcon_atomic_flush_pending (u64 stop_seq , bool allow_unsafe_takeover )
1643+ static void __nbcon_atomic_flush_pending (u64 stop_seq )
16291644{
16301645 struct console * con ;
16311646 int cookie ;
@@ -1643,7 +1658,7 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq, bool allow_unsafe_takeove
16431658 if (nbcon_seq_read (con ) >= stop_seq )
16441659 continue ;
16451660
1646- nbcon_atomic_flush_pending_con (con , stop_seq , allow_unsafe_takeover );
1661+ nbcon_atomic_flush_pending_con (con , stop_seq );
16471662 }
16481663 console_srcu_read_unlock (cookie );
16491664}
@@ -1659,7 +1674,7 @@ static void __nbcon_atomic_flush_pending(u64 stop_seq, bool allow_unsafe_takeove
16591674 */
16601675void nbcon_atomic_flush_pending (void )
16611676{
1662- __nbcon_atomic_flush_pending (prb_next_reserve_seq (prb ), false );
1677+ __nbcon_atomic_flush_pending (prb_next_reserve_seq (prb ));
16631678}
16641679
16651680/**
@@ -1671,7 +1686,9 @@ void nbcon_atomic_flush_pending(void)
16711686 */
16721687void nbcon_atomic_flush_unsafe (void )
16731688{
1674- __nbcon_atomic_flush_pending (prb_next_reserve_seq (prb ), true);
1689+ panic_nbcon_allow_unsafe_takeover = true;
1690+ __nbcon_atomic_flush_pending (prb_next_reserve_seq (prb ));
1691+ panic_nbcon_allow_unsafe_takeover = false;
16751692}
16761693
16771694/**
@@ -1894,7 +1911,7 @@ void nbcon_device_release(struct console *con)
18941911 * using the legacy loop.
18951912 */
18961913 if (ft .nbcon_atomic ) {
1897- __nbcon_atomic_flush_pending_con (con , prb_next_reserve_seq (prb ), false );
1914+ __nbcon_atomic_flush_pending_con (con , prb_next_reserve_seq (prb ));
18981915 } else if (ft .legacy_direct ) {
18991916 if (console_trylock ())
19001917 console_unlock ();
@@ -1964,5 +1981,5 @@ void nbcon_kdb_release(struct nbcon_write_context *wctxt)
19641981 * The console was locked only when the write_atomic() callback
19651982 * was usable.
19661983 */
1967- __nbcon_atomic_flush_pending_con (ctxt -> console , prb_next_reserve_seq (prb ), false );
1984+ __nbcon_atomic_flush_pending_con (ctxt -> console , prb_next_reserve_seq (prb ));
19681985}
0 commit comments