File Index
Files and directories
Sign in
FILE

stackdump_test.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/coredump/stackdump_test.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <assert.h>
  4#include <fcntl.h>
  5#include <inttypes.h>
  6#include <libgen.h>
  7#include <limits.h>
  8#include <linux/coredump.h>
  9#include <linux/fs.h>
 10#include <linux/limits.h>
 11#include <pthread.h>
 12#include <string.h>
 13#include <sys/mount.h>
 14#include <poll.h>
 15#include <sys/epoll.h>
 16#include <sys/resource.h>
 17#include <sys/stat.h>
 18#include <sys/socket.h>
 19#include <sys/un.h>
 20#include <unistd.h>
 21
 22#include "kselftest_harness.h"
 23#include "../filesystems/wrappers.h"
 24#include "../pidfd/pidfd.h"
 25
 26#include "coredump_test.h"
 27
 28#define STACKDUMP_FILE "stack_values"
 29#define STACKDUMP_SCRIPT "stackdump"
 30
 31#ifndef PAGE_SIZE
 32#define PAGE_SIZE 4096
 33#endif
 34
 35FIXTURE_SETUP(coredump)
 36{
 37	FILE *file;
 38	int ret;
 39
 40	self->pid_coredump_server = -ESRCH;
 41	self->fd_tmpfs_detached = -1;
 42	file = fopen("/proc/sys/kernel/core_pattern", "r");
 43	ASSERT_NE(NULL, file);
 44
 45	ret = fread(self->original_core_pattern, 1, sizeof(self->original_core_pattern), file);
 46	ASSERT_TRUE(ret || feof(file));
 47	ASSERT_LT(ret, sizeof(self->original_core_pattern));
 48
 49	self->original_core_pattern[ret] = '\0';
 50	self->fd_tmpfs_detached = create_detached_tmpfs();
 51	ASSERT_GE(self->fd_tmpfs_detached, 0);
 52
 53	ret = fclose(file);
 54	ASSERT_EQ(0, ret);
 55}
 56
 57FIXTURE_TEARDOWN(coredump)
 58{
 59	const char *reason;
 60	FILE *file;
 61	int ret, status;
 62
 63	unlink(STACKDUMP_FILE);
 64
 65	if (self->pid_coredump_server > 0) {
 66		kill(self->pid_coredump_server, SIGTERM);
 67		waitpid(self->pid_coredump_server, &status, 0);
 68	}
 69	unlink("/tmp/coredump.file");
 70	unlink("/tmp/coredump.socket");
 71
 72	file = fopen("/proc/sys/kernel/core_pattern", "w");
 73	if (!file) {
 74		reason = "Unable to open core_pattern";
 75		goto fail;
 76	}
 77
 78	ret = fprintf(file, "%s", self->original_core_pattern);
 79	if (ret < 0) {
 80		reason = "Unable to write to core_pattern";
 81		goto fail;
 82	}
 83
 84	ret = fclose(file);
 85	if (ret) {
 86		reason = "Unable to close core_pattern";
 87		goto fail;
 88	}
 89
 90	if (self->fd_tmpfs_detached >= 0) {
 91		ret = close(self->fd_tmpfs_detached);
 92		if (ret < 0) {
 93			reason = "Unable to close detached tmpfs";
 94			goto fail;
 95		}
 96		self->fd_tmpfs_detached = -1;
 97	}
 98
 99	return;
100fail:
101	/* This should never happen */
102	fprintf(stderr, "Failed to cleanup stackdump test: %s\n", reason);
103}
104
105TEST_F_TIMEOUT(coredump, stackdump, 120)
106{
107	unsigned long long stack;
108	char *test_dir, *line;
109	size_t line_length;
110	char buf[PAGE_SIZE];
111	int ret, i, status;
112	FILE *file;
113	pid_t pid;
114
115	/*
116	 * Step 1: Setup core_pattern so that the stackdump script is executed when the child
117	 * process crashes
118	 */
119	ret = readlink("/proc/self/exe", buf, sizeof(buf));
120	ASSERT_NE(-1, ret);
121	ASSERT_LT(ret, sizeof(buf));
122	buf[ret] = '\0';
123
124	test_dir = dirname(buf);
125
126	file = fopen("/proc/sys/kernel/core_pattern", "w");
127	ASSERT_NE(NULL, file);
128
129	ret = fprintf(file, "|%1$s/%2$s %%P %1$s/%3$s", test_dir, STACKDUMP_SCRIPT, STACKDUMP_FILE);
130	ASSERT_LT(0, ret);
131
132	ret = fclose(file);
133	ASSERT_EQ(0, ret);
134
135	/* Step 2: Create a process who spawns some threads then crashes */
136	pid = fork();
137	ASSERT_TRUE(pid >= 0);
138	if (pid == 0)
139		crashing_child();
140
141	/*
142	 * Step 3: Wait for the stackdump script to write the stack pointers to the stackdump file
143	 */
144	waitpid(pid, &status, 0);
145	ASSERT_TRUE(WIFSIGNALED(status));
146	ASSERT_TRUE(WCOREDUMP(status));
147
148	for (i = 0; i < 10; ++i) {
149		file = fopen(STACKDUMP_FILE, "r");
150		if (file)
151			break;
152		sleep(1);
153	}
154	ASSERT_NE(file, NULL);
155
156	/* Step 4: Make sure all stack pointer values are non-zero */
157	line = NULL;
158	for (i = 0; -1 != getline(&line, &line_length, file); ++i) {
159		stack = strtoull(line, NULL, 10);
160		ASSERT_NE(stack, 0);
161	}
162	free(line);
163
164	ASSERT_EQ(i, 1 + NUM_THREAD_SPAWN);
165
166	fclose(file);
167}
168
169TEST_HARNESS_MAIN
~/ Read-only file preview.