xref: /linux/tools/testing/selftests/coredump/coredump_test_helpers.c (revision a6656aefd328d544420ecec121fc898b7f067827)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <assert.h>
4 #include <elf.h>
5 #include <endian.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <limits.h>
9 #include <link.h>
10 #include <linux/stddef.h>
11 #include <linux/io_uring.h>
12 #include <linux/swab.h>
13 #include <linux/coredump.h>
14 #include <linux/fs.h>
15 #include <poll.h>
16 #include <pthread.h>
17 #include <stdbool.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/epoll.h>
22 #include <sys/ioctl.h>
23 #include <sys/mman.h>
24 #include <sys/socket.h>
25 #include <sys/stat.h>
26 #include <sys/syscall.h>
27 #include <sys/types.h>
28 #include <sys/un.h>
29 #include <sys/wait.h>
30 #include <unistd.h>
31 
32 #include "../filesystems/wrappers.h"
33 #include "coredump_notify_signal.h"
34 
35 #include "coredump_test_helpers.h"
36 
37 #if __ELF_NATIVE_CLASS == 64
38 #define COREDUMP_ELFCLASS ELFCLASS64
39 #else
40 #define COREDUMP_ELFCLASS ELFCLASS32
41 #endif
42 
43 #ifndef SO_PEERPIDFD_THREAD
44 #define SO_PEERPIDFD_THREAD 87
45 #endif
46 
do_nothing(void * arg)47 void *do_nothing(void *arg)
48 {
49 	(void)arg;
50 	while (1)
51 		pause();
52 
53 	return NULL;
54 }
55 
crashing_child(void)56 void crashing_child(void)
57 {
58 	pthread_t thread;
59 	int i;
60 
61 	for (i = 0; i < NUM_THREAD_SPAWN; ++i)
62 		pthread_create(&thread, NULL, do_nothing, NULL);
63 
64 	/* crash on purpose */
65 	i = *(volatile int *)NULL;
66 }
67 
crashing_child_sparse(size_t size)68 void crashing_child_sparse(size_t size)
69 {
70 	char *p;
71 
72 	/*
73 	 * Touch the first and the last page. This will cause the whole mapping
74 	 * to be dumped because it has been written to. Everything between
75 	 * those two pages is a hole though.
76 	 */
77 	p = mmap(NULL, size, PROT_READ | PROT_WRITE,
78 		 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
79 	if (p != MAP_FAILED) {
80 		p[0] = 'x';
81 		p[size - 1] = 'x';
82 	}
83 
84 	/* crash on purpose */
85 	*(volatile int *)NULL = 0;
86 }
87 
88 /* Select @types through the caller's own /proc/self/coredump_filter. */
set_coredump_filter(__u64 types)89 static bool set_coredump_filter(__u64 types)
90 {
91 	char buf[32];
92 	int fd, len;
93 	bool ok;
94 
95 	fd = open("/proc/self/coredump_filter", O_WRONLY | O_CLOEXEC);
96 	if (fd < 0)
97 		return false;
98 
99 	len = snprintf(buf, sizeof(buf), "0x%llx", (unsigned long long)types);
100 	ok = write_nointr(fd, buf, len) == len;
101 	close(fd);
102 	return ok;
103 }
104 
105 /*
106  * Map shared anonymous memory, touch it, tell the server where it is and
107  * crash. A @task_filter other than FILTER_TASK_INHERIT is selected first.
108  */
crashing_child_memory(__u64 task_filter,int fd_addr)109 void crashing_child_memory(__u64 task_filter, int fd_addr)
110 {
111 	char *p;
112 
113 	if (task_filter != FILTER_TASK_INHERIT && !set_coredump_filter(task_filter))
114 		_exit(EXIT_FAILURE);
115 
116 	p = mmap(NULL, MEMORY_MAPPING_SIZE, PROT_READ | PROT_WRITE,
117 		 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
118 	if (p == MAP_FAILED)
119 		_exit(EXIT_FAILURE);
120 	p[0] = 'x';
121 
122 	if (write_nointr(fd_addr, &p, sizeof(p)) != sizeof(p))
123 		_exit(EXIT_FAILURE);
124 	close(fd_addr);
125 
126 	/* crash on purpose */
127 	*(volatile int *)NULL = 0;
128 }
129 
130 /* Sink a reassembled record stream is handed to, record by record. */
131 struct coredump_record_sink {
132 	/* @len bytes of coredump data that belong at @offset. */
133 	int (*data)(void *ctx, const void *buf, size_t len, __u64 offset);
134 	/* @len zero bytes that belong at @offset. */
135 	int (*zero)(void *ctx, __u64 offset, __u64 len);
136 	void *ctx;
137 };
138 
139 /* Read @len bytes off the socket and hand them to @sink, if there is one. */
recv_record_bytes(int fd_coredump,__u64 len,const struct coredump_record_sink * sink,__u64 offset)140 static ssize_t recv_record_bytes(int fd_coredump, __u64 len,
141 				 const struct coredump_record_sink *sink,
142 				 __u64 offset)
143 {
144 	ssize_t received = 0;
145 
146 	while (len) {
147 		char buffer[PAGE_SIZE];
148 		size_t chunk = len < sizeof(buffer) ? len : sizeof(buffer);
149 		ssize_t ret;
150 
151 		ret = recv(fd_coredump, buffer, chunk, MSG_WAITALL);
152 		if (ret <= 0) {
153 			fprintf(stderr, "%s: short read %zd: %m\n",
154 				__func__, ret);
155 			return -1;
156 		}
157 
158 		if (sink && sink->data(sink->ctx, buffer, ret, offset + received))
159 			return -1;
160 
161 		received += ret;
162 		len -= ret;
163 	}
164 
165 	return received;
166 }
167 
168 /* Put the data where the records say it goes and leave the holes alone. */
file_sink_data(void * ctx,const void * buf,size_t len,__u64 offset)169 static int file_sink_data(void *ctx, const void *buf, size_t len, __u64 offset)
170 {
171 	int fd = *(int *)ctx;
172 
173 	if (pwrite(fd, buf, len, offset) != (ssize_t)len) {
174 		fprintf(stderr, "%s: pwrite failed: %m\n", __func__);
175 		return -1;
176 	}
177 
178 	return 0;
179 }
180 
file_sink_zero(void * ctx,__u64 offset,__u64 len)181 static int file_sink_zero(void *ctx, __u64 offset, __u64 len)
182 {
183 	/* Nothing has to be written for a hole. */
184 	return 0;
185 }
186 
187 /*
188  * Read a coredump strea and funnel it into @sink. Allow to pass in a
189  * @fd_peer_pidfd to simulate coredump truncation by killing it after having
190  * received a coredump record.
191  */
__recv_coredump_records(int fd_coredump,const struct coredump_record_sink * sink,off_t * coredump_size,bool * truncated,int fd_peer_pidfd)192 static ssize_t __recv_coredump_records(int fd_coredump,
193 				       const struct coredump_record_sink *sink,
194 				       off_t *coredump_size, bool *truncated,
195 				       int fd_peer_pidfd)
196 {
197 	ssize_t received = 0;
198 	off_t size = 0;
199 	bool is_truncated = false;
200 	bool ended = false;
201 	char trailing;
202 
203 	while (!ended) {
204 		struct coredump_record_header record = {};
205 		size_t known_size;
206 		ssize_t ret;
207 
208 		/* Peek the header size the way read_coredump_req() does. */
209 		ret = recv(fd_coredump, &record, sizeof(record.size),
210 			   MSG_PEEK | MSG_WAITALL);
211 		if (ret == 0) {
212 			/* Nothing closed the stream, so the coredump was cut short. */
213 			if (truncated) {
214 				is_truncated = true;
215 				break;
216 			}
217 			fprintf(stderr, "%s: stream ended without an end record\n",
218 				__func__);
219 			return -1;
220 		}
221 		if (ret != sizeof(record.size)) {
222 			fprintf(stderr, "%s: short record peek %zd: %m\n",
223 				__func__, ret);
224 			return -1;
225 		}
226 
227 		if (record.size < COREDUMP_RECORD_HEADER_SIZE_VER0) {
228 			fprintf(stderr, "%s: header size %u below minimum %u\n",
229 				__func__, record.size,
230 				COREDUMP_RECORD_HEADER_SIZE_VER0);
231 			return -1;
232 		}
233 
234 		/* Consume as much of the header as we know about. */
235 		known_size = record.size < sizeof(record) ? record.size : sizeof(record);
236 		ret = recv(fd_coredump, &record, known_size, MSG_WAITALL);
237 		if (ret != (ssize_t)known_size) {
238 			fprintf(stderr, "%s: short record read %zd: %m\n",
239 				__func__, ret);
240 			return -1;
241 		}
242 		received += ret;
243 
244 		/*
245 		 * A flag changes what the record means, so refuse one we
246 		 * don't know rather than guess.
247 		 */
248 		if (record.flags) {
249 			fprintf(stderr, "%s: unknown header flags 0x%llx\n",
250 				__func__, (unsigned long long)record.flags);
251 			return -1;
252 		}
253 
254 		/* Discard any part of the header we have no use for. */
255 		ret = recv_record_bytes(fd_coredump, record.size - known_size,
256 					NULL, 0);
257 		if (ret < 0)
258 			return -1;
259 		received += ret;
260 
261 		/* Records are sent in order and they don't leave gaps. */
262 		if (record.offset != (__u64)size) {
263 			fprintf(stderr, "%s: record at %llu, expected %llu\n",
264 				__func__, (unsigned long long)record.offset,
265 				(unsigned long long)size);
266 			return -1;
267 		}
268 
269 		switch (record.type) {
270 		case COREDUMP_RECORD_ZERO:
271 			/* A hole. It comes with no data and needs none. */
272 			if (sink->zero(sink->ctx, record.offset, record.len))
273 				return -1;
274 			break;
275 		case COREDUMP_RECORD_DATA:
276 			ret = recv_record_bytes(fd_coredump, record.len, sink,
277 						record.offset);
278 			if (ret < 0)
279 				return -1;
280 			received += ret;
281 			if (fd_peer_pidfd >= 0) {
282 				if (sys_pidfd_send_signal(fd_peer_pidfd, SIGKILL,
283 							  NULL, 0)) {
284 					fprintf(stderr, "%s: kill failed: %m\n",
285 						__func__);
286 					return -1;
287 				}
288 				fd_peer_pidfd = -1;
289 			}
290 			break;
291 		case COREDUMP_RECORD_END:
292 			/* The coredump ends here and nothing follows it. */
293 			if (record.len) {
294 				fprintf(stderr, "%s: end record covers %llu bytes\n",
295 					__func__,
296 					(unsigned long long)record.len);
297 				return -1;
298 			}
299 			ended = true;
300 			break;
301 		default:
302 			fprintf(stderr, "%s: unknown record type %u\n",
303 				__func__, record.type);
304 			return -1;
305 		}
306 
307 		size += record.len;
308 	}
309 
310 	/* The end record is the last thing on the wire. */
311 	if (recv(fd_coredump, &trailing, sizeof(trailing), MSG_DONTWAIT) > 0) {
312 		fprintf(stderr, "%s: data after the end record\n", __func__);
313 		return -1;
314 	}
315 
316 	if (truncated)
317 		*truncated = is_truncated;
318 
319 	*coredump_size = size;
320 
321 	fprintf(stderr, "Received %zd bytes for a %s coredump of %llu bytes\n",
322 		received, is_truncated ? "truncated" : "complete",
323 		(unsigned long long)size);
324 	return received;
325 }
326 
327 /* Reassemble a record stream into the coredump it describes. */
recv_coredump_records(int fd_coredump,int fd_core_file,off_t * coredump_size,bool * truncated,int fd_peer_pidfd)328 ssize_t recv_coredump_records(int fd_coredump, int fd_core_file,
329 			      off_t *coredump_size, bool *truncated,
330 			      int fd_peer_pidfd)
331 {
332 	struct coredump_record_sink sink = {
333 		.data	= file_sink_data,
334 		.zero	= file_sink_zero,
335 		.ctx	= &fd_core_file,
336 	};
337 	ssize_t received;
338 	off_t size = 0;
339 
340 	received = __recv_coredump_records(fd_coredump, &sink, &size, truncated,
341 					   fd_peer_pidfd);
342 	if (received < 0)
343 		return -1;
344 
345 	/*
346 	 * Nothing is written for a hole, so grow the file to the size the
347 	 * records describe in case the coredump ended in one.
348 	 */
349 	if (ftruncate(fd_core_file, size) < 0) {
350 		fprintf(stderr, "%s: ftruncate to %llu failed: %m\n",
351 			__func__, (unsigned long long)size);
352 		return -1;
353 	}
354 
355 	if (coredump_size)
356 		*coredump_size = size;
357 
358 	return received;
359 }
360 
361 /* The ELF header of a native core file. */
is_core_ehdr(const ElfW (Ehdr)* ehdr)362 static bool is_core_ehdr(const ElfW(Ehdr) *ehdr)
363 {
364 	return !memcmp(ehdr->e_ident, ELFMAG, SELFMAG) &&
365 	       ehdr->e_ident[EI_CLASS] == COREDUMP_ELFCLASS &&
366 	       ehdr->e_type == ET_CORE;
367 }
368 
369 /* Whatever the server ends up with has to be an ELF core file. */
is_elf_core(int fd)370 bool is_elf_core(int fd)
371 {
372 	ElfW(Ehdr) ehdr;
373 
374 	if (pread(fd, &ehdr, sizeof(ehdr), 0) != sizeof(ehdr)) {
375 		fprintf(stderr, "%s: short read: %m\n", __func__);
376 		return false;
377 	}
378 
379 	if (!is_core_ehdr(&ehdr)) {
380 		fprintf(stderr, "%s: not an ELF core file\n", __func__);
381 		return false;
382 	}
383 
384 	return true;
385 }
386 
387 /*
388  * A coredump server that uploads to a blob store can't upload a sparse
389  * file and can't seek in the object it is uploading. It streams the data
390  * records into the object as they arrive, remembers the holes it left
391  * out, and uploads the program header table that describes the result
392  * last. What comes out is an ordinary ELF core file without the holes.
393  */
394 
395 /* A run of the coredump the object doesn't carry. */
396 struct compact_hole {
397 	__u64 offset;
398 	__u64 len;
399 };
400 
401 /* A program header of the object and where its bytes sat in the coredump. */
402 struct compact_piece {
403 	ElfW(Phdr) phdr;
404 	__u64 src;
405 };
406 
407 struct compact_ctx {
408 	int fd_body;			/* the object's payload, append only */
409 	int fd_reference;		/* the coredump with its holes, for the test */
410 	unsigned char *head;		/* everything ahead of the segment data */
411 	size_t head_len;
412 	size_t head_cap;
413 	__u64 data_offset;		/* where the segment data starts, 0 while unknown */
414 	struct compact_hole *holes;
415 	size_t nr_holes;
416 	size_t holes_cap;
417 	__u64 body_len;
418 };
419 
420 /* Write @len bytes out, short writes and all. */
compact_write(int fd,const void * buf,size_t len)421 static int compact_write(int fd, const void *buf, size_t len)
422 {
423 	const unsigned char *pos = buf;
424 
425 	while (len) {
426 		ssize_t ret = write(fd, pos, len);
427 
428 		if (ret <= 0) {
429 			fprintf(stderr, "%s: write failed: %m\n", __func__);
430 			return -1;
431 		}
432 
433 		pos += ret;
434 		len -= ret;
435 	}
436 
437 	return 0;
438 }
439 
440 /* Keep @len bytes of the head, or @len zeroes if @buf is NULL. */
compact_head_append(struct compact_ctx * ctx,const void * buf,size_t len)441 static int compact_head_append(struct compact_ctx *ctx, const void *buf,
442 			       size_t len)
443 {
444 	if (ctx->head_len + len > ctx->head_cap) {
445 		size_t cap = ctx->head_cap ? ctx->head_cap : PAGE_SIZE;
446 		unsigned char *head;
447 
448 		while (cap < ctx->head_len + len)
449 			cap *= 2;
450 
451 		head = realloc(ctx->head, cap);
452 		if (!head) {
453 			fprintf(stderr, "%s: out of memory\n", __func__);
454 			return -1;
455 		}
456 		ctx->head = head;
457 		ctx->head_cap = cap;
458 	}
459 
460 	if (buf)
461 		memcpy(ctx->head + ctx->head_len, buf, len);
462 	else
463 		memset(ctx->head + ctx->head_len, 0, len);
464 	ctx->head_len += len;
465 
466 	return 0;
467 }
468 
469 /* Remember a hole so the program header table can account for it later. */
compact_keep_hole(struct compact_ctx * ctx,__u64 offset,__u64 len)470 static int compact_keep_hole(struct compact_ctx *ctx, __u64 offset, __u64 len)
471 {
472 	if (ctx->nr_holes == ctx->holes_cap) {
473 		size_t cap = ctx->holes_cap ? ctx->holes_cap * 2 : 64;
474 		struct compact_hole *holes;
475 
476 		holes = realloc(ctx->holes, cap * sizeof(*holes));
477 		if (!holes) {
478 			fprintf(stderr, "%s: out of memory\n", __func__);
479 			return -1;
480 		}
481 		ctx->holes = holes;
482 		ctx->holes_cap = cap;
483 	}
484 
485 	ctx->holes[ctx->nr_holes].offset = offset;
486 	ctx->holes[ctx->nr_holes].len = len;
487 	ctx->nr_holes++;
488 
489 	return 0;
490 }
491 
492 /* The segment data starts where the first PT_LOAD points. */
compact_probe(struct compact_ctx * ctx)493 static int compact_probe(struct compact_ctx *ctx)
494 {
495 	const ElfW(Ehdr) *ehdr = (const ElfW(Ehdr) *)ctx->head;
496 	const ElfW(Phdr) *phdr;
497 	size_t i;
498 
499 	if (ctx->data_offset || ctx->head_len < sizeof(*ehdr))
500 		return 0;
501 
502 	if (!is_core_ehdr(ehdr)) {
503 		fprintf(stderr, "%s: not an ELF core file\n", __func__);
504 		return -1;
505 	}
506 
507 	if (ehdr->e_phoff != sizeof(*ehdr) ||
508 	    ehdr->e_phentsize != sizeof(ElfW(Phdr)) ||
509 	    ehdr->e_phnum == 0 || ehdr->e_phnum == PN_XNUM) {
510 		fprintf(stderr, "%s: unhandled program header table\n", __func__);
511 		return -1;
512 	}
513 
514 	if (ctx->head_len < ehdr->e_phoff +
515 			    (size_t)ehdr->e_phnum * ehdr->e_phentsize)
516 		return 0;
517 
518 	phdr = (const ElfW(Phdr) *)(ctx->head + ehdr->e_phoff);
519 	for (i = 0; i < ehdr->e_phnum; i++) {
520 		if (phdr[i].p_type != PT_LOAD)
521 			continue;
522 		if (!ctx->data_offset || phdr[i].p_offset < ctx->data_offset)
523 			ctx->data_offset = phdr[i].p_offset;
524 	}
525 
526 	if (!ctx->data_offset) {
527 		fprintf(stderr, "%s: coredump without a single segment\n",
528 			__func__);
529 		return -1;
530 	}
531 
532 	return 0;
533 }
534 
535 /*
536  * Take whatever of [@offset, @offset + @len) still belongs to the head.
537  * @buf is NULL for a hole. Returns how much was taken.
538  */
compact_head_take(struct compact_ctx * ctx,const void * buf,__u64 offset,__u64 len)539 static ssize_t compact_head_take(struct compact_ctx *ctx, const void *buf,
540 				 __u64 offset, __u64 len)
541 {
542 	__u64 chunk;
543 
544 	if (!len || (ctx->data_offset && offset >= ctx->data_offset))
545 		return 0;
546 
547 	chunk = len;
548 	if (ctx->data_offset && offset + chunk > ctx->data_offset)
549 		chunk = ctx->data_offset - offset;
550 
551 	if (offset != ctx->head_len) {
552 		fprintf(stderr, "%s: head has a gap at %llu\n", __func__,
553 			(unsigned long long)offset);
554 		return -1;
555 	}
556 
557 	if (compact_head_append(ctx, buf, chunk))
558 		return -1;
559 
560 	return chunk;
561 }
562 
compact_data(void * arg,const void * buf,size_t len,__u64 offset)563 static int compact_data(void *arg, const void *buf, size_t len, __u64 offset)
564 {
565 	struct compact_ctx *ctx = arg;
566 	const unsigned char *pos = buf;
567 	ssize_t head;
568 
569 	/* Only the test needs a coredump with the holes still in it. */
570 	if (pwrite(ctx->fd_reference, pos, len, offset) != (ssize_t)len) {
571 		fprintf(stderr, "%s: pwrite failed: %m\n", __func__);
572 		return -1;
573 	}
574 
575 	/* The head has to be rewritten at the end, so hold on to it. */
576 	head = compact_head_take(ctx, pos, offset, len);
577 	if (head < 0)
578 		return -1;
579 	if (head && compact_probe(ctx))
580 		return -1;
581 
582 	pos += head;
583 	len -= head;
584 	if (!len)
585 		return 0;
586 
587 	/* Everything else goes into the object as it arrives. */
588 	if (compact_write(ctx->fd_body, pos, len))
589 		return -1;
590 	ctx->body_len += len;
591 
592 	return 0;
593 }
594 
compact_zero(void * arg,__u64 offset,__u64 len)595 static int compact_zero(void *arg, __u64 offset, __u64 len)
596 {
597 	struct compact_ctx *ctx = arg;
598 	ssize_t head;
599 
600 	/* A hole in the head is alignment padding. Write it out. */
601 	head = compact_head_take(ctx, NULL, offset, len);
602 	if (head < 0)
603 		return -1;
604 
605 	offset += head;
606 	len -= head;
607 	if (!len)
608 		return 0;
609 
610 	/* This is what the object doesn't have to carry. */
611 	return compact_keep_hole(ctx, offset, len);
612 }
613 
614 /* Where @offset ends up in the object once the holes ahead of it are gone. */
compact_offset(const struct compact_ctx * ctx,__u64 body_start,__u64 offset)615 static __u64 compact_offset(const struct compact_ctx *ctx, __u64 body_start,
616 			    __u64 offset)
617 {
618 	__u64 elided = 0;
619 	size_t i;
620 
621 	for (i = 0; i < ctx->nr_holes; i++) {
622 		__u64 len = ctx->holes[i].len;
623 
624 		if (ctx->holes[i].offset >= offset)
625 			break;
626 		if (ctx->holes[i].offset + len > offset)
627 			len = offset - ctx->holes[i].offset;
628 		elided += len;
629 	}
630 
631 	return body_start + (offset - ctx->data_offset) - elided;
632 }
633 
634 /* A run of segment data that made it into the object. */
compact_add_data(struct compact_piece * pieces,size_t * nr,const ElfW (Phdr)* phdr,__u64 start,__u64 end)635 static void compact_add_data(struct compact_piece *pieces, size_t *nr,
636 			     const ElfW(Phdr) *phdr, __u64 start, __u64 end)
637 {
638 	struct compact_piece *piece = &pieces[(*nr)++];
639 
640 	piece->phdr = *phdr;
641 	piece->phdr.p_vaddr = phdr->p_vaddr + (start - phdr->p_offset);
642 	piece->phdr.p_paddr = 0;
643 	piece->phdr.p_filesz = end - start;
644 	piece->phdr.p_memsz = end - start;
645 	piece->src = start;
646 }
647 
648 /*
649  * A run of @len bytes the object doesn't carry. It grows the piece in
650  * front of it if this segment already has one, because everything a
651  * segment covers past p_filesz is zeroes anyway.
652  */
compact_add_zero(struct compact_piece * pieces,size_t * nr,size_t first,const ElfW (Phdr)* phdr,__u64 vaddr,__u64 len)653 static void compact_add_zero(struct compact_piece *pieces, size_t *nr,
654 			     size_t first, const ElfW(Phdr) *phdr, __u64 vaddr,
655 			     __u64 len)
656 {
657 	struct compact_piece *piece;
658 
659 	if (*nr > first) {
660 		pieces[*nr - 1].phdr.p_memsz += len;
661 		return;
662 	}
663 
664 	piece = &pieces[(*nr)++];
665 	piece->phdr = *phdr;
666 	piece->phdr.p_vaddr = vaddr;
667 	piece->phdr.p_paddr = 0;
668 	piece->phdr.p_filesz = 0;
669 	piece->phdr.p_memsz = len;
670 	piece->src = 0;
671 }
672 
673 /* Split the segments at the holes and write out what the object became. */
compact_build(struct compact_ctx * ctx,int fd_object)674 static int compact_build(struct compact_ctx *ctx, int fd_object)
675 {
676 	__u64 note_offset = 0, note_len = 0, note_new;
677 	__u64 align = 0, head_len, body_start, pos;
678 	size_t nr_old, nr_new = 0, note_piece = 0, i;
679 	struct compact_piece *pieces;
680 	char buffer[PAGE_SIZE];
681 	const ElfW(Phdr) *old;
682 	ElfW(Ehdr) ehdr;
683 	int ret = -1;
684 
685 	if (!ctx->data_offset) {
686 		fprintf(stderr, "%s: coredump without segment data\n", __func__);
687 		return -1;
688 	}
689 
690 	memcpy(&ehdr, ctx->head, sizeof(ehdr));
691 	if (ehdr.e_shoff) {
692 		fprintf(stderr, "%s: section headers are not handled\n",
693 			__func__);
694 		return -1;
695 	}
696 
697 	old = (const ElfW(Phdr) *)(ctx->head + ehdr.e_phoff);
698 	nr_old = ehdr.e_phnum;
699 
700 	pieces = calloc(nr_old + 2 * ctx->nr_holes + 1, sizeof(*pieces));
701 	if (!pieces) {
702 		fprintf(stderr, "%s: out of memory\n", __func__);
703 		return -1;
704 	}
705 
706 	for (i = 0; i < nr_old; i++) {
707 		ElfW(Phdr) phdr = old[i];
708 		__u64 end = phdr.p_offset + phdr.p_filesz;
709 		__u64 cur = phdr.p_offset;
710 		size_t first = nr_new, h;
711 
712 		/* The notes move because the table in front of them grows. */
713 		if (phdr.p_type == PT_NOTE) {
714 			if (note_len) {
715 				fprintf(stderr, "%s: more than one note segment\n",
716 					__func__);
717 				goto out;
718 			}
719 			note_offset = phdr.p_offset;
720 			note_len = phdr.p_filesz;
721 			note_piece = nr_new;
722 			pieces[nr_new].phdr = phdr;
723 			pieces[nr_new++].src = 0;
724 			continue;
725 		}
726 
727 		if (phdr.p_type != PT_LOAD) {
728 			if (phdr.p_filesz && phdr.p_offset < ctx->data_offset) {
729 				fprintf(stderr, "%s: segment %zu is in the head\n",
730 					__func__, i);
731 				goto out;
732 			}
733 			pieces[nr_new].phdr = phdr;
734 			pieces[nr_new++].src = phdr.p_offset;
735 			continue;
736 		}
737 
738 		if (!align)
739 			align = phdr.p_align;
740 
741 		for (h = 0; h < ctx->nr_holes && cur < end; h++) {
742 			__u64 start = ctx->holes[h].offset;
743 			__u64 stop = start + ctx->holes[h].len;
744 
745 			if (stop <= cur)
746 				continue;
747 			if (start >= end)
748 				break;
749 
750 			/* A hole can span more than this one segment. */
751 			if (start < cur)
752 				start = cur;
753 			if (stop > end)
754 				stop = end;
755 
756 			if (start > cur) {
757 				compact_add_data(pieces, &nr_new, &phdr, cur,
758 						 start);
759 				cur = start;
760 			}
761 			compact_add_zero(pieces, &nr_new, first, &phdr,
762 					 phdr.p_vaddr + (cur - phdr.p_offset),
763 					 stop - cur);
764 			cur = stop;
765 		}
766 
767 		if (cur < end)
768 			compact_add_data(pieces, &nr_new, &phdr, cur, end);
769 
770 		/* Whatever the kernel didn't dump of this mapping. */
771 		if (phdr.p_memsz > phdr.p_filesz)
772 			compact_add_zero(pieces, &nr_new, first, &phdr,
773 					 phdr.p_vaddr + phdr.p_filesz,
774 					 phdr.p_memsz - phdr.p_filesz);
775 	}
776 
777 	if (!note_len || note_offset + note_len > ctx->head_len) {
778 		fprintf(stderr, "%s: notes aren't where they should be\n",
779 			__func__);
780 		goto out;
781 	}
782 
783 	if (nr_new >= PN_XNUM) {
784 		fprintf(stderr, "%s: %zu program headers don't fit\n", __func__,
785 			nr_new);
786 		goto out;
787 	}
788 
789 	if (!align || (align & (align - 1)))
790 		align = sysconf(_SC_PAGESIZE);
791 
792 	note_new = sizeof(ehdr) + (__u64)nr_new * sizeof(ElfW(Phdr));
793 	head_len = note_new + note_len;
794 	body_start = (head_len + align - 1) & ~(align - 1);
795 
796 	for (i = 0; i < nr_new; i++) {
797 		struct compact_piece *piece = &pieces[i];
798 
799 		if (i == note_piece)
800 			piece->phdr.p_offset = note_new;
801 		else if (piece->phdr.p_filesz)
802 			piece->phdr.p_offset = compact_offset(ctx, body_start,
803 							      piece->src);
804 		else
805 			piece->phdr.p_offset = 0;
806 	}
807 
808 	/* Only now is the head known. That's why it is uploaded last. */
809 	ehdr.e_phnum = nr_new;
810 	if (compact_write(fd_object, &ehdr, sizeof(ehdr)))
811 		goto out;
812 
813 	for (i = 0; i < nr_new; i++)
814 		if (compact_write(fd_object, &pieces[i].phdr,
815 				  sizeof(pieces[i].phdr)))
816 			goto out;
817 
818 	if (compact_write(fd_object, ctx->head + note_offset, note_len))
819 		goto out;
820 
821 	/* Keep the segments aligned the way a debugger expects them. */
822 	memset(buffer, 0, sizeof(buffer));
823 	for (pos = head_len; pos < body_start; ) {
824 		__u64 chunk = body_start - pos;
825 
826 		if (chunk > sizeof(buffer))
827 			chunk = sizeof(buffer);
828 		if (compact_write(fd_object, buffer, chunk))
829 			goto out;
830 		pos += chunk;
831 	}
832 
833 	/* Putting the parts together is the blob store's job. Do it here. */
834 	for (pos = 0; pos < ctx->body_len; ) {
835 		ssize_t chunk = pread(ctx->fd_body, buffer, sizeof(buffer), pos);
836 
837 		if (chunk <= 0) {
838 			fprintf(stderr, "%s: short read %zd: %m\n", __func__,
839 				chunk);
840 			goto out;
841 		}
842 		if (compact_write(fd_object, buffer, chunk))
843 			goto out;
844 		pos += chunk;
845 	}
846 
847 	fprintf(stderr, "Object is %llu bytes in %zu program headers, %zu holes left out\n",
848 		(unsigned long long)(body_start + ctx->body_len), nr_new,
849 		ctx->nr_holes);
850 	ret = 0;
851 out:
852 	free(pieces);
853 	return ret;
854 }
855 
856 /*
857  * Reassemble a record stream into an ELF core file that has no holes in
858  * it, the way a coredump server that uploads to a blob store has to. If
859  * @fd_reference is valid it gets the coredump the records describe,
860  * holes and all, so the test can compare the two.
861  */
recv_coredump_compact(int fd_coredump,int fd_object,int fd_reference,off_t * coredump_size)862 ssize_t recv_coredump_compact(int fd_coredump, int fd_object, int fd_reference,
863 			      off_t *coredump_size)
864 {
865 	struct compact_ctx ctx = {
866 		.fd_body	= -1,
867 		.fd_reference	= fd_reference,
868 	};
869 	struct coredump_record_sink sink = {
870 		.data	= compact_data,
871 		.zero	= compact_zero,
872 		.ctx	= &ctx,
873 	};
874 	ssize_t received;
875 	off_t size = 0;
876 	FILE *body;
877 
878 	body = tmpfile();
879 	if (!body) {
880 		fprintf(stderr, "%s: tmpfile failed: %m\n", __func__);
881 		return -1;
882 	}
883 	ctx.fd_body = fileno(body);
884 
885 	/* An upload is appended to. Make sure nothing here can seek. */
886 	if (fcntl(ctx.fd_body, F_SETFL, O_APPEND)) {
887 		fprintf(stderr, "%s: F_SETFL failed: %m\n", __func__);
888 		received = -1;
889 		goto out;
890 	}
891 
892 	received = __recv_coredump_records(fd_coredump, &sink, &size, NULL, -1);
893 	if (received < 0)
894 		goto out;
895 
896 	/*
897 	 * Nothing is written for a hole, so grow the reference to the size
898 	 * the records describe in case the coredump ended in one.
899 	 */
900 	if (ftruncate(fd_reference, size) < 0) {
901 		fprintf(stderr, "%s: ftruncate to %llu failed: %m\n",
902 			__func__, (unsigned long long)size);
903 		received = -1;
904 		goto out;
905 	}
906 
907 	if (compact_build(&ctx, fd_object)) {
908 		received = -1;
909 		goto out;
910 	}
911 
912 	if (coredump_size)
913 		*coredump_size = size;
914 out:
915 	fclose(body);
916 	free(ctx.head);
917 	free(ctx.holes);
918 	return received;
919 }
920 
921 /* Read the ELF header and the program header table of @fd. */
ElfW(Phdr)922 static ElfW(Phdr) *read_phdrs(int fd, size_t *nr)
923 {
924 	ElfW(Ehdr) ehdr;
925 	ElfW(Phdr) *phdr;
926 	size_t size;
927 
928 	if (pread(fd, &ehdr, sizeof(ehdr), 0) != sizeof(ehdr)) {
929 		fprintf(stderr, "%s: no ELF header: %m\n", __func__);
930 		return NULL;
931 	}
932 
933 	if (!is_core_ehdr(&ehdr) || !ehdr.e_phnum ||
934 	    ehdr.e_phentsize != sizeof(*phdr)) {
935 		fprintf(stderr, "%s: not an ELF core file\n", __func__);
936 		return NULL;
937 	}
938 
939 	size = (size_t)ehdr.e_phnum * ehdr.e_phentsize;
940 	phdr = malloc(size);
941 	if (!phdr) {
942 		fprintf(stderr, "%s: out of memory\n", __func__);
943 		return NULL;
944 	}
945 
946 	if (pread(fd, phdr, size, ehdr.e_phoff) != (ssize_t)size) {
947 		fprintf(stderr, "%s: short program header table: %m\n", __func__);
948 		free(phdr);
949 		return NULL;
950 	}
951 
952 	*nr = ehdr.e_phnum;
953 	return phdr;
954 }
955 
956 /* The segment @vaddr falls into. */
ElfW(Phdr)957 static const ElfW(Phdr) *find_segment(const ElfW(Phdr) *phdr, size_t nr,
958 				      __u64 vaddr)
959 {
960 	size_t i;
961 
962 	for (i = 0; i < nr; i++) {
963 		if (phdr[i].p_type != PT_LOAD)
964 			continue;
965 		if (vaddr >= phdr[i].p_vaddr &&
966 		    vaddr < phdr[i].p_vaddr + phdr[i].p_memsz)
967 			return &phdr[i];
968 	}
969 
970 	return NULL;
971 }
972 
973 /* The PT_LOAD segment @vaddr falls into. */
find_coredump_segment(int fd,__u64 vaddr,ElfW (Phdr)* segment)974 bool find_coredump_segment(int fd, __u64 vaddr, ElfW(Phdr) *segment)
975 {
976 	const ElfW(Phdr) *found;
977 	ElfW(Phdr) *phdr;
978 	size_t nr;
979 
980 	phdr = read_phdrs(fd, &nr);
981 	if (!phdr)
982 		return false;
983 
984 	found = find_segment(phdr, nr, vaddr);
985 	if (found)
986 		*segment = *found;
987 	else
988 		fprintf(stderr, "%s: no segment for 0x%llx\n", __func__,
989 			(unsigned long long)vaddr);
990 
991 	free(phdr);
992 	return found;
993 }
994 
995 /* How many bytes the PT_LOAD and the PT_NOTE segments of @fd carry. */
sum_coredump_segments(int fd,__u64 * data,__u64 * notes)996 bool sum_coredump_segments(int fd, __u64 *data, __u64 *notes)
997 {
998 	ElfW(Phdr) *phdr;
999 	size_t nr, i;
1000 
1001 	phdr = read_phdrs(fd, &nr);
1002 	if (!phdr)
1003 		return false;
1004 
1005 	*data = 0;
1006 	*notes = 0;
1007 	for (i = 0; i < nr; i++) {
1008 		if (phdr[i].p_type == PT_LOAD)
1009 			*data += phdr[i].p_filesz;
1010 		else if (phdr[i].p_type == PT_NOTE)
1011 			*notes += phdr[i].p_filesz;
1012 	}
1013 
1014 	free(phdr);
1015 	return true;
1016 }
1017 
1018 /* The coredump in @fd is at least as long as every segment it declares. */
check_coredump_extent(int fd)1019 bool check_coredump_extent(int fd)
1020 {
1021 	ElfW(Phdr) *phdr;
1022 	struct stat st;
1023 	size_t nr, i;
1024 	bool ok = true;
1025 
1026 	if (fstat(fd, &st)) {
1027 		fprintf(stderr, "%s: fstat: %m\n", __func__);
1028 		return false;
1029 	}
1030 
1031 	phdr = read_phdrs(fd, &nr);
1032 	if (!phdr)
1033 		return false;
1034 
1035 	for (i = 0; i < nr; i++) {
1036 		if (phdr[i].p_offset + phdr[i].p_filesz <= (__u64)st.st_size)
1037 			continue;
1038 		fprintf(stderr, "%s: segment %zu ends at %llu, the coredump at %llu\n",
1039 			__func__, i,
1040 			(unsigned long long)(phdr[i].p_offset + phdr[i].p_filesz),
1041 			(unsigned long long)st.st_size);
1042 		ok = false;
1043 	}
1044 
1045 	free(phdr);
1046 	return ok;
1047 }
1048 
1049 /* The next stretch of memory the segments cover, split ones merged back. */
next_range(const ElfW (Phdr)* phdr,size_t nr,size_t * i,__u64 * start,__u64 * end)1050 static bool next_range(const ElfW(Phdr) *phdr, size_t nr, size_t *i,
1051 		       __u64 *start, __u64 *end)
1052 {
1053 	while (*i < nr && phdr[*i].p_type != PT_LOAD)
1054 		(*i)++;
1055 
1056 	if (*i >= nr)
1057 		return false;
1058 
1059 	*start = phdr[*i].p_vaddr;
1060 	*end = phdr[*i].p_vaddr + phdr[*i].p_memsz;
1061 	(*i)++;
1062 
1063 	while (*i < nr) {
1064 		if (phdr[*i].p_type != PT_LOAD) {
1065 			(*i)++;
1066 			continue;
1067 		}
1068 		if (phdr[*i].p_vaddr != *end)
1069 			break;
1070 		*end = phdr[*i].p_vaddr + phdr[*i].p_memsz;
1071 		(*i)++;
1072 	}
1073 
1074 	return true;
1075 }
1076 
1077 /* Compare @len bytes at @offset against @len bytes at @offset_ref. */
compare_range(int fd,__u64 offset,int fd_ref,__u64 offset_ref,__u64 len)1078 static int compare_range(int fd, __u64 offset, int fd_ref, __u64 offset_ref,
1079 			 __u64 len)
1080 {
1081 	char buffer[PAGE_SIZE], buffer_ref[PAGE_SIZE];
1082 
1083 	while (len) {
1084 		size_t chunk = len < sizeof(buffer) ? len : sizeof(buffer);
1085 
1086 		if (pread(fd, buffer, chunk, offset) != (ssize_t)chunk ||
1087 		    pread(fd_ref, buffer_ref, chunk, offset_ref) != (ssize_t)chunk) {
1088 			fprintf(stderr, "%s: short read at %llu: %m\n",
1089 				__func__, (unsigned long long)offset);
1090 			return -1;
1091 		}
1092 
1093 		if (memcmp(buffer, buffer_ref, chunk)) {
1094 			fprintf(stderr, "%s: %llu differs from %llu\n", __func__,
1095 				(unsigned long long)offset,
1096 				(unsigned long long)offset_ref);
1097 			return -1;
1098 		}
1099 
1100 		offset += chunk;
1101 		offset_ref += chunk;
1102 		len -= chunk;
1103 	}
1104 
1105 	return 0;
1106 }
1107 
1108 /* The @len bytes at @offset the object left out have to have been zeroes. */
check_zero_range(int fd,__u64 offset,__u64 len)1109 static int check_zero_range(int fd, __u64 offset, __u64 len)
1110 {
1111 	static const char zeroes[PAGE_SIZE];
1112 	char buffer[PAGE_SIZE];
1113 
1114 	while (len) {
1115 		size_t chunk = len < sizeof(buffer) ? len : sizeof(buffer);
1116 
1117 		if (pread(fd, buffer, chunk, offset) != (ssize_t)chunk) {
1118 			fprintf(stderr, "%s: short read at %llu: %m\n",
1119 				__func__, (unsigned long long)offset);
1120 			return -1;
1121 		}
1122 
1123 		if (memcmp(buffer, zeroes, chunk)) {
1124 			fprintf(stderr, "%s: %llu isn't a hole\n", __func__,
1125 				(unsigned long long)offset);
1126 			return -1;
1127 		}
1128 
1129 		offset += chunk;
1130 		len -= chunk;
1131 	}
1132 
1133 	return 0;
1134 }
1135 
1136 /*
1137  * The object has to describe the same memory as the coredump it was built
1138  * from, and it has to describe it correctly.
1139  */
check_compact_coredump(int fd_object,int fd_reference)1140 int check_compact_coredump(int fd_object, int fd_reference)
1141 {
1142 	ElfW(Phdr) *object = NULL, *reference = NULL;
1143 	size_t nr_object, nr_reference, i;
1144 	size_t io = 0, ir = 0;
1145 	int ret = -1;
1146 
1147 	object = read_phdrs(fd_object, &nr_object);
1148 	reference = read_phdrs(fd_reference, &nr_reference);
1149 	if (!object || !reference)
1150 		goto out;
1151 
1152 	/* Nothing may have been dropped and nothing may have been added. */
1153 	for (;;) {
1154 		__u64 start = 0, end = 0, start_ref = 0, end_ref = 0;
1155 		bool has, has_ref;
1156 
1157 		has = next_range(object, nr_object, &io, &start, &end);
1158 		has_ref = next_range(reference, nr_reference, &ir, &start_ref,
1159 				     &end_ref);
1160 		if (!has && !has_ref)
1161 			break;
1162 
1163 		if (has != has_ref || start != start_ref || end != end_ref) {
1164 			fprintf(stderr, "%s: object covers 0x%llx-0x%llx, coredump 0x%llx-0x%llx\n",
1165 				__func__, (unsigned long long)start,
1166 				(unsigned long long)end,
1167 				(unsigned long long)start_ref,
1168 				(unsigned long long)end_ref);
1169 			goto out;
1170 		}
1171 	}
1172 
1173 	for (i = 0; i < nr_object; i++) {
1174 		const ElfW(Phdr) *segment;
1175 		__u64 offset, dumped;
1176 
1177 		if (object[i].p_type != PT_LOAD || !object[i].p_memsz)
1178 			continue;
1179 
1180 		segment = find_segment(reference, nr_reference,
1181 				       object[i].p_vaddr);
1182 		if (!segment) {
1183 			fprintf(stderr, "%s: 0x%llx isn't in the coredump\n",
1184 				__func__,
1185 				(unsigned long long)object[i].p_vaddr);
1186 			goto out;
1187 		}
1188 
1189 		offset = object[i].p_vaddr - segment->p_vaddr;
1190 		dumped = offset < segment->p_filesz ?
1191 				 segment->p_filesz - offset : 0;
1192 
1193 		/* What the object carries is what the coredump had. */
1194 		if (object[i].p_filesz > dumped) {
1195 			fprintf(stderr, "%s: object carries %llu bytes the coredump doesn't have\n",
1196 				__func__,
1197 				(unsigned long long)(object[i].p_filesz - dumped));
1198 			goto out;
1199 		}
1200 
1201 		if (compare_range(fd_object, object[i].p_offset, fd_reference,
1202 				  segment->p_offset + offset,
1203 				  object[i].p_filesz))
1204 			goto out;
1205 
1206 		/* And what it left out was a hole. */
1207 		if (object[i].p_memsz > object[i].p_filesz &&
1208 		    dumped > object[i].p_filesz) {
1209 			__u64 left_out = dumped - object[i].p_filesz;
1210 
1211 			if (left_out > object[i].p_memsz - object[i].p_filesz)
1212 				left_out = object[i].p_memsz - object[i].p_filesz;
1213 
1214 			if (check_zero_range(fd_reference,
1215 					     segment->p_offset + offset +
1216 					     object[i].p_filesz, left_out))
1217 				goto out;
1218 		}
1219 	}
1220 
1221 	ret = 0;
1222 out:
1223 	free(object);
1224 	free(reference);
1225 	return ret;
1226 }
1227 
1228 /* Read a plain coredump byte stream to end-of-file. */
recv_coredump_bytes(int fd_coredump,int fd_core_file)1229 ssize_t recv_coredump_bytes(int fd_coredump, int fd_core_file)
1230 {
1231 	ssize_t received = 0;
1232 
1233 	for (;;) {
1234 		char buffer[PAGE_SIZE];
1235 		ssize_t ret = read_nointr(fd_coredump, buffer, sizeof(buffer));
1236 
1237 		if (ret < 0) {
1238 			fprintf(stderr, "%s: read failed: %m\n", __func__);
1239 			return -1;
1240 		}
1241 		if (ret == 0)
1242 			break;
1243 
1244 		if (write_nointr(fd_core_file, buffer, ret) != ret) {
1245 			fprintf(stderr, "%s: write failed: %m\n", __func__);
1246 			return -1;
1247 		}
1248 		received += ret;
1249 	}
1250 
1251 	fprintf(stderr, "Received %zd bytes of coredump\n", received);
1252 	return received;
1253 }
1254 
crashing_thread(void * arg)1255 static void *crashing_thread(void *arg)
1256 {
1257 	int *p;
1258 
1259 	(void)arg;
1260 
1261 	/* crash on purpose with SEGV_MAPERR */
1262 	p = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
1263 		 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1264 	if (p == MAP_FAILED)
1265 		return NULL;
1266 	munmap(p, PAGE_SIZE);
1267 	*p = 0;
1268 
1269 	return NULL;
1270 }
1271 
crashing_child_thread(void)1272 void crashing_child_thread(void)
1273 {
1274 	pthread_t thread;
1275 	int i;
1276 
1277 	for (i = 0; i < NUM_THREAD_SPAWN; ++i)
1278 		pthread_create(&thread, NULL, do_nothing, NULL);
1279 
1280 	/* crash from a non-leader thread */
1281 	pthread_create(&thread, NULL, crashing_thread, NULL);
1282 	pause();
1283 }
1284 
create_detached_tmpfs(void)1285 int create_detached_tmpfs(void)
1286 {
1287 	int fd_context, fd_tmpfs;
1288 
1289 	fd_context = sys_fsopen("tmpfs", 0);
1290 	if (fd_context < 0)
1291 		return -1;
1292 
1293 	if (sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0) < 0)
1294 		return -1;
1295 
1296 	fd_tmpfs = sys_fsmount(fd_context, 0, 0);
1297 	close(fd_context);
1298 	return fd_tmpfs;
1299 }
1300 
create_and_listen_unix_socket(const char * path)1301 int create_and_listen_unix_socket(const char *path)
1302 {
1303 	struct sockaddr_un addr = {
1304 		.sun_family = AF_UNIX,
1305 	};
1306 	assert(strlen(path) < sizeof(addr.sun_path) - 1);
1307 	strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
1308 	size_t addr_len =
1309 		offsetof(struct sockaddr_un, sun_path) + strlen(path) + 1;
1310 	int fd, ret;
1311 
1312 	fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
1313 	if (fd < 0)
1314 		goto out;
1315 
1316 	ret = bind(fd, (const struct sockaddr *)&addr, addr_len);
1317 	if (ret < 0)
1318 		goto out;
1319 
1320 	ret = listen(fd, 128);
1321 	if (ret < 0)
1322 		goto out;
1323 
1324 	return fd;
1325 
1326 out:
1327 	fprintf(stderr, "%s: %s: %m\n", __func__, path);
1328 	if (fd >= 0)
1329 		close(fd);
1330 	return -1;
1331 }
1332 
set_core_pattern(const char * pattern)1333 bool set_core_pattern(const char *pattern)
1334 {
1335 	int fd;
1336 	ssize_t ret;
1337 
1338 	fd = open("/proc/sys/kernel/core_pattern", O_WRONLY | O_CLOEXEC);
1339 	if (fd < 0)
1340 		return false;
1341 
1342 	ret = write(fd, pattern, strlen(pattern));
1343 	close(fd);
1344 	if (ret < 0)
1345 		return false;
1346 
1347 	fprintf(stderr, "Set core_pattern to '%s' | %zu == %zu\n", pattern, ret, strlen(pattern));
1348 	return ret == strlen(pattern);
1349 }
1350 
get_peer_pidfd(int fd)1351 int get_peer_pidfd(int fd)
1352 {
1353 	int fd_peer_pidfd;
1354 	socklen_t fd_peer_pidfd_len = sizeof(fd_peer_pidfd);
1355 	int ret = getsockopt(fd, SOL_SOCKET, SO_PEERPIDFD, &fd_peer_pidfd,
1356 			     &fd_peer_pidfd_len);
1357 	if (ret < 0) {
1358 		fprintf(stderr, "get_peer_pidfd: getsockopt(SO_PEERPIDFD) failed: %m\n");
1359 		return -1;
1360 	}
1361 	fprintf(stderr, "get_peer_pidfd: successfully retrieved pidfd %d\n", fd_peer_pidfd);
1362 	return fd_peer_pidfd;
1363 }
1364 
get_peer_pidfd_thread(int fd)1365 int get_peer_pidfd_thread(int fd)
1366 {
1367 	int fd_peer_pidfd;
1368 	socklen_t fd_peer_pidfd_len = sizeof(fd_peer_pidfd);
1369 	int ret = getsockopt(fd, SOL_SOCKET, SO_PEERPIDFD_THREAD, &fd_peer_pidfd,
1370 			     &fd_peer_pidfd_len);
1371 	if (ret < 0) {
1372 		fprintf(stderr, "%s: getsockopt(SO_PEERPIDFD_THREAD) failed: %m\n", __func__);
1373 		return -1;
1374 	}
1375 	fprintf(stderr, "%s: successfully retrieved pidfd %d\n", __func__, fd_peer_pidfd);
1376 	return fd_peer_pidfd;
1377 }
1378 
get_pidfd_info(int fd_peer_pidfd,struct pidfd_info * info)1379 bool get_pidfd_info(int fd_peer_pidfd, struct pidfd_info *info)
1380 {
1381 	int ret;
1382 	memset(info, 0, sizeof(*info));
1383 	info->mask = PIDFD_INFO_EXIT | PIDFD_INFO_COREDUMP | PIDFD_INFO_COREDUMP_SIGNAL;
1384 	ret = ioctl(fd_peer_pidfd, PIDFD_GET_INFO, info);
1385 	if (ret < 0) {
1386 		fprintf(stderr, "get_pidfd_info: ioctl(PIDFD_GET_INFO) failed: %m\n");
1387 		return false;
1388 	}
1389 	fprintf(stderr, "get_pidfd_info: mask=0x%llx, coredump_mask=0x%x, coredump_signal=%d, coredump_code=%d\n",
1390 		(unsigned long long)info->mask, info->coredump_mask, info->coredump_signal, info->coredump_code);
1391 	return true;
1392 }
1393 
1394 /*
1395  * How much the peer has mapped. The task is parked in the coredump
1396  * handshake, so its mm is still there to be looked at.
1397  */
peer_vm_size(int fd_peer_pidfd)1398 ssize_t peer_vm_size(int fd_peer_pidfd)
1399 {
1400 	struct pidfd_info info = {};
1401 	unsigned long pages;
1402 	char path[64];
1403 	FILE *f;
1404 
1405 	if (!get_pidfd_info(fd_peer_pidfd, &info))
1406 		return -1;
1407 
1408 	snprintf(path, sizeof(path), "/proc/%d/statm", info.pid);
1409 	f = fopen(path, "r");
1410 	if (!f) {
1411 		fprintf(stderr, "%s: %s: %m\n", __func__, path);
1412 		return -1;
1413 	}
1414 
1415 	if (fscanf(f, "%lu", &pages) != 1) {
1416 		fprintf(stderr, "%s: %s: no size\n", __func__, path);
1417 		fclose(f);
1418 		return -1;
1419 	}
1420 	fclose(f);
1421 
1422 	return (ssize_t)pages * sysconf(_SC_PAGESIZE);
1423 }
1424 
1425 /* Protocol helper functions */
1426 
1427 /* The peer's /proc/<pid>/coredump_filter, which is in memory types. */
peer_coredump_filter(int fd_peer_pidfd,__u64 * memory_types)1428 bool peer_coredump_filter(int fd_peer_pidfd, __u64 *memory_types)
1429 {
1430 	struct pidfd_info info = {};
1431 	unsigned long value;
1432 	char path[64];
1433 	FILE *f;
1434 	int ret;
1435 
1436 	if (!get_pidfd_info(fd_peer_pidfd, &info))
1437 		return false;
1438 
1439 	snprintf(path, sizeof(path), "/proc/%d/coredump_filter", info.pid);
1440 	f = fopen(path, "r");
1441 	if (!f) {
1442 		fprintf(stderr, "%s: %s: %m\n", __func__, path);
1443 		return false;
1444 	}
1445 
1446 	ret = fscanf(f, "%lx", &value);
1447 	fclose(f);
1448 	if (ret != 1) {
1449 		fprintf(stderr, "%s: %s: no value\n", __func__, path);
1450 		return false;
1451 	}
1452 
1453 	*memory_types = value;
1454 	return true;
1455 }
1456 
1457 /* Read @len bytes at @addr from the peer's /proc/<pid>/mem. */
peer_read_mem(int fd_peer_pidfd,__u64 addr,void * buf,size_t len)1458 ssize_t peer_read_mem(int fd_peer_pidfd, __u64 addr, void *buf, size_t len)
1459 {
1460 	struct pidfd_info info = {};
1461 	char path[64];
1462 	ssize_t ret;
1463 	int fd;
1464 
1465 	if (!get_pidfd_info(fd_peer_pidfd, &info))
1466 		return -1;
1467 
1468 	snprintf(path, sizeof(path), "/proc/%d/mem", info.pid);
1469 	fd = open(path, O_RDONLY | O_CLOEXEC);
1470 	if (fd < 0) {
1471 		fprintf(stderr, "%s: %s: %m\n", __func__, path);
1472 		return -1;
1473 	}
1474 
1475 	ret = pread(fd, buf, len, addr);
1476 	if (ret < 0)
1477 		fprintf(stderr, "%s: %s at 0x%llx: %m\n", __func__, path,
1478 			(unsigned long long)addr);
1479 	close(fd);
1480 	return ret;
1481 }
1482 
recv_marker(int fd)1483 ssize_t recv_marker(int fd)
1484 {
1485 	enum coredump_mark mark = COREDUMP_MARK_REQACK;
1486 	ssize_t ret;
1487 
1488 	ret = recv(fd, &mark, sizeof(mark), MSG_WAITALL);
1489 	if (ret != sizeof(mark))
1490 		return -1;
1491 
1492 	switch (mark) {
1493 	case COREDUMP_MARK_REQACK:
1494 		fprintf(stderr, "Received marker: ReqAck\n");
1495 		return COREDUMP_MARK_REQACK;
1496 	case COREDUMP_MARK_MINSIZE:
1497 		fprintf(stderr, "Received marker: MinSize\n");
1498 		return COREDUMP_MARK_MINSIZE;
1499 	case COREDUMP_MARK_MAXSIZE:
1500 		fprintf(stderr, "Received marker: MaxSize\n");
1501 		return COREDUMP_MARK_MAXSIZE;
1502 	case COREDUMP_MARK_UNSUPPORTED:
1503 		fprintf(stderr, "Received marker: Unsupported\n");
1504 		return COREDUMP_MARK_UNSUPPORTED;
1505 	case COREDUMP_MARK_CONFLICTING:
1506 		fprintf(stderr, "Received marker: Conflicting\n");
1507 		return COREDUMP_MARK_CONFLICTING;
1508 	default:
1509 		fprintf(stderr, "Received unknown marker: %u\n", mark);
1510 		break;
1511 	}
1512 	return -1;
1513 }
1514 
read_marker(int fd,enum coredump_mark mark)1515 bool read_marker(int fd, enum coredump_mark mark)
1516 {
1517 	ssize_t ret;
1518 
1519 	ret = recv_marker(fd);
1520 	if (ret < 0)
1521 		return false;
1522 	return ret == mark;
1523 }
1524 
1525 /*
1526  * The kernel hung up without sending anything more: end of stream, or a
1527  * reset if it refused the ack on its peeked size and never read it.
1528  */
read_hangup(int fd)1529 bool read_hangup(int fd)
1530 {
1531 	ssize_t ret;
1532 	char c;
1533 
1534 	ret = recv(fd, &c, sizeof(c), MSG_WAITALL);
1535 	if (ret == 0) {
1536 		fprintf(stderr, "Kernel closed the connection\n");
1537 		return true;
1538 	}
1539 	if (ret < 0 && errno == ECONNRESET) {
1540 		fprintf(stderr, "Kernel closed the connection with the ack unread\n");
1541 		return true;
1542 	}
1543 
1544 	fprintf(stderr, "%s: expected a hangup, got %zd: %m\n", __func__, ret);
1545 	return false;
1546 }
1547 
1548 /* Read the request as a server built with a @user_size byte struct does. */
read_coredump_req_sized(int fd,struct coredump_req * req,size_t user_size)1549 bool read_coredump_req_sized(int fd, struct coredump_req *req, size_t user_size)
1550 {
1551 	ssize_t ret;
1552 	size_t field_size, known_size, kernel_size, remaining_size;
1553 
1554 	memset(req, 0, sizeof(*req));
1555 	field_size = sizeof(req->size);
1556 
1557 	/* Peek the size of the coredump request. */
1558 	ret = recv(fd, req, field_size, MSG_PEEK | MSG_WAITALL);
1559 	if (ret != field_size) {
1560 		fprintf(stderr, "%s: peek failed (got %zd, expected %zu): %m\n", __func__,
1561 			ret, field_size);
1562 		return false;
1563 	}
1564 	kernel_size = req->size;
1565 
1566 	if (kernel_size < COREDUMP_REQ_SIZE_VER0) {
1567 		fprintf(stderr, "%s: kernel_size %zu < min %d\n", __func__,
1568 			kernel_size, COREDUMP_REQ_SIZE_VER0);
1569 		return false;
1570 	}
1571 	if (kernel_size >= PAGE_SIZE) {
1572 		fprintf(stderr, "%s: kernel_size %zu >= PAGE_SIZE %d\n", __func__,
1573 			kernel_size, PAGE_SIZE);
1574 		return false;
1575 	}
1576 
1577 	/* Consume as much of the request as we know about. */
1578 	known_size = user_size < kernel_size ? user_size : kernel_size;
1579 	ret = recv(fd, req, known_size, MSG_WAITALL);
1580 	if (ret != known_size)
1581 		return false;
1582 
1583 	fprintf(stderr, "Read coredump request with size %u and mask 0x%llx\n",
1584 		req->size, (unsigned long long)req->mask);
1585 
1586 	if (kernel_size > user_size)
1587 		remaining_size = kernel_size - user_size;
1588 	else
1589 		remaining_size = 0;
1590 
1591 	if (PAGE_SIZE <= remaining_size)
1592 		return false;
1593 
1594 	/*
1595 	 * Discard any additional data if the kernel's request was larger than
1596 	 * what we knew about or cared about.
1597 	 */
1598 	if (remaining_size) {
1599 		char buffer[PAGE_SIZE];
1600 
1601 		ret = recv(fd, buffer, remaining_size, MSG_WAITALL);
1602 		if (ret != remaining_size)
1603 			return false;
1604 		fprintf(stderr, "Discarded %zu bytes of data after coredump request\n", remaining_size);
1605 	}
1606 
1607 	return true;
1608 }
1609 
read_coredump_req(int fd,struct coredump_req * req)1610 bool read_coredump_req(int fd, struct coredump_req *req)
1611 {
1612 	return read_coredump_req_sized(fd, req, sizeof(*req));
1613 }
1614 
1615 /* Send @len bytes of @ack as they are, more than the struct if asked to. */
send_coredump_ack_bytes(int fd,const struct coredump_ack * ack,size_t len)1616 bool send_coredump_ack_bytes(int fd, const struct coredump_ack *ack, size_t len)
1617 {
1618 	ssize_t ret;
1619 	/*
1620 	 * Wrap struct coredump_ack in a larger struct so we can
1621 	 * simulate sending to much data to the kernel.
1622 	 */
1623 	struct large_ack_for_size_testing {
1624 		struct coredump_ack ack;
1625 		char buffer[PAGE_SIZE];
1626 	} large_ack = {};
1627 
1628 	if (len > sizeof(large_ack))
1629 		return false;
1630 
1631 	large_ack.ack = *ack;
1632 	ret = send(fd, &large_ack, len, MSG_NOSIGNAL);
1633 	if (ret != len) {
1634 		fprintf(stderr, "%s: short send %zd: %m\n", __func__, ret);
1635 		return false;
1636 	}
1637 
1638 	fprintf(stderr, "Sent %zu bytes of coredump ack: size %u, mask 0x%llx, types 0x%llx\n",
1639 		len, ack->size, (unsigned long long)ack->mask,
1640 		(unsigned long long)ack->memory_types);
1641 	return true;
1642 }
1643 
send_coredump_ack_types(int fd,const struct coredump_req * req,__u64 mask,__u64 memory_types,size_t size_ack)1644 bool send_coredump_ack_types(int fd, const struct coredump_req *req,
1645 			      __u64 mask, __u64 memory_types, size_t size_ack)
1646 {
1647 	struct coredump_ack ack = {
1648 		.mask = mask,
1649 		.memory_types = memory_types,
1650 	};
1651 
1652 	if (!size_ack)
1653 		size_ack = sizeof(struct coredump_ack) < req->size_ack ?
1654 				   sizeof(struct coredump_ack) :
1655 				   req->size_ack;
1656 	ack.size = size_ack;
1657 	return send_coredump_ack_bytes(fd, &ack, size_ack);
1658 }
1659 
send_coredump_ack(int fd,const struct coredump_req * req,__u64 mask,size_t size_ack)1660 bool send_coredump_ack(int fd, const struct coredump_req *req,
1661 		       __u64 mask, size_t size_ack)
1662 {
1663 	return send_coredump_ack_types(fd, req, mask, 0, size_ack);
1664 }
1665 
1666 /* Every option the kernel is expected to advertise in coredump_req->mask. */
1667 #define TEST_REQ_MASK_ALL					\
1668 	(COREDUMP_KERNEL | COREDUMP_USERSPACE |			\
1669 	 COREDUMP_REJECT | COREDUMP_WAIT |			\
1670 	 COREDUMP_RECORDS | COREDUMP_SPARSE | COREDUMP_MEMORY_TYPES)
1671 
check_coredump_req(const struct coredump_req * req)1672 bool check_coredump_req(const struct coredump_req *req)
1673 {
1674 	if (req->size != COREDUMP_REQ_SIZE_VER1) {
1675 		fprintf(stderr, "%s: size %u, expected %d\n",
1676 			__func__, req->size, COREDUMP_REQ_SIZE_VER1);
1677 		return false;
1678 	}
1679 	if (req->size_ack != COREDUMP_ACK_SIZE_VER1) {
1680 		fprintf(stderr, "%s: size_ack %u, expected %d\n",
1681 			__func__, req->size_ack, COREDUMP_ACK_SIZE_VER1);
1682 		return false;
1683 	}
1684 	if (req->mask != TEST_REQ_MASK_ALL) {
1685 		fprintf(stderr, "%s: mask 0x%llx, expected 0x%llx\n",
1686 			__func__, (unsigned long long)req->mask,
1687 			(unsigned long long)TEST_REQ_MASK_ALL);
1688 		return false;
1689 	}
1690 	if (req->memory_types_mask != TEST_MEMORY_ALL) {
1691 		fprintf(stderr, "%s: memory_types_mask 0x%llx, expected 0x%llx\n",
1692 			__func__, (unsigned long long)req->memory_types_mask,
1693 			(unsigned long long)TEST_MEMORY_ALL);
1694 		return false;
1695 	}
1696 	return true;
1697 }
1698 
open_coredump_tmpfile(int fd_tmpfs_detached)1699 int open_coredump_tmpfile(int fd_tmpfs_detached)
1700 {
1701 	return openat(fd_tmpfs_detached, ".", O_TMPFILE | O_RDWR | O_EXCL, 0600);
1702 }
1703 
process_coredump_worker(int fd_coredump,int fd_peer_pidfd,int fd_core_file)1704 void process_coredump_worker(int fd_coredump, int fd_peer_pidfd, int fd_core_file)
1705 {
1706 	int epfd = -1;
1707 	int exit_code = EXIT_FAILURE;
1708 	struct epoll_event ev;
1709 	int flags;
1710 
1711 	/* Set socket to non-blocking mode for edge-triggered epoll */
1712 	flags = fcntl(fd_coredump, F_GETFL, 0);
1713 	if (flags < 0) {
1714 		fprintf(stderr, "Worker: fcntl(F_GETFL) failed: %m\n");
1715 		goto out;
1716 	}
1717 	if (fcntl(fd_coredump, F_SETFL, flags | O_NONBLOCK) < 0) {
1718 		fprintf(stderr, "Worker: fcntl(F_SETFL, O_NONBLOCK) failed: %m\n");
1719 		goto out;
1720 	}
1721 
1722 	epfd = epoll_create1(0);
1723 	if (epfd < 0) {
1724 		fprintf(stderr, "Worker: epoll_create1() failed: %m\n");
1725 		goto out;
1726 	}
1727 
1728 	ev.events = EPOLLIN | EPOLLRDHUP | EPOLLET;
1729 	ev.data.fd = fd_coredump;
1730 	if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd_coredump, &ev) < 0) {
1731 		fprintf(stderr, "Worker: epoll_ctl(EPOLL_CTL_ADD) failed: %m\n");
1732 		goto out;
1733 	}
1734 
1735 	for (;;) {
1736 		struct epoll_event events[1];
1737 		int n = epoll_wait(epfd, events, 1, -1);
1738 		if (n < 0) {
1739 			fprintf(stderr, "Worker: epoll_wait() failed: %m\n");
1740 			break;
1741 		}
1742 
1743 		if (events[0].events & (EPOLLIN | EPOLLRDHUP)) {
1744 			for (;;) {
1745 				char buffer[4096];
1746 				ssize_t bytes_read = read(fd_coredump, buffer, sizeof(buffer));
1747 				if (bytes_read < 0) {
1748 					if (errno == EAGAIN || errno == EWOULDBLOCK)
1749 						break;
1750 					fprintf(stderr, "Worker: read() failed: %m\n");
1751 					goto out;
1752 				}
1753 				if (bytes_read == 0)
1754 					goto done;
1755 				ssize_t bytes_write = write(fd_core_file, buffer, bytes_read);
1756 				if (bytes_write != bytes_read) {
1757 					if (bytes_write < 0 && errno == ENOSPC)
1758 						continue;
1759 					fprintf(stderr, "Worker: write() failed (read=%zd, write=%zd): %m\n",
1760 						bytes_read, bytes_write);
1761 					goto out;
1762 				}
1763 			}
1764 		}
1765 	}
1766 
1767 done:
1768 	exit_code = EXIT_SUCCESS;
1769 	fprintf(stderr, "Worker: completed successfully\n");
1770 out:
1771 	if (epfd >= 0)
1772 		close(epfd);
1773 	if (fd_core_file >= 0)
1774 		close(fd_core_file);
1775 	if (fd_peer_pidfd >= 0)
1776 		close(fd_peer_pidfd);
1777 	if (fd_coredump >= 0)
1778 		close(fd_coredump);
1779 	_exit(exit_code);
1780 }
1781 
1782 /*
1783  * TIF_NOTIFY_SIGNAL coredump helpers.
1784  *
1785  * __dump_emit() takes anything short of a full write as the end of the
1786  * dump, so every emit that blocks on a full transport can lose the rest
1787  * of it. The NT_FILE note is the one emit that is certain to block,
1788  * because it is the only one larger than the transport, so these helpers
1789  * build a note large enough for that and then raise TIF_NOTIFY_SIGNAL on
1790  * the dumping task while that write is in flight.
1791  */
1792 
io_uring_setup_raw(unsigned int entries,struct io_uring_params * p)1793 static int io_uring_setup_raw(unsigned int entries, struct io_uring_params *p)
1794 {
1795 	return syscall(__NR_io_uring_setup, entries, p);
1796 }
1797 
1798 /* io_uring reads poll32_events back through swahw32() on big endian. */
notify_poll_mask(__u32 events)1799 static __u32 notify_poll_mask(__u32 events)
1800 {
1801 #if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN
1802 	return __swahw32(events);
1803 #else
1804 	return events;
1805 #endif
1806 }
1807 
coredump_io_uring_available(void)1808 bool coredump_io_uring_available(void)
1809 {
1810 	struct io_uring_params p = {};
1811 	int fd;
1812 
1813 	fd = io_uring_setup_raw(1, &p);
1814 	if (fd < 0)
1815 		return false;
1816 	close(fd);
1817 	return true;
1818 }
1819 
1820 /*
1821  * Arm a poll on @fd. io_uring leaves ctx->notify_method at TWA_SIGNAL
1822  * unless the ring asks for SQPOLL or COOP_TASKRUN, so the completion runs
1823  * set_notify_signal() against the task that submitted it. That is us, and
1824  * we are about to become the coredumping task.
1825  */
arm_poll_notify(int trigger_fd)1826 static int arm_poll_notify(int trigger_fd)
1827 {
1828 	struct io_uring_params p = {};
1829 	unsigned int *sq_tail, *sq_array;
1830 	struct io_uring_sqe *sqes;
1831 	size_t sqring_sz;
1832 	void *sq;
1833 	int ring;
1834 
1835 	ring = io_uring_setup_raw(8, &p);
1836 	if (ring < 0)
1837 		return -1;
1838 
1839 	sqring_sz = p.sq_off.array + p.sq_entries * sizeof(unsigned int);
1840 	sq = mmap(NULL, sqring_sz, PROT_READ | PROT_WRITE,
1841 		  MAP_SHARED | MAP_POPULATE, ring, IORING_OFF_SQ_RING);
1842 	if (sq == MAP_FAILED)
1843 		return -1;
1844 
1845 	sqes = mmap(NULL, p.sq_entries * sizeof(*sqes), PROT_READ | PROT_WRITE,
1846 		    MAP_SHARED | MAP_POPULATE, ring, IORING_OFF_SQES);
1847 	if (sqes == MAP_FAILED)
1848 		return -1;
1849 
1850 	sq_tail = (unsigned int *)((char *)sq + p.sq_off.tail);
1851 	sq_array = (unsigned int *)((char *)sq + p.sq_off.array);
1852 
1853 	memset(&sqes[0], 0, sizeof(sqes[0]));
1854 	sqes[0].opcode = IORING_OP_POLL_ADD;
1855 	sqes[0].fd = trigger_fd;
1856 	sqes[0].poll32_events = notify_poll_mask(POLLIN);
1857 
1858 	sq_array[0] = 0;
1859 	__atomic_store_n(sq_tail, 1, __ATOMIC_RELEASE);
1860 
1861 	if (syscall(__NR_io_uring_enter, ring, 1, 0, 0, NULL, 0) < 0)
1862 		return -1;
1863 
1864 	/* Deliberately leaked, we are about to crash. */
1865 	return 0;
1866 }
1867 
1868 /*
1869  * Adjacent mappings with identical flags and contiguous file offsets are
1870  * merged into one VMA, which would collapse NT_FILE back to nothing, so
1871  * alternate the protection to keep every mapping an entry of its own.
1872  * Not PROT_EXEC, /tmp is often mounted noexec. Nothing is ever written
1873  * through these so they get no anon_vma and stay out of the dump itself.
1874  */
make_file_mappings(void)1875 static int make_file_mappings(void)
1876 {
1877 	long pgsz = sysconf(_SC_PAGESIZE);
1878 	int fd, i;
1879 
1880 	fd = open(NOTIFY_SIGNAL_MAPFILE,
1881 		  O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
1882 	if (fd < 0)
1883 		return 0;
1884 	if (ftruncate(fd, (off_t)NOTIFY_SIGNAL_MAP_COUNT * pgsz)) {
1885 		close(fd);
1886 		return 0;
1887 	}
1888 
1889 	for (i = 0; i < NOTIFY_SIGNAL_MAP_COUNT; i++) {
1890 		int prot = (i & 1) ? PROT_READ : (PROT_READ | PROT_WRITE);
1891 
1892 		if (mmap(NULL, pgsz, prot, MAP_PRIVATE, fd,
1893 			 (off_t)i * pgsz) == MAP_FAILED)
1894 			break;
1895 	}
1896 	close(fd);
1897 	return i;
1898 }
1899 
crashing_child_notify_signal(void)1900 void crashing_child_notify_signal(void)
1901 {
1902 	long pgsz = sysconf(_SC_PAGESIZE);
1903 	unsigned char *p;
1904 	int trigger_fd;
1905 	unsigned long off;
1906 
1907 	/* Open the read side first so the reader's open() cannot block. */
1908 	trigger_fd = open(NOTIFY_SIGNAL_TRIGGER, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
1909 
1910 	/* Exit rather than crash: a dump without the poll armed proves nothing. */
1911 	if (trigger_fd < 0)
1912 		_exit(EXIT_FAILURE);
1913 
1914 	if (make_file_mappings() < NOTIFY_SIGNAL_MAP_COUNT)
1915 		_exit(EXIT_FAILURE);
1916 
1917 	p = mmap(NULL, NOTIFY_SIGNAL_ANON_BYTES, PROT_READ | PROT_WRITE,
1918 		 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1919 	if (p == MAP_FAILED)
1920 		_exit(EXIT_FAILURE);
1921 	for (off = 0; off < NOTIFY_SIGNAL_ANON_BYTES; off += pgsz)
1922 		p[off] = 1;
1923 
1924 	if (arm_poll_notify(trigger_fd))
1925 		_exit(EXIT_FAILURE);
1926 
1927 	/* crash on purpose */
1928 	*(volatile int *)NULL = 0;
1929 	_exit(EXIT_FAILURE);
1930 }
1931 
pull_trigger(void)1932 static int pull_trigger(void)
1933 {
1934 	int fd;
1935 
1936 	fd = open(NOTIFY_SIGNAL_TRIGGER, O_WRONLY | O_NONBLOCK | O_CLOEXEC);
1937 	if (fd < 0) {
1938 		fprintf(stderr, "%s: open failed: %m\n", __func__);
1939 		return -1;
1940 	}
1941 	if (write(fd, "x", 1) != 1) {
1942 		fprintf(stderr, "%s: write failed: %m\n", __func__);
1943 		close(fd);
1944 		return -1;
1945 	}
1946 	close(fd);
1947 	return 0;
1948 }
1949 
1950 /*
1951  * phdr[0] is the PT_NOTE entry: elf_core_dump() emits it right after the
1952  * ELF header. Its p_offset is where the notes begin.
1953  */
note_offset(const unsigned char * hdr)1954 static long long note_offset(const unsigned char *hdr)
1955 {
1956 	ElfW(Phdr) ph;
1957 	ElfW(Ehdr) eh;
1958 
1959 	memcpy(&eh, hdr, sizeof(eh));
1960 	if (memcmp(eh.e_ident, ELFMAG, SELFMAG) || eh.e_type != ET_CORE)
1961 		return -1;
1962 	memcpy(&ph, hdr + sizeof(eh), sizeof(ph));
1963 	if (ph.p_type != PT_NOTE)
1964 		return -1;
1965 	return (long long)ph.p_offset;
1966 }
1967 
1968 /*
1969  * Drain a coredump off @fd, counting what arrives. Once the notes have
1970  * started the kernel is inside the one big note write, so poke the fifo
1971  * the crashing task is polling and stop reading, which keeps the
1972  * transport full and the write blocked with a partial count when the
1973  * wakeup lands. Then carry on to end of file.
1974  *
1975  * What arrives is written to @fd_out when that is not negative.
1976  * Returns the number of bytes received, or -1. Failing to trip the fifo
1977  * is an error too: a dump that was never interrupted proves nothing.
1978  */
recv_coredump_notify_signal(int fd,int fd_out,bool arm)1979 ssize_t recv_coredump_notify_signal(int fd, int fd_out, bool arm)
1980 {
1981 	unsigned char hdr[sizeof(ElfW(Ehdr)) + sizeof(ElfW(Phdr))];
1982 	static char buf[64 << 10];
1983 	long pgsz = sysconf(_SC_PAGESIZE);
1984 	long long note_off = 0;
1985 	size_t hdrlen = 0;
1986 	ssize_t total = 0;
1987 	bool armed = false;
1988 
1989 	for (;;) {
1990 		ssize_t n = read(fd, buf, sizeof(buf));
1991 
1992 		if (n < 0) {
1993 			if (errno == EINTR)
1994 				continue;
1995 			return -1;
1996 		}
1997 		if (n == 0)
1998 			break;
1999 		if (fd_out >= 0 && write(fd_out, buf, n) != n)
2000 			return -1;
2001 
2002 		if (hdrlen < sizeof(hdr)) {
2003 			size_t want = sizeof(hdr) - hdrlen;
2004 
2005 			if (want > (size_t)n)
2006 				want = (size_t)n;
2007 			memcpy(hdr + hdrlen, buf, want);
2008 			hdrlen += want;
2009 			if (hdrlen == sizeof(hdr))
2010 				note_off = note_offset(hdr);
2011 		}
2012 
2013 		total += n;
2014 
2015 		if (arm && !armed && note_off > 0 &&
2016 		    total > note_off + (long long)pgsz) {
2017 			if (pull_trigger())
2018 				return -1;
2019 			armed = true;
2020 			usleep(NOTIFY_SIGNAL_STALL_US);
2021 			continue;
2022 		}
2023 	}
2024 
2025 	if (arm && !armed)
2026 		return -1;
2027 
2028 	return total;
2029 }
2030 
2031 /*
2032  * How large the dump was meant to be. The ELF header and the program
2033  * headers are the first thing emitted, so even a truncated dump says how
2034  * far it should have run: the end is max(p_offset + p_filesz).
2035  *
2036  * That end is exact even when the last segment ends in a hole:
2037  * coredump_write() flushes the pending cprm->to_skip with a final one
2038  * byte emit and __dump_skip() writes zeroes for transports that cannot
2039  * seek, so a whole dump carries every byte the headers promise.
2040  */
coredump_expected_size(const char * path)2041 long long coredump_expected_size(const char *path)
2042 {
2043 	ElfW(Phdr) *phdr = NULL;
2044 	long long expected = 0;
2045 	unsigned int nphdr, i;
2046 	ElfW(Ehdr) eh;
2047 	int fd;
2048 
2049 	fd = open(path, O_RDONLY | O_CLOEXEC);
2050 	if (fd < 0)
2051 		return -1;
2052 	if (read(fd, &eh, sizeof(eh)) != sizeof(eh))
2053 		goto err;
2054 	if (memcmp(eh.e_ident, ELFMAG, SELFMAG) || eh.e_type != ET_CORE)
2055 		goto err;
2056 	if (!eh.e_phnum || eh.e_phentsize != sizeof(*phdr))
2057 		goto err;
2058 
2059 	nphdr = eh.e_phnum;
2060 	phdr = calloc(nphdr, sizeof(*phdr));
2061 	if (!phdr)
2062 		goto err;
2063 	if (pread(fd, phdr, (size_t)nphdr * sizeof(*phdr), (off_t)eh.e_phoff) !=
2064 	    (ssize_t)((size_t)nphdr * sizeof(*phdr)))
2065 		goto err;
2066 
2067 	for (i = 0; i < nphdr; i++) {
2068 		long long end = (long long)phdr[i].p_offset +
2069 				(long long)phdr[i].p_filesz;
2070 		if (end > expected)
2071 			expected = end;
2072 	}
2073 
2074 	free(phdr);
2075 	close(fd);
2076 	return expected;
2077 err:
2078 	free(phdr);
2079 	close(fd);
2080 	return -1;
2081 }
2082