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