diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 25 | ||||
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | src/.gitignore | 1 | ||||
-rw-r--r-- | src/journal/coredump.c | 173 | ||||
-rw-r--r-- | src/systemd/sd-messages.h | 2 | ||||
-rw-r--r-- | sysctl.d/.gitignore | 1 | ||||
l--------- | sysctl.d/Makefile | 1 | ||||
-rw-r--r-- | sysctl.d/coredump.conf.in | 10 |
9 files changed, 222 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore index c260210311..011aecec95 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/systemd-coredump /systemd-cat /systemd-rc-local-generator /libsystemd-id128.pc diff --git a/Makefile.am b/Makefile.am index d94de56ff1..607ae7eadd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,6 +52,7 @@ bashcompletiondir=$(sysconfdir)/bash_completion.d pkgsysconfdir=$(sysconfdir)/systemd userunitdir=$(prefix)/lib/systemd/user tmpfilesdir=$(prefix)/lib/tmpfiles.d +sysctldir=$(prefix)/lib/sysctl.d usergeneratordir=$(pkglibexecdir)/user-generators pkgincludedir=$(includedir)/systemd @@ -1397,6 +1398,27 @@ EXTRA_DIST += \ CLEANFILES += \ src/journal/journald-gperf.c +if ENABLE_COREDUMP + +systemd_coredump_SOURCES = \ + src/journal/coredump.c + +systemd_coredump_LDADD = \ + libsystemd-basic.la \ + libsystemd-journal.la \ + libsystemd-login.la + +rootlibexec_PROGRAMS += \ + systemd-coredump + +sysctl_DATA = \ + sysctl.d/coredump.conf + +EXTRA_DIST += \ + sysctl.d/coredump.conf.in + +endif + # ------------------------------------------------------------------------------ if ENABLE_BINFMT systemd_binfmt_SOURCES = \ @@ -2074,6 +2096,9 @@ units/%: units/%.in Makefile man/%: man/%.in Makefile $(SED_PROCESS) +sysctl.d/%: sysctl.d/%.in Makefile + $(SED_PROCESS) + %.pc: %.pc.in Makefile $(SED_PROCESS) diff --git a/configure.ac b/configure.ac index 80d0156916..194caa5d5f 100644 --- a/configure.ac +++ b/configure.ac @@ -372,6 +372,13 @@ if test "x$enable_localed" != "xno"; then fi AM_CONDITIONAL(ENABLE_LOCALED, [test "$have_localed" = "yes"]) +have_coredump=no +AC_ARG_ENABLE(coredump, AS_HELP_STRING([--disable-coredump], [disable coredump hook])) +if test "x$enable_coredump" != "xno"; then + have_coredump=yes +fi +AM_CONDITIONAL(ENABLE_COREDUMP, [test "$have_coredump" = "yes"]) + have_gtk=no AC_ARG_ENABLE(gtk, AS_HELP_STRING([--disable-gtk], [disable GTK tools])) if test "x$enable_gtk" != "xno"; then @@ -646,6 +653,7 @@ AC_MSG_RESULT([ hostnamed: ${have_hostnamed} timedated: ${have_timedated} localed: ${have_localed} + coredump: ${have_coredump} plymouth: ${have_plymouth} prefix: ${prefix} rootprefix: ${with_rootprefix} diff --git a/src/.gitignore b/src/.gitignore index ff2737b761..c54c6f6514 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,3 +1,4 @@ +/*.pc load-fragment-gperf-nulstr.c load-fragment-gperf.c load-fragment-gperf.gperf diff --git a/src/journal/coredump.c b/src/journal/coredump.c new file mode 100644 index 0000000000..f160270168 --- /dev/null +++ b/src/journal/coredump.c @@ -0,0 +1,173 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2012 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <errno.h> +#include <unistd.h> + +#include <systemd/sd-journal.h> +#include <systemd/sd-login.h> + +#include "log.h" +#include "util.h" + +#define COREDUMP_MAX (64*1024) + +enum { + ARG_PID = 1, + ARG_UID, + ARG_GID, + ARG_SIGNAL, + ARG_TIMESTAMP, + ARG_COMM, + _ARG_MAX +}; + +int main(int argc, char* argv[]) { + int r, j = 0; + char *p = NULL; + ssize_t n; + pid_t pid; + struct iovec iovec[14]; + 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, *t; + + log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); + log_parse_environment(); + log_open(); + + if (argc != _ARG_MAX) { + log_error("Invalid number of arguments passed from kernel."); + r = -EINVAL; + goto finish; + } + + r = parse_pid(argv[ARG_PID], &pid); + if (r < 0) { + log_error("Failed to parse PID."); + r = -EINVAL; + goto finish; + } + + p = malloc(9 + COREDUMP_MAX); + if (!p) { + log_error("Out of memory"); + r = -ENOMEM; + goto finish; + } + + memcpy(p, "COREDUMP=", 9); + + n = loop_read(STDIN_FILENO, p + 9, COREDUMP_MAX, false); + if (n < 0) { + log_error("Failed to read core dump data: %s", strerror(-n)); + r = (int) n; + goto finish; + } + + zero(iovec); + iovec[j].iov_base = p; + iovec[j].iov_len = 9 + n; + j++; + + core_pid = strappend("COREDUMP_PID=", argv[ARG_PID]); + if (core_pid) + IOVEC_SET_STRING(iovec[j++], core_pid); + + core_uid = strappend("COREDUMP_UID=", argv[ARG_UID]); + if (core_uid) + IOVEC_SET_STRING(iovec[j++], core_uid); + + core_gid = strappend("COREDUMP_GID=", argv[ARG_GID]); + if (core_gid) + IOVEC_SET_STRING(iovec[j++], core_gid); + + core_signal = strappend("COREDUMP_SIGNAL=", argv[ARG_SIGNAL]); + if (core_signal) + IOVEC_SET_STRING(iovec[j++], core_signal); + + core_comm = strappend("COREDUMP_COMM=", argv[ARG_COMM]); + if (core_comm) + IOVEC_SET_STRING(iovec[j++], core_comm); + + if (sd_pid_get_session(pid, &t) >= 0) { + core_session = strappend("COREDUMP_SESSION=", t); + free(t); + + if (core_session) + IOVEC_SET_STRING(iovec[j++], core_session); + } + + if (sd_pid_get_unit(pid, &t) >= 0) { + core_unit = strappend("COREDUMP_UNIT=", t); + free(t); + + if (core_unit) + IOVEC_SET_STRING(iovec[j++], core_unit); + } + + if (get_process_exe(pid, &t) >= 0) { + core_exe = strappend("COREDUMP_EXE=", t); + free(t); + + if (core_exe) + IOVEC_SET_STRING(iovec[j++], core_exe); + } + + if (get_process_cmdline(pid, LINE_MAX, false, &t) >= 0) { + core_cmdline = strappend("COREDUMP_CMDLINE=", t); + free(t); + + if (core_cmdline) + IOVEC_SET_STRING(iovec[j++], core_cmdline); + } + + core_timestamp = join("COREDUMP_TIMESTAMP=", argv[ARG_TIMESTAMP], "000000", NULL); + if (core_timestamp) + IOVEC_SET_STRING(iovec[j++], core_timestamp); + + IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); + IOVEC_SET_STRING(iovec[j++], "PRIORITY=2"); + + core_message = join("MESSAGE=Process ", argv[ARG_PID], " (", argv[ARG_COMM], ") dumped core.", NULL); + if (core_message) + IOVEC_SET_STRING(iovec[j++], core_message); + + r = sd_journal_sendv(iovec, j); + if (r < 0) + log_error("Failed to send coredump: %s", strerror(-r)); + +finish: + free(p); + free(core_pid); + free(core_uid); + free(core_gid); + free(core_signal); + free(core_timestamp); + free(core_comm); + free(core_exe); + free(core_cmdline); + free(core_unit); + free(core_session); + free(core_message); + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h index 5fd1aa7e31..c5ac3abd0c 100644 --- a/src/systemd/sd-messages.h +++ b/src/systemd/sd-messages.h @@ -32,6 +32,8 @@ extern "C" { #define SD_MESSAGE_JOURNAL_STOP SD_ID128_MAKE(d9,3f,b3,c9,c2,4d,45,1a,97,ce,a6,15,ce,59,c0,0b) #define SD_MESSAGE_JOURNAL_DROPPED SD_ID128_MAKE(a5,96,d6,fe,7b,fa,49,94,82,8e,72,30,9e,95,d6,1e) +#define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) + #ifdef __cplusplus } #endif diff --git a/sysctl.d/.gitignore b/sysctl.d/.gitignore new file mode 100644 index 0000000000..7563539ab0 --- /dev/null +++ b/sysctl.d/.gitignore @@ -0,0 +1 @@ +/coredump.conf diff --git a/sysctl.d/Makefile b/sysctl.d/Makefile new file mode 120000 index 0000000000..bd1047548b --- /dev/null +++ b/sysctl.d/Makefile @@ -0,0 +1 @@ +../src/Makefile
\ No newline at end of file diff --git a/sysctl.d/coredump.conf.in b/sysctl.d/coredump.conf.in new file mode 100644 index 0000000000..ab19b1e988 --- /dev/null +++ b/sysctl.d/coredump.conf.in @@ -0,0 +1,10 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +# See sysctl.d(5) for details + +kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %p %u %g %s %t %e |