]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/coredump/coredump.c
Rework cmdline printing to use unicode
[thirdparty/systemd.git] / src / coredump / coredump.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <stdio.h>
5 #include <sys/prctl.h>
6 #include <sys/xattr.h>
7 #include <unistd.h>
8
9 #if HAVE_ELFUTILS
10 #include <dwarf.h>
11 #include <elfutils/libdwfl.h>
12 #endif
13
14 #include "sd-daemon.h"
15 #include "sd-journal.h"
16 #include "sd-login.h"
17 #include "sd-messages.h"
18
19 #include "acl-util.h"
20 #include "alloc-util.h"
21 #include "capability-util.h"
22 #include "cgroup-util.h"
23 #include "compress.h"
24 #include "conf-parser.h"
25 #include "copy.h"
26 #include "coredump-vacuum.h"
27 #include "dirent-util.h"
28 #include "escape.h"
29 #include "fd-util.h"
30 #include "fileio.h"
31 #include "fs-util.h"
32 #include "io-util.h"
33 #include "journal-importer.h"
34 #include "log.h"
35 #include "macro.h"
36 #include "main-func.h"
37 #include "memory-util.h"
38 #include "missing.h"
39 #include "mkdir.h"
40 #include "parse-util.h"
41 #include "process-util.h"
42 #include "signal-util.h"
43 #include "socket-util.h"
44 #include "special.h"
45 #include "stacktrace.h"
46 #include "string-table.h"
47 #include "string-util.h"
48 #include "strv.h"
49 #include "tmpfile-util.h"
50 #include "user-util.h"
51
52 /* The maximum size up to which we process coredumps */
53 #define PROCESS_SIZE_MAX ((uint64_t) (2LLU*1024LLU*1024LLU*1024LLU))
54
55 /* The maximum size up to which we leave the coredump around on disk */
56 #define EXTERNAL_SIZE_MAX PROCESS_SIZE_MAX
57
58 /* The maximum size up to which we store the coredump in the journal */
59 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
60 #define JOURNAL_SIZE_MAX ((size_t) (767LU*1024LU*1024LU))
61 #else
62 /* oss-fuzz limits memory usage. */
63 #define JOURNAL_SIZE_MAX ((size_t) (10LU*1024LU*1024LU))
64 #endif
65
66 /* Make sure to not make this larger than the maximum journal entry
67 * size. See DATA_SIZE_MAX in journal-importer.h. */
68 assert_cc(JOURNAL_SIZE_MAX <= DATA_SIZE_MAX);
69
70 enum {
71 /* We use this as array indexes for a couple of special fields we use for
72 * naming coredump files, and attaching xattrs, and for indexing argv[].
73
74 * Our pattern for man:systectl(1) kernel.core_pattern is such that the
75 * kernel passes fields until CONTEXT_RLIMIT as arguments in argv[]. After
76 * that it gets complicated: the kernel passes "comm" as one or more fields
77 * starting at index CONTEXT_COMM (in other words, full "comm" is under index
78 * CONTEXT_COMM when it does not contain spaces, which is the common
79 * case). This mapping is not reversible, so we prefer to retrieve "comm"
80 * from /proc. We only fall back to argv[CONTEXT_COMM...] when that fails.
81 *
82 * In the internal context[] array, fields before CONTEXT_COMM are the
83 * strings from argv[], so they should not be freed. The strings at indices
84 * CONTEXT_COMM and higher are allocated by us and should be freed at the
85 * end.
86 */
87 CONTEXT_PID,
88 CONTEXT_UID,
89 CONTEXT_GID,
90 CONTEXT_SIGNAL,
91 CONTEXT_TIMESTAMP,
92 CONTEXT_RLIMIT,
93 CONTEXT_HOSTNAME,
94 CONTEXT_COMM,
95 CONTEXT_EXE,
96 CONTEXT_UNIT,
97 _CONTEXT_MAX
98 };
99
100 typedef enum CoredumpStorage {
101 COREDUMP_STORAGE_NONE,
102 COREDUMP_STORAGE_EXTERNAL,
103 COREDUMP_STORAGE_JOURNAL,
104 _COREDUMP_STORAGE_MAX,
105 _COREDUMP_STORAGE_INVALID = -1
106 } CoredumpStorage;
107
108 static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = {
109 [COREDUMP_STORAGE_NONE] = "none",
110 [COREDUMP_STORAGE_EXTERNAL] = "external",
111 [COREDUMP_STORAGE_JOURNAL] = "journal",
112 };
113
114 DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage);
115 static DEFINE_CONFIG_PARSE_ENUM(config_parse_coredump_storage, coredump_storage, CoredumpStorage, "Failed to parse storage setting");
116
117 static CoredumpStorage arg_storage = COREDUMP_STORAGE_EXTERNAL;
118 static bool arg_compress = true;
119 static uint64_t arg_process_size_max = PROCESS_SIZE_MAX;
120 static uint64_t arg_external_size_max = EXTERNAL_SIZE_MAX;
121 static uint64_t arg_journal_size_max = JOURNAL_SIZE_MAX;
122 static uint64_t arg_keep_free = (uint64_t) -1;
123 static uint64_t arg_max_use = (uint64_t) -1;
124
125 static int parse_config(void) {
126 static const ConfigTableItem items[] = {
127 { "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage },
128 { "Coredump", "Compress", config_parse_bool, 0, &arg_compress },
129 { "Coredump", "ProcessSizeMax", config_parse_iec_uint64, 0, &arg_process_size_max },
130 { "Coredump", "ExternalSizeMax", config_parse_iec_uint64, 0, &arg_external_size_max },
131 { "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max },
132 { "Coredump", "KeepFree", config_parse_iec_uint64, 0, &arg_keep_free },
133 { "Coredump", "MaxUse", config_parse_iec_uint64, 0, &arg_max_use },
134 {}
135 };
136
137 return config_parse_many_nulstr(PKGSYSCONFDIR "/coredump.conf",
138 CONF_PATHS_NULSTR("systemd/coredump.conf.d"),
139 "Coredump\0",
140 config_item_table_lookup, items,
141 CONFIG_PARSE_WARN, NULL);
142 }
143
144 static uint64_t storage_size_max(void) {
145 if (arg_storage == COREDUMP_STORAGE_EXTERNAL)
146 return arg_external_size_max;
147 if (arg_storage == COREDUMP_STORAGE_JOURNAL)
148 return arg_journal_size_max;
149 assert(arg_storage == COREDUMP_STORAGE_NONE);
150 return 0;
151 }
152
153 static int fix_acl(int fd, uid_t uid) {
154
155 #if HAVE_ACL
156 _cleanup_(acl_freep) acl_t acl = NULL;
157 acl_entry_t entry;
158 acl_permset_t permset;
159 int r;
160
161 assert(fd >= 0);
162
163 if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY)
164 return 0;
165
166 /* Make sure normal users can read (but not write or delete)
167 * their own coredumps */
168
169 acl = acl_get_fd(fd);
170 if (!acl)
171 return log_error_errno(errno, "Failed to get ACL: %m");
172
173 if (acl_create_entry(&acl, &entry) < 0 ||
174 acl_set_tag_type(entry, ACL_USER) < 0 ||
175 acl_set_qualifier(entry, &uid) < 0)
176 return log_error_errno(errno, "Failed to patch ACL: %m");
177
178 if (acl_get_permset(entry, &permset) < 0 ||
179 acl_add_perm(permset, ACL_READ) < 0)
180 return log_warning_errno(errno, "Failed to patch ACL: %m");
181
182 r = calc_acl_mask_if_needed(&acl);
183 if (r < 0)
184 return log_warning_errno(r, "Failed to patch ACL: %m");
185
186 if (acl_set_fd(fd, acl) < 0)
187 return log_error_errno(errno, "Failed to apply ACL: %m");
188 #endif
189
190 return 0;
191 }
192
193 static int fix_xattr(int fd, const char *context[_CONTEXT_MAX]) {
194
195 static const char * const xattrs[_CONTEXT_MAX] = {
196 [CONTEXT_PID] = "user.coredump.pid",
197 [CONTEXT_UID] = "user.coredump.uid",
198 [CONTEXT_GID] = "user.coredump.gid",
199 [CONTEXT_SIGNAL] = "user.coredump.signal",
200 [CONTEXT_TIMESTAMP] = "user.coredump.timestamp",
201 [CONTEXT_RLIMIT] = "user.coredump.rlimit",
202 [CONTEXT_HOSTNAME] = "user.coredump.hostname",
203 [CONTEXT_COMM] = "user.coredump.comm",
204 [CONTEXT_EXE] = "user.coredump.exe",
205 };
206
207 int r = 0;
208 unsigned i;
209
210 assert(fd >= 0);
211
212 /* Attach some metadata to coredumps via extended
213 * attributes. Just because we can. */
214
215 for (i = 0; i < _CONTEXT_MAX; i++) {
216 int k;
217
218 if (isempty(context[i]) || !xattrs[i])
219 continue;
220
221 k = fsetxattr(fd, xattrs[i], context[i], strlen(context[i]), XATTR_CREATE);
222 if (k < 0 && r == 0)
223 r = -errno;
224 }
225
226 return r;
227 }
228
229 #define filename_escape(s) xescape((s), "./ ")
230
231 static const char *coredump_tmpfile_name(const char *s) {
232 return s ? s : "(unnamed temporary file)";
233 }
234
235 static int fix_permissions(
236 int fd,
237 const char *filename,
238 const char *target,
239 const char *context[_CONTEXT_MAX],
240 uid_t uid) {
241
242 int r;
243
244 assert(fd >= 0);
245 assert(target);
246 assert(context);
247
248 /* Ignore errors on these */
249 (void) fchmod(fd, 0640);
250 (void) fix_acl(fd, uid);
251 (void) fix_xattr(fd, context);
252
253 if (fsync(fd) < 0)
254 return log_error_errno(errno, "Failed to sync coredump %s: %m", coredump_tmpfile_name(filename));
255
256 (void) fsync_directory_of_file(fd);
257
258 r = link_tmpfile(fd, filename, target);
259 if (r < 0)
260 return log_error_errno(r, "Failed to move coredump %s into place: %m", target);
261
262 return 0;
263 }
264
265 static int maybe_remove_external_coredump(const char *filename, uint64_t size) {
266
267 /* Returns 1 if might remove, 0 if will not remove, < 0 on error. */
268
269 if (arg_storage == COREDUMP_STORAGE_EXTERNAL &&
270 size <= arg_external_size_max)
271 return 0;
272
273 if (!filename)
274 return 1;
275
276 if (unlink(filename) < 0 && errno != ENOENT)
277 return log_error_errno(errno, "Failed to unlink %s: %m", filename);
278
279 return 1;
280 }
281
282 static int make_filename(const char *context[_CONTEXT_MAX], char **ret) {
283 _cleanup_free_ char *c = NULL, *u = NULL, *p = NULL, *t = NULL;
284 sd_id128_t boot = {};
285 int r;
286
287 assert(context);
288
289 c = filename_escape(context[CONTEXT_COMM]);
290 if (!c)
291 return -ENOMEM;
292
293 u = filename_escape(context[CONTEXT_UID]);
294 if (!u)
295 return -ENOMEM;
296
297 r = sd_id128_get_boot(&boot);
298 if (r < 0)
299 return r;
300
301 p = filename_escape(context[CONTEXT_PID]);
302 if (!p)
303 return -ENOMEM;
304
305 t = filename_escape(context[CONTEXT_TIMESTAMP]);
306 if (!t)
307 return -ENOMEM;
308
309 if (asprintf(ret,
310 "/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s000000",
311 c,
312 u,
313 SD_ID128_FORMAT_VAL(boot),
314 p,
315 t) < 0)
316 return -ENOMEM;
317
318 return 0;
319 }
320
321 static int save_external_coredump(
322 const char *context[_CONTEXT_MAX],
323 int input_fd,
324 char **ret_filename,
325 int *ret_node_fd,
326 int *ret_data_fd,
327 uint64_t *ret_size,
328 bool *ret_truncated) {
329
330 _cleanup_free_ char *fn = NULL, *tmp = NULL;
331 _cleanup_close_ int fd = -1;
332 uint64_t rlimit, process_limit, max_size;
333 struct stat st;
334 uid_t uid;
335 int r;
336
337 assert(context);
338 assert(ret_filename);
339 assert(ret_node_fd);
340 assert(ret_data_fd);
341 assert(ret_size);
342
343 r = parse_uid(context[CONTEXT_UID], &uid);
344 if (r < 0)
345 return log_error_errno(r, "Failed to parse UID: %m");
346
347 r = safe_atou64(context[CONTEXT_RLIMIT], &rlimit);
348 if (r < 0)
349 return log_error_errno(r, "Failed to parse resource limit '%s': %m", context[CONTEXT_RLIMIT]);
350 if (rlimit < page_size()) {
351 /* Is coredumping disabled? Then don't bother saving/processing the coredump.
352 * Anything below PAGE_SIZE cannot give a readable coredump (the kernel uses
353 * ELF_EXEC_PAGESIZE which is not easily accessible, but is usually the same as PAGE_SIZE. */
354 return log_info_errno(SYNTHETIC_ERRNO(EBADSLT),
355 "Resource limits disable core dumping for process %s (%s).",
356 context[CONTEXT_PID], context[CONTEXT_COMM]);
357 }
358
359 process_limit = MAX(arg_process_size_max, storage_size_max());
360 if (process_limit == 0)
361 return log_debug_errno(SYNTHETIC_ERRNO(EBADSLT),
362 "Limits for coredump processing and storage are both 0, not dumping core.");
363
364 /* Never store more than the process configured, or than we actually shall keep or process */
365 max_size = MIN(rlimit, process_limit);
366
367 r = make_filename(context, &fn);
368 if (r < 0)
369 return log_error_errno(r, "Failed to determine coredump file name: %m");
370
371 (void) mkdir_p_label("/var/lib/systemd/coredump", 0755);
372
373 fd = open_tmpfile_linkable(fn, O_RDWR|O_CLOEXEC, &tmp);
374 if (fd < 0)
375 return log_error_errno(fd, "Failed to create temporary file for coredump %s: %m", fn);
376
377 r = copy_bytes(input_fd, fd, max_size, 0);
378 if (r < 0) {
379 log_error_errno(r, "Cannot store coredump of %s (%s): %m", context[CONTEXT_PID], context[CONTEXT_COMM]);
380 goto fail;
381 }
382 *ret_truncated = r == 1;
383 if (*ret_truncated)
384 log_struct(LOG_INFO,
385 LOG_MESSAGE("Core file was truncated to %zu bytes.", max_size),
386 "SIZE_LIMIT=%zu", max_size,
387 "MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR);
388
389 if (fstat(fd, &st) < 0) {
390 log_error_errno(errno, "Failed to fstat core file %s: %m", coredump_tmpfile_name(tmp));
391 goto fail;
392 }
393
394 if (lseek(fd, 0, SEEK_SET) == (off_t) -1) {
395 log_error_errno(errno, "Failed to seek on %s: %m", coredump_tmpfile_name(tmp));
396 goto fail;
397 }
398
399 #if HAVE_XZ || HAVE_LZ4
400 /* If we will remove the coredump anyway, do not compress. */
401 if (arg_compress && !maybe_remove_external_coredump(NULL, st.st_size)) {
402
403 _cleanup_free_ char *fn_compressed = NULL, *tmp_compressed = NULL;
404 _cleanup_close_ int fd_compressed = -1;
405
406 fn_compressed = strappend(fn, COMPRESSED_EXT);
407 if (!fn_compressed) {
408 log_oom();
409 goto uncompressed;
410 }
411
412 fd_compressed = open_tmpfile_linkable(fn_compressed, O_RDWR|O_CLOEXEC, &tmp_compressed);
413 if (fd_compressed < 0) {
414 log_error_errno(fd_compressed, "Failed to create temporary file for coredump %s: %m", fn_compressed);
415 goto uncompressed;
416 }
417
418 r = compress_stream(fd, fd_compressed, -1);
419 if (r < 0) {
420 log_error_errno(r, "Failed to compress %s: %m", coredump_tmpfile_name(tmp_compressed));
421 goto fail_compressed;
422 }
423
424 r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid);
425 if (r < 0)
426 goto fail_compressed;
427
428 /* OK, this worked, we can get rid of the uncompressed version now */
429 if (tmp)
430 unlink_noerrno(tmp);
431
432 *ret_filename = TAKE_PTR(fn_compressed); /* compressed */
433 *ret_node_fd = TAKE_FD(fd_compressed); /* compressed */
434 *ret_data_fd = TAKE_FD(fd); /* uncompressed */
435 *ret_size = (uint64_t) st.st_size; /* uncompressed */
436
437 return 0;
438
439 fail_compressed:
440 if (tmp_compressed)
441 (void) unlink(tmp_compressed);
442 }
443
444 uncompressed:
445 #endif
446
447 r = fix_permissions(fd, tmp, fn, context, uid);
448 if (r < 0)
449 goto fail;
450
451 *ret_filename = TAKE_PTR(fn);
452 *ret_data_fd = TAKE_FD(fd);
453 *ret_node_fd = -1;
454 *ret_size = (uint64_t) st.st_size;
455
456 return 0;
457
458 fail:
459 if (tmp)
460 (void) unlink(tmp);
461 return r;
462 }
463
464 static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_size) {
465 _cleanup_free_ char *field = NULL;
466 ssize_t n;
467
468 assert(fd >= 0);
469 assert(ret);
470 assert(ret_size);
471
472 if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
473 return log_warning_errno(errno, "Failed to seek: %m");
474
475 field = malloc(9 + size);
476 if (!field) {
477 log_warning("Failed to allocate memory for coredump, coredump will not be stored.");
478 return -ENOMEM;
479 }
480
481 memcpy(field, "COREDUMP=", 9);
482
483 n = read(fd, field + 9, size);
484 if (n < 0)
485 return log_error_errno((int) n, "Failed to read core data: %m");
486 if ((size_t) n < size)
487 return log_error_errno(SYNTHETIC_ERRNO(EIO),
488 "Core data too short.");
489
490 *ret = TAKE_PTR(field);
491 *ret_size = size + 9;
492
493 return 0;
494 }
495
496 /* Joins /proc/[pid]/fd/ and /proc/[pid]/fdinfo/ into the following lines:
497 * 0:/dev/pts/23
498 * pos: 0
499 * flags: 0100002
500 *
501 * 1:/dev/pts/23
502 * pos: 0
503 * flags: 0100002
504 *
505 * 2:/dev/pts/23
506 * pos: 0
507 * flags: 0100002
508 * EOF
509 */
510 static int compose_open_fds(pid_t pid, char **open_fds) {
511 _cleanup_closedir_ DIR *proc_fd_dir = NULL;
512 _cleanup_close_ int proc_fdinfo_fd = -1;
513 _cleanup_free_ char *buffer = NULL;
514 _cleanup_fclose_ FILE *stream = NULL;
515 const char *fddelim = "", *path;
516 struct dirent *dent = NULL;
517 size_t size = 0;
518 int r;
519
520 assert(pid >= 0);
521 assert(open_fds != NULL);
522
523 path = procfs_file_alloca(pid, "fd");
524 proc_fd_dir = opendir(path);
525 if (!proc_fd_dir)
526 return -errno;
527
528 proc_fdinfo_fd = openat(dirfd(proc_fd_dir), "../fdinfo", O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC|O_PATH);
529 if (proc_fdinfo_fd < 0)
530 return -errno;
531
532 stream = open_memstream_unlocked(&buffer, &size);
533 if (!stream)
534 return -ENOMEM;
535
536 FOREACH_DIRENT(dent, proc_fd_dir, return -errno) {
537 _cleanup_fclose_ FILE *fdinfo = NULL;
538 _cleanup_free_ char *fdname = NULL;
539 int fd;
540
541 r = readlinkat_malloc(dirfd(proc_fd_dir), dent->d_name, &fdname);
542 if (r < 0)
543 return r;
544
545 fprintf(stream, "%s%s:%s\n", fddelim, dent->d_name, fdname);
546 fddelim = "\n";
547
548 /* Use the directory entry from /proc/[pid]/fd with /proc/[pid]/fdinfo */
549 fd = openat(proc_fdinfo_fd, dent->d_name, O_NOFOLLOW|O_CLOEXEC|O_RDONLY);
550 if (fd < 0)
551 continue;
552
553 fdinfo = fdopen(fd, "r");
554 if (!fdinfo) {
555 safe_close(fd);
556 continue;
557 }
558
559 for (;;) {
560 _cleanup_free_ char *line = NULL;
561
562 r = read_line(fdinfo, LONG_LINE_MAX, &line);
563 if (r < 0)
564 return r;
565 if (r == 0)
566 break;
567
568 fputs(line, stream);
569 fputc('\n', stream);
570 }
571 }
572
573 errno = 0;
574 stream = safe_fclose(stream);
575
576 if (errno > 0)
577 return -errno;
578
579 *open_fds = TAKE_PTR(buffer);
580
581 return 0;
582 }
583
584 static int get_process_ns(pid_t pid, const char *namespace, ino_t *ns) {
585 const char *p;
586 struct stat stbuf;
587 _cleanup_close_ int proc_ns_dir_fd;
588
589 p = procfs_file_alloca(pid, "ns");
590
591 proc_ns_dir_fd = open(p, O_DIRECTORY | O_CLOEXEC | O_RDONLY);
592 if (proc_ns_dir_fd < 0)
593 return -errno;
594
595 if (fstatat(proc_ns_dir_fd, namespace, &stbuf, /* flags */0) < 0)
596 return -errno;
597
598 *ns = stbuf.st_ino;
599 return 0;
600 }
601
602 static int get_mount_namespace_leader(pid_t pid, pid_t *container_pid) {
603 pid_t cpid = pid, ppid = 0;
604 ino_t proc_mntns;
605 int r = 0;
606
607 r = get_process_ns(pid, "mnt", &proc_mntns);
608 if (r < 0)
609 return r;
610
611 for (;;) {
612 ino_t parent_mntns;
613
614 r = get_process_ppid(cpid, &ppid);
615 if (r < 0)
616 return r;
617
618 r = get_process_ns(ppid, "mnt", &parent_mntns);
619 if (r < 0)
620 return r;
621
622 if (proc_mntns != parent_mntns)
623 break;
624
625 if (ppid == 1)
626 return -ENOENT;
627
628 cpid = ppid;
629 }
630
631 *container_pid = ppid;
632 return 0;
633 }
634
635 /* Returns 1 if the parent was found.
636 * Returns 0 if there is not a process we can call the pid's
637 * container parent (the pid's process isn't 'containerized').
638 * Returns a negative number on errors.
639 */
640 static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) {
641 int r = 0;
642 pid_t container_pid;
643 const char *proc_root_path;
644 struct stat root_stat, proc_root_stat;
645
646 /* To compare inodes of / and /proc/[pid]/root */
647 if (stat("/", &root_stat) < 0)
648 return -errno;
649
650 proc_root_path = procfs_file_alloca(pid, "root");
651 if (stat(proc_root_path, &proc_root_stat) < 0)
652 return -errno;
653
654 /* The process uses system root. */
655 if (proc_root_stat.st_ino == root_stat.st_ino) {
656 *cmdline = NULL;
657 return 0;
658 }
659
660 r = get_mount_namespace_leader(pid, &container_pid);
661 if (r < 0)
662 return r;
663
664 r = get_process_cmdline(container_pid, SIZE_MAX, false, cmdline);
665 if (r < 0)
666 return r;
667
668 return 1;
669 }
670
671 static int change_uid_gid(const char *context[]) {
672 uid_t uid;
673 gid_t gid;
674 int r;
675
676 r = parse_uid(context[CONTEXT_UID], &uid);
677 if (r < 0)
678 return r;
679
680 if (uid <= SYSTEM_UID_MAX) {
681 const char *user = "systemd-coredump";
682
683 r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
684 if (r < 0) {
685 log_warning_errno(r, "Cannot resolve %s user. Proceeding to dump core as root: %m", user);
686 uid = gid = 0;
687 }
688 } else {
689 r = parse_gid(context[CONTEXT_GID], &gid);
690 if (r < 0)
691 return r;
692 }
693
694 return drop_privileges(uid, gid, 0);
695 }
696
697 static bool is_journald_crash(const char *context[_CONTEXT_MAX]) {
698 assert(context);
699
700 return streq_ptr(context[CONTEXT_UNIT], SPECIAL_JOURNALD_SERVICE);
701 }
702
703 static bool is_pid1_crash(const char *context[_CONTEXT_MAX]) {
704 assert(context);
705
706 return streq_ptr(context[CONTEXT_UNIT], SPECIAL_INIT_SCOPE) ||
707 streq_ptr(context[CONTEXT_PID], "1");
708 }
709
710 #define SUBMIT_COREDUMP_FIELDS 4
711
712 static int submit_coredump(
713 const char *context[_CONTEXT_MAX],
714 struct iovec *iovec,
715 size_t n_iovec_allocated,
716 size_t n_iovec,
717 int input_fd) {
718
719 _cleanup_close_ int coredump_fd = -1, coredump_node_fd = -1;
720 _cleanup_free_ char *core_message = NULL, *filename = NULL, *coredump_data = NULL;
721 uint64_t coredump_size = UINT64_MAX;
722 bool truncated = false, journald_crash;
723 int r;
724
725 assert(context);
726 assert(iovec);
727 assert(n_iovec_allocated >= n_iovec + SUBMIT_COREDUMP_FIELDS);
728 assert(input_fd >= 0);
729
730 journald_crash = is_journald_crash(context);
731
732 /* Vacuum before we write anything again */
733 (void) coredump_vacuum(-1, arg_keep_free, arg_max_use);
734
735 /* Always stream the coredump to disk, if that's possible */
736 r = save_external_coredump(context, input_fd,
737 &filename, &coredump_node_fd, &coredump_fd, &coredump_size, &truncated);
738 if (r < 0)
739 /* Skip whole core dumping part */
740 goto log;
741
742 /* If we don't want to keep the coredump on disk, remove it now, as later on we will lack the privileges for
743 * it. However, we keep the fd to it, so that we can still process it and log it. */
744 r = maybe_remove_external_coredump(filename, coredump_size);
745 if (r < 0)
746 return r;
747 if (r == 0) {
748 const char *coredump_filename;
749
750 coredump_filename = strjoina("COREDUMP_FILENAME=", filename);
751 iovec[n_iovec++] = IOVEC_MAKE_STRING(coredump_filename);
752 } else if (arg_storage == COREDUMP_STORAGE_EXTERNAL)
753 log_info("The core will not be stored: size %"PRIu64" is greater than %"PRIu64" (the configured maximum)",
754 coredump_size, arg_external_size_max);
755
756 /* Vacuum again, but exclude the coredump we just created */
757 (void) coredump_vacuum(coredump_node_fd >= 0 ? coredump_node_fd : coredump_fd, arg_keep_free, arg_max_use);
758
759 /* Now, let's drop privileges to become the user who owns the segfaulted process and allocate the coredump
760 * memory under the user's uid. This also ensures that the credentials journald will see are the ones of the
761 * coredumping user, thus making sure the user gets access to the core dump. Let's also get rid of all
762 * capabilities, if we run as root, we won't need them anymore. */
763 r = change_uid_gid(context);
764 if (r < 0)
765 return log_error_errno(r, "Failed to drop privileges: %m");
766
767 #if HAVE_ELFUTILS
768 /* Try to get a stack trace if we can */
769 if (coredump_size <= arg_process_size_max) {
770 _cleanup_free_ char *stacktrace = NULL;
771
772 r = coredump_make_stack_trace(coredump_fd, context[CONTEXT_EXE], &stacktrace);
773 if (r >= 0)
774 core_message = strjoin("MESSAGE=Process ", context[CONTEXT_PID],
775 " (", context[CONTEXT_COMM], ") of user ",
776 context[CONTEXT_UID], " dumped core.",
777 journald_crash ? "\nCoredump diverted to " : "",
778 journald_crash ? filename : "",
779 "\n\n", stacktrace);
780 else if (r == -EINVAL)
781 log_warning("Failed to generate stack trace: %s", dwfl_errmsg(dwfl_errno()));
782 else
783 log_warning_errno(r, "Failed to generate stack trace: %m");
784 } else
785 log_debug("Not generating stack trace: core size %"PRIu64" is greater than %"PRIu64" (the configured maximum)",
786 coredump_size, arg_process_size_max);
787
788 if (!core_message)
789 #endif
790 log:
791 core_message = strjoin("MESSAGE=Process ", context[CONTEXT_PID],
792 " (", context[CONTEXT_COMM], ") of user ",
793 context[CONTEXT_UID], " dumped core.",
794 journald_crash && filename ? "\nCoredump diverted to " : NULL,
795 journald_crash && filename ? filename : NULL);
796 if (!core_message)
797 return log_oom();
798
799 if (journald_crash) {
800 /* We cannot log to the journal, so just print the message.
801 * The target was set previously to something safe. */
802 assert(startswith(core_message, "MESSAGE="));
803 log_dispatch(LOG_ERR, 0, core_message + strlen("MESSAGE="));
804 return 0;
805 }
806
807 iovec[n_iovec++] = IOVEC_MAKE_STRING(core_message);
808
809 if (truncated)
810 iovec[n_iovec++] = IOVEC_MAKE_STRING("COREDUMP_TRUNCATED=1");
811
812 /* Optionally store the entire coredump in the journal */
813 if (arg_storage == COREDUMP_STORAGE_JOURNAL) {
814 if (coredump_size <= arg_journal_size_max) {
815 size_t sz = 0;
816
817 /* Store the coredump itself in the journal */
818
819 r = allocate_journal_field(coredump_fd, (size_t) coredump_size, &coredump_data, &sz);
820 if (r >= 0)
821 iovec[n_iovec++] = IOVEC_MAKE(coredump_data, sz);
822 else
823 log_warning_errno(r, "Failed to attach the core to the journal entry: %m");
824 } else
825 log_info("The core will not be stored: size %"PRIu64" is greater than %"PRIu64" (the configured maximum)",
826 coredump_size, arg_journal_size_max);
827 }
828
829 assert(n_iovec <= n_iovec_allocated);
830
831 r = sd_journal_sendv(iovec, n_iovec);
832 if (r < 0)
833 return log_error_errno(r, "Failed to log coredump: %m");
834
835 return 0;
836 }
837
838 static void map_context_fields(const struct iovec *iovec, const char* context[]) {
839
840 static const char * const context_field_names[] = {
841 [CONTEXT_PID] = "COREDUMP_PID=",
842 [CONTEXT_UID] = "COREDUMP_UID=",
843 [CONTEXT_GID] = "COREDUMP_GID=",
844 [CONTEXT_SIGNAL] = "COREDUMP_SIGNAL=",
845 [CONTEXT_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
846 [CONTEXT_RLIMIT] = "COREDUMP_RLIMIT=",
847 [CONTEXT_HOSTNAME] = "COREDUMP_HOSTNAME=",
848 [CONTEXT_COMM] = "COREDUMP_COMM=",
849 [CONTEXT_EXE] = "COREDUMP_EXE=",
850 };
851
852 unsigned i;
853
854 assert(iovec);
855 assert(context);
856
857 for (i = 0; i < ELEMENTSOF(context_field_names); i++) {
858 char *p;
859
860 if (!context_field_names[i])
861 continue;
862
863 p = memory_startswith(iovec->iov_base, iovec->iov_len, context_field_names[i]);
864 if (!p)
865 continue;
866
867 /* Note that these strings are NUL terminated, because we made sure that a trailing NUL byte is in the
868 * buffer, though not included in the iov_len count. (see below) */
869 context[i] = p;
870 break;
871 }
872 }
873
874 static int process_socket(int fd) {
875 _cleanup_close_ int coredump_fd = -1;
876 struct iovec *iovec = NULL;
877 size_t n_iovec = 0, n_allocated = 0, i, k;
878 const char *context[_CONTEXT_MAX] = {};
879 int r;
880
881 assert(fd >= 0);
882
883 log_setup_service();
884
885 log_debug("Processing coredump received on stdin...");
886
887 for (;;) {
888 union {
889 struct cmsghdr cmsghdr;
890 uint8_t buf[CMSG_SPACE(sizeof(int))];
891 } control = {};
892 struct msghdr mh = {
893 .msg_control = &control,
894 .msg_controllen = sizeof(control),
895 .msg_iovlen = 1,
896 };
897 ssize_t n;
898 ssize_t l;
899
900 if (!GREEDY_REALLOC(iovec, n_allocated, n_iovec + SUBMIT_COREDUMP_FIELDS)) {
901 r = log_oom();
902 goto finish;
903 }
904
905 l = next_datagram_size_fd(fd);
906 if (l < 0) {
907 r = log_error_errno(l, "Failed to determine datagram size to read: %m");
908 goto finish;
909 }
910
911 assert(l >= 0);
912
913 iovec[n_iovec].iov_len = l;
914 iovec[n_iovec].iov_base = malloc(l + 1);
915 if (!iovec[n_iovec].iov_base) {
916 r = log_oom();
917 goto finish;
918 }
919
920 mh.msg_iov = iovec + n_iovec;
921
922 n = recvmsg(fd, &mh, MSG_CMSG_CLOEXEC);
923 if (n < 0) {
924 free(iovec[n_iovec].iov_base);
925 r = log_error_errno(errno, "Failed to receive datagram: %m");
926 goto finish;
927 }
928
929 if (n == 0) {
930 struct cmsghdr *cmsg, *found = NULL;
931 /* The final zero-length datagram carries the file descriptor and tells us that we're done. */
932
933 free(iovec[n_iovec].iov_base);
934
935 CMSG_FOREACH(cmsg, &mh) {
936 if (cmsg->cmsg_level == SOL_SOCKET &&
937 cmsg->cmsg_type == SCM_RIGHTS &&
938 cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
939 assert(!found);
940 found = cmsg;
941 }
942 }
943
944 if (!found) {
945 log_error("Coredump file descriptor missing.");
946 r = -EBADMSG;
947 goto finish;
948 }
949
950 assert(coredump_fd < 0);
951 coredump_fd = *(int*) CMSG_DATA(found);
952 break;
953 }
954
955 /* Add trailing NUL byte, in case these are strings */
956 ((char*) iovec[n_iovec].iov_base)[n] = 0;
957 iovec[n_iovec].iov_len = (size_t) n;
958
959 cmsg_close_all(&mh);
960 map_context_fields(iovec + n_iovec, context);
961 n_iovec++;
962 }
963
964 if (!GREEDY_REALLOC(iovec, n_allocated, n_iovec + SUBMIT_COREDUMP_FIELDS)) {
965 r = log_oom();
966 goto finish;
967 }
968
969 /* Make sure we got all data we really need */
970 assert(context[CONTEXT_PID]);
971 assert(context[CONTEXT_UID]);
972 assert(context[CONTEXT_GID]);
973 assert(context[CONTEXT_SIGNAL]);
974 assert(context[CONTEXT_TIMESTAMP]);
975 assert(context[CONTEXT_RLIMIT]);
976 assert(context[CONTEXT_HOSTNAME]);
977 assert(context[CONTEXT_COMM]);
978 assert(coredump_fd >= 0);
979
980 /* Small quirk: the journal fields contain the timestamp padded with six zeroes, so that the kernel-supplied 1s
981 * granularity timestamps becomes 1µs granularity, i.e. the granularity systemd usually operates in. Since we
982 * are reconstructing the original kernel context, we chop this off again, here. */
983 k = strlen(context[CONTEXT_TIMESTAMP]);
984 if (k > 6)
985 context[CONTEXT_TIMESTAMP] = strndupa(context[CONTEXT_TIMESTAMP], k - 6);
986
987 r = submit_coredump(context, iovec, n_allocated, n_iovec, coredump_fd);
988
989 finish:
990 for (i = 0; i < n_iovec; i++)
991 free(iovec[i].iov_base);
992 free(iovec);
993
994 return r;
995 }
996
997 static int send_iovec(const struct iovec iovec[], size_t n_iovec, int input_fd) {
998
999 static const union sockaddr_union sa = {
1000 .un.sun_family = AF_UNIX,
1001 .un.sun_path = "/run/systemd/coredump",
1002 };
1003 _cleanup_close_ int fd = -1;
1004 size_t i;
1005 int r;
1006
1007 assert(iovec || n_iovec <= 0);
1008 assert(input_fd >= 0);
1009
1010 fd = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0);
1011 if (fd < 0)
1012 return log_error_errno(errno, "Failed to create coredump socket: %m");
1013
1014 if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
1015 return log_error_errno(errno, "Failed to connect to coredump service: %m");
1016
1017 for (i = 0; i < n_iovec; i++) {
1018 struct msghdr mh = {
1019 .msg_iov = (struct iovec*) iovec + i,
1020 .msg_iovlen = 1,
1021 };
1022 struct iovec copy[2];
1023
1024 for (;;) {
1025 if (sendmsg(fd, &mh, MSG_NOSIGNAL) >= 0)
1026 break;
1027
1028 if (errno == EMSGSIZE && mh.msg_iov[0].iov_len > 0) {
1029 /* This field didn't fit? That's a pity. Given that this is just metadata,
1030 * let's truncate the field at half, and try again. We append three dots, in
1031 * order to show that this is truncated. */
1032
1033 if (mh.msg_iov != copy) {
1034 /* We don't want to modify the caller's iovec, hence let's create our
1035 * own array, consisting of two new iovecs, where the first is a
1036 * (truncated) copy of what we want to send, and the second one
1037 * contains the trailing dots. */
1038 copy[0] = iovec[i];
1039 copy[1] = IOVEC_MAKE(((char[]){'.', '.', '.'}), 3);
1040
1041 mh.msg_iov = copy;
1042 mh.msg_iovlen = 2;
1043 }
1044
1045 copy[0].iov_len /= 2; /* halve it, and try again */
1046 continue;
1047 }
1048
1049 return log_error_errno(errno, "Failed to send coredump datagram: %m");
1050 }
1051 }
1052
1053 r = send_one_fd(fd, input_fd, 0);
1054 if (r < 0)
1055 return log_error_errno(r, "Failed to send coredump fd: %m");
1056
1057 return 0;
1058 }
1059
1060 static char* set_iovec_field_free(struct iovec *iovec, size_t *n_iovec, const char *field, char *value) {
1061 char *x;
1062
1063 x = set_iovec_string_field(iovec, n_iovec, field, value);
1064 free(value);
1065 return x;
1066 }
1067
1068 static int gather_pid_metadata(
1069 char* context[_CONTEXT_MAX],
1070 char **comm_fallback,
1071 struct iovec *iovec, size_t *n_iovec) {
1072
1073 /* We need 27 empty slots in iovec!
1074 *
1075 * Note that if we fail on oom later on, we do not roll-back changes to the iovec structure. (It remains valid,
1076 * with the first n_iovec fields initialized.) */
1077
1078 uid_t owner_uid;
1079 pid_t pid;
1080 char *t;
1081 const char *p;
1082 int r, signo;
1083
1084 r = parse_pid(context[CONTEXT_PID], &pid);
1085 if (r < 0)
1086 return log_error_errno(r, "Failed to parse PID \"%s\": %m", context[CONTEXT_PID]);
1087
1088 r = get_process_comm(pid, &context[CONTEXT_COMM]);
1089 if (r < 0) {
1090 log_warning_errno(r, "Failed to get COMM, falling back to the command line: %m");
1091 context[CONTEXT_COMM] = strv_join(comm_fallback, " ");
1092 if (!context[CONTEXT_COMM])
1093 return log_oom();
1094 }
1095
1096 r = get_process_exe(pid, &context[CONTEXT_EXE]);
1097 if (r < 0)
1098 log_warning_errno(r, "Failed to get EXE, ignoring: %m");
1099
1100 if (cg_pid_get_unit(pid, &context[CONTEXT_UNIT]) >= 0) {
1101 if (!is_journald_crash((const char**) context)) {
1102 /* OK, now we know it's not the journal, hence we can make use of it now. */
1103 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1104 log_open();
1105 }
1106
1107 /* If this is PID 1 disable coredump collection, we'll unlikely be able to process it later on. */
1108 if (is_pid1_crash((const char**) context)) {
1109 log_notice("Due to PID 1 having crashed coredump collection will now be turned off.");
1110 disable_coredumps();
1111 }
1112
1113 set_iovec_string_field(iovec, n_iovec, "COREDUMP_UNIT=", context[CONTEXT_UNIT]);
1114 }
1115
1116 if (cg_pid_get_user_unit(pid, &t) >= 0)
1117 set_iovec_field_free(iovec, n_iovec, "COREDUMP_USER_UNIT=", t);
1118
1119 /* The next few are mandatory */
1120 if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_PID=", context[CONTEXT_PID]))
1121 return log_oom();
1122
1123 if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_UID=", context[CONTEXT_UID]))
1124 return log_oom();
1125
1126 if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_GID=", context[CONTEXT_GID]))
1127 return log_oom();
1128
1129 if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL]))
1130 return log_oom();
1131
1132 if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT]))
1133 return log_oom();
1134
1135 if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_HOSTNAME=", context[CONTEXT_HOSTNAME]))
1136 return log_oom();
1137
1138 if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_COMM=", context[CONTEXT_COMM]))
1139 return log_oom();
1140
1141 if (context[CONTEXT_EXE] &&
1142 !set_iovec_string_field(iovec, n_iovec, "COREDUMP_EXE=", context[CONTEXT_EXE]))
1143 return log_oom();
1144
1145 if (sd_pid_get_session(pid, &t) >= 0)
1146 set_iovec_field_free(iovec, n_iovec, "COREDUMP_SESSION=", t);
1147
1148 if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) {
1149 r = asprintf(&t, "COREDUMP_OWNER_UID=" UID_FMT, owner_uid);
1150 if (r > 0)
1151 iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(t);
1152 }
1153
1154 if (sd_pid_get_slice(pid, &t) >= 0)
1155 set_iovec_field_free(iovec, n_iovec, "COREDUMP_SLICE=", t);
1156
1157 if (get_process_cmdline(pid, SIZE_MAX, false, &t) >= 0)
1158 set_iovec_field_free(iovec, n_iovec, "COREDUMP_CMDLINE=", t);
1159
1160 if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0)
1161 set_iovec_field_free(iovec, n_iovec, "COREDUMP_CGROUP=", t);
1162
1163 if (compose_open_fds(pid, &t) >= 0)
1164 set_iovec_field_free(iovec, n_iovec, "COREDUMP_OPEN_FDS=", t);
1165
1166 p = procfs_file_alloca(pid, "status");
1167 if (read_full_file(p, &t, NULL) >= 0)
1168 set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_STATUS=", t);
1169
1170 p = procfs_file_alloca(pid, "maps");
1171 if (read_full_file(p, &t, NULL) >= 0)
1172 set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_MAPS=", t);
1173
1174 p = procfs_file_alloca(pid, "limits");
1175 if (read_full_file(p, &t, NULL) >= 0)
1176 set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_LIMITS=", t);
1177
1178 p = procfs_file_alloca(pid, "cgroup");
1179 if (read_full_file(p, &t, NULL) >=0)
1180 set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_CGROUP=", t);
1181
1182 p = procfs_file_alloca(pid, "mountinfo");
1183 if (read_full_file(p, &t, NULL) >=0)
1184 set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_MOUNTINFO=", t);
1185
1186 if (get_process_cwd(pid, &t) >= 0)
1187 set_iovec_field_free(iovec, n_iovec, "COREDUMP_CWD=", t);
1188
1189 if (get_process_root(pid, &t) >= 0) {
1190 bool proc_self_root_is_slash;
1191
1192 proc_self_root_is_slash = strcmp(t, "/") == 0;
1193
1194 set_iovec_field_free(iovec, n_iovec, "COREDUMP_ROOT=", t);
1195
1196 /* If the process' root is "/", then there is a chance it has
1197 * mounted own root and hence being containerized. */
1198 if (proc_self_root_is_slash && get_process_container_parent_cmdline(pid, &t) > 0)
1199 set_iovec_field_free(iovec, n_iovec, "COREDUMP_CONTAINER_CMDLINE=", t);
1200 }
1201
1202 if (get_process_environ(pid, &t) >= 0)
1203 set_iovec_field_free(iovec, n_iovec, "COREDUMP_ENVIRON=", t);
1204
1205 t = strjoin("COREDUMP_TIMESTAMP=", context[CONTEXT_TIMESTAMP], "000000");
1206 if (t)
1207 iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(t);
1208
1209 if (safe_atoi(context[CONTEXT_SIGNAL], &signo) >= 0 && SIGNAL_VALID(signo))
1210 set_iovec_string_field(iovec, n_iovec, "COREDUMP_SIGNAL_NAME=SIG", signal_to_string(signo));
1211
1212 return 0; /* we successfully acquired all metadata */
1213 }
1214
1215 static int process_kernel(int argc, char* argv[]) {
1216
1217 char* context[_CONTEXT_MAX] = {};
1218 struct iovec iovec[29 + SUBMIT_COREDUMP_FIELDS];
1219 size_t i, n_iovec, n_to_free = 0;
1220 int r;
1221
1222 log_debug("Processing coredump received from the kernel...");
1223
1224 if (argc < CONTEXT_COMM + 1)
1225 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1226 "Not enough arguments passed by the kernel (%i, expected %i).",
1227 argc - 1, CONTEXT_COMM + 1 - 1);
1228
1229 context[CONTEXT_PID] = argv[1 + CONTEXT_PID];
1230 context[CONTEXT_UID] = argv[1 + CONTEXT_UID];
1231 context[CONTEXT_GID] = argv[1 + CONTEXT_GID];
1232 context[CONTEXT_SIGNAL] = argv[1 + CONTEXT_SIGNAL];
1233 context[CONTEXT_TIMESTAMP] = argv[1 + CONTEXT_TIMESTAMP];
1234 context[CONTEXT_RLIMIT] = argv[1 + CONTEXT_RLIMIT];
1235 context[CONTEXT_HOSTNAME] = argv[1 + CONTEXT_HOSTNAME];
1236
1237 r = gather_pid_metadata(context, argv + 1 + CONTEXT_COMM, iovec, &n_to_free);
1238 if (r < 0)
1239 goto finish;
1240
1241 n_iovec = n_to_free;
1242
1243 iovec[n_iovec++] = IOVEC_MAKE_STRING("MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR);
1244
1245 assert_cc(2 == LOG_CRIT);
1246 iovec[n_iovec++] = IOVEC_MAKE_STRING("PRIORITY=2");
1247
1248 assert(n_iovec <= ELEMENTSOF(iovec));
1249
1250 if (is_journald_crash((const char**) context) || is_pid1_crash((const char**) context))
1251 r = submit_coredump((const char**) context,
1252 iovec, ELEMENTSOF(iovec), n_iovec,
1253 STDIN_FILENO);
1254 else
1255 r = send_iovec(iovec, n_iovec, STDIN_FILENO);
1256
1257 finish:
1258 for (i = 0; i < n_to_free; i++)
1259 free(iovec[i].iov_base);
1260
1261 /* Those fields are allocated by gather_pid_metadata */
1262 free(context[CONTEXT_COMM]);
1263 free(context[CONTEXT_EXE]);
1264 free(context[CONTEXT_UNIT]);
1265
1266 return r;
1267 }
1268
1269 static int process_backtrace(int argc, char *argv[]) {
1270 char *context[_CONTEXT_MAX] = {};
1271 _cleanup_free_ char *message = NULL;
1272 _cleanup_free_ struct iovec *iovec = NULL;
1273 size_t n_iovec, n_allocated, n_to_free = 0, i;
1274 int r;
1275 JournalImporter importer = {
1276 .fd = STDIN_FILENO,
1277 };
1278
1279 log_debug("Processing backtrace on stdin...");
1280
1281 if (argc < CONTEXT_COMM + 1)
1282 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1283 "Not enough arguments passed (%i, expected %i).",
1284 argc - 1, CONTEXT_COMM + 1 - 1);
1285
1286 context[CONTEXT_PID] = argv[2 + CONTEXT_PID];
1287 context[CONTEXT_UID] = argv[2 + CONTEXT_UID];
1288 context[CONTEXT_GID] = argv[2 + CONTEXT_GID];
1289 context[CONTEXT_SIGNAL] = argv[2 + CONTEXT_SIGNAL];
1290 context[CONTEXT_TIMESTAMP] = argv[2 + CONTEXT_TIMESTAMP];
1291 context[CONTEXT_RLIMIT] = argv[2 + CONTEXT_RLIMIT];
1292 context[CONTEXT_HOSTNAME] = argv[2 + CONTEXT_HOSTNAME];
1293
1294 n_allocated = 34 + COREDUMP_STORAGE_EXTERNAL;
1295 /* 26 metadata, 2 static, +unknown input, 4 storage, rounded up */
1296 iovec = new(struct iovec, n_allocated);
1297 if (!iovec)
1298 return log_oom();
1299
1300 r = gather_pid_metadata(context, argv + 2 + CONTEXT_COMM, iovec, &n_to_free);
1301 if (r < 0)
1302 goto finish;
1303 if (r > 0) {
1304 /* This was a special crash, and has already been processed. */
1305 r = 0;
1306 goto finish;
1307 }
1308 n_iovec = n_to_free;
1309
1310 for (;;) {
1311 r = journal_importer_process_data(&importer);
1312 if (r < 0) {
1313 log_error_errno(r, "Failed to parse journal entry on stdin: %m");
1314 goto finish;
1315 }
1316 if (r == 1 || /* complete entry */
1317 journal_importer_eof(&importer)) /* end of data */
1318 break;
1319 }
1320
1321 if (!GREEDY_REALLOC(iovec, n_allocated, n_iovec + importer.iovw.count + 2))
1322 return log_oom();
1323
1324 if (journal_importer_eof(&importer)) {
1325 log_warning("Did not receive a full journal entry on stdin, ignoring message sent by reporter");
1326
1327 message = strjoin("MESSAGE=Process ", context[CONTEXT_PID],
1328 " (", context[CONTEXT_COMM], ")"
1329 " of user ", context[CONTEXT_UID],
1330 " failed with ", context[CONTEXT_SIGNAL]);
1331 if (!message) {
1332 r = log_oom();
1333 goto finish;
1334 }
1335 iovec[n_iovec++] = IOVEC_MAKE_STRING(message);
1336 } else {
1337 for (i = 0; i < importer.iovw.count; i++)
1338 iovec[n_iovec++] = importer.iovw.iovec[i];
1339 }
1340
1341 iovec[n_iovec++] = IOVEC_MAKE_STRING("MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR);
1342 assert_cc(2 == LOG_CRIT);
1343 iovec[n_iovec++] = IOVEC_MAKE_STRING("PRIORITY=2");
1344
1345 assert(n_iovec <= n_allocated);
1346
1347 r = sd_journal_sendv(iovec, n_iovec);
1348 if (r < 0)
1349 log_error_errno(r, "Failed to log backtrace: %m");
1350
1351 finish:
1352 for (i = 0; i < n_to_free; i++)
1353 free(iovec[i].iov_base);
1354
1355 /* Those fields are allocated by gather_pid_metadata */
1356 free(context[CONTEXT_COMM]);
1357 free(context[CONTEXT_EXE]);
1358 free(context[CONTEXT_UNIT]);
1359
1360 return r;
1361 }
1362
1363 static int run(int argc, char *argv[]) {
1364 int r;
1365
1366 /* First, log to a safe place, since we don't know what crashed and it might
1367 * be journald which we'd rather not log to then. */
1368
1369 log_set_target(LOG_TARGET_KMSG);
1370 log_open();
1371
1372 /* Make sure we never enter a loop */
1373 (void) prctl(PR_SET_DUMPABLE, 0);
1374
1375 /* Ignore all parse errors */
1376 (void) parse_config();
1377
1378 log_debug("Selected storage '%s'.", coredump_storage_to_string(arg_storage));
1379 log_debug("Selected compression %s.", yes_no(arg_compress));
1380
1381 r = sd_listen_fds(false);
1382 if (r < 0)
1383 return log_error_errno(r, "Failed to determine the number of file descriptors: %m");
1384
1385 /* If we got an fd passed, we are running in coredumpd mode. Otherwise we
1386 * are invoked from the kernel as coredump handler. */
1387 if (r == 0) {
1388 if (streq_ptr(argv[1], "--backtrace"))
1389 return process_backtrace(argc, argv);
1390 else
1391 return process_kernel(argc, argv);
1392 } else if (r == 1)
1393 return process_socket(SD_LISTEN_FDS_START);
1394
1395 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
1396 "Received unexpected number of file descriptors.");
1397 }
1398
1399 DEFINE_MAIN_FUNCTION(run);