[PATCH v4 5/5] lib/vsprintf: Validate spinlock context during restricted pointer formatting

From: Thomas Weißschuh

Date: Mon Jun 08 2026 - 10:28:43 EST


Depending on the system configuration, the restricted pointer formatting
might call into the security subsystem which takes spinlocks, which
might sleep under PREEMPT_RT. As %pK is intended to be only used from
read handlers of virtual files, which always run in task context,
this should not be a problem in practice.
However, developers have used %pK before from atomic context without
realizing this restriction. While all existing user of %pK through
printk() have been removed, new ones might be reintroduced accidentally
in the future.

Add a lockdep annotation to unconditionally introduce a fake spinlock in
restricted_pointer(), so lockdep can detect misuse even if the current
test system configuration would not exhibit the issue.
This is intentionally a single lock instance shared by all callers,
as that mirrors what can happen in the security subsystem.

This check comes intentionally after the in_task() one, to have the
clearer diagnostic first when the function is called from IRQ context,
which will trigger both.

Link: https://lore.kernel.org/lkml/20250113171731-dc10e3c1-da64-4af0-b767-7c7070468023@xxxxxxxxxxxxx/
Link: https://lore.kernel.org/lkml/20241217142032.55793-1-acarmina@xxxxxxxxxx/
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@xxxxxxxxxxxxx>
Reviewed-by: Petr Mladek <pmladek@xxxxxxxx>
---
lib/vsprintf.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 09e0e5194d41..728a1acd69ae 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -864,7 +864,14 @@ static noinline_for_stack
char *restricted_pointer(char *buf, char *end, const void *ptr,
struct printf_spec spec)
{
+ /*
+ * has_capability_noaudit() may use spinlocks.
+ * Make sure %pK is only used from valid contexts.
+ */
+ static DEFINE_WAIT_ASSERT_MAP(vsprintf_restricted_pointer_map, LD_WAIT_CONFIG);
+
lockdep_assert(in_task());
+ guard(lock_map_acquire)(&vsprintf_restricted_pointer_map);

switch (kptr_restrict) {
case 0:

--
2.54.0