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