Introduce various lockdep related crash tests.

Signed-off-by: Tzung-Bi Shih <[email protected]>
---
v3:
- Add some entries in tools/testing/selftests/lkdtm/tests.txt.

v2: https://lore.kernel.org/all/[email protected]/
- Fix "warning: suggest braces around empty body in an 'else' statement 
[-Wempty-body]"
  reported by 0day test robot.

v1: 
https://lore.kernel.org/lkml/[email protected]/T/#u

 drivers/misc/lkdtm/Makefile             |  1 +
 drivers/misc/lkdtm/core.c               |  1 +
 drivers/misc/lkdtm/lkdtm.h              |  1 +
 drivers/misc/lkdtm/lockdep.c            | 98 +++++++++++++++++++++++++
 tools/testing/selftests/lkdtm/tests.txt |  8 ++
 5 files changed, 109 insertions(+)
 create mode 100644 drivers/misc/lkdtm/lockdep.c

diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile
index 03ebe33185f9..830b71c8e6a0 100644
--- a/drivers/misc/lkdtm/Makefile
+++ b/drivers/misc/lkdtm/Makefile
@@ -11,6 +11,7 @@ lkdtm-$(CONFIG_LKDTM)         += usercopy.o
 lkdtm-$(CONFIG_LKDTM)          += kstack_erase.o
 lkdtm-$(CONFIG_LKDTM)          += cfi.o
 lkdtm-$(CONFIG_LKDTM)          += fortify.o
+lkdtm-$(CONFIG_LKDTM)          += lockdep.o
 lkdtm-$(CONFIG_PPC_64S_HASH_MMU)       += powerpc.o
 
 KASAN_SANITIZE_stackleak.o     := n
diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c
index 5732fd59a227..43e91388940f 100644
--- a/drivers/misc/lkdtm/core.c
+++ b/drivers/misc/lkdtm/core.c
@@ -96,6 +96,7 @@ static const struct crashtype_category 
*crashtype_categories[] = {
        &stackleak_crashtypes,
        &cfi_crashtypes,
        &fortify_crashtypes,
+       &lockdep_crashtypes,
 #ifdef CONFIG_PPC_64S_HASH_MMU
        &powerpc_crashtypes,
 #endif
diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h
index 015e0484026b..d2d97e6f323e 100644
--- a/drivers/misc/lkdtm/lkdtm.h
+++ b/drivers/misc/lkdtm/lkdtm.h
@@ -84,6 +84,7 @@ extern struct crashtype_category usercopy_crashtypes;
 extern struct crashtype_category stackleak_crashtypes;
 extern struct crashtype_category cfi_crashtypes;
 extern struct crashtype_category fortify_crashtypes;
+extern struct crashtype_category lockdep_crashtypes;
 extern struct crashtype_category powerpc_crashtypes;
 
 /* Each category's init/exit routines. */
diff --git a/drivers/misc/lkdtm/lockdep.c b/drivers/misc/lkdtm/lockdep.c
new file mode 100644
index 000000000000..e029e9e60ce6
--- /dev/null
+++ b/drivers/misc/lkdtm/lockdep.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 Google LLC
+ *
+ * Tests related to lockdep warnings.
+ */
+#include "lkdtm.h"
+#include <linux/cleanup.h>
+#include <linux/irqflags.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/srcu.h>
+
+static DEFINE_SPINLOCK(lock_A);
+static DEFINE_SPINLOCK(lock_B);
+
+/* For "WARNING: possible circular locking dependency detected". */
+static void lkdtm_LOCKDEP_CIRCULAR_LOCK(void)
+{
+       scoped_guard(spinlock, &lock_A)
+               scoped_guard(spinlock, &lock_B) {}
+       scoped_guard(spinlock, &lock_B)
+               scoped_guard(spinlock, &lock_A) {}
+}
+
+/* For "WARNING: possible recursive locking detected". */
+static void lkdtm_LOCKDEP_RECURSIVE_LOCK(void)
+{
+       guard(spinlock)(&lock_A);
+       guard(spinlock)(&lock_A);
+}
+
+/* For "WARNING: inconsistent lock state". */
+static void lkdtm_LOCKDEP_INCONSISTENT_LOCK(void)
+{
+       lockdep_softirq_enter();
+       scoped_guard(spinlock, &lock_A) {}
+       lockdep_softirq_exit();
+
+       scoped_guard(spinlock, &lock_A) {}
+}
+
+/* For "WARNING: Nested lock was not taken". */
+static void lkdtm_LOCKDEP_NESTED_LOCK_NOT_HELD(void)
+{
+       spin_lock_nest_lock(&lock_B, &lock_A);
+}
+
+/* For "WARNING: bad unlock balance detected!". */
+static void lkdtm_LOCKDEP_BAD_UNLOCK_BALANCE(void)
+{
+       spin_unlock(&lock_A);
+}
+
+/* For "WARNING: held lock freed!". */
+static void lkdtm_LOCKDEP_HELD_LOCK_FREED(void)
+{
+       spin_lock(&lock_A);
+       spin_lock_init(&lock_A);
+}
+
+/* For "WARNING: lock held when returning to user space!". */
+static void lkdtm_LOCKDEP_HELD_LOCK(void)
+{
+       spin_lock(&lock_A);
+}
+
+/* For "WARNING: suspicious RCU usage". */
+static void lkdtm_LOCKDEP_SUSPICIOUS_RCU(void)
+{
+       struct srcu_struct srcu;
+       void __rcu *res = NULL;
+       int idx;
+
+       init_srcu_struct(&srcu);
+
+       idx = srcu_read_lock(&srcu);
+       rcu_dereference(res);
+       srcu_read_unlock(&srcu, idx);
+
+       cleanup_srcu_struct(&srcu);
+}
+
+static struct crashtype crashtypes[] = {
+       CRASHTYPE(LOCKDEP_CIRCULAR_LOCK),
+       CRASHTYPE(LOCKDEP_RECURSIVE_LOCK),
+       CRASHTYPE(LOCKDEP_INCONSISTENT_LOCK),
+       CRASHTYPE(LOCKDEP_NESTED_LOCK_NOT_HELD),
+       CRASHTYPE(LOCKDEP_BAD_UNLOCK_BALANCE),
+       CRASHTYPE(LOCKDEP_HELD_LOCK_FREED),
+       CRASHTYPE(LOCKDEP_HELD_LOCK),
+       CRASHTYPE(LOCKDEP_SUSPICIOUS_RCU),
+};
+
+struct crashtype_category lockdep_crashtypes = {
+       .crashtypes = crashtypes,
+       .len        = ARRAY_SIZE(crashtypes),
+};
diff --git a/tools/testing/selftests/lkdtm/tests.txt 
b/tools/testing/selftests/lkdtm/tests.txt
index cff124c1eddd..7b32dece3d3a 100644
--- a/tools/testing/selftests/lkdtm/tests.txt
+++ b/tools/testing/selftests/lkdtm/tests.txt
@@ -83,3 +83,11 @@ FORTIFY_STR_MEMBER detected buffer overflow
 FORTIFY_MEM_OBJECT detected buffer overflow
 FORTIFY_MEM_MEMBER detected field-spanning write
 PPC_SLB_MULTIHIT Recovered
+#LOCKDEP_CIRCULAR_LOCK Lockdep can only trigger once
+#LOCKDEP_RECURSIVE_LOCK Hangs the system
+#LOCKDEP_INCONSISTENT_LOCK Lockdep can only trigger once
+#LOCKDEP_NESTED_LOCK_NOT_HELD Cause a deadlock in subsequent lockdep tests
+#LOCKDEP_BAD_UNLOCK_BALANCE Lockdep can only trigger once
+#LOCKDEP_HELD_LOCK_FREED Lockdep can only trigger once
+#LOCKDEP_HELD_LOCK Cause a deadlock in subsequent lockdep tests
+#LOCKDEP_SUSPICIOUS_RCU Lockdep can only trigger once
-- 
2.52.0.305.g3fc767764a-goog


Reply via email to