lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <9ffc0801a64e5f7d0685c263c1908a34cf89d1a5.1763492585.git.chris@chrisdown.name>
Date: Wed, 19 Nov 2025 03:07:17 +0800
From: Chris Down <chris@...isdown.name>
To: Petr Mladek <pmladek@...e.com>
Cc: linux-kernel@...r.kernel.org,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Sergey Senozhatsky <senozhatsky@...omium.org>,
	Steven Rostedt <rostedt@...dmis.org>,
	John Ogness <john.ogness@...utronix.de>,
	Geert Uytterhoeven <geert@...ux-m68k.org>,
	Tony Lindgren <tony.lindgren@...ux.intel.com>, kernel-team@...com
Subject: [PATCH v7 05/13] printk: Add synchronisation for concurrent console
 state changes

The syslog actions SYSLOG_ACTION_CONSOLE_OFF and
SYSLOG_ACTION_CONSOLE_ON currently run without any locking. This creates
a race condition if two processes attempt to toggle the console state
simultaneously.

While this race has existed for donkey's years, it was previously
somewhat tolerable because it involved only a single integer variable
(saved_console_loglevel). However, upcoming changes will introduce a
second piece of state (saved_ignore_per_console_loglevel) to be saved
and restored. With two variables, this can result in saved state getting
lost.

Here is a demonstration:

 CPU 0 (SYSLOG_ACTION_CONSOLE_OFF)        CPU 1 (SYSLOG_ACTION_CONSOLE_ON)
 ---------------------------------        --------------------------------
 // saved_console_loglevel is DEFAULT
 if (saved == DEFAULT) (True)
   saved = console_loglevel (7)
                                          // Race triggers here
                                          if (saved != DEFAULT) (True)
                                            loglevel = saved (7)
                                            saved = DEFAULT
   // CPU 0 continues, unaware saved
   // was just reset by CPU 1
   loglevel = minimum_console_loglevel (1)

The result is that the console is now set to the minimum loglevel, but
saved_console_loglevel is LOGLEVEL_DEFAULT. A subsequent CONSOLE_ON call
will see saved == LOGLEVEL_DEFAULT and thus refuse to restore the
original loglevel. The console is effectively stuck in quiet mode until
manually reset via sysctl. Oh dear.

The callers of do_syslog are syscalls (so user context) or procfs write
handlers. These contexts are allowed to sleep, so acquiring a mutex is
safe. We also already make use of syslog_lock in
SYSLOG_ACTION_SIZE_UNREAD and SYSLOG_ACTION_READ, so this is consistent.

Signed-off-by: Chris Down <chris@...isdown.name>
---
 kernel/printk/printk.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 928d77c56c77..b8679b0da42f 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1903,16 +1903,20 @@ int do_syslog(int type, char __user *buf, int len, int source)
 		break;
 	/* Disable logging to console */
 	case SYSLOG_ACTION_CONSOLE_OFF:
+		mutex_lock(&syslog_lock);
 		if (saved_console_loglevel == LOGLEVEL_DEFAULT)
 			saved_console_loglevel = console_loglevel;
 		console_loglevel = minimum_console_loglevel;
+		mutex_unlock(&syslog_lock);
 		break;
 	/* Enable logging to console */
 	case SYSLOG_ACTION_CONSOLE_ON:
+		mutex_lock(&syslog_lock);
 		if (saved_console_loglevel != LOGLEVEL_DEFAULT) {
 			console_loglevel = saved_console_loglevel;
 			saved_console_loglevel = LOGLEVEL_DEFAULT;
 		}
+		mutex_unlock(&syslog_lock);
 		break;
 	/* Set level of messages printed to console */
 	case SYSLOG_ACTION_CONSOLE_LEVEL:
-- 
2.51.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ