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