]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/coredump/coredump.c
tree-wide: use TAKE_PTR() and TAKE_FD() macros
[thirdparty/systemd.git] / src / coredump / coredump.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
f5e04665
LP
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
5430f7f2
LP
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
f5e04665
LP
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
5430f7f2 15 Lesser General Public License for more details.
f5e04665 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
f5e04665
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
21#include <errno.h>
803a3464 22#include <stdio.h>
0d536673 23#include <stdio_ext.h>
803a3464 24#include <sys/prctl.h>
cacd6403 25#include <sys/xattr.h>
4f5dd394 26#include <unistd.h>
f5e04665 27
349cc4a5 28#if HAVE_ELFUTILS
3c171f0b
LP
29#include <dwarf.h>
30#include <elfutils/libdwfl.h>
4d229b31
UTL
31#endif
32
73a99163 33#include "sd-daemon.h"
f11943c5
LP
34#include "sd-journal.h"
35#include "sd-login.h"
73a99163 36#include "sd-messages.h"
4f5dd394
LP
37
38#include "acl-util.h"
b5efdb8a 39#include "alloc-util.h"
430f0182 40#include "capability-util.h"
ba1261bc 41#include "cgroup-util.h"
4f5dd394 42#include "compress.h"
34c10968
LP
43#include "conf-parser.h"
44#include "copy.h"
f11943c5 45#include "coredump-vacuum.h"
a0956174 46#include "dirent-util.h"
4f5dd394 47#include "escape.h"
3ffd4af2 48#include "fd-util.h"
4f5dd394 49#include "fileio.h"
f4f15635 50#include "fs-util.h"
afc5dbf3 51#include "io-util.h"
b18453ed 52#include "journal-importer.h"
4f5dd394
LP
53#include "log.h"
54#include "macro.h"
0c773903 55#include "missing.h"
4f5dd394 56#include "mkdir.h"
6bedfcbb 57#include "parse-util.h"
0b452006 58#include "process-util.h"
d14bcb4e 59#include "signal-util.h"
3c171f0b 60#include "socket-util.h"
4f5dd394
LP
61#include "special.h"
62#include "stacktrace.h"
8b43440b 63#include "string-table.h"
07630cea 64#include "string-util.h"
4f5dd394 65#include "strv.h"
b1d4f8e1 66#include "user-util.h"
4f5dd394 67#include "util.h"
34727273 68
34c10968 69/* The maximum size up to which we process coredumps */
59f448cf 70#define PROCESS_SIZE_MAX ((uint64_t) (2LLU*1024LLU*1024LLU*1024LLU))
34c10968 71
bdfd7b2c 72/* The maximum size up to which we leave the coredump around on disk */
34c10968
LP
73#define EXTERNAL_SIZE_MAX PROCESS_SIZE_MAX
74
bdfd7b2c 75/* The maximum size up to which we store the coredump in the journal */
34c10968 76#define JOURNAL_SIZE_MAX ((size_t) (767LU*1024LU*1024LU))
f5e04665 77
c4aa09b0 78/* Make sure to not make this larger than the maximum journal entry
874bc134
ZJS
79 * size. See DATA_SIZE_MAX in journald-native.c. */
80assert_cc(JOURNAL_SIZE_MAX <= DATA_SIZE_MAX);
f5e04665
LP
81
82enum {
ea5cc2a8
ZJS
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 */
3c171f0b
LP
99 CONTEXT_PID,
100 CONTEXT_UID,
101 CONTEXT_GID,
102 CONTEXT_SIGNAL,
103 CONTEXT_TIMESTAMP,
bdfd7b2c 104 CONTEXT_RLIMIT,
f45b8015 105 CONTEXT_HOSTNAME,
3c171f0b
LP
106 CONTEXT_COMM,
107 CONTEXT_EXE,
92e92d71 108 CONTEXT_UNIT,
3c171f0b 109 _CONTEXT_MAX
f5e04665
LP
110};
111
34c10968
LP
112typedef enum CoredumpStorage {
113 COREDUMP_STORAGE_NONE,
114 COREDUMP_STORAGE_EXTERNAL,
115 COREDUMP_STORAGE_JOURNAL,
34c10968
LP
116 _COREDUMP_STORAGE_MAX,
117 _COREDUMP_STORAGE_INVALID = -1
118} CoredumpStorage;
119
34c10968
LP
120static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = {
121 [COREDUMP_STORAGE_NONE] = "none",
122 [COREDUMP_STORAGE_EXTERNAL] = "external",
123 [COREDUMP_STORAGE_JOURNAL] = "journal",
34c10968
LP
124};
125
126DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage);
8c9571d0 127static DEFINE_CONFIG_PARSE_ENUM(config_parse_coredump_storage, coredump_storage, CoredumpStorage, "Failed to parse storage setting");
34727273
ZJS
128
129static CoredumpStorage arg_storage = COREDUMP_STORAGE_EXTERNAL;
8c9571d0 130static bool arg_compress = true;
59f448cf
LP
131static uint64_t arg_process_size_max = PROCESS_SIZE_MAX;
132static uint64_t arg_external_size_max = EXTERNAL_SIZE_MAX;
6e2b4a69 133static uint64_t arg_journal_size_max = JOURNAL_SIZE_MAX;
59f448cf
LP
134static uint64_t arg_keep_free = (uint64_t) -1;
135static uint64_t arg_max_use = (uint64_t) -1;
34c10968
LP
136
137static int parse_config(void) {
34c10968 138 static const ConfigTableItem items[] = {
8c9571d0
LP
139 { "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage },
140 { "Coredump", "Compress", config_parse_bool, 0, &arg_compress },
59f448cf
LP
141 { "Coredump", "ProcessSizeMax", config_parse_iec_uint64, 0, &arg_process_size_max },
142 { "Coredump", "ExternalSizeMax", config_parse_iec_uint64, 0, &arg_external_size_max },
8c9571d0 143 { "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max },
59f448cf
LP
144 { "Coredump", "KeepFree", config_parse_iec_uint64, 0, &arg_keep_free },
145 { "Coredump", "MaxUse", config_parse_iec_uint64, 0, &arg_max_use },
34c10968
LP
146 {}
147 };
148
43688c49 149 return config_parse_many_nulstr(PKGSYSCONFDIR "/coredump.conf",
da412854
YW
150 CONF_PATHS_NULSTR("systemd/coredump.conf.d"),
151 "Coredump\0",
152 config_item_table_lookup, items,
bcde742e 153 CONFIG_PARSE_WARN, NULL);
34c10968
LP
154}
155
73a99163
ZJS
156static inline uint64_t storage_size_max(void) {
157 return arg_storage == COREDUMP_STORAGE_EXTERNAL ? arg_external_size_max : arg_journal_size_max;
158}
159
34c10968
LP
160static int fix_acl(int fd, uid_t uid) {
161
349cc4a5 162#if HAVE_ACL
34c10968
LP
163 _cleanup_(acl_freep) acl_t acl = NULL;
164 acl_entry_t entry;
165 acl_permset_t permset;
709f6e46 166 int r;
34c10968 167
b59233e6
LP
168 assert(fd >= 0);
169
05fd2156 170 if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY)
34c10968
LP
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);
4a62c710
MS
177 if (!acl)
178 return log_error_errno(errno, "Failed to get ACL: %m");
34c10968
LP
179
180 if (acl_create_entry(&acl, &entry) < 0 ||
181 acl_set_tag_type(entry, ACL_USER) < 0 ||
d710aaf7
ZJS
182 acl_set_qualifier(entry, &uid) < 0)
183 return log_error_errno(errno, "Failed to patch ACL: %m");
34c10968
LP
184
185 if (acl_get_permset(entry, &permset) < 0 ||
709f6e46
MS
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");
34c10968 192
4a62c710
MS
193 if (acl_set_fd(fd, acl) < 0)
194 return log_error_errno(errno, "Failed to apply ACL: %m");
34c10968
LP
195#endif
196
197 return 0;
198}
199
3c171f0b 200static int fix_xattr(int fd, const char *context[_CONTEXT_MAX]) {
0cd77f97 201
3c171f0b
LP
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",
6d337300 208 [CONTEXT_RLIMIT] = "user.coredump.rlimit",
f45b8015 209 [CONTEXT_HOSTNAME] = "user.coredump.hostname",
3c171f0b
LP
210 [CONTEXT_COMM] = "user.coredump.comm",
211 [CONTEXT_EXE] = "user.coredump.exe",
0cd77f97
LP
212 };
213
34c10968 214 int r = 0;
0cd77f97 215 unsigned i;
34c10968 216
b59233e6
LP
217 assert(fd >= 0);
218
1eef15b1 219 /* Attach some metadata to coredumps via extended
34c10968
LP
220 * attributes. Just because we can. */
221
3c171f0b 222 for (i = 0; i < _CONTEXT_MAX; i++) {
1eef15b1
ZJS
223 int k;
224
3c171f0b 225 if (isempty(context[i]) || !xattrs[i])
0cd77f97 226 continue;
34c10968 227
3c171f0b 228 k = fsetxattr(fd, xattrs[i], context[i], strlen(context[i]), XATTR_CREATE);
1eef15b1 229 if (k < 0 && r == 0)
34c10968 230 r = -errno;
0cd77f97 231 }
34c10968
LP
232
233 return r;
234}
235
b0b21dce 236#define filename_escape(s) xescape((s), "./ ")
34c10968 237
0c773903
EV
238static inline const char *coredump_tmpfile_name(const char *s) {
239 return s ? s : "(unnamed temporary file)";
240}
241
b59233e6
LP
242static int fix_permissions(
243 int fd,
244 const char *filename,
245 const char *target,
3c171f0b 246 const char *context[_CONTEXT_MAX],
b59233e6
LP
247 uid_t uid) {
248
03532f0a
LP
249 int r;
250
b59233e6 251 assert(fd >= 0);
b59233e6 252 assert(target);
3c171f0b 253 assert(context);
cfd652ed
ZJS
254
255 /* Ignore errors on these */
3c171f0b
LP
256 (void) fchmod(fd, 0640);
257 (void) fix_acl(fd, uid);
258 (void) fix_xattr(fd, context);
cfd652ed 259
4a62c710 260 if (fsync(fd) < 0)
0c773903 261 return log_error_errno(errno, "Failed to sync coredump %s: %m", coredump_tmpfile_name(filename));
cfd652ed 262
8ac2f74f
LP
263 (void) fsync_directory_of_file(fd);
264
03532f0a
LP
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);
cfd652ed
ZJS
268
269 return 0;
270}
271
59f448cf 272static int maybe_remove_external_coredump(const char *filename, uint64_t size) {
cfd652ed 273
b59233e6 274 /* Returns 1 if might remove, 0 if will not remove, < 0 on error. */
cfd652ed 275
fc6cec86 276 if (arg_storage == COREDUMP_STORAGE_EXTERNAL &&
cfd652ed
ZJS
277 size <= arg_external_size_max)
278 return 0;
279
280 if (!filename)
281 return 1;
282
4a62c710
MS
283 if (unlink(filename) < 0 && errno != ENOENT)
284 return log_error_errno(errno, "Failed to unlink %s: %m", filename);
cfd652ed
ZJS
285
286 return 1;
287}
288
3c171f0b 289static int make_filename(const char *context[_CONTEXT_MAX], char **ret) {
b59233e6 290 _cleanup_free_ char *c = NULL, *u = NULL, *p = NULL, *t = NULL;
a7f7d1bd 291 sd_id128_t boot = {};
34c10968
LP
292 int r;
293
3c171f0b 294 assert(context);
34c10968 295
3c171f0b 296 c = filename_escape(context[CONTEXT_COMM]);
34c10968 297 if (!c)
b59233e6 298 return -ENOMEM;
34c10968 299
3c171f0b 300 u = filename_escape(context[CONTEXT_UID]);
0dc5d23c 301 if (!u)
b59233e6 302 return -ENOMEM;
34c10968
LP
303
304 r = sd_id128_get_boot(&boot);
b59233e6 305 if (r < 0)
34c10968 306 return r;
34c10968 307
3c171f0b 308 p = filename_escape(context[CONTEXT_PID]);
b59233e6
LP
309 if (!p)
310 return -ENOMEM;
311
3c171f0b 312 t = filename_escape(context[CONTEXT_TIMESTAMP]);
b59233e6
LP
313 if (!t)
314 return -ENOMEM;
315
316 if (asprintf(ret,
0dc5d23c 317 "/var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR ".%s.%s000000",
34c10968 318 c,
0dc5d23c 319 u,
34c10968
LP
320 SD_ID128_FORMAT_VAL(boot),
321 p,
b59233e6
LP
322 t) < 0)
323 return -ENOMEM;
324
325 return 0;
326}
327
328static int save_external_coredump(
3c171f0b
LP
329 const char *context[_CONTEXT_MAX],
330 int input_fd,
b59233e6 331 char **ret_filename,
5f3e0a74
HW
332 int *ret_node_fd,
333 int *ret_data_fd,
0cd4e913 334 uint64_t *ret_size,
cc4419ed 335 bool *ret_truncated) {
b59233e6
LP
336
337 _cleanup_free_ char *fn = NULL, *tmp = NULL;
338 _cleanup_close_ int fd = -1;
bdfd7b2c 339 uint64_t rlimit, max_size;
b59233e6 340 struct stat st;
3c171f0b 341 uid_t uid;
b59233e6
LP
342 int r;
343
3c171f0b 344 assert(context);
b59233e6 345 assert(ret_filename);
5f3e0a74
HW
346 assert(ret_node_fd);
347 assert(ret_data_fd);
b59233e6
LP
348 assert(ret_size);
349
3c171f0b
LP
350 r = parse_uid(context[CONTEXT_UID], &uid);
351 if (r < 0)
352 return log_error_errno(r, "Failed to parse UID: %m");
353
bdfd7b2c
LP
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]);
6998b540
ZJS
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. */
73a99163
ZJS
361 log_info("Resource limits disable core dumping for process %s (%s).",
362 context[CONTEXT_PID], context[CONTEXT_COMM]);
bdfd7b2c
LP
363 return -EBADSLT;
364 }
365
366 /* Never store more than the process configured, or than we actually shall keep or process */
73a99163 367 max_size = MIN(rlimit, MAX(arg_process_size_max, storage_size_max()));
bdfd7b2c 368
3c171f0b 369 r = make_filename(context, &fn);
23bbb0de
MS
370 if (r < 0)
371 return log_error_errno(r, "Failed to determine coredump file name: %m");
34c10968 372
d2e54fae 373 mkdir_p_label("/var/lib/systemd/coredump", 0755);
803a3464 374
03532f0a 375 fd = open_tmpfile_linkable(fn, O_RDWR|O_CLOEXEC, &tmp);
4a62c710 376 if (fd < 0)
03532f0a 377 return log_error_errno(fd, "Failed to create temporary file for coredump %s: %m", fn);
803a3464 378
1c876927 379 r = copy_bytes(input_fd, fd, max_size, 0);
73a99163
ZJS
380 if (r < 0) {
381 log_error_errno(r, "Cannot store coredump of %s (%s): %m", context[CONTEXT_PID], context[CONTEXT_COMM]);
93240d3a 382 goto fail;
0cd4e913 383 }
cc4419ed
ZJS
384 *ret_truncated = r == 1;
385 if (*ret_truncated)
73a99163
ZJS
386 log_struct(LOG_INFO,
387 LOG_MESSAGE("Core file was truncated to %zu bytes.", max_size),
388 "SIZE_LIMIT=%zu", max_size,
2b044526 389 "MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR,
73a99163 390 NULL);
803a3464 391
34c10968 392 if (fstat(fd, &st) < 0) {
73a99163 393 log_error_errno(errno, "Failed to fstat core file %s: %m", coredump_tmpfile_name(tmp));
34c10968
LP
394 goto fail;
395 }
396
7849c2ac 397 if (lseek(fd, 0, SEEK_SET) == (off_t) -1) {
0c773903 398 log_error_errno(errno, "Failed to seek on %s: %m", coredump_tmpfile_name(tmp));
b59233e6 399 goto fail;
7849c2ac
TA
400 }
401
349cc4a5 402#if HAVE_XZ || HAVE_LZ4
cfd652ed 403 /* If we will remove the coredump anyway, do not compress. */
6e9ef603 404 if (arg_compress && !maybe_remove_external_coredump(NULL, st.st_size)) {
cfd652ed 405
b59233e6
LP
406 _cleanup_free_ char *fn_compressed = NULL, *tmp_compressed = NULL;
407 _cleanup_close_ int fd_compressed = -1;
cfd652ed 408
d89c8fdf 409 fn_compressed = strappend(fn, COMPRESSED_EXT);
b59233e6 410 if (!fn_compressed) {
d89c8fdf 411 log_oom();
cfd652ed
ZJS
412 goto uncompressed;
413 }
414
03532f0a
LP
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);
b59233e6 418 goto uncompressed;
03532f0a 419 }
cfd652ed 420
d89c8fdf 421 r = compress_stream(fd, fd_compressed, -1);
b59233e6 422 if (r < 0) {
0c773903 423 log_error_errno(r, "Failed to compress %s: %m", coredump_tmpfile_name(tmp_compressed));
b59233e6
LP
424 goto fail_compressed;
425 }
426
3c171f0b 427 r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid);
cfd652ed 428 if (r < 0)
b59233e6
LP
429 goto fail_compressed;
430
431 /* OK, this worked, we can get rid of the uncompressed version now */
0c773903
EV
432 if (tmp)
433 unlink_noerrno(tmp);
cfd652ed 434
1cc6c93a
YW
435 *ret_filename = TAKE_PTR(fn_compressed); /* compressed */
436 *ret_node_fd = TAKE_FD(fd_compressed); /* compressed */
437 *ret_data_fd = TAKE_FD(fd); /* uncompressed */
59f448cf 438 *ret_size = (uint64_t) st.st_size; /* uncompressed */
cfd652ed 439
cfd652ed
ZJS
440 return 0;
441
b59233e6 442 fail_compressed:
0c773903
EV
443 if (tmp_compressed)
444 (void) unlink(tmp_compressed);
34c10968 445 }
cfd652ed
ZJS
446
447uncompressed:
3b1a55e1 448#endif
5f3e0a74 449
3c171f0b 450 r = fix_permissions(fd, tmp, fn, context, uid);
cfd652ed
ZJS
451 if (r < 0)
452 goto fail;
34c10968 453
1cc6c93a
YW
454 *ret_filename = TAKE_PTR(fn);
455 *ret_data_fd = TAKE_FD(fd);
5f3e0a74 456 *ret_node_fd = -1;
59f448cf 457 *ret_size = (uint64_t) st.st_size;
34c10968 458
34c10968
LP
459 return 0;
460
461fail:
0c773903
EV
462 if (tmp)
463 (void) unlink(tmp);
34c10968
LP
464 return r;
465}
466
467static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_size) {
468 _cleanup_free_ char *field = NULL;
469 ssize_t n;
470
8d4e028f 471 assert(fd >= 0);
34c10968
LP
472 assert(ret);
473 assert(ret_size);
474
4a62c710
MS
475 if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
476 return log_warning_errno(errno, "Failed to seek: %m");
803a3464 477
34c10968
LP
478 field = malloc(9 + size);
479 if (!field) {
cfd652ed 480 log_warning("Failed to allocate memory for coredump, coredump will not be stored.");
34c10968
LP
481 return -ENOMEM;
482 }
483
484 memcpy(field, "COREDUMP=", 9);
485
486 n = read(fd, field + 9, size);
23bbb0de
MS
487 if (n < 0)
488 return log_error_errno((int) n, "Failed to read core data: %m");
34c10968
LP
489 if ((size_t) n < size) {
490 log_error("Core data too short.");
491 return -EIO;
492 }
493
1cc6c93a 494 *ret = TAKE_PTR(field);
34c10968
LP
495 *ret_size = size + 9;
496
34c10968
LP
497 return 0;
498}
803a3464 499
3f132692
JF
500/* Joins /proc/[pid]/fd/ and /proc/[pid]/fdinfo/ into the following lines:
501 * 0:/dev/pts/23
502 * pos: 0
503 * flags: 0100002
504 *
505 * 1:/dev/pts/23
506 * pos: 0
507 * flags: 0100002
508 *
509 * 2:/dev/pts/23
510 * pos: 0
511 * flags: 0100002
512 * EOF
513 */
514static int compose_open_fds(pid_t pid, char **open_fds) {
4d84bc2f
LP
515 _cleanup_closedir_ DIR *proc_fd_dir = NULL;
516 _cleanup_close_ int proc_fdinfo_fd = -1;
517 _cleanup_free_ char *buffer = NULL;
3f132692 518 _cleanup_fclose_ FILE *stream = NULL;
59059b4a 519 const char *fddelim = "", *path;
3f132692 520 struct dirent *dent = NULL;
4d84bc2f 521 size_t size = 0;
3f132692
JF
522 int r = 0;
523
524 assert(pid >= 0);
525 assert(open_fds != NULL);
526
59059b4a 527 path = procfs_file_alloca(pid, "fd");
3f132692 528 proc_fd_dir = opendir(path);
59059b4a
ZJS
529 if (!proc_fd_dir)
530 return -errno;
3f132692 531
4d84bc2f 532 proc_fdinfo_fd = openat(dirfd(proc_fd_dir), "../fdinfo", O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC|O_PATH);
59059b4a
ZJS
533 if (proc_fdinfo_fd < 0)
534 return -errno;
3f132692 535
4d84bc2f 536 stream = open_memstream(&buffer, &size);
3f132692
JF
537 if (!stream)
538 return -ENOMEM;
539
0d536673
LP
540 (void) __fsetlocking(stream, FSETLOCKING_BYCALLER);
541
4d84bc2f 542 FOREACH_DIRENT(dent, proc_fd_dir, return -errno) {
3f132692 543 _cleanup_fclose_ FILE *fdinfo = NULL;
4d84bc2f 544 _cleanup_free_ char *fdname = NULL;
59059b4a 545 char line[LINE_MAX];
4d84bc2f 546 int fd;
3f132692 547
59059b4a 548 r = readlinkat_malloc(dirfd(proc_fd_dir), dent->d_name, &fdname);
3f132692
JF
549 if (r < 0)
550 return r;
551
552 fprintf(stream, "%s%s:%s\n", fddelim, dent->d_name, fdname);
553 fddelim = "\n";
554
555 /* Use the directory entry from /proc/[pid]/fd with /proc/[pid]/fdinfo */
59059b4a
ZJS
556 fd = openat(proc_fdinfo_fd, dent->d_name, O_NOFOLLOW|O_CLOEXEC|O_RDONLY);
557 if (fd < 0)
3f132692
JF
558 continue;
559
59059b4a 560 fdinfo = fdopen(fd, "re");
234519ae 561 if (!fdinfo) {
0d536673 562 safe_close(fd);
3f132692 563 continue;
59059b4a 564 }
3f132692 565
4d84bc2f 566 FOREACH_LINE(line, fdinfo, break) {
0d536673 567 fputs(line, stream);
4d84bc2f
LP
568 if (!endswith(line, "\n"))
569 fputc('\n', stream);
570 }
3f132692
JF
571 }
572
4d84bc2f 573 errno = 0;
74ca738f 574 stream = safe_fclose(stream);
4d84bc2f 575
b3267152 576 if (errno > 0)
4d84bc2f
LP
577 return -errno;
578
ae2a15bc 579 *open_fds = TAKE_PTR(buffer);
4d84bc2f 580
3f132692
JF
581 return 0;
582}
583
7ed03ce6
JF
584static 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
602static 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
aa7530d6 611 for (;;) {
7ed03ce6
JF
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 */
640static 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
d3cba4ea
EV
664 r = get_process_cmdline(container_pid, 0, false, cmdline);
665 if (r < 0)
666 return r;
667
668 return 1;
7ed03ce6
JF
669}
670
3c171f0b
LP
671static int change_uid_gid(const char *context[]) {
672 uid_t uid;
673 gid_t gid;
674 int r;
34c10968 675
3c171f0b
LP
676 r = parse_uid(context[CONTEXT_UID], &uid);
677 if (r < 0)
678 return r;
8c8549db 679
888e378d
LP
680 if (uid <= SYSTEM_UID_MAX) {
681 const char *user = "systemd-coredump";
682
683 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
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 }
3c171f0b
LP
693
694 return drop_privileges(uid, gid, 0);
695}
8c8549db 696
b8cda92d
LP
697static 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
703static 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
0cd4e913
ZJS
710#define SUBMIT_COREDUMP_FIELDS 4
711
3c171f0b
LP
712static 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) {
34c10968 718
5f3e0a74 719 _cleanup_close_ int coredump_fd = -1, coredump_node_fd = -1;
3c171f0b 720 _cleanup_free_ char *core_message = NULL, *filename = NULL, *coredump_data = NULL;
a5ca3649 721 uint64_t coredump_size = UINT64_MAX;
92e92d71 722 bool truncated = false, journald_crash;
3c171f0b 723 int r;
f5e04665 724
3c171f0b
LP
725 assert(context);
726 assert(iovec);
0cd4e913 727 assert(n_iovec_allocated >= n_iovec + SUBMIT_COREDUMP_FIELDS);
3c171f0b 728 assert(input_fd >= 0);
f5e04665 729
b8cda92d 730 journald_crash = is_journald_crash(context);
92e92d71 731
3c171f0b
LP
732 /* Vacuum before we write anything again */
733 (void) coredump_vacuum(-1, arg_keep_free, arg_max_use);
803a3464 734
3c171f0b 735 /* Always stream the coredump to disk, if that's possible */
0cd4e913
ZJS
736 r = save_external_coredump(context, input_fd,
737 &filename, &coredump_node_fd, &coredump_fd, &coredump_size, &truncated);
3c171f0b
LP
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);
e6a7ec4b 751 iovec[n_iovec++] = IOVEC_MAKE_STRING(coredump_filename);
6e9ef603 752 } else if (arg_storage == COREDUMP_STORAGE_EXTERNAL)
5206a724 753 log_info("The core will not be stored: size %"PRIu64" is greater than %"PRIu64" (the configured maximum)",
6e9ef603 754 coredump_size, arg_external_size_max);
f5e04665 755
3c171f0b
LP
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);
8c9571d0 758
3c171f0b
LP
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");
34c10968 766
349cc4a5 767#if HAVE_ELFUTILS
3c171f0b
LP
768 /* Try to get a strack 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)
605405c6
ZJS
774 core_message = strjoin("MESSAGE=Process ", context[CONTEXT_PID],
775 " (", context[CONTEXT_COMM], ") of user ",
92e92d71
ZJS
776 context[CONTEXT_UID], " dumped core.",
777 journald_crash ? "\nCoredump diverted to " : "",
778 journald_crash ? filename : "",
779 "\n\n", stacktrace);
3c171f0b
LP
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");
6e9ef603 784 } else
5206a724 785 log_debug("Not generating stack trace: core size %"PRIu64" is greater than %"PRIu64" (the configured maximum)",
6e9ef603 786 coredump_size, arg_process_size_max);
803a3464 787
3c171f0b
LP
788 if (!core_message)
789#endif
790log:
92e92d71
ZJS
791 core_message = strjoin("MESSAGE=Process ", context[CONTEXT_PID],
792 " (", context[CONTEXT_COMM], ") of user ",
793 context[CONTEXT_UID], " dumped core.",
794 journald_crash ? "\nCoredump diverted to " : NULL,
795 journald_crash ? 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. */
ae2173d6 802 log_dispatch(LOG_ERR, 0, core_message);
92e92d71
ZJS
803 return 0;
804 }
805
e6a7ec4b 806 iovec[n_iovec++] = IOVEC_MAKE_STRING(core_message);
3c171f0b 807
0cd4e913 808 if (truncated)
e6a7ec4b 809 iovec[n_iovec++] = IOVEC_MAKE_STRING("COREDUMP_TRUNCATED=1");
0cd4e913 810
3c171f0b 811 /* Optionally store the entire coredump in the journal */
6e9ef603
ZJS
812 if (arg_storage == COREDUMP_STORAGE_JOURNAL) {
813 if (coredump_size <= arg_journal_size_max) {
814 size_t sz = 0;
815
816 /* Store the coredump itself in the journal */
817
818 r = allocate_journal_field(coredump_fd, (size_t) coredump_size, &coredump_data, &sz);
e6a7ec4b
LP
819 if (r >= 0)
820 iovec[n_iovec++] = IOVEC_MAKE(coredump_data, sz);
821 else
6e9ef603
ZJS
822 log_warning_errno(r, "Failed to attach the core to the journal entry: %m");
823 } else
5206a724 824 log_info("The core will not be stored: size %"PRIu64" is greater than %"PRIu64" (the configured maximum)",
6e9ef603 825 coredump_size, arg_journal_size_max);
f5e04665
LP
826 }
827
3c171f0b
LP
828 assert(n_iovec <= n_iovec_allocated);
829
830 r = sd_journal_sendv(iovec, n_iovec);
831 if (r < 0)
832 return log_error_errno(r, "Failed to log coredump: %m");
833
834 return 0;
835}
836
ea5cc2a8 837static void map_context_fields(const struct iovec *iovec, const char* context[]) {
3c171f0b 838
92e92d71 839 static const char * const context_field_names[] = {
3c171f0b
LP
840 [CONTEXT_PID] = "COREDUMP_PID=",
841 [CONTEXT_UID] = "COREDUMP_UID=",
842 [CONTEXT_GID] = "COREDUMP_GID=",
843 [CONTEXT_SIGNAL] = "COREDUMP_SIGNAL=",
844 [CONTEXT_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
92e92d71 845 [CONTEXT_RLIMIT] = "COREDUMP_RLIMIT=",
f45b8015 846 [CONTEXT_HOSTNAME] = "COREDUMP_HOSTNAME=",
3c171f0b
LP
847 [CONTEXT_COMM] = "COREDUMP_COMM=",
848 [CONTEXT_EXE] = "COREDUMP_EXE=",
849 };
850
851 unsigned i;
852
853 assert(iovec);
854 assert(context);
855
92e92d71 856 for (i = 0; i < ELEMENTSOF(context_field_names); i++) {
3c171f0b
LP
857 size_t l;
858
92e92d71
ZJS
859 if (!context_field_names[i])
860 continue;
861
3c171f0b
LP
862 l = strlen(context_field_names[i]);
863 if (iovec->iov_len < l)
864 continue;
865
866 if (memcmp(iovec->iov_base, context_field_names[i], l) != 0)
867 continue;
868
869 /* Note that these strings are NUL terminated, because we made sure that a trailing NUL byte is in the
870 * buffer, though not included in the iov_len count. (see below) */
871 context[i] = (char*) iovec->iov_base + l;
872 break;
873 }
874}
875
876static int process_socket(int fd) {
877 _cleanup_close_ int coredump_fd = -1;
878 struct iovec *iovec = NULL;
80002f66 879 size_t n_iovec = 0, n_allocated = 0, i, k;
3c171f0b
LP
880 const char *context[_CONTEXT_MAX] = {};
881 int r;
882
883 assert(fd >= 0);
884
885 log_set_target(LOG_TARGET_AUTO);
886 log_parse_environment();
887 log_open();
888
988e89ee
ZJS
889 log_debug("Processing coredump received on stdin...");
890
3c171f0b
LP
891 for (;;) {
892 union {
893 struct cmsghdr cmsghdr;
894 uint8_t buf[CMSG_SPACE(sizeof(int))];
895 } control = {};
896 struct msghdr mh = {
897 .msg_control = &control,
898 .msg_controllen = sizeof(control),
899 .msg_iovlen = 1,
900 };
901 ssize_t n;
fe1ef0f8 902 ssize_t l;
3c171f0b 903
0cd4e913 904 if (!GREEDY_REALLOC(iovec, n_allocated, n_iovec + SUBMIT_COREDUMP_FIELDS)) {
3c171f0b
LP
905 r = log_oom();
906 goto finish;
907 }
908
fe1ef0f8
EV
909 l = next_datagram_size_fd(fd);
910 if (l < 0) {
911 r = log_error_errno(l, "Failed to determine datagram size to read: %m");
3c171f0b
LP
912 goto finish;
913 }
914
915 assert(l >= 0);
916
917 iovec[n_iovec].iov_len = l;
918 iovec[n_iovec].iov_base = malloc(l + 1);
3c171f0b
LP
919 if (!iovec[n_iovec].iov_base) {
920 r = log_oom();
921 goto finish;
922 }
923
924 mh.msg_iov = iovec + n_iovec;
925
926 n = recvmsg(fd, &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
927 if (n < 0) {
928 free(iovec[n_iovec].iov_base);
929 r = log_error_errno(errno, "Failed to receive datagram: %m");
930 goto finish;
931 }
932
933 if (n == 0) {
934 struct cmsghdr *cmsg, *found = NULL;
935 /* The final zero-length datagram carries the file descriptor and tells us that we're done. */
936
937 free(iovec[n_iovec].iov_base);
938
939 CMSG_FOREACH(cmsg, &mh) {
940 if (cmsg->cmsg_level == SOL_SOCKET &&
941 cmsg->cmsg_type == SCM_RIGHTS &&
942 cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
943 assert(!found);
944 found = cmsg;
945 }
946 }
947
948 if (!found) {
949 log_error("Coredump file descriptor missing.");
950 r = -EBADMSG;
951 goto finish;
952 }
953
954 assert(coredump_fd < 0);
955 coredump_fd = *(int*) CMSG_DATA(found);
956 break;
957 }
958
959 /* Add trailing NUL byte, in case these are strings */
960 ((char*) iovec[n_iovec].iov_base)[n] = 0;
961 iovec[n_iovec].iov_len = (size_t) n;
962
963 cmsg_close_all(&mh);
964 map_context_fields(iovec + n_iovec, context);
965 n_iovec++;
966 }
967
0cd4e913 968 if (!GREEDY_REALLOC(iovec, n_allocated, n_iovec + SUBMIT_COREDUMP_FIELDS)) {
3c171f0b 969 r = log_oom();
34c10968
LP
970 goto finish;
971 }
972
61233823 973 /* Make sure we got all data we really need */
3c171f0b
LP
974 assert(context[CONTEXT_PID]);
975 assert(context[CONTEXT_UID]);
976 assert(context[CONTEXT_GID]);
977 assert(context[CONTEXT_SIGNAL]);
978 assert(context[CONTEXT_TIMESTAMP]);
bdfd7b2c 979 assert(context[CONTEXT_RLIMIT]);
f45b8015 980 assert(context[CONTEXT_HOSTNAME]);
3c171f0b
LP
981 assert(context[CONTEXT_COMM]);
982 assert(coredump_fd >= 0);
983
80002f66
LP
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
5b45a160 991 r = submit_coredump(context, iovec, n_allocated, n_iovec, coredump_fd);
3c171f0b
LP
992
993finish:
994 for (i = 0; i < n_iovec; i++)
995 free(iovec[i].iov_base);
996 free(iovec);
997
998 return r;
999}
1000
1001static 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
fc2fffe7 1018 if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
3c171f0b
LP
1019 return log_error_errno(errno, "Failed to connect to coredump service: %m");
1020
1021 for (i = 0; i < n_iovec; i++) {
fec603eb
LP
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 }
3c171f0b 1055
3c171f0b 1056 return log_error_errno(errno, "Failed to send coredump datagram: %m");
fec603eb 1057 }
1eef15b1
ZJS
1058 }
1059
3c171f0b
LP
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");
1eef15b1 1063
3c171f0b
LP
1064 return 0;
1065}
1eef15b1 1066
f45b8015 1067static char* set_iovec_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value) {
9aa82023 1068 char *x;
3c171f0b 1069
9aa82023
ZJS
1070 x = strappend(field, value);
1071 if (x)
e6a7ec4b 1072 iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(x);
9aa82023
ZJS
1073 return x;
1074}
3c171f0b 1075
f45b8015 1076static char* set_iovec_field_free(struct iovec *iovec, size_t *n_iovec, const char *field, char *value) {
9aa82023
ZJS
1077 char *x;
1078
1079 x = set_iovec_field(iovec, n_iovec, field, value);
1080 free(value);
1081 return x;
1082}
1083
92e92d71 1084static int gather_pid_metadata(
ea5cc2a8 1085 char* context[_CONTEXT_MAX],
9aa82023 1086 char **comm_fallback,
5b45a160 1087 struct iovec *iovec, size_t *n_iovec) {
d14bcb4e 1088
f45b8015 1089 /* We need 27 empty slots in iovec!
d14bcb4e
LP
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.) */
3c171f0b 1093
3c171f0b 1094 uid_t owner_uid;
3c171f0b
LP
1095 pid_t pid;
1096 char *t;
9aa82023 1097 const char *p;
d14bcb4e 1098 int r, signo;
3c171f0b 1099
9aa82023 1100 r = parse_pid(context[CONTEXT_PID], &pid);
3c171f0b 1101 if (r < 0)
988e89ee 1102 return log_error_errno(r, "Failed to parse PID \"%s\": %m", context[CONTEXT_PID]);
3c171f0b 1103
ea5cc2a8 1104 r = get_process_comm(pid, &context[CONTEXT_COMM]);
3c171f0b
LP
1105 if (r < 0) {
1106 log_warning_errno(r, "Failed to get COMM, falling back to the command line: %m");
ea5cc2a8
ZJS
1107 context[CONTEXT_COMM] = strv_join(comm_fallback, " ");
1108 if (!context[CONTEXT_COMM])
3c171f0b
LP
1109 return log_oom();
1110 }
1111
ea5cc2a8 1112 r = get_process_exe(pid, &context[CONTEXT_EXE]);
3c171f0b
LP
1113 if (r < 0)
1114 log_warning_errno(r, "Failed to get EXE, ignoring: %m");
1115
92e92d71 1116 if (cg_pid_get_unit(pid, &context[CONTEXT_UNIT]) >= 0) {
b8cda92d 1117 if (!is_journald_crash((const char**) context)) {
92e92d71
ZJS
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 }
3c171f0b 1122
c8091d92 1123 /* If this is PID 1 disable coredump collection, we'll unlikely be able to process it later on. */
b8cda92d 1124 if (is_pid1_crash((const char**) context)) {
c8091d92 1125 log_notice("Due to PID 1 having crashed coredump collection will now be turned off.");
e557b1a6 1126 disable_coredumps();
c8091d92
LP
1127 }
1128
92e92d71 1129 set_iovec_field(iovec, n_iovec, "COREDUMP_UNIT=", context[CONTEXT_UNIT]);
8c8549db 1130 }
803a3464 1131
9aa82023
ZJS
1132 if (cg_pid_get_user_unit(pid, &t) >= 0)
1133 set_iovec_field_free(iovec, n_iovec, "COREDUMP_USER_UNIT=", t);
3c171f0b 1134
9aa82023
ZJS
1135 /* The next few are mandatory */
1136 if (!set_iovec_field(iovec, n_iovec, "COREDUMP_PID=", context[CONTEXT_PID]))
1137 return log_oom();
3c171f0b 1138
9aa82023
ZJS
1139 if (!set_iovec_field(iovec, n_iovec, "COREDUMP_UID=", context[CONTEXT_UID]))
1140 return log_oom();
f5e04665 1141
9aa82023
ZJS
1142 if (!set_iovec_field(iovec, n_iovec, "COREDUMP_GID=", context[CONTEXT_GID]))
1143 return log_oom();
f5e04665 1144
9aa82023
ZJS
1145 if (!set_iovec_field(iovec, n_iovec, "COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL]))
1146 return log_oom();
f5e04665 1147
9aa82023
ZJS
1148 if (!set_iovec_field(iovec, n_iovec, "COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT]))
1149 return log_oom();
f5e04665 1150
f45b8015
JF
1151 if (!set_iovec_field(iovec, n_iovec, "COREDUMP_HOSTNAME=", context[CONTEXT_HOSTNAME]))
1152 return log_oom();
1153
ea5cc2a8 1154 if (!set_iovec_field(iovec, n_iovec, "COREDUMP_COMM=", context[CONTEXT_COMM]))
9aa82023 1155 return log_oom();
bdfd7b2c 1156
ea5cc2a8
ZJS
1157 if (context[CONTEXT_EXE] &&
1158 !set_iovec_field(iovec, n_iovec, "COREDUMP_EXE=", context[CONTEXT_EXE]))
9aa82023 1159 return log_oom();
f5e04665 1160
9aa82023
ZJS
1161 if (sd_pid_get_session(pid, &t) >= 0)
1162 set_iovec_field_free(iovec, n_iovec, "COREDUMP_SESSION=", t);
f5e04665 1163
a035f819 1164 if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) {
9aa82023 1165 r = asprintf(&t, "COREDUMP_OWNER_UID=" UID_FMT, owner_uid);
7de80bfe 1166 if (r > 0)
e6a7ec4b 1167 iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(t);
f5e04665
LP
1168 }
1169
9aa82023
ZJS
1170 if (sd_pid_get_slice(pid, &t) >= 0)
1171 set_iovec_field_free(iovec, n_iovec, "COREDUMP_SLICE=", t);
f5e04665 1172
9aa82023
ZJS
1173 if (get_process_cmdline(pid, 0, false, &t) >= 0)
1174 set_iovec_field_free(iovec, n_iovec, "COREDUMP_CMDLINE=", t);
a035f819 1175
9aa82023
ZJS
1176 if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0)
1177 set_iovec_field_free(iovec, n_iovec, "COREDUMP_CGROUP=", t);
a035f819 1178
9aa82023
ZJS
1179 if (compose_open_fds(pid, &t) >= 0)
1180 set_iovec_field_free(iovec, n_iovec, "COREDUMP_OPEN_FDS=", t);
3f132692
JF
1181
1182 p = procfs_file_alloca(pid, "status");
9aa82023
ZJS
1183 if (read_full_file(p, &t, NULL) >= 0)
1184 set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_STATUS=", t);
3f132692
JF
1185
1186 p = procfs_file_alloca(pid, "maps");
9aa82023
ZJS
1187 if (read_full_file(p, &t, NULL) >= 0)
1188 set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_MAPS=", t);
3f132692
JF
1189
1190 p = procfs_file_alloca(pid, "limits");
9aa82023
ZJS
1191 if (read_full_file(p, &t, NULL) >= 0)
1192 set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_LIMITS=", t);
3f132692
JF
1193
1194 p = procfs_file_alloca(pid, "cgroup");
9aa82023
ZJS
1195 if (read_full_file(p, &t, NULL) >=0)
1196 set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_CGROUP=", t);
3f132692 1197
d7032b1f 1198 p = procfs_file_alloca(pid, "mountinfo");
9aa82023
ZJS
1199 if (read_full_file(p, &t, NULL) >=0)
1200 set_iovec_field_free(iovec, n_iovec, "COREDUMP_PROC_MOUNTINFO=", t);
d7032b1f 1201
9aa82023
ZJS
1202 if (get_process_cwd(pid, &t) >= 0)
1203 set_iovec_field_free(iovec, n_iovec, "COREDUMP_CWD=", t);
3f132692
JF
1204
1205 if (get_process_root(pid, &t) >= 0) {
9aa82023
ZJS
1206 bool proc_self_root_is_slash;
1207
1208 proc_self_root_is_slash = strcmp(t, "/") == 0;
3f132692 1209
9aa82023 1210 set_iovec_field_free(iovec, n_iovec, "COREDUMP_ROOT=", t);
7ed03ce6
JF
1211
1212 /* If the process' root is "/", then there is a chance it has
1213 * mounted own root and hence being containerized. */
9aa82023
ZJS
1214 if (proc_self_root_is_slash && get_process_container_parent_cmdline(pid, &t) > 0)
1215 set_iovec_field_free(iovec, n_iovec, "COREDUMP_CONTAINER_CMDLINE=", t);
3f132692
JF
1216 }
1217
9aa82023
ZJS
1218 if (get_process_environ(pid, &t) >= 0)
1219 set_iovec_field_free(iovec, n_iovec, "COREDUMP_ENVIRON=", t);
1220
4600a396 1221 t = strjoin("COREDUMP_TIMESTAMP=", context[CONTEXT_TIMESTAMP], "000000");
9aa82023 1222 if (t)
e6a7ec4b 1223 iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(t);
9aa82023 1224
d14bcb4e
LP
1225 if (safe_atoi(context[CONTEXT_SIGNAL], &signo) >= 0 && SIGNAL_VALID(signo))
1226 set_iovec_field(iovec, n_iovec, "COREDUMP_SIGNAL_NAME=SIG", signal_to_string(signo));
1227
92e92d71 1228 return 0; /* we successfully acquired all metadata */
9aa82023 1229}
3f132692 1230
9aa82023
ZJS
1231static int process_kernel(int argc, char* argv[]) {
1232
ea5cc2a8 1233 char* context[_CONTEXT_MAX] = {};
f45b8015 1234 struct iovec iovec[29 + SUBMIT_COREDUMP_FIELDS];
988e89ee 1235 size_t i, n_iovec, n_to_free = 0;
9aa82023
ZJS
1236 int r;
1237
988e89ee
ZJS
1238 log_debug("Processing coredump received from the kernel...");
1239
9aa82023 1240 if (argc < CONTEXT_COMM + 1) {
988e89ee 1241 log_error("Not enough arguments passed by the kernel (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1);
9aa82023 1242 return -EINVAL;
3f132692
JF
1243 }
1244
ea5cc2a8
ZJS
1245 context[CONTEXT_PID] = argv[1 + CONTEXT_PID];
1246 context[CONTEXT_UID] = argv[1 + CONTEXT_UID];
1247 context[CONTEXT_GID] = argv[1 + CONTEXT_GID];
1248 context[CONTEXT_SIGNAL] = argv[1 + CONTEXT_SIGNAL];
1249 context[CONTEXT_TIMESTAMP] = argv[1 + CONTEXT_TIMESTAMP];
1250 context[CONTEXT_RLIMIT] = argv[1 + CONTEXT_RLIMIT];
f45b8015 1251 context[CONTEXT_HOSTNAME] = argv[1 + CONTEXT_HOSTNAME];
9aa82023 1252
92e92d71
ZJS
1253 r = gather_pid_metadata(context, argv + 1 + CONTEXT_COMM, iovec, &n_to_free);
1254 if (r < 0)
86562420 1255 goto finish;
86562420 1256
988e89ee 1257 n_iovec = n_to_free;
f5e04665 1258
e6a7ec4b 1259 iovec[n_iovec++] = IOVEC_MAKE_STRING("MESSAGE_ID=" SD_MESSAGE_COREDUMP_STR);
4850d39a
LP
1260
1261 assert_cc(2 == LOG_CRIT);
e6a7ec4b 1262 iovec[n_iovec++] = IOVEC_MAKE_STRING("PRIORITY=2");
0dc5d23c 1263
3c171f0b 1264 assert(n_iovec <= ELEMENTSOF(iovec));
34c10968 1265
b8cda92d 1266 if (is_journald_crash((const char**) context) || is_pid1_crash((const char**) context))
92e92d71
ZJS
1267 r = submit_coredump((const char**) context,
1268 iovec, ELEMENTSOF(iovec), n_iovec,
1269 STDIN_FILENO);
1270 else
1271 r = send_iovec(iovec, n_iovec, STDIN_FILENO);
9aa82023
ZJS
1272
1273 finish:
1274 for (i = 0; i < n_to_free; i++)
1275 free(iovec[i].iov_base);
1276
92e92d71 1277 /* Those fields are allocated by gather_pid_metadata */
ea5cc2a8
ZJS
1278 free(context[CONTEXT_COMM]);
1279 free(context[CONTEXT_EXE]);
92e92d71 1280 free(context[CONTEXT_UNIT]);
ea5cc2a8 1281
9aa82023 1282 return r;
3c171f0b 1283}
34c10968 1284
988e89ee 1285static int process_backtrace(int argc, char *argv[]) {
ea5cc2a8
ZJS
1286 char *context[_CONTEXT_MAX] = {};
1287 _cleanup_free_ char *message = NULL;
5b45a160
ZJS
1288 _cleanup_free_ struct iovec *iovec = NULL;
1289 size_t n_iovec, n_allocated, n_to_free = 0, i;
988e89ee 1290 int r;
5b45a160
ZJS
1291 JournalImporter importer = {
1292 .fd = STDIN_FILENO,
1293 };
988e89ee
ZJS
1294
1295 log_debug("Processing backtrace on stdin...");
1296
1297 if (argc < CONTEXT_COMM + 1) {
1298 log_error("Not enough arguments passed (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1);
1299 return -EINVAL;
1300 }
1301
ea5cc2a8
ZJS
1302 context[CONTEXT_PID] = argv[2 + CONTEXT_PID];
1303 context[CONTEXT_UID] = argv[2 + CONTEXT_UID];
1304 context[CONTEXT_GID] = argv[2 + CONTEXT_GID];
1305 context[CONTEXT_SIGNAL] = argv[2 + CONTEXT_SIGNAL];
1306 context[CONTEXT_TIMESTAMP] = argv[2 + CONTEXT_TIMESTAMP];
1307 context[CONTEXT_RLIMIT] = argv[2 + CONTEXT_RLIMIT];
f45b8015 1308 context[CONTEXT_HOSTNAME] = argv[2 + CONTEXT_HOSTNAME];
988e89ee 1309
f45b8015
JF
1310 n_allocated = 34 + COREDUMP_STORAGE_EXTERNAL;
1311 /* 26 metadata, 2 static, +unknown input, 4 storage, rounded up */
5b45a160
ZJS
1312 iovec = new(struct iovec, n_allocated);
1313 if (!iovec)
1314 return log_oom();
1315
92e92d71 1316 r = gather_pid_metadata(context, argv + 2 + CONTEXT_COMM, iovec, &n_to_free);
988e89ee
ZJS
1317 if (r < 0)
1318 goto finish;
86562420
LP
1319 if (r > 0) {
1320 /* This was a special crash, and has already been processed. */
1321 r = 0;
1322 goto finish;
1323 }
5b45a160 1324 n_iovec = n_to_free;
988e89ee 1325
86562420 1326 for (;;) {
5b45a160
ZJS
1327 r = journal_importer_process_data(&importer);
1328 if (r < 0) {
1329 log_error_errno(r, "Failed to parse journal entry on stdin: %m");
1330 goto finish;
1331 }
d74dc4f2
ZJS
1332 if (r == 1 || /* complete entry */
1333 journal_importer_eof(&importer)) /* end of data */
5b45a160 1334 break;
988e89ee 1335 }
988e89ee 1336
5b45a160
ZJS
1337 if (!GREEDY_REALLOC(iovec, n_allocated, n_iovec + importer.iovw.count + 2))
1338 return log_oom();
1339
1340 if (journal_importer_eof(&importer)) {
1341 log_warning("Did not receive a full journal entry on stdin, ignoring message sent by reporter");
988e89ee 1342
ea5cc2a8
ZJS
1343 message = strjoin("MESSAGE=Process ", context[CONTEXT_PID],
1344 " (", context[CONTEXT_COMM], ")"
5b45a160
ZJS
1345 " of user ", context[CONTEXT_UID],
1346 " failed with ", context[CONTEXT_SIGNAL]);
1347 if (!message) {
1348 r = log_oom();
1349 goto finish;
1350 }
e6a7ec4b 1351 iovec[n_iovec++] = IOVEC_MAKE_STRING(message);
5b45a160
ZJS
1352 } else {
1353 for (i = 0; i < importer.iovw.count; i++)
1354 iovec[n_iovec++] = importer.iovw.iovec[i];
1355 }
988e89ee 1356
e6a7ec4b 1357 iovec[n_iovec++] = IOVEC_MAKE_STRING("MESSAGE_ID=" SD_MESSAGE_BACKTRACE_STR);
988e89ee 1358 assert_cc(2 == LOG_CRIT);
e6a7ec4b 1359 iovec[n_iovec++] = IOVEC_MAKE_STRING("PRIORITY=2");
988e89ee 1360
5b45a160 1361 assert(n_iovec <= n_allocated);
988e89ee
ZJS
1362
1363 r = sd_journal_sendv(iovec, n_iovec);
1364 if (r < 0)
1365 log_error_errno(r, "Failed to log backtrace: %m");
1366
1367 finish:
1368 for (i = 0; i < n_to_free; i++)
1369 free(iovec[i].iov_base);
1370
92e92d71 1371 /* Those fields are allocated by gather_pid_metadata */
ea5cc2a8
ZJS
1372 free(context[CONTEXT_COMM]);
1373 free(context[CONTEXT_EXE]);
92e92d71 1374 free(context[CONTEXT_UNIT]);
ea5cc2a8 1375
988e89ee
ZJS
1376 return r;
1377}
1378
3c171f0b
LP
1379int main(int argc, char *argv[]) {
1380 int r;
fee80f69 1381
9aa82023
ZJS
1382 /* First, log to a safe place, since we don't know what crashed and it might
1383 * be journald which we'd rather not log to then. */
8d4e028f 1384
3c171f0b
LP
1385 log_set_target(LOG_TARGET_KMSG);
1386 log_open();
8d4e028f 1387
3c171f0b
LP
1388 /* Make sure we never enter a loop */
1389 (void) prctl(PR_SET_DUMPABLE, 0);
8d4e028f 1390
3c171f0b
LP
1391 /* Ignore all parse errors */
1392 (void) parse_config();
fee80f69 1393
3c171f0b
LP
1394 log_debug("Selected storage '%s'.", coredump_storage_to_string(arg_storage));
1395 log_debug("Selected compression %s.", yes_no(arg_compress));
fee80f69 1396
3c171f0b
LP
1397 r = sd_listen_fds(false);
1398 if (r < 0) {
1399 log_error_errno(r, "Failed to determine number of file descriptor: %m");
1400 goto finish;
fee80f69
LP
1401 }
1402
9aa82023
ZJS
1403 /* If we got an fd passed, we are running in coredumpd mode. Otherwise we
1404 * are invoked from the kernel as coredump handler. */
988e89ee
ZJS
1405 if (r == 0) {
1406 if (streq_ptr(argv[1], "--backtrace"))
1407 r = process_backtrace(argc, argv);
1408 else
1409 r = process_kernel(argc, argv);
1410 } else if (r == 1)
3c171f0b
LP
1411 r = process_socket(SD_LISTEN_FDS_START);
1412 else {
1413 log_error("Received unexpected number of file descriptors.");
1414 r = -EINVAL;
1415 }
f5e04665
LP
1416
1417finish:
f5e04665
LP
1418 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1419}