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