Linux Test Project
 help / color / mirror / Atom feed
* Re: [LTP] lib: Add SAFE_FILE_VPRINTF()
  2026-09-09 10:04 [LTP] [PATCH v9 1/3] " Andrea Cervesato
@ 2026-09-09 10:35 ` linuxtestproject.agent
  2026-09-09 12:05   ` Andrea Cervesato via ltp
  0 siblings, 1 reply; 14+ messages in thread
From: linuxtestproject.agent @ 2026-09-09 10:35 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi Andrea,

On Wed, 9 Sep 2026 12:04:48 +0200, Andrea Cervesato <andrea.cervesato@suse.com> wrote:
> [PATCH 1/3] lib: Add SAFE_FILE_VPRINTF()

--- [PATCH 1/3] ---

> +#define SAFE_FILE_VPRINTF(path, fmt, va) \
> +	safe_file_vprintf(__FILE__, __LINE__, NULL, \
> +			  (path), (fmt), (va))

Missing kernel-doc comment for SAFE_FILE_VPRINTF(). Public macros added to
include/tst_safe_file_ops.h must be documented with kernel-doc syntax
recognized by linuxdoc.

--- [PATCH 3/3] ---

> +	if (type == NT_PRPSINFO && descsz >= sizeof(struct elf_prpsinfo)) {
> +		struct elf_prpsinfo info;
> +
> +		memcpy(&info, desc, sizeof(info));
> +		TST_EXP_EQ_STRN(info.pr_fname, "coredump02", sizeof("coredump02"));
> +
> +		prpsinfo_seen = 1;

Using sizeof("coredump02") as the length argument triggers a
-Wsizeof-pointer-memaccess compiler warning from TST_EXP_EQ_STRN(). Use
TST_EXP_EQ_STR(info.pr_fname, "coredump02") since pr_fname is
null-terminated, or pass sizeof(info.pr_fname).

Verdict - Needs revision

---
Note:

The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.

Regards,
LTP AI Reviewer

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [LTP] lib: Add SAFE_FILE_VPRINTF()
  2026-09-09 10:35 ` [LTP] " linuxtestproject.agent
@ 2026-09-09 12:05   ` Andrea Cervesato via ltp
  0 siblings, 0 replies; 14+ messages in thread
From: Andrea Cervesato via ltp @ 2026-09-09 12:05 UTC (permalink / raw)
  To: linuxtestproject.agent; +Cc: ltp

> Hi Andrea,
> 
> On Wed, 9 Sep 2026 12:04:48 +0200, Andrea Cervesato <andrea.cervesato@suse.com> wrote:
> > [PATCH 1/3] lib: Add SAFE_FILE_VPRINTF()
> 
> --- [PATCH 1/3] ---
> 
> > +#define SAFE_FILE_VPRINTF(path, fmt, va) \
> > +	safe_file_vprintf(__FILE__, __LINE__, NULL, \
> > +			  (path), (fmt), (va))
> 
> Missing kernel-doc comment for SAFE_FILE_VPRINTF(). Public macros added to
> include/tst_safe_file_ops.h must be documented with kernel-doc syntax
> recognized by linuxdoc.
> 
> --- [PATCH 3/3] ---
> 
> > +	if (type == NT_PRPSINFO && descsz >= sizeof(struct elf_prpsinfo)) {
> > +		struct elf_prpsinfo info;
> > +
> > +		memcpy(&info, desc, sizeof(info));
> > +		TST_EXP_EQ_STRN(info.pr_fname, "coredump02", sizeof("coredump02"));
> > +
> > +		prpsinfo_seen = 1;
> 
> Using sizeof("coredump02") as the length argument triggers a
> -Wsizeof-pointer-memaccess compiler warning from TST_EXP_EQ_STRN(). Use
> TST_EXP_EQ_STR(info.pr_fname, "coredump02") since pr_fname is
> null-terminated, or pass sizeof(info.pr_fname).

both correct, im gonna send a patch

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [LTP] [PATCH v10 0/3] coredump testing suite
@ 2026-09-09 12:07 Andrea Cervesato
  2026-09-09 12:07 ` [LTP] [PATCH v10 1/3] lib: Add SAFE_FILE_VPRINTF() Andrea Cervesato
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Andrea Cervesato @ 2026-09-09 12:07 UTC (permalink / raw)
  To: Linux Test Project

Add a simple coredump01 test that simulate a coredump and verify that it
actually works. This is a small coverage that is missing inside LTP
testing suite.

Add a coredump02 test that verifies ELF data after a coredump.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
Changes in v10:
- add kernel-doc documentation for SAFE_FILE_VPRINTF()
- fix checkpatch formatting warnings in SAFE_FILE_VPRINTF() headers
- use TST_EXP_EQ_STR() to compare executable name in coredump02
- Link to v9: https://lore.kernel.org/20260909-coredump-v9-0-6b0ee752f57e@suse.com

Changes in v9:
- add SAFE_FILE_VPRINTF() helper in the test library
- factor out shared test logic into coredump_common.h
- use SAFE_FILE_VPRINTF() in set_pattern() to avoid intermediate buffers
- use struct tcase array for test case dispatch in coredump01
- return early in coredump01 if core file is missing before parsing ELF
- document root requirement in coredump02 description
- assert exactly one PT_NOTE segment in coredump02
- validate file bounds for PT_LOAD segments in coredump02
- use TST_EXP_EQ_STRN() to compare executable name in coredump02
- copy unaligned note descriptors to local stack structs to ensure 8-byte alignment
- Link to v8: https://lore.kernel.org/20260908-coredump-v8-0-591f96004543@suse.com

Changes in v8:
- check PT_LOAD data
- Link to v7: https://lore.kernel.org/20260904-coredump-v7-0-a32b7ca1acea@suse.com

Changes in v7:
- define a common header for the testing suite
- update commit message for coredump02
- Link to v6: https://lore.kernel.org/20260904-coredump-v6-0-b8e3947cc646@suse.com

Changes in v6:
- coredump01 check Elf
- add coredump02 test for Elf validation
- Link to v5: https://lore.kernel.org/20260903-coredump-v5-1-2ea86fa29107@suse.com

Changes in v5:
- resolve path from root for helper
- Link to v4: https://lore.kernel.org/20260902-coredump-v4-1-3f511ea1c96a@suse.com

Changes in v4:
- read back core_pattern after writing and abort with TBROK on mismatch
- read CONFIG_STATIC_USERMODEHELPER once in setup() and cache the result
- remove namespace visibility scaffolding and skip logic from verify_pipe_pattern()
- resolve helper path with tst_get_path() instead of /proc/self/exe readlink
- Link to v3: https://lore.kernel.org/20260824-coredump-v3-1-6429da674718@suse.com

Changes in v3:
- check for CONFIG_COREDUMP=y
- Link to v2: https://lore.kernel.org/20260824-coredump-v2-1-42428acf5216@suse.com

Changes in v2:
- fix CI agent spotted errors
- Link to v1: https://lore.kernel.org/20260820-coredump-v1-1-7ce51603cefb@suse.com

To: Linux Test Project <ltp@lists.linux.it>

---
Andrea Cervesato (3):
      lib: Add SAFE_FILE_VPRINTF()
      coredump01: New core_pattern specifiers test
      coredump02: Verify ELF structure and notes

 include/safe_file_ops_fn.h                    |   6 +
 include/tst_safe_file_ops.h                   |  14 ++
 lib/safe_file_ops.c                           |   2 +-
 runtest/kernel_misc                           |   2 +
 testcases/kernel/Makefile                     |   1 +
 testcases/kernel/coredump/.gitignore          |   3 +
 testcases/kernel/coredump/Makefile            |   7 +
 testcases/kernel/coredump/coredump01.c        | 162 +++++++++++++++++++++
 testcases/kernel/coredump/coredump01_helper.c |  73 ++++++++++
 testcases/kernel/coredump/coredump02.c        | 196 ++++++++++++++++++++++++++
 testcases/kernel/coredump/coredump_common.h   |  52 +++++++
 11 files changed, 517 insertions(+), 1 deletion(-)
---
base-commit: 043bdc49af410f55ece6f61abcdaba7d9580f86a
change-id: 20260820-coredump-22fc731bde08

Best regards,
--  
Andrea Cervesato <andrea.cervesato@suse.com>


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [LTP] [PATCH v10 1/3] lib: Add SAFE_FILE_VPRINTF()
  2026-09-09 12:07 [LTP] [PATCH v10 0/3] coredump testing suite Andrea Cervesato
@ 2026-09-09 12:07 ` Andrea Cervesato
  2026-09-09 13:40   ` [LTP] " linuxtestproject.agent
  2026-09-09 12:07 ` [LTP] [PATCH v10 2/3] coredump01: New core_pattern specifiers test Andrea Cervesato
  2026-09-09 12:07 ` [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes Andrea Cervesato
  2 siblings, 1 reply; 14+ messages in thread
From: Andrea Cervesato @ 2026-09-09 12:07 UTC (permalink / raw)
  To: Linux Test Project

From: Andrea Cervesato <andrea.cervesato@suse.com>

Expose safe_file_vprintf() as SAFE_FILE_VPRINTF() macro to allow
formatting directly into files with a va_list without requiring
an intermediate buffer.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 include/safe_file_ops_fn.h  |  6 ++++++
 include/tst_safe_file_ops.h | 14 ++++++++++++++
 lib/safe_file_ops.c         |  2 +-
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/include/safe_file_ops_fn.h b/include/safe_file_ops_fn.h
index 223fb0d68..1edaac794 100644
--- a/include/safe_file_ops_fn.h
+++ b/include/safe_file_ops_fn.h
@@ -20,6 +20,7 @@
 
 #include <sys/stat.h>
 #include <time.h>
+#include <stdarg.h>
 
 #include "lapi/utime.h"
 
@@ -62,6 +63,11 @@ void safe_file_printf(const char *file, const int lineno,
                       const char *path, const char *fmt, ...)
                       __attribute__ ((format (printf, 5, 6)));
 
+void safe_file_vprintf(const char *file, const int lineno,
+		       void (*cleanup_fn)(void),
+		       const char *path, const char *fmt, va_list va)
+	__attribute__ ((format (printf, 5, 0)));
+
 void safe_try_file_printf(const char *file, const int lineno,
 	void (*cleanup_fn)(void), const char *path, const char *fmt, ...)
 	__attribute__ ((format (printf, 5, 6)));
diff --git a/include/tst_safe_file_ops.h b/include/tst_safe_file_ops.h
index 73ebd2ab8..0fc1a160c 100644
--- a/include/tst_safe_file_ops.h
+++ b/include/tst_safe_file_ops.h
@@ -65,6 +65,20 @@ void safe_file_read_str(const char *file, const int lineno,
 	safe_file_printf(__FILE__, __LINE__, NULL, \
 	                 (path), (fmt), ## __VA_ARGS__)
 
+/**
+ * SAFE_FILE_VPRINTF() - Formats and writes a va_list argument into a file.
+ *
+ * Writes formatted output to the file at @path using the format string @fmt
+ * and variable arguments @va. Aborts the test with TBROK on failure.
+ *
+ * @path: A path to a file.
+ * @fmt: A printf format string.
+ * @va: A variable argument list.
+ */
+#define SAFE_FILE_VPRINTF(path, fmt, va) \
+	safe_file_vprintf(__FILE__, __LINE__, NULL, \
+			  (path), (fmt), (va))
+
 /* Same as SAFE_FILE_PRINTF() but returns quietly if the path doesn't exist */
 #define SAFE_TRY_FILE_PRINTF(path, fmt, ...) \
 	safe_try_file_printf(__FILE__, __LINE__, NULL, \
diff --git a/lib/safe_file_ops.c b/lib/safe_file_ops.c
index 19da1fd97..1069a017f 100644
--- a/lib/safe_file_ops.c
+++ b/lib/safe_file_ops.c
@@ -280,7 +280,7 @@ err:
 	return 1;
 }
 
-static void safe_file_vprintf(const char *file, const int lineno,
+void safe_file_vprintf(const char *file, const int lineno,
 	void (*cleanup_fn)(void), const char *path, const char *fmt,
 	va_list va)
 {

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [LTP] [PATCH v10 2/3] coredump01: New core_pattern specifiers test
  2026-09-09 12:07 [LTP] [PATCH v10 0/3] coredump testing suite Andrea Cervesato
  2026-09-09 12:07 ` [LTP] [PATCH v10 1/3] lib: Add SAFE_FILE_VPRINTF() Andrea Cervesato
@ 2026-09-09 12:07 ` Andrea Cervesato
  2026-09-09 12:07 ` [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes Andrea Cervesato
  2 siblings, 0 replies; 14+ messages in thread
From: Andrea Cervesato @ 2026-09-09 12:07 UTC (permalink / raw)
  To: Linux Test Project

From: Andrea Cervesato <andrea.cervesato@suse.com>

LTP has no coverage for the core_pattern specifiers expansion, neither
for the pipe flavor of core_pattern, where the kernel spawns a user
space helper and writes the core dump into its standard input.

The new test verifies that %e, %p and %s are expanded both in the core
file name and in the arguments of a piped helper, checking also that
the helper really receives an ELF core dump.

Root is required to rewrite the system wide core_pattern, which is
restored by the test library on all exit paths.

Reviewed-by: Li Wang <li.wang@linux.dev>
Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/kernel_misc                           |   1 +
 testcases/kernel/Makefile                     |   1 +
 testcases/kernel/coredump/.gitignore          |   2 +
 testcases/kernel/coredump/Makefile            |   7 ++
 testcases/kernel/coredump/coredump01.c        | 162 ++++++++++++++++++++++++++
 testcases/kernel/coredump/coredump01_helper.c |  73 ++++++++++++
 testcases/kernel/coredump/coredump_common.h   |  52 +++++++++
 7 files changed, 298 insertions(+)

diff --git a/runtest/kernel_misc b/runtest/kernel_misc
index cc3562cb7..ecf9ee2a2 100644
--- a/runtest/kernel_misc
+++ b/runtest/kernel_misc
@@ -17,3 +17,4 @@ zram02 zram02.sh
 zram03 zram03
 umip_basic_test umip_basic_test
 aslr01 aslr01
+coredump01 coredump01
diff --git a/testcases/kernel/Makefile b/testcases/kernel/Makefile
index ac816e4e8..6b303c14b 100644
--- a/testcases/kernel/Makefile
+++ b/testcases/kernel/Makefile
@@ -19,6 +19,7 @@ SUBDIRS			+= lib
 SUBDIRS			+= connectors \
 			   containers \
 			   controllers \
+			   coredump \
 			   crypto \
 			   device-drivers \
 			   firmware \
diff --git a/testcases/kernel/coredump/.gitignore b/testcases/kernel/coredump/.gitignore
new file mode 100644
index 000000000..cd0b51700
--- /dev/null
+++ b/testcases/kernel/coredump/.gitignore
@@ -0,0 +1,2 @@
+/coredump01
+/coredump01_helper
diff --git a/testcases/kernel/coredump/Makefile b/testcases/kernel/coredump/Makefile
new file mode 100644
index 000000000..951a3e976
--- /dev/null
+++ b/testcases/kernel/coredump/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2026 Linux Test Project
+
+top_srcdir		?= ../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/coredump/coredump01.c b/testcases/kernel/coredump/coredump01.c
new file mode 100644
index 000000000..c4fb92e4d
--- /dev/null
+++ b/testcases/kernel/coredump/coredump01.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Linux Test Project
+ */
+
+/*\
+ * Verify that the kernel expands the :manpage:`core(5)` specifiers %e
+ * (executable name), %p (PID) and %s (signal number) when it creates a
+ * core dump.
+ *
+ * Both flavors of ``/proc/sys/kernel/core_pattern`` are tested:
+ *
+ * - a plain file name, where the specifiers become part of the core file
+ *   name
+ * - a pipe to a user space helper, where the specifiers are expanded in
+ *   the helper arguments and the core dump is written to the helper
+ *   standard input
+ *
+ * The test needs root because it rewrites the system wide core_pattern.
+ * The original value is saved and restored by the test library on all
+ * exit paths.
+ *
+ * [Algorithm]
+ *
+ * - Point core_pattern into the test temporary directory
+ * - Fork a child which aborts itself to produce a core dump
+ * - For the file pattern check that ``core.<exe>.<pid>.<signal>`` was created
+ * - For the pipe pattern check the arguments the helper was called with
+ *   and that it received an ELF core dump on its standard input
+ */
+
+#include "coredump_common.h"
+#include "tst_kconfig.h"
+
+#define HELPER "coredump01_helper"
+#define HELPER_TIMEOUT 10
+
+static char helper_path[PATH_MAX];
+static int static_usermodehelper;
+
+/*
+ * e_ident[] and e_type live at the same file offset in ELF32 and ELF64,
+ * so we can validate both without picking a class.
+ */
+static void verify_elf_core(const char *path)
+{
+	unsigned char hdr[EI_NIDENT + sizeof(Elf32_Half)];
+	Elf32_Half e_type;
+	int fd;
+
+	fd = SAFE_OPEN(path, O_RDONLY);
+	SAFE_READ(1, fd, hdr, sizeof(hdr));
+	SAFE_CLOSE(fd);
+
+	memcpy(&e_type, hdr + EI_NIDENT, sizeof(e_type));
+
+	TST_EXP_EXPR(!memcmp(hdr, ELFMAG, SELFMAG), "%s starts with ELF magic", path);
+	TST_EXP_EQ_LI(e_type, ET_CORE);
+}
+
+static void verify_file_pattern(void)
+{
+	char dump[PATH_MAX + 32];
+	pid_t pid;
+
+	set_pattern("%s/core.%%e.%%p.%%s", cwd);
+
+	pid = crash_child();
+
+	snprintf(dump, sizeof(dump), "%s/core.coredump01.%d.%d", cwd, pid, SIGABRT);
+
+	TST_EXP_PASS(access(dump, F_OK), "core.%%e.%%p.%%s expanded to core.coredump01.%d.%d",
+		     pid, SIGABRT);
+	if (!TST_PASS)
+		return;
+
+	verify_elf_core(dump);
+}
+
+static void verify_pipe_pattern(void)
+{
+	char res[PATH_MAX + 32], exe[PATH_MAX];
+	int pid_seen, sig_seen, elf, et_core;
+	long long bytes;
+	pid_t pid;
+
+	if (static_usermodehelper) {
+		tst_res(TCONF, "CONFIG_STATIC_USERMODEHELPER is enabled, skipping pipe core_pattern");
+		return;
+	}
+
+	set_pattern("|%s %%e %%p %%s %s/res.%%p", helper_path, cwd);
+
+	pid = crash_child();
+
+	snprintf(res, sizeof(res), "%s/res.%d", cwd, pid);
+
+	/* the kernel spawns the helper asynchronously */
+	if (TST_RETRY_FN_EXP_BACKOFF(access(res, F_OK), TST_RETVAL_EQ0, HELPER_TIMEOUT)) {
+		tst_res(TFAIL, "%s did not report any core dump", HELPER);
+		return;
+	}
+
+	SAFE_FILE_SCANF(res, "exe=%15s pid=%d sig=%d bytes=%lld elf=%d et_core=%d",
+			exe, &pid_seen, &sig_seen, &bytes, &elf, &et_core);
+
+	TST_EXP_EQ_STR(exe, "coredump01");
+	TST_EXP_EQ_LI(pid_seen, pid);
+	TST_EXP_EQ_LI(sig_seen, SIGABRT);
+	TST_EXP_EXPR(elf && bytes > 0, "%s read %lli bytes of ELF core dump", HELPER, bytes);
+	TST_EXP_EQ_LI(et_core, 1);
+}
+
+static struct tcase {
+	void (*verify_fn)(void);
+	const char *desc;
+} tcases[] = {
+	{verify_file_pattern, "file core_pattern"},
+	{verify_pipe_pattern, "pipe core_pattern"},
+};
+
+static void run(unsigned int n)
+{
+	struct tcase *tc = &tcases[n];
+
+	tst_res(TINFO, "Testing %s", tc->desc);
+	tc->verify_fn();
+}
+
+static void setup(void)
+{
+	char path[PATH_MAX];
+	struct tst_kconfig_var kconfig = TST_KCONFIG_INIT("CONFIG_STATIC_USERMODEHELPER");
+
+	coredump_setup();
+
+	tst_kconfig_read(&kconfig, 1);
+	static_usermodehelper = (kconfig.choice == 'y');
+
+	if (tst_get_path(HELPER, path, sizeof(path)))
+		tst_brk(TCONF, "'%s' not found in $PATH", HELPER);
+
+	if (!realpath(path, helper_path))
+		tst_brk(TBROK | TERRNO, "realpath(%s) failed", path);
+}
+
+static struct tst_test test = {
+	.test = run,
+	.tcnt = ARRAY_SIZE(tcases),
+	.setup = setup,
+	.needs_root = 1,
+	.needs_tmpdir = 1,
+	.forks_child = 1,
+	.needs_kconfigs = (const char* []) {
+		"CONFIG_COREDUMP=y",
+		NULL,
+	},
+	.save_restore = (const struct tst_path_val[]) {
+		{PATH_KERN_CORE_PATTERN, NULL, TST_SR_TCONF},
+		{}
+	},
+};
diff --git a/testcases/kernel/coredump/coredump01_helper.c b/testcases/kernel/coredump/coredump01_helper.c
new file mode 100644
index 000000000..b454de476
--- /dev/null
+++ b/testcases/kernel/coredump/coredump01_helper.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Linux Test Project
+ */
+
+/*
+ * Core dump collector for the piped core_pattern tested by coredump01.
+ *
+ * Avoiding the LTP API here is correct, since the kernel spawns the helper
+ * through ``call_usermodehelper()`` without the LTP IPC environment.
+ *
+ * The helper is called as:
+ *
+ *	coredump01_helper <exe> <pid> <signal> <result file>
+ *
+ * and stores what it received in the result file, which is published with
+ * :manpage:`rename()` so that the polling test never reads a partial line.
+ */
+
+#include <elf.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+	unsigned char buf[4096], hdr[EI_NIDENT + sizeof(Elf32_Half)];
+	char tmp[PATH_MAX];
+	unsigned int hdr_len = 0;
+	long long bytes = 0;
+	ssize_t rval, i;
+	int fd, elf = 0, et_core = 0;
+	Elf32_Half e_type;
+
+	if (argc < 5)
+		return 1;
+
+	/*
+	 * The ELF header is only meaningful at the very beginning of the
+	 * stream. Collect enough bytes to read e_ident and e_type.
+	 */
+	while ((rval = read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
+		for (i = 0; i < rval && hdr_len < sizeof(hdr); i++)
+			hdr[hdr_len++] = buf[i];
+
+		bytes += rval;
+	}
+
+	if (rval < 0)
+		return 1;
+
+	if (hdr_len >= sizeof(hdr)) {
+		if (!memcmp(hdr, ELFMAG, SELFMAG))
+			elf = 1;
+		memcpy(&e_type, hdr + EI_NIDENT, sizeof(e_type));
+		et_core = (e_type == ET_CORE);
+	}
+
+	snprintf(tmp, sizeof(tmp), "%s.tmp", argv[4]);
+
+	fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+	if (fd < 0)
+		return 1;
+
+	dprintf(fd, "exe=%s pid=%s sig=%s bytes=%lld elf=%d et_core=%d\n",
+		argv[1], argv[2], argv[3], bytes, elf, et_core);
+
+	close(fd);
+
+	return rename(tmp, argv[4]) ? 1 : 0;
+}
diff --git a/testcases/kernel/coredump/coredump_common.h b/testcases/kernel/coredump/coredump_common.h
new file mode 100644
index 000000000..bccb4bcaa
--- /dev/null
+++ b/testcases/kernel/coredump/coredump_common.h
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Linux Test Project
+ */
+
+#ifndef COREDUMP_COMMON_H
+#define COREDUMP_COMMON_H
+
+#include <elf.h>
+#include <sys/wait.h>
+
+#include "tst_test.h"
+#include "lapi/prctl.h"
+
+static char cwd[PATH_MAX];
+
+static void set_pattern(const char *fmt, ...)
+{
+	va_list va;
+
+	va_start(va, fmt);
+	SAFE_FILE_VPRINTF(PATH_KERN_CORE_PATTERN, fmt, va);
+	va_end(va);
+}
+
+static pid_t crash_child(void)
+{
+	int status;
+	pid_t pid;
+
+	pid = SAFE_FORK();
+	if (!pid)
+		abort();
+
+	SAFE_WAITPID(pid, &status, 0);
+
+	if (!WIFSIGNALED(status) || !WCOREDUMP(status))
+		tst_brk(TFAIL, "Child did not dump core");
+
+	return pid;
+}
+
+static void coredump_setup(void)
+{
+	struct rlimit rl = {RLIM_INFINITY, RLIM_INFINITY};
+
+	SAFE_SETRLIMIT(RLIMIT_CORE, &rl);
+	SAFE_PRCTL(PR_SET_DUMPABLE, 1, 0, 0, 0);
+	SAFE_GETCWD(cwd, sizeof(cwd));
+}
+
+#endif /* COREDUMP_COMMON_H */

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes
  2026-09-09 12:07 [LTP] [PATCH v10 0/3] coredump testing suite Andrea Cervesato
  2026-09-09 12:07 ` [LTP] [PATCH v10 1/3] lib: Add SAFE_FILE_VPRINTF() Andrea Cervesato
  2026-09-09 12:07 ` [LTP] [PATCH v10 2/3] coredump01: New core_pattern specifiers test Andrea Cervesato
@ 2026-09-09 12:07 ` Andrea Cervesato
  2026-09-10 10:21   ` Cyril Hrubis
  2 siblings, 1 reply; 14+ messages in thread
From: Andrea Cervesato @ 2026-09-09 12:07 UTC (permalink / raw)
  To: Linux Test Project

From: Andrea Cervesato <andrea.cervesato@suse.com>

LTP currently only tests core_pattern specifier expansion and basic
ELF magic in coredump01, leaving the internal ELF structure and notes
generated by the kernel unverified.

Add a test to verify that the kernel produces a valid ET_CORE ELF file
with the expected PT_NOTE and PT_LOAD segments, and that the
NT_PRPSINFO and NT_PRSTATUS notes contain the expected process name,
PID, and terminating signal.

Root is required to set the system-wide core_pattern into the test's
temporary directory.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/kernel_misc                    |   1 +
 testcases/kernel/coredump/.gitignore   |   1 +
 testcases/kernel/coredump/coredump02.c | 196 +++++++++++++++++++++++++++++++++
 3 files changed, 198 insertions(+)

diff --git a/runtest/kernel_misc b/runtest/kernel_misc
index ecf9ee2a2..3311e1929 100644
--- a/runtest/kernel_misc
+++ b/runtest/kernel_misc
@@ -18,3 +18,4 @@ zram03 zram03
 umip_basic_test umip_basic_test
 aslr01 aslr01
 coredump01 coredump01
+coredump02 coredump02
diff --git a/testcases/kernel/coredump/.gitignore b/testcases/kernel/coredump/.gitignore
index cd0b51700..e241a112e 100644
--- a/testcases/kernel/coredump/.gitignore
+++ b/testcases/kernel/coredump/.gitignore
@@ -1,2 +1,3 @@
 /coredump01
 /coredump01_helper
+/coredump02
diff --git a/testcases/kernel/coredump/coredump02.c b/testcases/kernel/coredump/coredump02.c
new file mode 100644
index 000000000..da7bdba45
--- /dev/null
+++ b/testcases/kernel/coredump/coredump02.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 Linux Test Project
+ */
+
+/*\
+ * Verify the ELF structure and note content of a kernel-generated core
+ * dump.
+ *
+ * A core dump written by the kernel is an ELF file of type ET_CORE. It
+ * contains:
+ *
+ * - one PT_NOTE program header holding process metadata
+ * - one or more PT_LOAD program headers for the mapped memory segments
+ *
+ * The PT_NOTE segment carries a stream of notes. Two of them describe
+ * the crashed process:
+ *
+ * - NT_PRPSINFO, whose descriptor is a struct elf_prpsinfo. The pr_fname
+ *   field holds the executable name.
+ * - NT_PRSTATUS, whose descriptor is a struct elf_prstatus. The pr_pid
+ *   field holds the PID and pr_cursig holds the terminating signal.
+ *
+ * The crashed child is a fork of the test binary, so the core dump has
+ * the same ELF class as the test. ElfW() is therefore safe here.
+ *
+ * The test needs root because it rewrites the system-wide core_pattern.
+ * The original value is saved and restored by the test library on all
+ * exit paths.
+ *
+ * [Algorithm]
+ *
+ * - Point core_pattern into the test temporary directory
+ * - Fork a child which aborts itself to produce a core dump
+ * - Read the core file into memory and parse the ELF header
+ * - Walk the program headers and verify PT_NOTE and PT_LOAD are present
+ * - Walk the notes in every PT_NOTE segment
+ * - Check that NT_PRPSINFO carries the expected executable name
+ * - Check that NT_PRSTATUS carries the expected PID and signal
+ */
+
+#include <link.h>
+#include <sys/procfs.h>
+
+#include "coredump_common.h"
+
+#define NOTE_ALIGN(x) (((x) + 3) & ~3U)
+
+static char *core_buf;
+static size_t core_len;
+static int prpsinfo_seen, prstatus_seen;
+
+static void load_core(const char *path)
+{
+	struct stat st;
+	int fd;
+
+	SAFE_STAT(path, &st);
+	if (st.st_size <= 0)
+		tst_brk(TFAIL, "core file %s is empty", path);
+
+	core_len = st.st_size;
+	core_buf = SAFE_MALLOC(core_len);
+
+	fd = SAFE_OPEN(path, O_RDONLY);
+	SAFE_READ(1, fd, core_buf, core_len);
+	SAFE_CLOSE(fd);
+}
+
+static void unload_core(void)
+{
+	free(core_buf);
+	core_buf = NULL;
+	core_len = 0;
+}
+
+static const void *core_at(size_t off, size_t need)
+{
+	if (off > core_len || need > core_len - off)
+		tst_brk(TFAIL, "core file truncated at %zu (need %zu, have %zu)",
+			off, need, core_len);
+
+	return core_buf + off;
+}
+
+static void handle_note(uint32_t type, const void *desc, size_t descsz, pid_t pid)
+{
+	if (type == NT_PRPSINFO && descsz >= sizeof(struct elf_prpsinfo)) {
+		struct elf_prpsinfo info;
+
+		memcpy(&info, desc, sizeof(info));
+		TST_EXP_EQ_STR(info.pr_fname, "coredump02");
+
+		prpsinfo_seen = 1;
+	} else if (type == NT_PRSTATUS && descsz >= sizeof(struct elf_prstatus)) {
+		struct elf_prstatus st;
+
+		memcpy(&st, desc, sizeof(st));
+
+		TST_EXP_EQ_LI(st.pr_pid, pid);
+		TST_EXP_EQ_LI(st.pr_cursig, SIGABRT);
+
+		prstatus_seen = 1;
+	}
+}
+
+static void walk_notes(size_t off, size_t size, pid_t pid)
+{
+	size_t pos = 0;
+
+	while (pos + sizeof(ElfW(Nhdr)) <= size) {
+		const ElfW(Nhdr) *nh = core_at(off + pos, sizeof(*nh));
+		size_t np = NOTE_ALIGN(nh->n_namesz);
+		size_t dp = NOTE_ALIGN(nh->n_descsz);
+		size_t total = sizeof(*nh) + np + dp;
+
+		if (pos + total > size)
+			tst_brk(TFAIL, "note extends past PT_NOTE (pos=%zu total=%zu size=%zu)",
+				pos, total, size);
+
+		handle_note(nh->n_type,
+			    core_at(off + pos + sizeof(*nh) + np, nh->n_descsz),
+			    nh->n_descsz, pid);
+
+		pos += total;
+	}
+}
+
+static void run(void)
+{
+	char dump[PATH_MAX + 32];
+	int pt_note_cnt = 0, have_load = 0;
+	const ElfW(Ehdr) *eh;
+	const ElfW(Phdr) *ph;
+	pid_t pid;
+	size_t i;
+
+	prpsinfo_seen = prstatus_seen = 0;
+
+	set_pattern("%s/core.%%p", cwd);
+
+	pid = crash_child();
+
+	snprintf(dump, sizeof(dump), "%s/core.%d", cwd, pid);
+	load_core(dump);
+
+	eh = core_at(0, sizeof(*eh));
+
+	TST_EXP_EXPR(!memcmp(eh->e_ident, ELFMAG, SELFMAG), "core has ELF magic");
+	TST_EXP_EQ_LI(eh->e_type, ET_CORE);
+
+	if (!eh->e_phnum)
+		tst_brk(TFAIL, "core has no program headers");
+
+	ph = core_at(eh->e_phoff, (size_t)eh->e_phnum * sizeof(*ph));
+
+	for (i = 0; i < eh->e_phnum; i++) {
+		if (ph[i].p_type == PT_NOTE) {
+			pt_note_cnt++;
+			walk_notes(ph[i].p_offset, ph[i].p_filesz, pid);
+		} else if (ph[i].p_type == PT_LOAD) {
+			have_load = 1;
+			core_at(ph[i].p_offset, ph[i].p_filesz);
+		}
+	}
+
+	TST_EXP_EQ_LI(pt_note_cnt, 1);
+	TST_EXP_EQ_LI(have_load, 1);
+	TST_EXP_EQ_LI(prpsinfo_seen, 1);
+	TST_EXP_EQ_LI(prstatus_seen, 1);
+
+	SAFE_UNLINK(dump);
+	unload_core();
+}
+
+static void cleanup(void)
+{
+	unload_core();
+}
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = coredump_setup,
+	.cleanup = cleanup,
+	.needs_root = 1,
+	.needs_tmpdir = 1,
+	.forks_child = 1,
+	.needs_kconfigs = (const char *[]) {
+		"CONFIG_COREDUMP=y",
+		NULL,
+	},
+	.save_restore = (const struct tst_path_val[]) {
+		{PATH_KERN_CORE_PATTERN, NULL, TST_SR_TCONF},
+		{}
+	},
+};

-- 
2.51.0


-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [LTP] lib: Add SAFE_FILE_VPRINTF()
  2026-09-09 12:07 ` [LTP] [PATCH v10 1/3] lib: Add SAFE_FILE_VPRINTF() Andrea Cervesato
@ 2026-09-09 13:40   ` linuxtestproject.agent
  0 siblings, 0 replies; 14+ messages in thread
From: linuxtestproject.agent @ 2026-09-09 13:40 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi Andrea,

On Wed Sep 9 14:07:15 2026 +0200, Andrea Cervesato wrote:
> lib: Add SAFE_FILE_VPRINTF()

Verdict - Reviewed

---
Note:

The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.

Regards,
LTP AI Reviewer

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes
  2026-09-09 12:07 ` [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes Andrea Cervesato
@ 2026-09-10 10:21   ` Cyril Hrubis
  2026-09-10 11:14     ` Andrea Cervesato via ltp
  0 siblings, 1 reply; 14+ messages in thread
From: Cyril Hrubis @ 2026-09-10 10:21 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: Linux Test Project

Hi!
> +static void handle_note(uint32_t type, const void *desc, size_t descsz, pid_t pid)
> +{
> +	if (type == NT_PRPSINFO && descsz >= sizeof(struct elf_prpsinfo)) {
> +		struct elf_prpsinfo info;
> +
> +		memcpy(&info, desc, sizeof(info));
> +		TST_EXP_EQ_STR(info.pr_fname, "coredump02");

I still do not see a reason why this can't be:

		struct elf_prpsinfo *info = desc;

		TST_EXP_EQ_STR(info->pr_name, "coredump02");

> +		prpsinfo_seen = 1;
> +	} else if (type == NT_PRSTATUS && descsz >= sizeof(struct elf_prstatus)) {
> +		struct elf_prstatus st;
> +
> +		memcpy(&st, desc, sizeof(st));
> +
> +		TST_EXP_EQ_LI(st.pr_pid, pid);
> +		TST_EXP_EQ_LI(st.pr_cursig, SIGABRT);

And here as well.


Otherwise:

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes
  2026-09-10 10:21   ` Cyril Hrubis
@ 2026-09-10 11:14     ` Andrea Cervesato via ltp
  2026-09-10 12:47       ` Cyril Hrubis
  0 siblings, 1 reply; 14+ messages in thread
From: Andrea Cervesato via ltp @ 2026-09-10 11:14 UTC (permalink / raw)
  To: Cyril Hrubis; +Cc: Linux Test Project

Hi Cyril,

> Hi!
> > +static void handle_note(uint32_t type, const void *desc, size_t descsz, pid_t pid)
> > +{
> > +	if (type == NT_PRPSINFO && descsz >= sizeof(struct elf_prpsinfo)) {
> > +		struct elf_prpsinfo info;
> > +
> > +		memcpy(&info, desc, sizeof(info));
> > +		TST_EXP_EQ_STR(info.pr_fname, "coredump02");
> 
> I still do not see a reason why this can't be:
> 
> 		struct elf_prpsinfo *info = desc;
> 
> 		TST_EXP_EQ_STR(info->pr_name, "coredump02");

because ELF notes in Linux are only 4-byte padded, desc pointers are not
guaranteed to be 8-byte aligned. Casting desc to struct elf_prpsinfo *
or struct elf_prstatus * creates a misaligned pointer, which is undefined
behavior in C.

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes
  2026-09-10 11:14     ` Andrea Cervesato via ltp
@ 2026-09-10 12:47       ` Cyril Hrubis
  2026-09-10 13:00         ` Andrea Cervesato via ltp
  0 siblings, 1 reply; 14+ messages in thread
From: Cyril Hrubis @ 2026-09-10 12:47 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: Linux Test Project

Hi!
> > > +static void handle_note(uint32_t type, const void *desc, size_t descsz, pid_t pid)
> > > +{
> > > +	if (type == NT_PRPSINFO && descsz >= sizeof(struct elf_prpsinfo)) {
> > > +		struct elf_prpsinfo info;
> > > +
> > > +		memcpy(&info, desc, sizeof(info));
> > > +		TST_EXP_EQ_STR(info.pr_fname, "coredump02");
> > 
> > I still do not see a reason why this can't be:
> > 
> > 		struct elf_prpsinfo *info = desc;
> > 
> > 		TST_EXP_EQ_STR(info->pr_name, "coredump02");
> 
> because ELF notes in Linux are only 4-byte padded, desc pointers are not
> guaranteed to be 8-byte aligned. Casting desc to struct elf_prpsinfo *
> or struct elf_prstatus * creates a misaligned pointer, which is undefined
> behavior in C.

AFAIK the 4 byte padding may happen on x86_64 only for a historical
reasons and x86_64 is at the same time capable of handling unaligned
access. AArch64 should have 8 byte padding.

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes
  2026-09-10 12:47       ` Cyril Hrubis
@ 2026-09-10 13:00         ` Andrea Cervesato via ltp
  2026-09-10 13:02           ` Cyril Hrubis
  0 siblings, 1 reply; 14+ messages in thread
From: Andrea Cervesato via ltp @ 2026-09-10 13:00 UTC (permalink / raw)
  To: Cyril Hrubis; +Cc: Linux Test Project

> AFAIK the 4 byte padding may happen on x86_64 only for a historical
> reasons and x86_64 is at the same time capable of handling unaligned
> access. AArch64 should have 8 byte padding.

yes, it happens only in x86_64, but I wouldn't rely too much on unaligned
access handling if it's just few bytes copy away. code is 100% stable like
this.

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes
  2026-09-10 13:00         ` Andrea Cervesato via ltp
@ 2026-09-10 13:02           ` Cyril Hrubis
  2026-09-10 13:26             ` Andrea Cervesato via ltp
  0 siblings, 1 reply; 14+ messages in thread
From: Cyril Hrubis @ 2026-09-10 13:02 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: Linux Test Project

Hi!
> > AFAIK the 4 byte padding may happen on x86_64 only for a historical
> > reasons and x86_64 is at the same time capable of handling unaligned
> > access. AArch64 should have 8 byte padding.
> 
> yes, it happens only in x86_64, but I wouldn't rely too much on unaligned
> access handling if it's just few bytes copy away. code is 100% stable like
> this.

It looks like working around potentional bugs rather than anything else.
The elements should be aligned so that they could be accessed on the
targed architecture.

-- 
Cyril Hrubis
chrubis@suse.cz

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes
  2026-09-10 13:02           ` Cyril Hrubis
@ 2026-09-10 13:26             ` Andrea Cervesato via ltp
  0 siblings, 0 replies; 14+ messages in thread
From: Andrea Cervesato via ltp @ 2026-09-10 13:26 UTC (permalink / raw)
  To: Cyril Hrubis; +Cc: Linux Test Project

> It looks like working around potentional bugs rather than anything else.
> The elements should be aligned so that they could be accessed on the
> targed architecture.
> 

ok, I will send the next version with the cast

--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [LTP] lib: Add SAFE_FILE_VPRINTF()
  2026-09-10 13:27 [LTP] [PATCH v11 1/3] lib: Add SAFE_FILE_VPRINTF() Andrea Cervesato
@ 2026-09-10 15:03 ` linuxtestproject.agent
  0 siblings, 0 replies; 14+ messages in thread
From: linuxtestproject.agent @ 2026-09-10 15:03 UTC (permalink / raw)
  To: Andrea Cervesato; +Cc: ltp

Hi Andrea,

On Thu Sep 10 15:27:11 2026 +0200, Andrea Cervesato wrote:
> lib: Add SAFE_FILE_VPRINTF()

Verdict - Reviewed

---
Note:

The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.

Regards,
LTP AI Reviewer

-- 
Mailing list info: https://lists.linux.it/listinfo/ltp

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-09-10 15:03 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09 12:07 [LTP] [PATCH v10 0/3] coredump testing suite Andrea Cervesato
2026-09-09 12:07 ` [LTP] [PATCH v10 1/3] lib: Add SAFE_FILE_VPRINTF() Andrea Cervesato
2026-09-09 13:40   ` [LTP] " linuxtestproject.agent
2026-09-09 12:07 ` [LTP] [PATCH v10 2/3] coredump01: New core_pattern specifiers test Andrea Cervesato
2026-09-09 12:07 ` [LTP] [PATCH v10 3/3] coredump02: Verify ELF structure and notes Andrea Cervesato
2026-09-10 10:21   ` Cyril Hrubis
2026-09-10 11:14     ` Andrea Cervesato via ltp
2026-09-10 12:47       ` Cyril Hrubis
2026-09-10 13:00         ` Andrea Cervesato via ltp
2026-09-10 13:02           ` Cyril Hrubis
2026-09-10 13:26             ` Andrea Cervesato via ltp
  -- strict thread matches above, loose matches on Subject: below --
2026-09-10 13:27 [LTP] [PATCH v11 1/3] lib: Add SAFE_FILE_VPRINTF() Andrea Cervesato
2026-09-10 15:03 ` [LTP] " linuxtestproject.agent
2026-09-09 10:04 [LTP] [PATCH v9 1/3] " Andrea Cervesato
2026-09-09 10:35 ` [LTP] " linuxtestproject.agent
2026-09-09 12:05   ` Andrea Cervesato via ltp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox