| From a2b1c03ad605cd2d8e8122d340905e1118fec43e Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 1 Feb 2023 20:42:52 -0800 |
| Subject: panic: Introduce warn_limit |
| |
| From: Kees Cook <keescook@chromium.org> |
| |
| commit 9fc9e278a5c0b708eeffaf47d6eb0c82aa74ed78 upstream. |
| |
| Like oops_limit, add warn_limit for limiting the number of warnings when |
| panic_on_warn is not set. |
| |
| Cc: Jonathan Corbet <corbet@lwn.net> |
| Cc: Andrew Morton <akpm@linux-foundation.org> |
| Cc: Baolin Wang <baolin.wang@linux.alibaba.com> |
| Cc: "Jason A. Donenfeld" <Jason@zx2c4.com> |
| Cc: Eric Biggers <ebiggers@google.com> |
| Cc: Huang Ying <ying.huang@intel.com> |
| Cc: Petr Mladek <pmladek@suse.com> |
| Cc: tangmeng <tangmeng@uniontech.com> |
| Cc: "Guilherme G. Piccoli" <gpiccoli@igalia.com> |
| Cc: Tiezhu Yang <yangtiezhu@loongson.cn> |
| Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| Cc: linux-doc@vger.kernel.org |
| Reviewed-by: Luis Chamberlain <mcgrof@kernel.org> |
| Signed-off-by: Kees Cook <keescook@chromium.org> |
| Link: https://lore.kernel.org/r/20221117234328.594699-5-keescook@chromium.org |
| Signed-off-by: Eric Biggers <ebiggers@google.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| Documentation/admin-guide/sysctl/kernel.rst | 10 ++++++++ |
| kernel/panic.c | 27 +++++++++++++++++++++ |
| 2 files changed, 37 insertions(+) |
| |
| diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst |
| index bc31c4a88f20..568c24ff00a7 100644 |
| --- a/Documentation/admin-guide/sysctl/kernel.rst |
| +++ b/Documentation/admin-guide/sysctl/kernel.rst |
| @@ -1186,6 +1186,16 @@ entry will default to 2 instead of 0. |
| 2 Unprivileged calls to ``bpf()`` are disabled |
| = ============================================================= |
| |
| + |
| +warn_limit |
| +========== |
| + |
| +Number of kernel warnings after which the kernel should panic when |
| +``panic_on_warn`` is not set. Setting this to 0 disables checking |
| +the warning count. Setting this to 1 has the same effect as setting |
| +``panic_on_warn=1``. The default value is 0. |
| + |
| + |
| watchdog: |
| ========= |
| |
| diff --git a/kernel/panic.c b/kernel/panic.c |
| index 7e4900eb25ac..8f72305dd501 100644 |
| --- a/kernel/panic.c |
| +++ b/kernel/panic.c |
| @@ -44,6 +44,7 @@ static int pause_on_oops_flag; |
| static DEFINE_SPINLOCK(pause_on_oops_lock); |
| bool crash_kexec_post_notifiers; |
| int panic_on_warn __read_mostly; |
| +static unsigned int warn_limit __read_mostly; |
| |
| int panic_timeout = CONFIG_PANIC_TIMEOUT; |
| EXPORT_SYMBOL_GPL(panic_timeout); |
| @@ -60,6 +61,26 @@ ATOMIC_NOTIFIER_HEAD(panic_notifier_list); |
| |
| EXPORT_SYMBOL(panic_notifier_list); |
| |
| +#ifdef CONFIG_SYSCTL |
| +static struct ctl_table kern_panic_table[] = { |
| + { |
| + .procname = "warn_limit", |
| + .data = &warn_limit, |
| + .maxlen = sizeof(warn_limit), |
| + .mode = 0644, |
| + .proc_handler = proc_douintvec, |
| + }, |
| + { } |
| +}; |
| + |
| +static __init int kernel_panic_sysctls_init(void) |
| +{ |
| + register_sysctl_init("kernel", kern_panic_table); |
| + return 0; |
| +} |
| +late_initcall(kernel_panic_sysctls_init); |
| +#endif |
| + |
| static long no_blink(int state) |
| { |
| return 0; |
| @@ -158,8 +179,14 @@ static void panic_print_sys_info(void) |
| |
| void check_panic_on_warn(const char *origin) |
| { |
| + static atomic_t warn_count = ATOMIC_INIT(0); |
| + |
| if (panic_on_warn) |
| panic("%s: panic_on_warn set ...\n", origin); |
| + |
| + if (atomic_inc_return(&warn_count) >= READ_ONCE(warn_limit) && warn_limit) |
| + panic("%s: system warned too often (kernel.warn_limit is %d)", |
| + origin, warn_limit); |
| } |
| |
| /** |
| -- |
| 2.39.0 |
| |