X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjournal%2Fcoredump.c;h=e80b2f7c79d319d877694a0087ec25805be16d51;hp=f423fa2a29c8f8fa03362e5c97bbdfd31ae4c8b5;hb=79008bddf679a5e0900369950eb346c9fa687107;hpb=3f85ef0f05ffc51e19f86fb83a1c51e8e3cd6817 diff --git a/src/journal/coredump.c b/src/journal/coredump.c index f423fa2a2..e80b2f7c7 100644 --- a/src/journal/coredump.c +++ b/src/journal/coredump.c @@ -36,6 +36,7 @@ #include "log.h" #include "util.h" +#include "fileio.h" #include "strv.h" #include "macro.h" #include "mkdir.h" @@ -329,7 +330,7 @@ static int save_external_coredump( } r = copy_bytes(STDIN_FILENO, fd, arg_process_size_max); - if (r == -E2BIG) { + if (r == -EFBIG) { log_error("Coredump of %s (%s) is larger than configured processing limit, refusing.", info[INFO_PID], info[INFO_COMM]); goto fail; } else if (IN_SET(r, -EDQUOT, -ENOSPC)) { @@ -461,24 +462,102 @@ static int allocate_journal_field(int fd, size_t size, char **ret, size_t *ret_s return 0; } +/* Joins /proc/[pid]/fd/ and /proc/[pid]/fdinfo/ into the following lines: + * 0:/dev/pts/23 + * pos: 0 + * flags: 0100002 + * + * 1:/dev/pts/23 + * pos: 0 + * flags: 0100002 + * + * 2:/dev/pts/23 + * pos: 0 + * flags: 0100002 + * EOF + */ +static int compose_open_fds(pid_t pid, char **open_fds) { + _cleanup_fclose_ FILE *stream = NULL; + size_t ignored_size; + const char *fddelim = "", *path; + struct dirent *dent = NULL; + _cleanup_closedir_ DIR *proc_fd_dir = NULL; + _cleanup_close_ int proc_fdinfo_fd = -1; + int r = 0; + + assert(pid >= 0); + assert(open_fds != NULL); + + path = procfs_file_alloca(pid, "fd"); + proc_fd_dir = opendir(path); + if (!proc_fd_dir) + return -errno; + + proc_fdinfo_fd = openat(dirfd(proc_fd_dir), "../fdinfo", + O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC|O_PATH); + if (proc_fdinfo_fd < 0) + return -errno; + + stream = open_memstream(open_fds, &ignored_size); + if (!stream) + return -ENOMEM; + + for (dent = readdir(proc_fd_dir); dent != NULL; dent = readdir(proc_fd_dir)) { + _cleanup_free_ char *fdname = NULL; + int fd; + _cleanup_fclose_ FILE *fdinfo = NULL; + char line[LINE_MAX]; + + if (dent->d_name[0] == '.' || strcmp(dent->d_name, "..") == 0) + continue; + + r = readlinkat_malloc(dirfd(proc_fd_dir), dent->d_name, &fdname); + if (r < 0) + return r; + + fprintf(stream, "%s%s:%s\n", fddelim, dent->d_name, fdname); + fddelim = "\n"; + + /* Use the directory entry from /proc/[pid]/fd with /proc/[pid]/fdinfo */ + fd = openat(proc_fdinfo_fd, dent->d_name, O_NOFOLLOW|O_CLOEXEC|O_RDONLY); + if (fd < 0) + continue; + + fdinfo = fdopen(fd, "re"); + if (fdinfo == NULL) { + close(fd); + continue; + } + + while(fgets(line, sizeof(line), fdinfo) != NULL) + fprintf(stream, "%s%s", + line, strchr(line, '\n') == NULL ? "\n" : ""); + } + + return 0; +} + int main(int argc, char* argv[]) { _cleanup_free_ char *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL, *core_timestamp = NULL, *core_comm = NULL, *core_exe = NULL, *core_unit = NULL, *core_session = NULL, *core_message = NULL, *core_cmdline = NULL, *coredump_data = NULL, - *core_slice = NULL, *core_cgroup = NULL, *core_owner_uid = NULL, + *core_slice = NULL, *core_cgroup = NULL, *core_owner_uid = NULL, *core_open_fds = NULL, + *core_proc_status = NULL, *core_proc_maps = NULL, *core_proc_limits = NULL, *core_proc_cgroup = NULL, + *core_cwd = NULL, *core_root = NULL, *core_environ = NULL, *exe = NULL, *comm = NULL, *filename = NULL; const char *info[_INFO_LEN]; _cleanup_close_ int coredump_fd = -1; - struct iovec iovec[18]; + struct iovec iovec[26]; off_t coredump_size; int r, j = 0; uid_t uid, owner_uid; gid_t gid; pid_t pid; char *t; + const char *p; /* Make sure we never enter a loop */ prctl(PR_SET_DUMPABLE, 0); @@ -638,6 +717,74 @@ int main(int argc, char* argv[]) { IOVEC_SET_STRING(iovec[j++], core_cgroup); } + if (compose_open_fds(pid, &t) >= 0) { + core_open_fds = strappend("COREDUMP_OPEN_FDS=", t); + free(t); + + if (core_open_fds) + IOVEC_SET_STRING(iovec[j++], core_open_fds); + } + + p = procfs_file_alloca(pid, "status"); + if (read_full_file(p, &t, NULL) >= 0) { + core_proc_status = strappend("COREDUMP_PROC_STATUS=", t); + free(t); + + if (core_proc_status) + IOVEC_SET_STRING(iovec[j++], core_proc_status); + } + + p = procfs_file_alloca(pid, "maps"); + if (read_full_file(p, &t, NULL) >= 0) { + core_proc_maps = strappend("COREDUMP_PROC_MAPS=", t); + free(t); + + if (core_proc_maps) + IOVEC_SET_STRING(iovec[j++], core_proc_maps); + } + + p = procfs_file_alloca(pid, "limits"); + if (read_full_file(p, &t, NULL) >= 0) { + core_proc_limits = strappend("COREDUMP_PROC_LIMITS=", t); + free(t); + + if (core_proc_limits) + IOVEC_SET_STRING(iovec[j++], core_proc_limits); + } + + p = procfs_file_alloca(pid, "cgroup"); + if (read_full_file(p, &t, NULL) >=0) { + core_proc_cgroup = strappend("COREDUMP_PROC_CGROUP=", t); + free(t); + + if (core_proc_cgroup) + IOVEC_SET_STRING(iovec[j++], core_proc_cgroup); + } + + if (get_process_cwd(pid, &t) >= 0) { + core_cwd = strappend("COREDUMP_CWD=", t); + free(t); + + if (core_cwd) + IOVEC_SET_STRING(iovec[j++], core_cwd); + } + + if (get_process_root(pid, &t) >= 0) { + core_root = strappend("COREDUMP_ROOT=", t); + free(t); + + if (core_root) + IOVEC_SET_STRING(iovec[j++], core_root); + } + + if (get_process_environ(pid, &t) >= 0) { + core_environ = strappend("COREDUMP_ENVIRON=", t); + free(t); + + if (core_environ) + IOVEC_SET_STRING(iovec[j++], core_environ); + } + core_timestamp = strjoin("COREDUMP_TIMESTAMP=", info[INFO_TIMESTAMP], "000000", NULL); if (core_timestamp) IOVEC_SET_STRING(iovec[j++], core_timestamp);