diff --git a/include/linux/bug.h b/include/linux/bug.h index 7f4818673c41..91eedf5fae38 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -109,4 +109,10 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr, } #endif /* CONFIG_GENERIC_BUG */ + +#ifdef CONFIG_PANIC_ON_DATA_CORRUPTION +#define PANIC_CORRUPTION 1 +#else +#define PANIC_CORRUPTION 0 +#endif /* CONFIG_PANIC_ON_DATA_CORRUPTION */ #endif /* _LINUX_BUG_H */ diff --git a/kernel/locking/spinlock_debug.c b/kernel/locking/spinlock_debug.c index 0374a596cffa..6011c190e2b1 100644 --- a/kernel/locking/spinlock_debug.c +++ b/kernel/locking/spinlock_debug.c @@ -12,6 +12,7 @@ #include #include #include +#include void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name, struct lock_class_key *key) @@ -64,6 +65,7 @@ static void spin_dump(raw_spinlock_t *lock, const char *msg) owner ? owner->comm : "", owner ? task_pid_nr(owner) : -1, lock->owner_cpu); + BUG_ON(PANIC_CORRUPTION); dump_stack(); } diff --git a/kernel/workqueue.c b/kernel/workqueue.c index c579dbab2e36..15dacf9590cb 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "workqueue_internal.h" @@ -2042,6 +2043,7 @@ __acquires(&pool->lock) current->comm, preempt_count(), task_pid_nr(current), worker->current_func); debug_show_held_locks(current); + BUG_ON(PANIC_CORRUPTION); dump_stack(); } diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 97d6c08dd9f7..810e6c31d130 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1893,6 +1893,13 @@ config TEST_STATIC_KEYS If unsure, say N. +config PANIC_ON_DATA_CORRUPTION + bool "Cause a Kernel Panic When Data Corruption is detected" + help + Select this option to upgrade warnings for potentially + recoverable data corruption scenarios to system-halting panics, + for easier detection and debug. + source "samples/Kconfig" source "lib/Kconfig.kgdb" diff --git a/lib/list_debug.c b/lib/list_debug.c index c24c2f7e296f..8cf180bfaabe 100644 --- a/lib/list_debug.c +++ b/lib/list_debug.c @@ -11,6 +11,7 @@ #include #include #include +#include /* * Insert a new entry between two known consecutive entries. @@ -34,6 +35,10 @@ void __list_add(struct list_head *new, WARN(new == prev || new == next, "list_add double add: new=%p, prev=%p, next=%p.\n", new, prev, next); + + BUG_ON((prev->next != next || next->prev != prev || + new == prev || new == next) && PANIC_CORRUPTION); + next->prev = new; new->next = next; new->prev = prev; @@ -59,8 +64,10 @@ void __list_del_entry(struct list_head *entry) "but was %p\n", entry, prev->next) || WARN(next->prev != entry, "list_del corruption. next->prev should be %p, " - "but was %p\n", entry, next->prev)) + "but was %p\n", entry, next->prev)) { + BUG_ON(PANIC_CORRUPTION); return; + } __list_del(prev, next); }