diff --git a/include/linux/bug.h b/include/linux/bug.h index 72961c39576..cd141a4a085 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -96,4 +96,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/workqueue.c b/kernel/workqueue.c index f1a6e9e8e06..90fd57da8ea 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "workqueue_sched.h" @@ -1878,6 +1879,7 @@ __acquires(&gcwq->lock) printk(KERN_ERR " last function: "); print_symbol("%s\n", (unsigned long)f); debug_show_held_locks(current); + BUG_ON(PANIC_CORRUPTION); dump_stack(); } diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 097d70fa02d..b9060a1250c 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1290,6 +1290,13 @@ config ASYNC_RAID6_TEST 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 982b850d4e7..6a039a62841 100644 --- a/lib/list_debug.c +++ b/lib/list_debug.c @@ -10,6 +10,7 @@ #include #include #include +#include /* * Insert a new entry between two known consecutive entries. @@ -30,6 +31,10 @@ void __list_add(struct list_head *new, "list_add corruption. prev->next should be " "next (%p), but was %p. (prev=%p).\n", next, prev->next, prev); + + BUG_ON(((prev->next != next) || (next->prev != prev)) && + PANIC_CORRUPTION); + next->prev = new; new->next = next; new->prev = prev; @@ -55,8 +60,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); } diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c index f2aa5de6f6c..ac516f4f59e 100644 --- a/lib/spinlock_debug.c +++ b/lib/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(); }