From: "Daniel P. Berrangé" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Marc-André Lureau" <marcandre.lureau@redhat.com>,
"Michael Roth" <michael.roth@amd.com>,
"Philippe Mathieu-Daudé" <philmd@oss.qualcomm.com>,
"Fabiano Rosas" <farosas@suse.de>,
"Richard Henderson" <richard.henderson@linaro.org>,
"Dr. David Alan Gilbert" <dave@treblig.org>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Markus Armbruster" <armbru@redhat.com>,
"Pierrick Bouvier" <pierrick.bouvier@oss.qualcomm.com>,
"Eric Blake" <eblake@redhat.com>,
"Daniel P. Berrangé" <berrange@redhat.com>,
"Laurent Vivier" <lvivier@redhat.com>
Subject: [PATCH 20/21] qtest: add 'crash' command to generate 'authentic' process crashes
Date: Thu, 15 Oct 2026 12:20:43 +0100 [thread overview]
Message-ID: <20261015112044.1999748-21-berrange@redhat.com> (raw)
In-Reply-To: <20261015112044.1999748-1-berrange@redhat.com>
The 'crash' command provides a mechanism to generate process crashes,
which serve to test the signal catching and handling facilities in
a more authentic manner than simply running 'raise(SIG..)' against
ourself.
Available usage is
crash null-pointer -> SIGSEGV on null pointer
crash invalid-addr -> SIGSEGV on derefence invalid address
crash mapping-not-backed -> SIGBUS on writing to map with no storage
crash bad-alignment -> SIGBUS on unaligned data write
crash fpe-div-zero -> SIGFPE on floating point divide by zero
crash assert -> SIGABRT on assertion failure
crash illegal-inst -> SIGILL on illegal instruction
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
system/qtest.c | 50 ++++++++++++++++++++++++++++++++++++++++++
tests/qtest/libqtest.c | 26 ++++++++++++++++++++++
tests/qtest/libqtest.h | 16 ++++++++++++++
3 files changed, 92 insertions(+)
diff --git a/system/qtest.c b/system/qtest.c
index 47c954838dd..0ff04cf24e8 100644
--- a/system/qtest.c
+++ b/system/qtest.c
@@ -811,6 +811,56 @@ static void qtest_process_command(CharFrontend *chr, gchar **words)
qtest_sendf(chr, err ? "FAIL %s\n" : "OK\n",
err ? error_get_pretty(err) : NULL);
error_free(err);
+ } else if (strcmp(words[0], "crash") == 0) {
+ if (strcmp(words[1], "null-pointer") == 0) {
+ char *c = (void *)0x0;
+ *c = 'a'; /* SIGSEGV */
+ } else if (strcmp(words[1], "invalid-addr") == 0) {
+ /* Hopefully invalid addr on all supported targets */
+ char *c = (void *)0x12345;
+ *c = 'b'; /* SIGSEGV */
+#ifndef WIN32
+ } else if (strcmp(words[1], "mapping-not-backed") == 0) {
+ char *m;
+ g_autofree char *tmpname = NULL;
+ int tmpfd = g_file_open_tmp("qtestcrash-XXXXXX", &tmpname, NULL);
+ m = (char *)mmap(0, 4, PROT_WRITE, MAP_PRIVATE, tmpfd, 0);
+ unlink(tmpname);
+ assert(m != MAP_FAILED);
+ /*
+ * Since no writes have been made to 'tmpfd', the backing
+ * store is still zero-length, and thus writes should
+ * trigger a bus error
+ */
+ m[0] = 0; /* SIGBUS */
+#if defined(__x86_64__) || defined(__aarch64__)
+ } else if (strcmp(words[1], "bad-alignment") == 0) {
+ /*
+ * XXX: can we assume any other arches will generate
+ * bus errors on unaligned writes ?
+ */
+ char *cptr = g_malloc(sizeof(int) + 1) + 1;
+ int *iptr = (int *)cptr;
+#ifdef __x86_64__
+ /* Turn on alignment checks */
+ __asm__("pushf\norl $0x40000,(%rsp)\npopf");
+#endif
+ *iptr = 42; /* SIGBUS */
+#endif
+#endif
+ } else if (strcmp(words[1], "fpe-div-zero") == 0) {
+ volatile int foo = 1729; /* volatile to stop optimizing */
+ volatile int bar = 0; /* volatile to stop optimizing */
+
+ foo = foo / bar; /* SIGFPE */
+ (void)foo;
+ } else if (strcmp(words[1], "assert") == 0) {
+ assert(1 == 2); /* SIGABRT */
+ } else if (strcmp(words[1], "illegal-inst") == 0) {
+ __builtin_trap(); /* SIGILL */
+ } else {
+ qtest_sendf(chr, "FAIL unsupported crash action '%s'", words[1]);
+ }
} else if (process_command_cb && process_command_cb(chr, words)) {
/* Command got consumed by the callback handler */
} else {
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index e65451171e4..d6ca97b1c11 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -828,6 +828,32 @@ static int qtest_query_target_endianness(QTestState *s)
return big_endian;
}
+static const char *crashtypestr[] = {
+ "null-pointer",
+ "invalid-addr",
+ "mapping-not-backed",
+#if defined(__x86_64__) || defined(__aarch64__)
+ "bad-alignment",
+#endif
+ "fpe-div-zero",
+ "assert",
+ "illegal-inst",
+};
+G_STATIC_ASSERT(G_N_ELEMENTS(crashtypestr) == QTEST_CRASH__MAX);
+
+void qtest_crash(QTestState *s, QTestCrashType type)
+{
+ char buf[1024];
+ ssize_t len;
+ assert(type < QTEST_CRASH__MAX);
+ qtest_sendf(s, "crash %s\n", crashtypestr[type]);
+ len = recv(s->fd, buf, sizeof(buf), 0);
+ if (len != 0) {
+ g_printerr("Expected crash from QEMU but saw qtest reply");
+ abort();
+ }
+}
+
QDict *qtest_qmp_receive(QTestState *s)
{
while (true) {
diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h
index ddcf075e33a..4988e627592 100644
--- a/tests/qtest/libqtest.h
+++ b/tests/qtest/libqtest.h
@@ -1232,4 +1232,20 @@ bool mkimg(const char *file, const char *fmt, unsigned size_mb);
*/
bool qtest_verbose(const char *domain);
+typedef enum {
+ QTEST_CRASH_NULL_POINTER,
+ QTEST_CRASH_INVALID_ADDR,
+ QTEST_CRASH_MAPPING_NOT_BACKED,
+#if defined(__x86_64__) || defined(__aarch64__)
+ QTEST_CRASH_BAD_ALIGNMENT,
+#endif
+ QTEST_CRASH_FPE_DIV_ZERO,
+ QTEST_CRASH_ASSERT,
+ QTEST_CRASH_ILLEGAL_INST,
+
+ QTEST_CRASH__MAX,
+} QTestCrashType;
+
+void qtest_crash(QTestState *s, QTestCrashType type);
+
#endif
--
2.56.0
next prev parent reply other threads:[~2026-10-15 11:22 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 11:20 [PATCH 00/21] system: introduce a live data recorder facility Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 01/21] osdep: add 'ignore_value(x)' macro Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 02/21] system: move SIGBUS signal handling to signal.c Daniel P. Berrangé
2026-10-15 12:15 ` marcandre.lureau
2026-10-15 11:20 ` [PATCH 03/21] system: rename qemu_init_sigbus to qemu_init_crash_signals Daniel P. Berrangé
2026-10-15 12:15 ` marcandre.lureau
2026-10-15 11:20 ` [PATCH 04/21] system: run SIGBUS handler on alternate signal stack Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 05/21] util: expand alternate signal stack to all threads Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 06/21] osdep: provide dummy siginfo_t definition Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 07/21] util: introduce 'tldr', a system data recorder for crash handling Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 08/21] qapi: add 'tldr-dump' command for on-demand data recorder output Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 09/21] system: trigger TLDR crash dump on unhandled SIGBUS Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 10/21] system: simplify signal handler logic Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 11/21] main: allow SIGBUS in the main loop Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 12/21] system: enable SIGBUS handling on non-Linux platforms Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 13/21] system: enable crash dumps on SIGSEGV, SIGILL, SIGFPE and SIGABRT Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 14/21] util: introduce capture of textual messages in data recorder Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 15/21] util: capture warnings and errors in the " Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 16/21] monitor: remove obsolete/redundant exports Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 17/21] monitor: capture monitor commands and events in data recorder Daniel P. Berrangé
2026-10-15 15:57 ` Dr. David Alan Gilbert
2026-10-15 16:11 ` Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 18/21] log: enable directing log messages to " Daniel P. Berrangé
2026-10-15 11:20 ` [PATCH 19/21] tests/qtest: add API to declare an expected crash signal Daniel P. Berrangé
2026-10-15 11:20 ` Daniel P. Berrangé [this message]
2026-10-15 11:20 ` [PATCH 21/21] tests/qtest: add test to validate data recorder on crashes Daniel P. Berrangé
2026-10-15 12:15 ` [PATCH 00/21] system: introduce a live data recorder facility marcandre.lureau
2026-10-15 12:32 ` Daniel P. Berrangé
2026-10-15 17:34 ` Pierrick Bouvier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261015112044.1999748-21-berrange@redhat.com \
--to=berrange@redhat.com \
--cc=armbru@redhat.com \
--cc=dave@treblig.org \
--cc=eblake@redhat.com \
--cc=farosas@suse.de \
--cc=lvivier@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=michael.roth@amd.com \
--cc=pbonzini@redhat.com \
--cc=philmd@oss.qualcomm.com \
--cc=pierrick.bouvier@oss.qualcomm.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.