summaryrefslogtreecommitdiff
path: root/src/coredump
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-12-21 22:06:22 +0100
committerMichael Biebl <biebl@debian.org>2018-12-21 22:06:22 +0100
commit6e866b331d7cd4a5e0759dd160dea6edabd3678e (patch)
tree4d24c1ffe4ae946f04d8910956090e8d13aecd9a /src/coredump
parentb012e92123bdc9fa10c2f079ec5bd9313b23e21a (diff)
downloadsystemd-6e866b331d7cd4a5e0759dd160dea6edabd3678e.tar.gz
New upstream version 240
Diffstat (limited to 'src/coredump')
-rw-r--r--src/coredump/coredump.c95
-rw-r--r--src/coredump/coredumpctl.c100
-rw-r--r--src/coredump/meson.build6
3 files changed, 112 insertions, 89 deletions
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 20a1cbdd45..0c888b26f9 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -34,6 +34,7 @@
#include "journal-importer.h"
#include "log.h"
#include "macro.h"
+#include "main-func.h"
#include "missing.h"
#include "mkdir.h"
#include "parse-util.h"
@@ -45,6 +46,7 @@
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
+#include "tmpfile-util.h"
#include "user-util.h"
#include "util.h"
@@ -55,10 +57,15 @@
#define EXTERNAL_SIZE_MAX PROCESS_SIZE_MAX
/* The maximum size up to which we store the coredump in the journal */
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
#define JOURNAL_SIZE_MAX ((size_t) (767LU*1024LU*1024LU))
+#else
+/* oss-fuzz limits memory usage. */
+#define JOURNAL_SIZE_MAX ((size_t) (10LU*1024LU*1024LU))
+#endif
/* Make sure to not make this larger than the maximum journal entry
- * size. See DATA_SIZE_MAX in journald-native.c. */
+ * size. See DATA_SIZE_MAX in journal-importer.h. */
assert_cc(JOURNAL_SIZE_MAX <= DATA_SIZE_MAX);
enum {
@@ -340,21 +347,20 @@ static int save_external_coredump(
r = safe_atou64(context[CONTEXT_RLIMIT], &rlimit);
if (r < 0)
- return log_error_errno(r, "Failed to parse resource limit: %s", context[CONTEXT_RLIMIT]);
+ return log_error_errno(r, "Failed to parse resource limit '%s': %m", context[CONTEXT_RLIMIT]);
if (rlimit < page_size()) {
/* Is coredumping disabled? Then don't bother saving/processing the coredump.
* Anything below PAGE_SIZE cannot give a readable coredump (the kernel uses
* ELF_EXEC_PAGESIZE which is not easily accessible, but is usually the same as PAGE_SIZE. */
- log_info("Resource limits disable core dumping for process %s (%s).",
- context[CONTEXT_PID], context[CONTEXT_COMM]);
- return -EBADSLT;
+ return log_info_errno(SYNTHETIC_ERRNO(EBADSLT),
+ "Resource limits disable core dumping for process %s (%s).",
+ context[CONTEXT_PID], context[CONTEXT_COMM]);
}
process_limit = MAX(arg_process_size_max, storage_size_max());
- if (process_limit == 0) {
- log_debug("Limits for coredump processing and storage are both 0, not dumping core.");
- return -EBADSLT;
- }
+ if (process_limit == 0)
+ return log_debug_errno(SYNTHETIC_ERRNO(EBADSLT),
+ "Limits for coredump processing and storage are both 0, not dumping core.");
/* Never store more than the process configured, or than we actually shall keep or process */
max_size = MIN(rlimit, process_limit);
@@ -478,10 +484,9 @@ static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_s
n = read(fd, field + 9, size);
if (n < 0)
return log_error_errno((int) n, "Failed to read core data: %m");
- if ((size_t) n < size) {
- log_error("Core data too short.");
- return -EIO;
- }
+ if ((size_t) n < size)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO),
+ "Core data too short.");
*ret = TAKE_PTR(field);
*ret_size = size + 9;
@@ -511,7 +516,7 @@ static int compose_open_fds(pid_t pid, char **open_fds) {
const char *fddelim = "", *path;
struct dirent *dent = NULL;
size_t size = 0;
- int r = 0;
+ int r;
assert(pid >= 0);
assert(open_fds != NULL);
@@ -534,7 +539,6 @@ static int compose_open_fds(pid_t pid, char **open_fds) {
FOREACH_DIRENT(dent, proc_fd_dir, return -errno) {
_cleanup_fclose_ FILE *fdinfo = NULL;
_cleanup_free_ char *fdname = NULL;
- char line[LINE_MAX];
int fd;
r = readlinkat_malloc(dirfd(proc_fd_dir), dent->d_name, &fdname);
@@ -549,16 +553,23 @@ static int compose_open_fds(pid_t pid, char **open_fds) {
if (fd < 0)
continue;
- fdinfo = fdopen(fd, "re");
+ fdinfo = fdopen(fd, "r");
if (!fdinfo) {
safe_close(fd);
continue;
}
- FOREACH_LINE(line, fdinfo, break) {
+ for (;;) {
+ _cleanup_free_ char *line = NULL;
+
+ r = read_line(fdinfo, LONG_LINE_MAX, &line);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ break;
+
fputs(line, stream);
- if (!endswith(line, "\n"))
- fputc('\n', stream);
+ fputc('\n', stream);
}
}
@@ -672,7 +683,7 @@ static int change_uid_gid(const char *context[]) {
if (uid <= SYSTEM_UID_MAX) {
const char *user = "systemd-coredump";
- r = get_user_creds(&user, &uid, &gid, NULL, NULL);
+ r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
if (r < 0) {
log_warning_errno(r, "Cannot resolve %s user. Proceeding to dump core as root: %m", user);
uid = gid = 0;
@@ -871,9 +882,7 @@ static int process_socket(int fd) {
assert(fd >= 0);
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
+ log_setup_service();
log_debug("Processing coredump received on stdin...");
@@ -1226,10 +1235,10 @@ static int process_kernel(int argc, char* argv[]) {
log_debug("Processing coredump received from the kernel...");
- if (argc < CONTEXT_COMM + 1) {
- log_error("Not enough arguments passed by the kernel (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1);
- return -EINVAL;
- }
+ if (argc < CONTEXT_COMM + 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Not enough arguments passed by the kernel (%i, expected %i).",
+ argc - 1, CONTEXT_COMM + 1 - 1);
context[CONTEXT_PID] = argv[1 + CONTEXT_PID];
context[CONTEXT_UID] = argv[1 + CONTEXT_UID];
@@ -1283,10 +1292,10 @@ static int process_backtrace(int argc, char *argv[]) {
log_debug("Processing backtrace on stdin...");
- if (argc < CONTEXT_COMM + 1) {
- log_error("Not enough arguments passed (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1);
- return -EINVAL;
- }
+ if (argc < CONTEXT_COMM + 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Not enough arguments passed (%i, expected %i).",
+ argc - 1, CONTEXT_COMM + 1 - 1);
context[CONTEXT_PID] = argv[2 + CONTEXT_PID];
context[CONTEXT_UID] = argv[2 + CONTEXT_UID];
@@ -1365,7 +1374,7 @@ static int process_backtrace(int argc, char *argv[]) {
return r;
}
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
int r;
/* First, log to a safe place, since we don't know what crashed and it might
@@ -1384,25 +1393,21 @@ int main(int argc, char *argv[]) {
log_debug("Selected compression %s.", yes_no(arg_compress));
r = sd_listen_fds(false);
- if (r < 0) {
- log_error_errno(r, "Failed to determine number of file descriptor: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to determine the number of file descriptors: %m");
/* If we got an fd passed, we are running in coredumpd mode. Otherwise we
* are invoked from the kernel as coredump handler. */
if (r == 0) {
if (streq_ptr(argv[1], "--backtrace"))
- r = process_backtrace(argc, argv);
+ return process_backtrace(argc, argv);
else
- r = process_kernel(argc, argv);
+ return process_kernel(argc, argv);
} else if (r == 1)
- r = process_socket(SD_LISTEN_FDS_START);
- else {
- log_error("Received unexpected number of file descriptors.");
- r = -EINVAL;
- }
+ return process_socket(SD_LISTEN_FDS_START);
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Received unexpected number of file descriptors.");
}
+
+DEFINE_MAIN_FUNCTION(run);
diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c
index 99d07c14fb..fbee242962 100644
--- a/src/coredump/coredumpctl.c
+++ b/src/coredump/coredumpctl.c
@@ -15,22 +15,26 @@
#include "bus-error.h"
#include "bus-util.h"
#include "compress.h"
+#include "def.h"
#include "fd-util.h"
-#include "fileio.h"
#include "fs-util.h"
#include "journal-internal.h"
#include "journal-util.h"
#include "log.h"
#include "macro.h"
+#include "main-func.h"
#include "pager.h"
#include "parse-util.h"
#include "path-util.h"
+#include "pretty-print.h"
#include "process-util.h"
+#include "rlimit-util.h"
#include "sigbus.h"
#include "signal-util.h"
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
+#include "tmpfile-util.h"
#include "user-util.h"
#include "util.h"
#include "verbs.h"
@@ -41,10 +45,10 @@ static usec_t arg_since = USEC_INFINITY, arg_until = USEC_INFINITY;
static const char* arg_field = NULL;
static const char *arg_debugger = NULL;
static const char *arg_directory = NULL;
-static bool arg_no_pager = false;
+static PagerFlags arg_pager_flags = 0;
static int arg_no_legend = false;
static int arg_one = false;
-static FILE* arg_output = NULL;
+static const char* arg_output = NULL;
static bool arg_reverse = false;
static bool arg_quiet = false;
@@ -135,6 +139,13 @@ static int acquire_journal(sd_journal **ret, char **matches) {
}
static int help(void) {
+ _cleanup_free_ char *link = NULL;
+ int r;
+
+ r = terminal_urlify_man("coredumpctl", "1", &link);
+ if (r < 0)
+ return log_oom();
+
printf("%s [OPTIONS...]\n\n"
"List or retrieve coredumps from the journal.\n\n"
"Flags:\n"
@@ -156,7 +167,10 @@ static int help(void) {
" info [MATCHES...] Show detailed information about one or more coredumps\n"
" dump [MATCHES...] Print first matching coredump to stdout\n"
" debug [MATCHES...] Start a debugger for the first matching coredump\n"
- , program_invocation_short_name);
+ "\nSee the %s for details.\n"
+ , program_invocation_short_name
+ , link
+ );
return 0;
}
@@ -199,7 +213,7 @@ static int parse_argv(int argc, char *argv[]) {
return version();
case ARG_NO_PAGER:
- arg_no_pager = true;
+ arg_pager_flags |= PAGER_DISABLE;
break;
case ARG_NO_LEGEND:
@@ -211,34 +225,29 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'o':
- if (arg_output) {
- log_error("Cannot set output more than once.");
- return -EINVAL;
- }
-
- arg_output = fopen(optarg, "we");
- if (!arg_output)
- return log_error_errno(errno, "writing to '%s': %m", optarg);
+ if (arg_output)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Cannot set output more than once.");
+ arg_output = optarg;
break;
case 'S':
r = parse_timestamp(optarg, &arg_since);
if (r < 0)
- return log_error_errno(r, "Failed to parse timestamp: %s", optarg);
+ return log_error_errno(r, "Failed to parse timestamp '%s': %m", optarg);
break;
case 'U':
r = parse_timestamp(optarg, &arg_until);
if (r < 0)
- return log_error_errno(r, "Failed to parse timestamp: %s", optarg);
+ return log_error_errno(r, "Failed to parse timestamp '%s': %m", optarg);
break;
case 'F':
- if (arg_field) {
- log_error("Cannot use --field/-F more than once.");
- return -EINVAL;
- }
+ if (arg_field)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Cannot use --field/-F more than once.");
arg_field = optarg;
break;
@@ -266,10 +275,9 @@ static int parse_argv(int argc, char *argv[]) {
}
if (arg_since != USEC_INFINITY && arg_until != USEC_INFINITY &&
- arg_since > arg_until) {
- log_error("--since= must be before --until=.");
- return -EINVAL;
- }
+ arg_since > arg_until)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "--since= must be before --until=.");
return 1;
}
@@ -617,10 +625,9 @@ static int focus(sd_journal *j) {
r = sd_journal_previous(j);
if (r < 0)
return log_error_errno(r, "Failed to search journal: %m");
- if (r == 0) {
- log_error("No match found.");
- return -ESRCH;
- }
+ if (r == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(ESRCH),
+ "No match found.");
return r;
}
@@ -647,14 +654,15 @@ static int dump_list(int argc, char **argv, void *userdata) {
if (r < 0)
return r;
- (void) pager_open(arg_no_pager, false);
+ (void) pager_open(arg_pager_flags);
/* The coredumps are likely to compressed, and for just
* listing them we don't need to decompress them, so let's
* pick a fairly low data threshold here */
sd_journal_set_data_threshold(j, 4096);
- if (arg_one) {
+ /* "info" without pattern implies "-1" */
+ if (arg_one || (verb_is_info && argc == 1)) {
r = focus(j);
if (r < 0)
return r;
@@ -788,7 +796,8 @@ static int save_core(sd_journal *j, FILE *file, char **path, bool *unlink_temp)
*/
if (!file) {
if (on_tty())
- return log_error_errno(ENOTTY, "Refusing to dump core to tty"
+ return log_error_errno(SYNTHETIC_ERRNO(ENOTTY),
+ "Refusing to dump core to tty"
" (use shell redirection or specify --output).");
file = stdout;
}
@@ -858,6 +867,7 @@ error:
static int dump_core(int argc, char **argv, void *userdata) {
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
int r;
if (arg_field) {
@@ -873,9 +883,15 @@ static int dump_core(int argc, char **argv, void *userdata) {
if (r < 0)
return r;
- print_info(arg_output ? stdout : stderr, j, false);
+ if (arg_output) {
+ f = fopen(arg_output, "we");
+ if (!f)
+ return log_error_errno(errno, "Failed to open \"%s\" for writing: %m", arg_output);
+ }
- r = save_core(j, arg_output, NULL, NULL);
+ print_info(f ? stdout : stderr, j, false);
+
+ r = save_core(j, f, NULL, NULL);
if (r < 0)
return r;
@@ -952,7 +968,7 @@ static int run_debug(int argc, char **argv, void *userdata) {
fork_name = strjoina("(", arg_debugger, ")");
- r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
+ r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
goto finish;
if (r == 0) {
@@ -976,7 +992,7 @@ finish:
}
static int check_units_active(void) {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@@ -1049,16 +1065,19 @@ static int coredumpctl_main(int argc, char *argv[]) {
return dispatch_verb(argc, argv, verbs, NULL);
}
-int main(int argc, char *argv[]) {
+static int run(int argc, char *argv[]) {
int r, units_active;
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
+ /* The journal merging logic potentially needs a lot of fds. */
+ (void) rlimit_nofile_bump(HIGH_RLIMIT_NOFILE);
+
r = parse_argv(argc, argv);
if (r <= 0)
- goto end;
+ return r;
sigbus_install();
@@ -1071,10 +1090,7 @@ int main(int argc, char *argv[]) {
ansi_highlight_red(),
units_active, units_active == 1 ? "unit is running" : "units are running",
ansi_normal());
-end:
- pager_close();
-
- safe_fclose(arg_output);
-
- return r >= 0 ? r : EXIT_FAILURE;
+ return r;
}
+
+DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
diff --git a/src/coredump/meson.build b/src/coredump/meson.build
index bfba7ef58c..7fa5942697 100644
--- a/src/coredump/meson.build
+++ b/src/coredump/meson.build
@@ -13,8 +13,10 @@ endif
coredumpctl_sources = files('coredumpctl.c')
-install_data('coredump.conf',
- install_dir : pkgsysconfdir)
+if conf.get('ENABLE_COREDUMP') == 1
+ install_data('coredump.conf',
+ install_dir : pkgsysconfdir)
+endif
tests += [
[['src/coredump/test-coredump-vacuum.c',