diff options
Diffstat (limited to 'src/coredump/coredump.c')
-rw-r--r-- | src/coredump/coredump.c | 95 |
1 files changed, 50 insertions, 45 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); |