From nobody Mon Jun 8 17:56:31 2026 Received: from mail-dy1-f173.google.com (mail-dy1-f173.google.com [74.125.82.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 59ED114ABE for ; Wed, 27 May 2026 16:57:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779901021; cv=none; b=mGOCTjeJIN5DowilI15Uv2Fff71t+IaaYRU1tve7rIOzGAczJu8duiv745jijISVVDSVcXO8nbyJWsApQ5Vjsp6SCEtATljWymTbwjsn1udqPqVTQRAWc6fz5tEtMoA1+rAIAvylP7lTQuN3rKFM5dnRz1A6R9NJQUceHiwdMl4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779901021; c=relaxed/simple; bh=b1a3l2GzhzzuUFAWKexdnVCf+dYvofSjRYoMl9iJghA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=N+xVTeFkdUCW+FBtUiT92p2v37YhCGk1d60lpVc8p7lDxdrlssSVl3w0GXhqsBw5wc9nvOzumQKACy/P4UZb5b+fRi89SVWe7y6YmiEPB8aSoEvmHej7UV9fKkkG7Dc10FLKgX2ikFotNpLixQm1qEIMiEqcfyzibUEMkFe6acA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=wbinvd.org; spf=pass smtp.mailfrom=wbinvd.org; dkim=pass (2048-bit key) header.d=wbinvd.org header.i=@wbinvd.org header.b=QSnx/KYZ; arc=none smtp.client-ip=74.125.82.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=wbinvd.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=wbinvd.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=wbinvd.org header.i=@wbinvd.org header.b="QSnx/KYZ" Received: by mail-dy1-f173.google.com with SMTP id 5a478bee46e88-304545f5206so7800444eec.0 for ; Wed, 27 May 2026 09:57:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=wbinvd.org; s=wbinvd; t=1779901019; x=1780505819; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=PJD4qvspWX2V5tElNZ2EYqawCD7Qlw0EpfioN/XHfTI=; b=QSnx/KYZLkP2g9Dd1+l5Op+peQ5ElNiixCoxkCj1HIn8OHcTq4314whaD+f3myoN90 tSgen1BJX0z+yT66LVTzLJgd1jknfd6j4nB4QySQCOeL6bNGaXjfmm5aVOg9Mayw2AfZ C9SQg71kzdV3f/YZWjsWPZ6oWMNj4lVrtOF6wMpjlY3ocXQY+MG1eHhkpeESH+KVnDAZ H6ZuBq6yN/4nC6BhW1p3XHCvLw0gfDPbJI9DVutAYLR9+AgCmrpaFFJe7VsBNBkgmPYm VKG8hs/2J2D0my5uPvyhuYMl4Xtwva5P2CYu/LArSNL2OUITBEowHL+NHjvntiYG/hLg ZYCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779901019; x=1780505819; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=PJD4qvspWX2V5tElNZ2EYqawCD7Qlw0EpfioN/XHfTI=; b=WoYJkdlsqClWGZVZt6WTFza8wwViqU0haRE7g2zCM8SYenq/okrDyFWy3L/LnMYHnL dlr9vr7311nHV5OVxYaQvqa5YXaGWO5CXdszjDPX6HYJDK16paE4u/c+wgVrBBVQoWep m9Ejq9g9xhPjqOAQh+liV88Zj9qRqNbDV311UwCfVJSxlPI9citZmZPs7zTWv+Yczcm4 r10Gh9vbDuRZCYpbboqcE6IoniIYJNDoTcZoLvknILF1AcOklpUKHKDGa3jOXAskR57c Tf/zFmHophvJXMGTWrhyMP1gLWGr8pLBAB9crxlRXZxVIZ0EGLl9sYUvF2zXm0TOrdbv kEOQ== X-Gm-Message-State: AOJu0Yz/14YRgJPJ+ZwcwH6LvSrQW6uRNS9fklbgrIWtgZZemRnqX5UI Zp0IgQFK2TuzAFn4R4tk0fo7QgT/3zbgxxsNak175Cg64xS3094WoQdcg22i1LGA74zvoY88vLF ui5OH X-Gm-Gg: Acq92OF6SC0tpDhOUBtSl4RC+77BHKAHGL2trTcM1dAHqXe+x5+lBVFtxlquYS2XJGG 1ivqOGKmL1S6EHjhwqRjHVemPVfXDnlBGNT036NYqU2+8EkIvmwY1DwQZ9T8SngRyrikXHCzXNJ nY49L6xo4e+D91lsHA3TLGqh3XG25/PVf7adwL+BSGjB6b0+EviOsulfxqlYNWm4PMCveB7Ua3y mVep8saws+sEOW4mW3E7QFEVrOyAduzf8Uk2GmOplTd5ZvwOv39EeN4HVipbRS+kZCzl105qZV3 u7F7+V5UBJFzN/xeY7qW27ft/LPbXaBhAUskJ8Ts9v+9uyu0Py6e1OjvUQAbbXbwFTbi+MllP7O JvC+WmjgOku+X9vY7c6KAdVHUipYPJVOOLy1J+hWdPqohSC5RQXYj6j1Ru+5NeFJSDya3MngbnD mOgqFVFSGq1CrXvPUE5AbhsA== X-Received: by 2002:a05:7300:b104:b0:2dd:6937:79d5 with SMTP id 5a478bee46e88-30448ffc85fmr11200797eec.8.1779901019285; Wed, 27 May 2026 09:56:59 -0700 (PDT) Received: from mozart.vkv.me ([2001:5a8:468b:d015:71db:ce4c:1c9:30]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-304b984d9b5sm2390346eec.7.2026.05.27.09.56.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 May 2026 09:56:58 -0700 (PDT) From: Calvin Owens To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Petr Mladek Subject: [PATCH] lib/test_crash: test module to trigger kernel crashes Date: Wed, 27 May 2026 09:56:44 -0700 Message-ID: <17c774c9032b5ea214b3ceb0c0a008caf2610e30.1779896981.git.calvin@wbinvd.org> X-Mailer: git-send-email 2.47.3 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This test calls panic() from various execution contexts in the kernel, so the user can see if a crash trace is successfully emitted. This is useful for testing console drivers, and can help rule out issues with the console itself when silent reboots or hangs are observed on a particular system. Signed-off-by: Calvin Owens --- I shared this upthread in [1] where it turned out to be useful for netconsole. Petr suggested it might be useful for others, so I've applied his feedback and cleaned everything up a bit more too. It's a superset of what 'echo c > /proc/sysrq-trigger' does, but extending that interface doesn't seem practical. The write() implementation requries the entire string be written in a single syscall: this is pretty common for these debugfs interfaces, so it didn't seem worth the complexity to handle partial writes. But I'm happy to do so if somebody cares :) [1] https://lore.kernel.org/lkml/aMGenGUNcBbRUUf9@pathway.suse.cz/ lib/Kconfig.debug | 18 +++++ lib/Makefile | 1 + lib/test_crash.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 lib/test_crash.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 8ff5adcfe1e0..f3c3ab90fc0c 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1385,6 +1385,24 @@ config TEST_LOCKUP =20 If unsure, say N. =20 +config TEST_CRASH + tristate "Test module to trigger crashes" + help + Expose a file in debugfs which triggers a panic() call in + various kernel execution contexts. + + $ cat /sys/kernel/debug/test_crash + irq + [...] + $ echo "irq" > /sys/kernel/debug/test_crash + Kernel panic - not syncing: User triggered crash in context irq + + This is useful for testing console drivers, and can help rule + out issues with the console itself when silent reboots or + hangs are observed on a particular system. + + If unsure, say N. + endmenu # "Debug lockups and hangs" =20 menu "Scheduler Debugging" diff --git a/lib/Makefile b/lib/Makefile index f33a24bf1c19..e2ac56887dd6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -100,6 +100,7 @@ obj-$(CONFIG_TEST_MEMCAT_P) +=3D test_memcat_p.o obj-$(CONFIG_TEST_OBJAGG) +=3D test_objagg.o obj-$(CONFIG_TEST_MEMINIT) +=3D test_meminit.o obj-$(CONFIG_TEST_LOCKUP) +=3D test_lockup.o +obj-$(CONFIG_TEST_CRASH) +=3D test_crash.o obj-$(CONFIG_TEST_HMM) +=3D test_hmm.o obj-$(CONFIG_TEST_FREE_PAGES) +=3D test_free_pages.o obj-$(CONFIG_TEST_REF_TRACKER) +=3D test_ref_tracker.o diff --git a/lib/test_crash.c b/lib/test_crash.c new file mode 100644 index 000000000000..a72284fbb062 --- /dev/null +++ b/lib/test_crash.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include +#include + +static void crash(const char *context) +{ + panic("User triggered crash in context %s", context); +} + +#define CRASH_TESTCASE_LIST \ + X(irq) \ + X(bh) \ + X(user) \ + X(user_nobh) \ + X(user_noirq) \ + X(user_nopreempt) \ + X(user_rculock) \ + X(user_conlock) \ + X(user_rtnllock) + +static void crash_irq_work(struct irq_work *work) +{ + crash("irq"); +} + +static struct irq_work irq_crash_work; + +static void crash_irq(void) +{ + if (!irq_work_queue(&irq_crash_work)) + return; + + irq_work_sync(&irq_crash_work); +} + +static void crash_bh_work(struct work_struct *work) +{ + crash("bh"); +} + +static struct work_struct bh_crash_work; + +static void crash_bh(void) +{ + if (!queue_work(system_bh_wq, &bh_crash_work)) + return; + + flush_work(&bh_crash_work); +} + +static void crash_user(void) +{ + crash("user"); +} + +static void crash_user_nobh(void) +{ + local_bh_disable(); + crash("user with bh disabled"); +} + +static void crash_user_noirq(void) +{ + local_irq_disable(); + crash("user with irqs disabled"); +} + +static void crash_user_nopreempt(void) +{ + preempt_disable(); + crash("user with preemption disabled"); +} + +static void crash_user_rculock(void) +{ + rcu_read_lock(); + crash("user in RCU critical section"); +} + +static void crash_user_conlock(void) +{ + console_lock(); + crash("user with console_lock held"); +} + +static void crash_user_rtnllock(void) +{ + rtnl_lock(); + crash("user with rtnl_lock held"); +} + +struct testcase { + void (*fn)(void); + const char *str; +}; + +#define X(name) (struct testcase){.fn =3D crash_##name, .str =3D #name "\n= " }, +static const struct testcase testcases[] =3D { + CRASH_TESTCASE_LIST +}; +#undef X + +static ssize_t test_crash_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) +{ + char tmp[16] =3D {0}; + int i; + + if (copy_from_user(tmp, buf, min(count, sizeof(tmp) - 1)) !=3D 0) + return -EFAULT; + + for (i =3D 0; i < ARRAY_SIZE(testcases); i++) { + const struct testcase *ctx =3D testcases + i; + + if (!strcmp(ctx->str, tmp)) + ctx->fn(); + } + + return -EINVAL; +} + +static ssize_t test_crash_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + #define X(name) #name "\n" + static const char help_string[] =3D CRASH_TESTCASE_LIST; + #undef X + static const int help_string_len =3D sizeof(help_string) - 1; + int off, len, done; + + off =3D clamp(*pos, 0, help_string_len); + if (off =3D=3D help_string_len) + return 0; + + len =3D min(count, help_string_len - off); + done =3D len - copy_to_user(buf, help_string + off, len); + *pos =3D off + done; + + return done ?: -EFAULT; +} + +static const struct file_operations test_crash_fops =3D { + .write =3D test_crash_write, + .read =3D test_crash_read, +}; + +static struct dentry *test_crash_dentry; + +static int __init setup_test_crash(void) +{ + INIT_WORK(&bh_crash_work, crash_bh_work); + init_irq_work(&irq_crash_work, crash_irq_work); + test_crash_dentry =3D debugfs_create_file("test_crash", 0600, NULL, NULL, + &test_crash_fops); + if (IS_ERR(test_crash_dentry)) + return PTR_ERR(test_crash_dentry); + + return 0; +} +late_initcall(setup_test_crash); + +static void __exit cleanup_test_crash(void) +{ + debugfs_remove(test_crash_dentry); +} +module_exit(cleanup_test_crash); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Calvin Owens "); +MODULE_DESCRIPTION("Test module to trigger crashes"); --=20 2.47.3