xref: /linux/tools/testing/selftests/coredump/stackdump_test.c (revision 055f213075fbfa8e950bed8f2c50d01ac71bbf37)
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 #define STACKDUMP_FILE "stack_values"
27 #define STACKDUMP_SCRIPT "stackdump"
28 #define NUM_THREAD_SPAWN 128
29 
30 #ifndef PAGE_SIZE
31 #define PAGE_SIZE 4096
32 #endif
33 
do_nothing(void *)34 static void *do_nothing(void *)
35 {
36 	while (1)
37 		pause();
38 
39 	return NULL;
40 }
41 
crashing_child(void)42 static void crashing_child(void)
43 {
44 	pthread_t thread;
45 	int i;
46 
47 	for (i = 0; i < NUM_THREAD_SPAWN; ++i)
48 		pthread_create(&thread, NULL, do_nothing, NULL);
49 
50 	/* crash on purpose */
51 	i = *(int *)NULL;
52 }
53 
FIXTURE(coredump)54 FIXTURE(coredump)
55 {
56 	char original_core_pattern[256];
57 	pid_t pid_coredump_server;
58 	int fd_tmpfs_detached;
59 };
60 
create_detached_tmpfs(void)61 static int create_detached_tmpfs(void)
62 {
63 	int fd_context, fd_tmpfs;
64 
65 	fd_context = sys_fsopen("tmpfs", 0);
66 	if (fd_context < 0)
67 		return -1;
68 
69 	if (sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0) < 0)
70 		return -1;
71 
72 	fd_tmpfs = sys_fsmount(fd_context, 0, 0);
73 	close(fd_context);
74 	return fd_tmpfs;
75 }
76 
FIXTURE_SETUP(coredump)77 FIXTURE_SETUP(coredump)
78 {
79 	FILE *file;
80 	int ret;
81 
82 	self->pid_coredump_server = -ESRCH;
83 	self->fd_tmpfs_detached = -1;
84 	file = fopen("/proc/sys/kernel/core_pattern", "r");
85 	ASSERT_NE(NULL, file);
86 
87 	ret = fread(self->original_core_pattern, 1, sizeof(self->original_core_pattern), file);
88 	ASSERT_TRUE(ret || feof(file));
89 	ASSERT_LT(ret, sizeof(self->original_core_pattern));
90 
91 	self->original_core_pattern[ret] = '\0';
92 	self->fd_tmpfs_detached = create_detached_tmpfs();
93 	ASSERT_GE(self->fd_tmpfs_detached, 0);
94 
95 	ret = fclose(file);
96 	ASSERT_EQ(0, ret);
97 }
98 
FIXTURE_TEARDOWN(coredump)99 FIXTURE_TEARDOWN(coredump)
100 {
101 	const char *reason;
102 	FILE *file;
103 	int ret, status;
104 
105 	unlink(STACKDUMP_FILE);
106 
107 	if (self->pid_coredump_server > 0) {
108 		kill(self->pid_coredump_server, SIGTERM);
109 		waitpid(self->pid_coredump_server, &status, 0);
110 	}
111 	unlink("/tmp/coredump.file");
112 	unlink("/tmp/coredump.socket");
113 
114 	file = fopen("/proc/sys/kernel/core_pattern", "w");
115 	if (!file) {
116 		reason = "Unable to open core_pattern";
117 		goto fail;
118 	}
119 
120 	ret = fprintf(file, "%s", self->original_core_pattern);
121 	if (ret < 0) {
122 		reason = "Unable to write to core_pattern";
123 		goto fail;
124 	}
125 
126 	ret = fclose(file);
127 	if (ret) {
128 		reason = "Unable to close core_pattern";
129 		goto fail;
130 	}
131 
132 	if (self->fd_tmpfs_detached >= 0) {
133 		ret = close(self->fd_tmpfs_detached);
134 		if (ret < 0) {
135 			reason = "Unable to close detached tmpfs";
136 			goto fail;
137 		}
138 		self->fd_tmpfs_detached = -1;
139 	}
140 
141 	return;
142 fail:
143 	/* This should never happen */
144 	fprintf(stderr, "Failed to cleanup stackdump test: %s\n", reason);
145 }
146 
147 TEST_F_TIMEOUT(coredump, stackdump, 120)
148 {
149 	unsigned long long stack;
150 	char *test_dir, *line;
151 	size_t line_length;
152 	char buf[PAGE_SIZE];
153 	int ret, i, status;
154 	FILE *file;
155 	pid_t pid;
156 
157 	/*
158 	 * Step 1: Setup core_pattern so that the stackdump script is executed when the child
159 	 * process crashes
160 	 */
161 	ret = readlink("/proc/self/exe", buf, sizeof(buf));
162 	ASSERT_NE(-1, ret);
163 	ASSERT_LT(ret, sizeof(buf));
164 	buf[ret] = '\0';
165 
166 	test_dir = dirname(buf);
167 
168 	file = fopen("/proc/sys/kernel/core_pattern", "w");
169 	ASSERT_NE(NULL, file);
170 
171 	ret = fprintf(file, "|%1$s/%2$s %%P %1$s/%3$s", test_dir, STACKDUMP_SCRIPT, STACKDUMP_FILE);
172 	ASSERT_LT(0, ret);
173 
174 	ret = fclose(file);
175 	ASSERT_EQ(0, ret);
176 
177 	/* Step 2: Create a process who spawns some threads then crashes */
178 	pid = fork();
179 	ASSERT_TRUE(pid >= 0);
180 	if (pid == 0)
181 		crashing_child();
182 
183 	/*
184 	 * Step 3: Wait for the stackdump script to write the stack pointers to the stackdump file
185 	 */
186 	waitpid(pid, &status, 0);
187 	ASSERT_TRUE(WIFSIGNALED(status));
188 	ASSERT_TRUE(WCOREDUMP(status));
189 
190 	for (i = 0; i < 10; ++i) {
191 		file = fopen(STACKDUMP_FILE, "r");
192 		if (file)
193 			break;
194 		sleep(1);
195 	}
196 	ASSERT_NE(file, NULL);
197 
198 	/* Step 4: Make sure all stack pointer values are non-zero */
199 	line = NULL;
200 	for (i = 0; -1 != getline(&line, &line_length, file); ++i) {
201 		stack = strtoull(line, NULL, 10);
202 		ASSERT_NE(stack, 0);
203 	}
204 	free(line);
205 
206 	ASSERT_EQ(i, 1 + NUM_THREAD_SPAWN);
207 
208 	fclose(file);
209 }
210 
create_and_listen_unix_socket(const char * path)211 static int create_and_listen_unix_socket(const char *path)
212 {
213 	struct sockaddr_un addr = {
214 		.sun_family = AF_UNIX,
215 	};
216 	assert(strlen(path) < sizeof(addr.sun_path) - 1);
217 	strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
218 	size_t addr_len =
219 		offsetof(struct sockaddr_un, sun_path) + strlen(path) + 1;
220 	int fd, ret;
221 
222 	fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
223 	if (fd < 0)
224 		goto out;
225 
226 	ret = bind(fd, (const struct sockaddr *)&addr, addr_len);
227 	if (ret < 0)
228 		goto out;
229 
230 	ret = listen(fd, 128);
231 	if (ret < 0)
232 		goto out;
233 
234 	return fd;
235 
236 out:
237 	if (fd >= 0)
238 		close(fd);
239 	return -1;
240 }
241 
set_core_pattern(const char * pattern)242 static bool set_core_pattern(const char *pattern)
243 {
244 	int fd;
245 	ssize_t ret;
246 
247 	fd = open("/proc/sys/kernel/core_pattern", O_WRONLY | O_CLOEXEC);
248 	if (fd < 0)
249 		return false;
250 
251 	ret = write(fd, pattern, strlen(pattern));
252 	close(fd);
253 	if (ret < 0)
254 		return false;
255 
256 	fprintf(stderr, "Set core_pattern to '%s' | %zu == %zu\n", pattern, ret, strlen(pattern));
257 	return ret == strlen(pattern);
258 }
259 
get_peer_pidfd(int fd)260 static int get_peer_pidfd(int fd)
261 {
262 	int fd_peer_pidfd;
263 	socklen_t fd_peer_pidfd_len = sizeof(fd_peer_pidfd);
264 	int ret = getsockopt(fd, SOL_SOCKET, SO_PEERPIDFD, &fd_peer_pidfd,
265 			     &fd_peer_pidfd_len);
266 	if (ret < 0) {
267 		fprintf(stderr, "%m - Failed to retrieve peer pidfd for coredump socket connection\n");
268 		return -1;
269 	}
270 	return fd_peer_pidfd;
271 }
272 
get_pidfd_info(int fd_peer_pidfd,struct pidfd_info * info)273 static bool get_pidfd_info(int fd_peer_pidfd, struct pidfd_info *info)
274 {
275 	memset(info, 0, sizeof(*info));
276 	info->mask = PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP;
277 	return ioctl(fd_peer_pidfd, PIDFD_GET_INFO, info) == 0;
278 }
279 
280 static void
wait_and_check_coredump_server(pid_t pid_coredump_server,struct __test_metadata * const _metadata,FIXTURE_DATA (coredump)* self)281 wait_and_check_coredump_server(pid_t pid_coredump_server,
282 			       struct __test_metadata *const _metadata,
283 			       FIXTURE_DATA(coredump)* self)
284 {
285 	int status;
286 	waitpid(pid_coredump_server, &status, 0);
287 	self->pid_coredump_server = -ESRCH;
288 	ASSERT_TRUE(WIFEXITED(status));
289 	ASSERT_EQ(WEXITSTATUS(status), 0);
290 }
291 
TEST_F(coredump,socket)292 TEST_F(coredump, socket)
293 {
294 	int pidfd, ret, status;
295 	pid_t pid, pid_coredump_server;
296 	struct stat st;
297 	struct pidfd_info info = {};
298 	int ipc_sockets[2];
299 	char c;
300 
301 	ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket"));
302 
303 	ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
304 	ASSERT_EQ(ret, 0);
305 
306 	pid_coredump_server = fork();
307 	ASSERT_GE(pid_coredump_server, 0);
308 	if (pid_coredump_server == 0) {
309 		int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1, fd_core_file = -1;
310 		int exit_code = EXIT_FAILURE;
311 
312 		close(ipc_sockets[0]);
313 
314 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
315 		if (fd_server < 0)
316 			goto out;
317 
318 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
319 			goto out;
320 
321 		close(ipc_sockets[1]);
322 
323 		fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
324 		if (fd_coredump < 0)
325 			goto out;
326 
327 		fd_peer_pidfd = get_peer_pidfd(fd_coredump);
328 		if (fd_peer_pidfd < 0)
329 			goto out;
330 
331 		if (!get_pidfd_info(fd_peer_pidfd, &info))
332 			goto out;
333 
334 		if (!(info.mask & PIDFD_INFO_COREDUMP))
335 			goto out;
336 
337 		if (!(info.coredump_mask & PIDFD_COREDUMPED))
338 			goto out;
339 
340 		fd_core_file = creat("/tmp/coredump.file", 0644);
341 		if (fd_core_file < 0)
342 			goto out;
343 
344 		for (;;) {
345 			char buffer[4096];
346 			ssize_t bytes_read, bytes_write;
347 
348 			bytes_read = read(fd_coredump, buffer, sizeof(buffer));
349 			if (bytes_read < 0)
350 				goto out;
351 
352 			if (bytes_read == 0)
353 				break;
354 
355 			bytes_write = write(fd_core_file, buffer, bytes_read);
356 			if (bytes_read != bytes_write)
357 				goto out;
358 		}
359 
360 		exit_code = EXIT_SUCCESS;
361 out:
362 		if (fd_core_file >= 0)
363 			close(fd_core_file);
364 		if (fd_peer_pidfd >= 0)
365 			close(fd_peer_pidfd);
366 		if (fd_coredump >= 0)
367 			close(fd_coredump);
368 		if (fd_server >= 0)
369 			close(fd_server);
370 		_exit(exit_code);
371 	}
372 	self->pid_coredump_server = pid_coredump_server;
373 
374 	EXPECT_EQ(close(ipc_sockets[1]), 0);
375 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
376 	EXPECT_EQ(close(ipc_sockets[0]), 0);
377 
378 	pid = fork();
379 	ASSERT_GE(pid, 0);
380 	if (pid == 0)
381 		crashing_child();
382 
383 	pidfd = sys_pidfd_open(pid, 0);
384 	ASSERT_GE(pidfd, 0);
385 
386 	waitpid(pid, &status, 0);
387 	ASSERT_TRUE(WIFSIGNALED(status));
388 	ASSERT_TRUE(WCOREDUMP(status));
389 
390 	ASSERT_TRUE(get_pidfd_info(pidfd, &info));
391 	ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
392 	ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0);
393 
394 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
395 
396 	ASSERT_EQ(stat("/tmp/coredump.file", &st), 0);
397 	ASSERT_GT(st.st_size, 0);
398 	system("file /tmp/coredump.file");
399 }
400 
TEST_F(coredump,socket_detect_userspace_client)401 TEST_F(coredump, socket_detect_userspace_client)
402 {
403 	int pidfd, ret, status;
404 	pid_t pid, pid_coredump_server;
405 	struct stat st;
406 	struct pidfd_info info = {};
407 	int ipc_sockets[2];
408 	char c;
409 
410 	ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket"));
411 
412 	ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
413 	ASSERT_EQ(ret, 0);
414 
415 	pid_coredump_server = fork();
416 	ASSERT_GE(pid_coredump_server, 0);
417 	if (pid_coredump_server == 0) {
418 		int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1;
419 		int exit_code = EXIT_FAILURE;
420 
421 		close(ipc_sockets[0]);
422 
423 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
424 		if (fd_server < 0)
425 			goto out;
426 
427 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
428 			goto out;
429 
430 		close(ipc_sockets[1]);
431 
432 		fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
433 		if (fd_coredump < 0)
434 			goto out;
435 
436 		fd_peer_pidfd = get_peer_pidfd(fd_coredump);
437 		if (fd_peer_pidfd < 0)
438 			goto out;
439 
440 		if (!get_pidfd_info(fd_peer_pidfd, &info))
441 			goto out;
442 
443 		if (!(info.mask & PIDFD_INFO_COREDUMP))
444 			goto out;
445 
446 		if (info.coredump_mask & PIDFD_COREDUMPED)
447 			goto out;
448 
449 		exit_code = EXIT_SUCCESS;
450 out:
451 		if (fd_peer_pidfd >= 0)
452 			close(fd_peer_pidfd);
453 		if (fd_coredump >= 0)
454 			close(fd_coredump);
455 		if (fd_server >= 0)
456 			close(fd_server);
457 		_exit(exit_code);
458 	}
459 	self->pid_coredump_server = pid_coredump_server;
460 
461 	EXPECT_EQ(close(ipc_sockets[1]), 0);
462 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
463 	EXPECT_EQ(close(ipc_sockets[0]), 0);
464 
465 	pid = fork();
466 	ASSERT_GE(pid, 0);
467 	if (pid == 0) {
468 		int fd_socket;
469 		ssize_t ret;
470 		const struct sockaddr_un coredump_sk = {
471 			.sun_family = AF_UNIX,
472 			.sun_path = "/tmp/coredump.socket",
473 		};
474 		size_t coredump_sk_len =
475 			offsetof(struct sockaddr_un, sun_path) +
476 			sizeof("/tmp/coredump.socket");
477 
478 		fd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
479 		if (fd_socket < 0)
480 			_exit(EXIT_FAILURE);
481 
482 		ret = connect(fd_socket, (const struct sockaddr *)&coredump_sk, coredump_sk_len);
483 		if (ret < 0)
484 			_exit(EXIT_FAILURE);
485 
486 		close(fd_socket);
487 		_exit(EXIT_SUCCESS);
488 	}
489 
490 	pidfd = sys_pidfd_open(pid, 0);
491 	ASSERT_GE(pidfd, 0);
492 
493 	waitpid(pid, &status, 0);
494 	ASSERT_TRUE(WIFEXITED(status));
495 	ASSERT_EQ(WEXITSTATUS(status), 0);
496 
497 	ASSERT_TRUE(get_pidfd_info(pidfd, &info));
498 	ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
499 	ASSERT_EQ((info.coredump_mask & PIDFD_COREDUMPED), 0);
500 
501 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
502 
503 	ASSERT_NE(stat("/tmp/coredump.file", &st), 0);
504 	ASSERT_EQ(errno, ENOENT);
505 }
506 
TEST_F(coredump,socket_enoent)507 TEST_F(coredump, socket_enoent)
508 {
509 	int pidfd, status;
510 	pid_t pid;
511 
512 	ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket"));
513 
514 	pid = fork();
515 	ASSERT_GE(pid, 0);
516 	if (pid == 0)
517 		crashing_child();
518 
519 	pidfd = sys_pidfd_open(pid, 0);
520 	ASSERT_GE(pidfd, 0);
521 
522 	waitpid(pid, &status, 0);
523 	ASSERT_TRUE(WIFSIGNALED(status));
524 	ASSERT_FALSE(WCOREDUMP(status));
525 }
526 
TEST_F(coredump,socket_no_listener)527 TEST_F(coredump, socket_no_listener)
528 {
529 	int pidfd, ret, status;
530 	pid_t pid, pid_coredump_server;
531 	int ipc_sockets[2];
532 	char c;
533 	const struct sockaddr_un coredump_sk = {
534 		.sun_family = AF_UNIX,
535 		.sun_path = "/tmp/coredump.socket",
536 	};
537 	size_t coredump_sk_len = offsetof(struct sockaddr_un, sun_path) +
538 				 sizeof("/tmp/coredump.socket");
539 
540 	ASSERT_TRUE(set_core_pattern("@/tmp/coredump.socket"));
541 
542 	ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
543 	ASSERT_EQ(ret, 0);
544 
545 	pid_coredump_server = fork();
546 	ASSERT_GE(pid_coredump_server, 0);
547 	if (pid_coredump_server == 0) {
548 		int fd_server = -1;
549 		int exit_code = EXIT_FAILURE;
550 
551 		close(ipc_sockets[0]);
552 
553 		fd_server = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
554 		if (fd_server < 0)
555 			goto out;
556 
557 		ret = bind(fd_server, (const struct sockaddr *)&coredump_sk, coredump_sk_len);
558 		if (ret < 0)
559 			goto out;
560 
561 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
562 			goto out;
563 
564 		exit_code = EXIT_SUCCESS;
565 out:
566 		if (fd_server >= 0)
567 			close(fd_server);
568 		close(ipc_sockets[1]);
569 		_exit(exit_code);
570 	}
571 	self->pid_coredump_server = pid_coredump_server;
572 
573 	EXPECT_EQ(close(ipc_sockets[1]), 0);
574 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
575 	EXPECT_EQ(close(ipc_sockets[0]), 0);
576 
577 	pid = fork();
578 	ASSERT_GE(pid, 0);
579 	if (pid == 0)
580 		crashing_child();
581 
582 	pidfd = sys_pidfd_open(pid, 0);
583 	ASSERT_GE(pidfd, 0);
584 
585 	waitpid(pid, &status, 0);
586 	ASSERT_TRUE(WIFSIGNALED(status));
587 	ASSERT_FALSE(WCOREDUMP(status));
588 
589 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
590 }
591 
recv_marker(int fd)592 static ssize_t recv_marker(int fd)
593 {
594 	enum coredump_mark mark = COREDUMP_MARK_REQACK;
595 	ssize_t ret;
596 
597 	ret = recv(fd, &mark, sizeof(mark), MSG_WAITALL);
598 	if (ret != sizeof(mark))
599 		return -1;
600 
601 	switch (mark) {
602 	case COREDUMP_MARK_REQACK:
603 		fprintf(stderr, "Received marker: ReqAck\n");
604 		return COREDUMP_MARK_REQACK;
605 	case COREDUMP_MARK_MINSIZE:
606 		fprintf(stderr, "Received marker: MinSize\n");
607 		return COREDUMP_MARK_MINSIZE;
608 	case COREDUMP_MARK_MAXSIZE:
609 		fprintf(stderr, "Received marker: MaxSize\n");
610 		return COREDUMP_MARK_MAXSIZE;
611 	case COREDUMP_MARK_UNSUPPORTED:
612 		fprintf(stderr, "Received marker: Unsupported\n");
613 		return COREDUMP_MARK_UNSUPPORTED;
614 	case COREDUMP_MARK_CONFLICTING:
615 		fprintf(stderr, "Received marker: Conflicting\n");
616 		return COREDUMP_MARK_CONFLICTING;
617 	default:
618 		fprintf(stderr, "Received unknown marker: %u\n", mark);
619 		break;
620 	}
621 	return -1;
622 }
623 
read_marker(int fd,enum coredump_mark mark)624 static bool read_marker(int fd, enum coredump_mark mark)
625 {
626 	ssize_t ret;
627 
628 	ret = recv_marker(fd);
629 	if (ret < 0)
630 		return false;
631 	return ret == mark;
632 }
633 
read_coredump_req(int fd,struct coredump_req * req)634 static bool read_coredump_req(int fd, struct coredump_req *req)
635 {
636 	ssize_t ret;
637 	size_t field_size, user_size, ack_size, kernel_size, remaining_size;
638 
639 	memset(req, 0, sizeof(*req));
640 	field_size = sizeof(req->size);
641 
642 	/* Peek the size of the coredump request. */
643 	ret = recv(fd, req, field_size, MSG_PEEK | MSG_WAITALL);
644 	if (ret != field_size)
645 		return false;
646 	kernel_size = req->size;
647 
648 	if (kernel_size < COREDUMP_ACK_SIZE_VER0)
649 		return false;
650 	if (kernel_size >= PAGE_SIZE)
651 		return false;
652 
653 	/* Use the minimum of user and kernel size to read the full request. */
654 	user_size = sizeof(struct coredump_req);
655 	ack_size = user_size < kernel_size ? user_size : kernel_size;
656 	ret = recv(fd, req, ack_size, MSG_WAITALL);
657 	if (ret != ack_size)
658 		return false;
659 
660 	fprintf(stderr, "Read coredump request with size %u and mask 0x%llx\n",
661 		req->size, (unsigned long long)req->mask);
662 
663 	if (user_size > kernel_size)
664 		remaining_size = user_size - kernel_size;
665 	else
666 		remaining_size = kernel_size - user_size;
667 
668 	if (PAGE_SIZE <= remaining_size)
669 		return false;
670 
671 	/*
672 	 * Discard any additional data if the kernel's request was larger than
673 	 * what we knew about or cared about.
674 	 */
675 	if (remaining_size) {
676 		char buffer[PAGE_SIZE];
677 
678 		ret = recv(fd, buffer, sizeof(buffer), MSG_WAITALL);
679 		if (ret != remaining_size)
680 			return false;
681 		fprintf(stderr, "Discarded %zu bytes of data after coredump request\n", remaining_size);
682 	}
683 
684 	return true;
685 }
686 
send_coredump_ack(int fd,const struct coredump_req * req,__u64 mask,size_t size_ack)687 static bool send_coredump_ack(int fd, const struct coredump_req *req,
688 			      __u64 mask, size_t size_ack)
689 {
690 	ssize_t ret;
691 	/*
692 	 * Wrap struct coredump_ack in a larger struct so we can
693 	 * simulate sending to much data to the kernel.
694 	 */
695 	struct large_ack_for_size_testing {
696 		struct coredump_ack ack;
697 		char buffer[PAGE_SIZE];
698 	} large_ack = {};
699 
700 	if (!size_ack)
701 		size_ack = sizeof(struct coredump_ack) < req->size_ack ?
702 				   sizeof(struct coredump_ack) :
703 				   req->size_ack;
704 	large_ack.ack.mask = mask;
705 	large_ack.ack.size = size_ack;
706 	ret = send(fd, &large_ack, size_ack, MSG_NOSIGNAL);
707 	if (ret != size_ack)
708 		return false;
709 
710 	fprintf(stderr, "Sent coredump ack with size %zu and mask 0x%llx\n",
711 		size_ack, (unsigned long long)mask);
712 	return true;
713 }
714 
check_coredump_req(const struct coredump_req * req,size_t min_size,__u64 required_mask)715 static bool check_coredump_req(const struct coredump_req *req, size_t min_size,
716 			       __u64 required_mask)
717 {
718 	if (req->size < min_size)
719 		return false;
720 	if ((req->mask & required_mask) != required_mask)
721 		return false;
722 	if (req->mask & ~required_mask)
723 		return false;
724 	return true;
725 }
726 
TEST_F(coredump,socket_request_kernel)727 TEST_F(coredump, socket_request_kernel)
728 {
729 	int pidfd, ret, status;
730 	pid_t pid, pid_coredump_server;
731 	struct stat st;
732 	struct pidfd_info info = {};
733 	int ipc_sockets[2];
734 	char c;
735 
736 	ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket"));
737 
738 	ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
739 	ASSERT_EQ(ret, 0);
740 
741 	pid_coredump_server = fork();
742 	ASSERT_GE(pid_coredump_server, 0);
743 	if (pid_coredump_server == 0) {
744 		struct coredump_req req = {};
745 		int fd_server = -1, fd_coredump = -1, fd_core_file = -1, fd_peer_pidfd = -1;
746 		int exit_code = EXIT_FAILURE;
747 
748 		close(ipc_sockets[0]);
749 
750 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
751 		if (fd_server < 0)
752 			goto out;
753 
754 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
755 			goto out;
756 
757 		close(ipc_sockets[1]);
758 
759 		fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
760 		if (fd_coredump < 0)
761 			goto out;
762 
763 		fd_peer_pidfd = get_peer_pidfd(fd_coredump);
764 		if (fd_peer_pidfd < 0)
765 			goto out;
766 
767 		if (!get_pidfd_info(fd_peer_pidfd, &info))
768 			goto out;
769 
770 		if (!(info.mask & PIDFD_INFO_COREDUMP))
771 			goto out;
772 
773 		if (!(info.coredump_mask & PIDFD_COREDUMPED))
774 			goto out;
775 
776 		fd_core_file = creat("/tmp/coredump.file", 0644);
777 		if (fd_core_file < 0)
778 			goto out;
779 
780 		if (!read_coredump_req(fd_coredump, &req))
781 			goto out;
782 
783 		if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0,
784 					COREDUMP_KERNEL | COREDUMP_USERSPACE |
785 					COREDUMP_REJECT | COREDUMP_WAIT))
786 			goto out;
787 
788 		if (!send_coredump_ack(fd_coredump, &req,
789 				       COREDUMP_KERNEL | COREDUMP_WAIT, 0))
790 			goto out;
791 
792 		if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK))
793 			goto out;
794 
795 		for (;;) {
796 			char buffer[4096];
797 			ssize_t bytes_read, bytes_write;
798 
799 			bytes_read = read(fd_coredump, buffer, sizeof(buffer));
800 			if (bytes_read < 0)
801 				goto out;
802 
803 			if (bytes_read == 0)
804 				break;
805 
806 			bytes_write = write(fd_core_file, buffer, bytes_read);
807 			if (bytes_read != bytes_write)
808 				goto out;
809 		}
810 
811 		exit_code = EXIT_SUCCESS;
812 out:
813 		if (fd_core_file >= 0)
814 			close(fd_core_file);
815 		if (fd_peer_pidfd >= 0)
816 			close(fd_peer_pidfd);
817 		if (fd_coredump >= 0)
818 			close(fd_coredump);
819 		if (fd_server >= 0)
820 			close(fd_server);
821 		_exit(exit_code);
822 	}
823 	self->pid_coredump_server = pid_coredump_server;
824 
825 	EXPECT_EQ(close(ipc_sockets[1]), 0);
826 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
827 	EXPECT_EQ(close(ipc_sockets[0]), 0);
828 
829 	pid = fork();
830 	ASSERT_GE(pid, 0);
831 	if (pid == 0)
832 		crashing_child();
833 
834 	pidfd = sys_pidfd_open(pid, 0);
835 	ASSERT_GE(pidfd, 0);
836 
837 	waitpid(pid, &status, 0);
838 	ASSERT_TRUE(WIFSIGNALED(status));
839 	ASSERT_TRUE(WCOREDUMP(status));
840 
841 	ASSERT_TRUE(get_pidfd_info(pidfd, &info));
842 	ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
843 	ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0);
844 
845 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
846 
847 	ASSERT_EQ(stat("/tmp/coredump.file", &st), 0);
848 	ASSERT_GT(st.st_size, 0);
849 	system("file /tmp/coredump.file");
850 }
851 
TEST_F(coredump,socket_request_userspace)852 TEST_F(coredump, socket_request_userspace)
853 {
854 	int pidfd, ret, status;
855 	pid_t pid, pid_coredump_server;
856 	struct pidfd_info info = {};
857 	int ipc_sockets[2];
858 	char c;
859 
860 	ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket"));
861 
862 	ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
863 	ASSERT_EQ(ret, 0);
864 
865 	pid_coredump_server = fork();
866 	ASSERT_GE(pid_coredump_server, 0);
867 	if (pid_coredump_server == 0) {
868 		struct coredump_req req = {};
869 		int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1;
870 		int exit_code = EXIT_FAILURE;
871 
872 		close(ipc_sockets[0]);
873 
874 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
875 		if (fd_server < 0)
876 			goto out;
877 
878 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
879 			goto out;
880 
881 		close(ipc_sockets[1]);
882 
883 		fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
884 		if (fd_coredump < 0)
885 			goto out;
886 
887 		fd_peer_pidfd = get_peer_pidfd(fd_coredump);
888 		if (fd_peer_pidfd < 0)
889 			goto out;
890 
891 		if (!get_pidfd_info(fd_peer_pidfd, &info))
892 			goto out;
893 
894 		if (!(info.mask & PIDFD_INFO_COREDUMP))
895 			goto out;
896 
897 		if (!(info.coredump_mask & PIDFD_COREDUMPED))
898 			goto out;
899 
900 		if (!read_coredump_req(fd_coredump, &req))
901 			goto out;
902 
903 		if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0,
904 					COREDUMP_KERNEL | COREDUMP_USERSPACE |
905 					COREDUMP_REJECT | COREDUMP_WAIT))
906 			goto out;
907 
908 		if (!send_coredump_ack(fd_coredump, &req,
909 				       COREDUMP_USERSPACE | COREDUMP_WAIT, 0))
910 			goto out;
911 
912 		if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK))
913 			goto out;
914 
915 		for (;;) {
916 			char buffer[4096];
917 			ssize_t bytes_read;
918 
919 			bytes_read = read(fd_coredump, buffer, sizeof(buffer));
920 			if (bytes_read > 0)
921 				goto out;
922 
923 			if (bytes_read < 0)
924 				goto out;
925 
926 			if (bytes_read == 0)
927 				break;
928 		}
929 
930 		exit_code = EXIT_SUCCESS;
931 out:
932 		if (fd_peer_pidfd >= 0)
933 			close(fd_peer_pidfd);
934 		if (fd_coredump >= 0)
935 			close(fd_coredump);
936 		if (fd_server >= 0)
937 			close(fd_server);
938 		_exit(exit_code);
939 	}
940 	self->pid_coredump_server = pid_coredump_server;
941 
942 	EXPECT_EQ(close(ipc_sockets[1]), 0);
943 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
944 	EXPECT_EQ(close(ipc_sockets[0]), 0);
945 
946 	pid = fork();
947 	ASSERT_GE(pid, 0);
948 	if (pid == 0)
949 		crashing_child();
950 
951 	pidfd = sys_pidfd_open(pid, 0);
952 	ASSERT_GE(pidfd, 0);
953 
954 	waitpid(pid, &status, 0);
955 	ASSERT_TRUE(WIFSIGNALED(status));
956 	ASSERT_TRUE(WCOREDUMP(status));
957 
958 	ASSERT_TRUE(get_pidfd_info(pidfd, &info));
959 	ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
960 	ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0);
961 
962 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
963 }
964 
TEST_F(coredump,socket_request_reject)965 TEST_F(coredump, socket_request_reject)
966 {
967 	int pidfd, ret, status;
968 	pid_t pid, pid_coredump_server;
969 	struct pidfd_info info = {};
970 	int ipc_sockets[2];
971 	char c;
972 
973 	ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket"));
974 
975 	ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
976 	ASSERT_EQ(ret, 0);
977 
978 	pid_coredump_server = fork();
979 	ASSERT_GE(pid_coredump_server, 0);
980 	if (pid_coredump_server == 0) {
981 		struct coredump_req req = {};
982 		int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1;
983 		int exit_code = EXIT_FAILURE;
984 
985 		close(ipc_sockets[0]);
986 
987 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
988 		if (fd_server < 0)
989 			goto out;
990 
991 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
992 			goto out;
993 
994 		close(ipc_sockets[1]);
995 
996 		fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
997 		if (fd_coredump < 0)
998 			goto out;
999 
1000 		fd_peer_pidfd = get_peer_pidfd(fd_coredump);
1001 		if (fd_peer_pidfd < 0)
1002 			goto out;
1003 
1004 		if (!get_pidfd_info(fd_peer_pidfd, &info))
1005 			goto out;
1006 
1007 		if (!(info.mask & PIDFD_INFO_COREDUMP))
1008 			goto out;
1009 
1010 		if (!(info.coredump_mask & PIDFD_COREDUMPED))
1011 			goto out;
1012 
1013 		if (!read_coredump_req(fd_coredump, &req))
1014 			goto out;
1015 
1016 		if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0,
1017 					COREDUMP_KERNEL | COREDUMP_USERSPACE |
1018 					COREDUMP_REJECT | COREDUMP_WAIT))
1019 			goto out;
1020 
1021 		if (!send_coredump_ack(fd_coredump, &req,
1022 				       COREDUMP_REJECT | COREDUMP_WAIT, 0))
1023 			goto out;
1024 
1025 		if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK))
1026 			goto out;
1027 
1028 		for (;;) {
1029 			char buffer[4096];
1030 			ssize_t bytes_read;
1031 
1032 			bytes_read = read(fd_coredump, buffer, sizeof(buffer));
1033 			if (bytes_read > 0)
1034 				goto out;
1035 
1036 			if (bytes_read < 0)
1037 				goto out;
1038 
1039 			if (bytes_read == 0)
1040 				break;
1041 		}
1042 
1043 		exit_code = EXIT_SUCCESS;
1044 out:
1045 		if (fd_peer_pidfd >= 0)
1046 			close(fd_peer_pidfd);
1047 		if (fd_coredump >= 0)
1048 			close(fd_coredump);
1049 		if (fd_server >= 0)
1050 			close(fd_server);
1051 		_exit(exit_code);
1052 	}
1053 	self->pid_coredump_server = pid_coredump_server;
1054 
1055 	EXPECT_EQ(close(ipc_sockets[1]), 0);
1056 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
1057 	EXPECT_EQ(close(ipc_sockets[0]), 0);
1058 
1059 	pid = fork();
1060 	ASSERT_GE(pid, 0);
1061 	if (pid == 0)
1062 		crashing_child();
1063 
1064 	pidfd = sys_pidfd_open(pid, 0);
1065 	ASSERT_GE(pidfd, 0);
1066 
1067 	waitpid(pid, &status, 0);
1068 	ASSERT_TRUE(WIFSIGNALED(status));
1069 	ASSERT_FALSE(WCOREDUMP(status));
1070 
1071 	ASSERT_TRUE(get_pidfd_info(pidfd, &info));
1072 	ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
1073 	ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0);
1074 
1075 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
1076 }
1077 
TEST_F(coredump,socket_request_invalid_flag_combination)1078 TEST_F(coredump, socket_request_invalid_flag_combination)
1079 {
1080 	int pidfd, ret, status;
1081 	pid_t pid, pid_coredump_server;
1082 	struct pidfd_info info = {};
1083 	int ipc_sockets[2];
1084 	char c;
1085 
1086 	ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket"));
1087 
1088 	ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
1089 	ASSERT_EQ(ret, 0);
1090 
1091 	pid_coredump_server = fork();
1092 	ASSERT_GE(pid_coredump_server, 0);
1093 	if (pid_coredump_server == 0) {
1094 		struct coredump_req req = {};
1095 		int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1;
1096 		int exit_code = EXIT_FAILURE;
1097 
1098 		close(ipc_sockets[0]);
1099 
1100 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
1101 		if (fd_server < 0)
1102 			goto out;
1103 
1104 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
1105 			goto out;
1106 
1107 		close(ipc_sockets[1]);
1108 
1109 		fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
1110 		if (fd_coredump < 0)
1111 			goto out;
1112 
1113 		fd_peer_pidfd = get_peer_pidfd(fd_coredump);
1114 		if (fd_peer_pidfd < 0)
1115 			goto out;
1116 
1117 		if (!get_pidfd_info(fd_peer_pidfd, &info))
1118 			goto out;
1119 
1120 		if (!(info.mask & PIDFD_INFO_COREDUMP))
1121 			goto out;
1122 
1123 		if (!(info.coredump_mask & PIDFD_COREDUMPED))
1124 			goto out;
1125 
1126 		if (!read_coredump_req(fd_coredump, &req))
1127 			goto out;
1128 
1129 		if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0,
1130 					COREDUMP_KERNEL | COREDUMP_USERSPACE |
1131 					COREDUMP_REJECT | COREDUMP_WAIT))
1132 			goto out;
1133 
1134 		if (!send_coredump_ack(fd_coredump, &req,
1135 				       COREDUMP_KERNEL | COREDUMP_REJECT | COREDUMP_WAIT, 0))
1136 			goto out;
1137 
1138 		if (!read_marker(fd_coredump, COREDUMP_MARK_CONFLICTING))
1139 			goto out;
1140 
1141 		exit_code = EXIT_SUCCESS;
1142 out:
1143 		if (fd_peer_pidfd >= 0)
1144 			close(fd_peer_pidfd);
1145 		if (fd_coredump >= 0)
1146 			close(fd_coredump);
1147 		if (fd_server >= 0)
1148 			close(fd_server);
1149 		_exit(exit_code);
1150 	}
1151 	self->pid_coredump_server = pid_coredump_server;
1152 
1153 	EXPECT_EQ(close(ipc_sockets[1]), 0);
1154 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
1155 	EXPECT_EQ(close(ipc_sockets[0]), 0);
1156 
1157 	pid = fork();
1158 	ASSERT_GE(pid, 0);
1159 	if (pid == 0)
1160 		crashing_child();
1161 
1162 	pidfd = sys_pidfd_open(pid, 0);
1163 	ASSERT_GE(pidfd, 0);
1164 
1165 	waitpid(pid, &status, 0);
1166 	ASSERT_TRUE(WIFSIGNALED(status));
1167 	ASSERT_FALSE(WCOREDUMP(status));
1168 
1169 	ASSERT_TRUE(get_pidfd_info(pidfd, &info));
1170 	ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
1171 	ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0);
1172 
1173 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
1174 }
1175 
TEST_F(coredump,socket_request_unknown_flag)1176 TEST_F(coredump, socket_request_unknown_flag)
1177 {
1178 	int pidfd, ret, status;
1179 	pid_t pid, pid_coredump_server;
1180 	struct pidfd_info info = {};
1181 	int ipc_sockets[2];
1182 	char c;
1183 
1184 	ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket"));
1185 
1186 	ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
1187 	ASSERT_EQ(ret, 0);
1188 
1189 	pid_coredump_server = fork();
1190 	ASSERT_GE(pid_coredump_server, 0);
1191 	if (pid_coredump_server == 0) {
1192 		struct coredump_req req = {};
1193 		int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1;
1194 		int exit_code = EXIT_FAILURE;
1195 
1196 		close(ipc_sockets[0]);
1197 
1198 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
1199 		if (fd_server < 0)
1200 			goto out;
1201 
1202 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
1203 			goto out;
1204 
1205 		close(ipc_sockets[1]);
1206 
1207 		fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
1208 		if (fd_coredump < 0)
1209 			goto out;
1210 
1211 		fd_peer_pidfd = get_peer_pidfd(fd_coredump);
1212 		if (fd_peer_pidfd < 0)
1213 			goto out;
1214 
1215 		if (!get_pidfd_info(fd_peer_pidfd, &info))
1216 			goto out;
1217 
1218 		if (!(info.mask & PIDFD_INFO_COREDUMP))
1219 			goto out;
1220 
1221 		if (!(info.coredump_mask & PIDFD_COREDUMPED))
1222 			goto out;
1223 
1224 		if (!read_coredump_req(fd_coredump, &req))
1225 			goto out;
1226 
1227 		if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0,
1228 					COREDUMP_KERNEL | COREDUMP_USERSPACE |
1229 					COREDUMP_REJECT | COREDUMP_WAIT))
1230 			goto out;
1231 
1232 		if (!send_coredump_ack(fd_coredump, &req, (1ULL << 63), 0))
1233 			goto out;
1234 
1235 		if (!read_marker(fd_coredump, COREDUMP_MARK_UNSUPPORTED))
1236 			goto out;
1237 
1238 		exit_code = EXIT_SUCCESS;
1239 out:
1240 		if (fd_peer_pidfd >= 0)
1241 			close(fd_peer_pidfd);
1242 		if (fd_coredump >= 0)
1243 			close(fd_coredump);
1244 		if (fd_server >= 0)
1245 			close(fd_server);
1246 		_exit(exit_code);
1247 	}
1248 	self->pid_coredump_server = pid_coredump_server;
1249 
1250 	EXPECT_EQ(close(ipc_sockets[1]), 0);
1251 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
1252 	EXPECT_EQ(close(ipc_sockets[0]), 0);
1253 
1254 	pid = fork();
1255 	ASSERT_GE(pid, 0);
1256 	if (pid == 0)
1257 		crashing_child();
1258 
1259 	pidfd = sys_pidfd_open(pid, 0);
1260 	ASSERT_GE(pidfd, 0);
1261 
1262 	waitpid(pid, &status, 0);
1263 	ASSERT_TRUE(WIFSIGNALED(status));
1264 	ASSERT_FALSE(WCOREDUMP(status));
1265 
1266 	ASSERT_TRUE(get_pidfd_info(pidfd, &info));
1267 	ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
1268 	ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0);
1269 
1270 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
1271 }
1272 
TEST_F(coredump,socket_request_invalid_size_small)1273 TEST_F(coredump, socket_request_invalid_size_small)
1274 {
1275 	int pidfd, ret, status;
1276 	pid_t pid, pid_coredump_server;
1277 	struct pidfd_info info = {};
1278 	int ipc_sockets[2];
1279 	char c;
1280 
1281 	ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket"));
1282 
1283 	ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
1284 	ASSERT_EQ(ret, 0);
1285 
1286 	pid_coredump_server = fork();
1287 	ASSERT_GE(pid_coredump_server, 0);
1288 	if (pid_coredump_server == 0) {
1289 		struct coredump_req req = {};
1290 		int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1;
1291 		int exit_code = EXIT_FAILURE;
1292 
1293 		close(ipc_sockets[0]);
1294 
1295 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
1296 		if (fd_server < 0)
1297 			goto out;
1298 
1299 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
1300 			goto out;
1301 
1302 		close(ipc_sockets[1]);
1303 
1304 		fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
1305 		if (fd_coredump < 0)
1306 			goto out;
1307 
1308 		fd_peer_pidfd = get_peer_pidfd(fd_coredump);
1309 		if (fd_peer_pidfd < 0)
1310 			goto out;
1311 
1312 		if (!get_pidfd_info(fd_peer_pidfd, &info))
1313 			goto out;
1314 
1315 		if (!(info.mask & PIDFD_INFO_COREDUMP))
1316 			goto out;
1317 
1318 		if (!(info.coredump_mask & PIDFD_COREDUMPED))
1319 			goto out;
1320 
1321 		if (!read_coredump_req(fd_coredump, &req))
1322 			goto out;
1323 
1324 		if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0,
1325 					COREDUMP_KERNEL | COREDUMP_USERSPACE |
1326 					COREDUMP_REJECT | COREDUMP_WAIT))
1327 			goto out;
1328 
1329 		if (!send_coredump_ack(fd_coredump, &req,
1330 				       COREDUMP_REJECT | COREDUMP_WAIT,
1331 				       COREDUMP_ACK_SIZE_VER0 / 2))
1332 			goto out;
1333 
1334 		if (!read_marker(fd_coredump, COREDUMP_MARK_MINSIZE))
1335 			goto out;
1336 
1337 		exit_code = EXIT_SUCCESS;
1338 out:
1339 		if (fd_peer_pidfd >= 0)
1340 			close(fd_peer_pidfd);
1341 		if (fd_coredump >= 0)
1342 			close(fd_coredump);
1343 		if (fd_server >= 0)
1344 			close(fd_server);
1345 		_exit(exit_code);
1346 	}
1347 	self->pid_coredump_server = pid_coredump_server;
1348 
1349 	EXPECT_EQ(close(ipc_sockets[1]), 0);
1350 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
1351 	EXPECT_EQ(close(ipc_sockets[0]), 0);
1352 
1353 	pid = fork();
1354 	ASSERT_GE(pid, 0);
1355 	if (pid == 0)
1356 		crashing_child();
1357 
1358 	pidfd = sys_pidfd_open(pid, 0);
1359 	ASSERT_GE(pidfd, 0);
1360 
1361 	waitpid(pid, &status, 0);
1362 	ASSERT_TRUE(WIFSIGNALED(status));
1363 	ASSERT_FALSE(WCOREDUMP(status));
1364 
1365 	ASSERT_TRUE(get_pidfd_info(pidfd, &info));
1366 	ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
1367 	ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0);
1368 
1369 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
1370 }
1371 
TEST_F(coredump,socket_request_invalid_size_large)1372 TEST_F(coredump, socket_request_invalid_size_large)
1373 {
1374 	int pidfd, ret, status;
1375 	pid_t pid, pid_coredump_server;
1376 	struct pidfd_info info = {};
1377 	int ipc_sockets[2];
1378 	char c;
1379 
1380 	ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket"));
1381 
1382 	ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
1383 	ASSERT_EQ(ret, 0);
1384 
1385 	pid_coredump_server = fork();
1386 	ASSERT_GE(pid_coredump_server, 0);
1387 	if (pid_coredump_server == 0) {
1388 		struct coredump_req req = {};
1389 		int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1;
1390 		int exit_code = EXIT_FAILURE;
1391 
1392 		close(ipc_sockets[0]);
1393 
1394 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
1395 		if (fd_server < 0)
1396 			goto out;
1397 
1398 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
1399 			goto out;
1400 
1401 		close(ipc_sockets[1]);
1402 
1403 		fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
1404 		if (fd_coredump < 0)
1405 			goto out;
1406 
1407 		fd_peer_pidfd = get_peer_pidfd(fd_coredump);
1408 		if (fd_peer_pidfd < 0)
1409 			goto out;
1410 
1411 		if (!get_pidfd_info(fd_peer_pidfd, &info))
1412 			goto out;
1413 
1414 		if (!(info.mask & PIDFD_INFO_COREDUMP))
1415 			goto out;
1416 
1417 		if (!(info.coredump_mask & PIDFD_COREDUMPED))
1418 			goto out;
1419 
1420 		if (!read_coredump_req(fd_coredump, &req))
1421 			goto out;
1422 
1423 		if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0,
1424 					COREDUMP_KERNEL | COREDUMP_USERSPACE |
1425 					COREDUMP_REJECT | COREDUMP_WAIT))
1426 			goto out;
1427 
1428 		if (!send_coredump_ack(fd_coredump, &req,
1429 				       COREDUMP_REJECT | COREDUMP_WAIT,
1430 				       COREDUMP_ACK_SIZE_VER0 + PAGE_SIZE))
1431 			goto out;
1432 
1433 		if (!read_marker(fd_coredump, COREDUMP_MARK_MAXSIZE))
1434 			goto out;
1435 
1436 		exit_code = EXIT_SUCCESS;
1437 out:
1438 		if (fd_peer_pidfd >= 0)
1439 			close(fd_peer_pidfd);
1440 		if (fd_coredump >= 0)
1441 			close(fd_coredump);
1442 		if (fd_server >= 0)
1443 			close(fd_server);
1444 		_exit(exit_code);
1445 	}
1446 	self->pid_coredump_server = pid_coredump_server;
1447 
1448 	EXPECT_EQ(close(ipc_sockets[1]), 0);
1449 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
1450 	EXPECT_EQ(close(ipc_sockets[0]), 0);
1451 
1452 	pid = fork();
1453 	ASSERT_GE(pid, 0);
1454 	if (pid == 0)
1455 		crashing_child();
1456 
1457 	pidfd = sys_pidfd_open(pid, 0);
1458 	ASSERT_GE(pidfd, 0);
1459 
1460 	waitpid(pid, &status, 0);
1461 	ASSERT_TRUE(WIFSIGNALED(status));
1462 	ASSERT_FALSE(WCOREDUMP(status));
1463 
1464 	ASSERT_TRUE(get_pidfd_info(pidfd, &info));
1465 	ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
1466 	ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0);
1467 
1468 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
1469 }
1470 
open_coredump_tmpfile(int fd_tmpfs_detached)1471 static int open_coredump_tmpfile(int fd_tmpfs_detached)
1472 {
1473 	return openat(fd_tmpfs_detached, ".", O_TMPFILE | O_RDWR | O_EXCL, 0600);
1474 }
1475 
1476 #define NUM_CRASHING_COREDUMPS 5
1477 
1478 TEST_F_TIMEOUT(coredump, socket_multiple_crashing_coredumps, 500)
1479 {
1480 	int pidfd[NUM_CRASHING_COREDUMPS], status[NUM_CRASHING_COREDUMPS];
1481 	pid_t pid[NUM_CRASHING_COREDUMPS], pid_coredump_server;
1482 	struct pidfd_info info = {};
1483 	int ipc_sockets[2];
1484 	char c;
1485 
1486 	ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket"));
1487 
1488 	ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets), 0);
1489 
1490 	pid_coredump_server = fork();
1491 	ASSERT_GE(pid_coredump_server, 0);
1492 	if (pid_coredump_server == 0) {
1493 		int fd_server = -1, fd_coredump = -1, fd_peer_pidfd = -1, fd_core_file = -1;
1494 		int exit_code = EXIT_FAILURE;
1495 		struct coredump_req req = {};
1496 
1497 		close(ipc_sockets[0]);
1498 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
1499 		if (fd_server < 0) {
1500 			fprintf(stderr, "Failed to create and listen on unix socket\n");
1501 			goto out;
1502 		}
1503 
1504 		if (write_nointr(ipc_sockets[1], "1", 1) < 0) {
1505 			fprintf(stderr, "Failed to notify parent via ipc socket\n");
1506 			goto out;
1507 		}
1508 		close(ipc_sockets[1]);
1509 
1510 		for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) {
1511 			fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
1512 			if (fd_coredump < 0) {
1513 				fprintf(stderr, "accept4 failed: %m\n");
1514 				goto out;
1515 			}
1516 
1517 			fd_peer_pidfd = get_peer_pidfd(fd_coredump);
1518 			if (fd_peer_pidfd < 0) {
1519 				fprintf(stderr, "get_peer_pidfd failed for fd %d: %m\n", fd_coredump);
1520 				goto out;
1521 			}
1522 
1523 			if (!get_pidfd_info(fd_peer_pidfd, &info)) {
1524 				fprintf(stderr, "get_pidfd_info failed for fd %d\n", fd_peer_pidfd);
1525 				goto out;
1526 			}
1527 
1528 			if (!(info.mask & PIDFD_INFO_COREDUMP)) {
1529 				fprintf(stderr, "pidfd info missing PIDFD_INFO_COREDUMP for fd %d\n", fd_peer_pidfd);
1530 				goto out;
1531 			}
1532 			if (!(info.coredump_mask & PIDFD_COREDUMPED)) {
1533 				fprintf(stderr, "pidfd info missing PIDFD_COREDUMPED for fd %d\n", fd_peer_pidfd);
1534 				goto out;
1535 			}
1536 
1537 			if (!read_coredump_req(fd_coredump, &req)) {
1538 				fprintf(stderr, "read_coredump_req failed for fd %d\n", fd_coredump);
1539 				goto out;
1540 			}
1541 
1542 			if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0,
1543 						COREDUMP_KERNEL | COREDUMP_USERSPACE |
1544 						COREDUMP_REJECT | COREDUMP_WAIT)) {
1545 				fprintf(stderr, "check_coredump_req failed for fd %d\n", fd_coredump);
1546 				goto out;
1547 			}
1548 
1549 			if (!send_coredump_ack(fd_coredump, &req,
1550 					       COREDUMP_KERNEL | COREDUMP_WAIT, 0)) {
1551 				fprintf(stderr, "send_coredump_ack failed for fd %d\n", fd_coredump);
1552 				goto out;
1553 			}
1554 
1555 			if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK)) {
1556 				fprintf(stderr, "read_marker failed for fd %d\n", fd_coredump);
1557 				goto out;
1558 			}
1559 
1560 			fd_core_file = open_coredump_tmpfile(self->fd_tmpfs_detached);
1561 			if (fd_core_file < 0) {
1562 				fprintf(stderr, "%m - open_coredump_tmpfile failed for fd %d\n", fd_coredump);
1563 				goto out;
1564 			}
1565 
1566 			for (;;) {
1567 				char buffer[4096];
1568 				ssize_t bytes_read, bytes_write;
1569 
1570 				bytes_read = read(fd_coredump, buffer, sizeof(buffer));
1571 				if (bytes_read < 0) {
1572 					fprintf(stderr, "read failed for fd %d: %m\n", fd_coredump);
1573 					goto out;
1574 				}
1575 
1576 				if (bytes_read == 0)
1577 					break;
1578 
1579 				bytes_write = write(fd_core_file, buffer, bytes_read);
1580 				if (bytes_read != bytes_write) {
1581 					fprintf(stderr, "write failed for fd %d: %m\n", fd_core_file);
1582 					goto out;
1583 				}
1584 			}
1585 
1586 			close(fd_core_file);
1587 			close(fd_peer_pidfd);
1588 			close(fd_coredump);
1589 			fd_peer_pidfd = -1;
1590 			fd_coredump = -1;
1591 		}
1592 
1593 		exit_code = EXIT_SUCCESS;
1594 out:
1595 		if (fd_core_file >= 0)
1596 			close(fd_core_file);
1597 		if (fd_peer_pidfd >= 0)
1598 			close(fd_peer_pidfd);
1599 		if (fd_coredump >= 0)
1600 			close(fd_coredump);
1601 		if (fd_server >= 0)
1602 			close(fd_server);
1603 		_exit(exit_code);
1604 	}
1605 	self->pid_coredump_server = pid_coredump_server;
1606 
1607 	EXPECT_EQ(close(ipc_sockets[1]), 0);
1608 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
1609 	EXPECT_EQ(close(ipc_sockets[0]), 0);
1610 
1611 	for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) {
1612 		pid[i] = fork();
1613 		ASSERT_GE(pid[i], 0);
1614 		if (pid[i] == 0)
1615 			crashing_child();
1616 		pidfd[i] = sys_pidfd_open(pid[i], 0);
1617 		ASSERT_GE(pidfd[i], 0);
1618 	}
1619 
1620 	for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) {
1621 		waitpid(pid[i], &status[i], 0);
1622 		ASSERT_TRUE(WIFSIGNALED(status[i]));
1623 		ASSERT_TRUE(WCOREDUMP(status[i]));
1624 	}
1625 
1626 	for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) {
1627 		info.mask = PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP;
1628 		ASSERT_EQ(ioctl(pidfd[i], PIDFD_GET_INFO, &info), 0);
1629 		ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
1630 		ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0);
1631 	}
1632 
1633 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
1634 }
1635 
1636 #define MAX_EVENTS 128
1637 
process_coredump_worker(int fd_coredump,int fd_peer_pidfd,int fd_core_file)1638 static void process_coredump_worker(int fd_coredump, int fd_peer_pidfd, int fd_core_file)
1639 {
1640 	int epfd = -1;
1641 	int exit_code = EXIT_FAILURE;
1642 
1643 	epfd = epoll_create1(0);
1644 	if (epfd < 0)
1645 		goto out;
1646 
1647 	struct epoll_event ev;
1648 	ev.events = EPOLLIN | EPOLLRDHUP | EPOLLET;
1649 	ev.data.fd = fd_coredump;
1650 	if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd_coredump, &ev) < 0)
1651 		goto out;
1652 
1653 	for (;;) {
1654 		struct epoll_event events[1];
1655 		int n = epoll_wait(epfd, events, 1, -1);
1656 		if (n < 0)
1657 			break;
1658 
1659 		if (events[0].events & (EPOLLIN | EPOLLRDHUP)) {
1660 			for (;;) {
1661 				char buffer[4096];
1662 				ssize_t bytes_read = read(fd_coredump, buffer, sizeof(buffer));
1663 				if (bytes_read < 0) {
1664 					if (errno == EAGAIN || errno == EWOULDBLOCK)
1665 						break;
1666 					goto out;
1667 				}
1668 				if (bytes_read == 0)
1669 					goto done;
1670 				ssize_t bytes_write = write(fd_core_file, buffer, bytes_read);
1671 				if (bytes_write != bytes_read)
1672 					goto out;
1673 			}
1674 		}
1675 	}
1676 
1677 done:
1678 	exit_code = EXIT_SUCCESS;
1679 out:
1680 	if (epfd >= 0)
1681 		close(epfd);
1682 	if (fd_core_file >= 0)
1683 		close(fd_core_file);
1684 	if (fd_peer_pidfd >= 0)
1685 		close(fd_peer_pidfd);
1686 	if (fd_coredump >= 0)
1687 		close(fd_coredump);
1688 	_exit(exit_code);
1689 }
1690 
1691 TEST_F_TIMEOUT(coredump, socket_multiple_crashing_coredumps_epoll_workers, 500)
1692 {
1693 	int pidfd[NUM_CRASHING_COREDUMPS], status[NUM_CRASHING_COREDUMPS];
1694 	pid_t pid[NUM_CRASHING_COREDUMPS], pid_coredump_server, worker_pids[NUM_CRASHING_COREDUMPS];
1695 	struct pidfd_info info = {};
1696 	int ipc_sockets[2];
1697 	char c;
1698 
1699 	ASSERT_TRUE(set_core_pattern("@@/tmp/coredump.socket"));
1700 	ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets), 0);
1701 
1702 	pid_coredump_server = fork();
1703 	ASSERT_GE(pid_coredump_server, 0);
1704 	if (pid_coredump_server == 0) {
1705 		int fd_server = -1, exit_code = EXIT_FAILURE, n_conns = 0;
1706 		fd_server = -1;
1707 		exit_code = EXIT_FAILURE;
1708 		n_conns = 0;
1709 		close(ipc_sockets[0]);
1710 		fd_server = create_and_listen_unix_socket("/tmp/coredump.socket");
1711 		if (fd_server < 0)
1712 			goto out;
1713 
1714 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
1715 			goto out;
1716 		close(ipc_sockets[1]);
1717 
1718 		while (n_conns < NUM_CRASHING_COREDUMPS) {
1719 			int fd_coredump = -1, fd_peer_pidfd = -1, fd_core_file = -1;
1720 			struct coredump_req req = {};
1721 			fd_coredump = accept4(fd_server, NULL, NULL, SOCK_CLOEXEC);
1722 			if (fd_coredump < 0) {
1723 				if (errno == EAGAIN || errno == EWOULDBLOCK)
1724 					continue;
1725 				goto out;
1726 			}
1727 			fd_peer_pidfd = get_peer_pidfd(fd_coredump);
1728 			if (fd_peer_pidfd < 0)
1729 				goto out;
1730 			if (!get_pidfd_info(fd_peer_pidfd, &info))
1731 				goto out;
1732 			if (!(info.mask & PIDFD_INFO_COREDUMP) || !(info.coredump_mask & PIDFD_COREDUMPED))
1733 				goto out;
1734 			if (!read_coredump_req(fd_coredump, &req))
1735 				goto out;
1736 			if (!check_coredump_req(&req, COREDUMP_ACK_SIZE_VER0,
1737 						COREDUMP_KERNEL | COREDUMP_USERSPACE |
1738 						COREDUMP_REJECT | COREDUMP_WAIT))
1739 				goto out;
1740 			if (!send_coredump_ack(fd_coredump, &req, COREDUMP_KERNEL | COREDUMP_WAIT, 0))
1741 				goto out;
1742 			if (!read_marker(fd_coredump, COREDUMP_MARK_REQACK))
1743 				goto out;
1744 			fd_core_file = open_coredump_tmpfile(self->fd_tmpfs_detached);
1745 			if (fd_core_file < 0)
1746 				goto out;
1747 			pid_t worker = fork();
1748 			if (worker == 0) {
1749 				close(fd_server);
1750 				process_coredump_worker(fd_coredump, fd_peer_pidfd, fd_core_file);
1751 			}
1752 			worker_pids[n_conns] = worker;
1753 			if (fd_coredump >= 0)
1754 				close(fd_coredump);
1755 			if (fd_peer_pidfd >= 0)
1756 				close(fd_peer_pidfd);
1757 			if (fd_core_file >= 0)
1758 				close(fd_core_file);
1759 			n_conns++;
1760 		}
1761 		exit_code = EXIT_SUCCESS;
1762 out:
1763 		if (fd_server >= 0)
1764 			close(fd_server);
1765 
1766 		// Reap all worker processes
1767 		for (int i = 0; i < n_conns; i++) {
1768 			int wstatus;
1769 			if (waitpid(worker_pids[i], &wstatus, 0) < 0) {
1770 				fprintf(stderr, "Failed to wait for worker %d: %m\n", worker_pids[i]);
1771 			} else if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != EXIT_SUCCESS) {
1772 				fprintf(stderr, "Worker %d exited with error code %d\n", worker_pids[i], WEXITSTATUS(wstatus));
1773 				exit_code = EXIT_FAILURE;
1774 			}
1775 		}
1776 
1777 		_exit(exit_code);
1778 	}
1779 	self->pid_coredump_server = pid_coredump_server;
1780 
1781 	EXPECT_EQ(close(ipc_sockets[1]), 0);
1782 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
1783 	EXPECT_EQ(close(ipc_sockets[0]), 0);
1784 
1785 	for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) {
1786 		pid[i] = fork();
1787 		ASSERT_GE(pid[i], 0);
1788 		if (pid[i] == 0)
1789 			crashing_child();
1790 		pidfd[i] = sys_pidfd_open(pid[i], 0);
1791 		ASSERT_GE(pidfd[i], 0);
1792 	}
1793 
1794 	for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) {
1795 		ASSERT_GE(waitpid(pid[i], &status[i], 0), 0);
1796 		ASSERT_TRUE(WIFSIGNALED(status[i]));
1797 		ASSERT_TRUE(WCOREDUMP(status[i]));
1798 	}
1799 
1800 	for (int i = 0; i < NUM_CRASHING_COREDUMPS; i++) {
1801 		info.mask = PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP;
1802 		ASSERT_EQ(ioctl(pidfd[i], PIDFD_GET_INFO, &info), 0);
1803 		ASSERT_GT((info.mask & PIDFD_INFO_COREDUMP), 0);
1804 		ASSERT_GT((info.coredump_mask & PIDFD_COREDUMPED), 0);
1805 	}
1806 
1807 	wait_and_check_coredump_server(pid_coredump_server, _metadata, self);
1808 }
1809 
TEST_F(coredump,socket_invalid_paths)1810 TEST_F(coredump, socket_invalid_paths)
1811 {
1812 	ASSERT_FALSE(set_core_pattern("@ /tmp/coredump.socket"));
1813 	ASSERT_FALSE(set_core_pattern("@/tmp/../coredump.socket"));
1814 	ASSERT_FALSE(set_core_pattern("@../coredump.socket"));
1815 	ASSERT_FALSE(set_core_pattern("@/tmp/coredump.socket/.."));
1816 	ASSERT_FALSE(set_core_pattern("@.."));
1817 
1818 	ASSERT_FALSE(set_core_pattern("@@ /tmp/coredump.socket"));
1819 	ASSERT_FALSE(set_core_pattern("@@/tmp/../coredump.socket"));
1820 	ASSERT_FALSE(set_core_pattern("@@../coredump.socket"));
1821 	ASSERT_FALSE(set_core_pattern("@@/tmp/coredump.socket/.."));
1822 	ASSERT_FALSE(set_core_pattern("@@.."));
1823 
1824 	ASSERT_FALSE(set_core_pattern("@@@/tmp/coredump.socket"));
1825 }
1826 
1827 TEST_HARNESS_MAIN
1828