hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/kernel/panic.c
....@@ -31,6 +31,7 @@
3131 #include <linux/bug.h>
3232 #include <linux/ratelimit.h>
3333 #include <linux/debugfs.h>
34
+#include <linux/sysfs.h>
3435 #include <asm/sections.h>
3536
3637 #define PANIC_TIMER_STEP 100
....@@ -41,7 +42,9 @@
4142 * Should we dump all CPUs backtraces in an oops event?
4243 * Defaults to 0, can be changed via sysctl.
4344 */
44
-unsigned int __read_mostly sysctl_oops_all_cpu_backtrace;
45
+static unsigned int __read_mostly sysctl_oops_all_cpu_backtrace;
46
+#else
47
+#define sysctl_oops_all_cpu_backtrace 0
4548 #endif /* CONFIG_SMP */
4649
4750 int panic_on_oops = CONFIG_PANIC_ON_OOPS_VALUE;
....@@ -54,6 +57,7 @@
5457 int panic_on_warn __read_mostly;
5558 unsigned long panic_on_taint;
5659 bool panic_on_taint_nousertaint = false;
60
+static unsigned int warn_limit __read_mostly;
5761
5862 int panic_timeout = CONFIG_PANIC_TIMEOUT;
5963 EXPORT_SYMBOL_GPL(panic_timeout);
....@@ -69,6 +73,56 @@
6973 ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
7074
7175 EXPORT_SYMBOL(panic_notifier_list);
76
+
77
+#ifdef CONFIG_SYSCTL
78
+static struct ctl_table kern_panic_table[] = {
79
+#ifdef CONFIG_SMP
80
+ {
81
+ .procname = "oops_all_cpu_backtrace",
82
+ .data = &sysctl_oops_all_cpu_backtrace,
83
+ .maxlen = sizeof(int),
84
+ .mode = 0644,
85
+ .proc_handler = proc_dointvec_minmax,
86
+ .extra1 = SYSCTL_ZERO,
87
+ .extra2 = SYSCTL_ONE,
88
+ },
89
+#endif
90
+ {
91
+ .procname = "warn_limit",
92
+ .data = &warn_limit,
93
+ .maxlen = sizeof(warn_limit),
94
+ .mode = 0644,
95
+ .proc_handler = proc_douintvec,
96
+ },
97
+ { }
98
+};
99
+
100
+static __init int kernel_panic_sysctls_init(void)
101
+{
102
+ register_sysctl_init("kernel", kern_panic_table);
103
+ return 0;
104
+}
105
+late_initcall(kernel_panic_sysctls_init);
106
+#endif
107
+
108
+static atomic_t warn_count = ATOMIC_INIT(0);
109
+
110
+#ifdef CONFIG_SYSFS
111
+static ssize_t warn_count_show(struct kobject *kobj, struct kobj_attribute *attr,
112
+ char *page)
113
+{
114
+ return sysfs_emit(page, "%d\n", atomic_read(&warn_count));
115
+}
116
+
117
+static struct kobj_attribute warn_count_attr = __ATTR_RO(warn_count);
118
+
119
+static __init int kernel_panic_sysfs_init(void)
120
+{
121
+ sysfs_add_file_to_group(kernel_kobj, &warn_count_attr.attr, NULL);
122
+ return 0;
123
+}
124
+late_initcall(kernel_panic_sysfs_init);
125
+#endif
72126
73127 static long no_blink(int state)
74128 {
....@@ -166,6 +220,19 @@
166220 ftrace_dump(DUMP_ALL);
167221 }
168222
223
+void check_panic_on_warn(const char *origin)
224
+{
225
+ unsigned int limit;
226
+
227
+ if (panic_on_warn)
228
+ panic("%s: panic_on_warn set ...\n", origin);
229
+
230
+ limit = READ_ONCE(warn_limit);
231
+ if (atomic_inc_return(&warn_count) >= limit && limit)
232
+ panic("%s: system warned too often (kernel.warn_limit is %d)",
233
+ origin, limit);
234
+}
235
+
169236 /**
170237 * panic - halt the system
171238 * @fmt: The text string to print
....@@ -182,6 +249,16 @@
182249 int state = 0;
183250 int old_cpu, this_cpu;
184251 bool _crash_kexec_post_notifiers = crash_kexec_post_notifiers;
252
+
253
+ if (panic_on_warn) {
254
+ /*
255
+ * This thread may hit another WARN() in the panic path.
256
+ * Resetting this prevents additional WARN() from panicking the
257
+ * system on this thread. Other threads are blocked by the
258
+ * panic_mutex in panic().
259
+ */
260
+ panic_on_warn = 0;
261
+ }
185262
186263 /*
187264 * Disable local interrupts. This will prevent panic_smp_self_stop
....@@ -594,16 +671,7 @@
594671 if (regs)
595672 show_regs(regs);
596673
597
- if (panic_on_warn) {
598
- /*
599
- * This thread may hit another WARN() in the panic path.
600
- * Resetting this prevents additional WARN() from panicking the
601
- * system on this thread. Other threads are blocked by the
602
- * panic_mutex in panic().
603
- */
604
- panic_on_warn = 0;
605
- panic("panic_on_warn set ...\n");
606
- }
674
+ check_panic_on_warn("kernel");
607675
608676 if (!regs)
609677 dump_stack();