diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/coredump/coredump.c | 97 | ||||
-rw-r--r-- | src/systemd/sd-messages.h | 1 |
2 files changed, 90 insertions, 8 deletions
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index d5b638d7ec..4d66b59fd6 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -830,6 +830,8 @@ static int process_socket(int fd) { log_parse_environment(); log_open(); + log_debug("Processing coredump received on stdin..."); + for (;;) { union { struct cmsghdr cmsghdr; @@ -1045,6 +1047,7 @@ static char* set_iovec_field_free(struct iovec iovec[27], size_t *n_iovec, const static int gather_pid_metadata( const char *context[_CONTEXT_MAX], char **comm_fallback, + char **comm_ret, struct iovec iovec[27], size_t *n_iovec) { _cleanup_free_ char *exe = NULL, *comm = NULL; @@ -1056,7 +1059,7 @@ static int gather_pid_metadata( r = parse_pid(context[CONTEXT_PID], &pid); if (r < 0) - return log_error_errno(r, "Failed to parse PID."); + return log_error_errno(r, "Failed to parse PID \"%s\": %m", context[CONTEXT_PID]); r = get_process_comm(pid, &comm); if (r < 0) { @@ -1182,6 +1185,11 @@ static int gather_pid_metadata( if (t) IOVEC_SET_STRING(iovec[(*n_iovec)++], t); + if (comm_ret) { + *comm_ret = comm; + comm = NULL; + } + return 0; } @@ -1189,11 +1197,13 @@ static int process_kernel(int argc, char* argv[]) { const char *context[_CONTEXT_MAX]; struct iovec iovec[27]; - size_t n_iovec = 0, i, n_to_free; + size_t i, n_iovec, n_to_free = 0; int r; + log_debug("Processing coredump received from the kernel..."); + if (argc < CONTEXT_COMM + 1) { - log_error("Not enough arguments passed from kernel (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1); + log_error("Not enough arguments passed by the kernel (%i, expected %i).", argc - 1, CONTEXT_COMM + 1 - 1); return -EINVAL; } @@ -1204,10 +1214,10 @@ static int process_kernel(int argc, char* argv[]) { context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 1]; context[CONTEXT_RLIMIT] = argv[CONTEXT_RLIMIT + 1]; - r = gather_pid_metadata(context, argv + CONTEXT_COMM + 1, iovec, &n_iovec); + r = gather_pid_metadata(context, argv + CONTEXT_COMM + 1, NULL, iovec, &n_to_free); if (r < 0) goto finish; - n_to_free = n_iovec; + n_iovec = n_to_free; IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); @@ -1225,6 +1235,74 @@ static int process_kernel(int argc, char* argv[]) { return r; } +static int process_backtrace(int argc, char *argv[]) { + const char *context[_CONTEXT_MAX]; + char *t; + _cleanup_free_ char *comm = NULL; + struct iovec iovec[27]; + size_t n_iovec = 0, i, n_to_free; + uint8_t buf[4096]; + ssize_t buf_bytes; + int r; + + 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; + } + + context[CONTEXT_PID] = argv[CONTEXT_PID + 2]; + context[CONTEXT_UID] = argv[CONTEXT_UID + 2]; + context[CONTEXT_GID] = argv[CONTEXT_GID + 2]; + context[CONTEXT_SIGNAL] = argv[CONTEXT_SIGNAL + 2]; + context[CONTEXT_TIMESTAMP] = argv[CONTEXT_TIMESTAMP + 2]; + context[CONTEXT_RLIMIT] = argv[CONTEXT_RLIMIT + 2]; + + r = gather_pid_metadata(context, argv + CONTEXT_COMM + 2, &comm, iovec, &n_iovec); + if (r < 0) + goto finish; + + if (isempty(context[CONTEXT_SIGNAL])) + context[CONTEXT_SIGNAL] = "an exception"; + + buf_bytes = loop_read(STDIN_FILENO, buf, sizeof(buf) - 1, false); + if (buf_bytes < 0) { + log_error_errno(buf_bytes, "Failed to read backtrace from stdin: %m"); + goto finish; + } + buf[buf_bytes] = '\0'; + + t = strjoin("MESSAGE=Process ", context[CONTEXT_PID], " (", comm, ")" + " of user ", context[CONTEXT_UID], + " failed with ", context[CONTEXT_SIGNAL], + ":\n\n", buf, NULL); + if (!t) { + log_oom(); + goto finish; + } + IOVEC_SET_STRING(iovec[n_iovec++], t); + + n_to_free = n_iovec; + + IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=1f4e0a44a88649939aaea34fc6da8c95"); + + assert_cc(2 == LOG_CRIT); + IOVEC_SET_STRING(iovec[n_iovec++], "PRIORITY=2"); + + assert(n_iovec <= ELEMENTSOF(iovec)); + + r = sd_journal_sendv(iovec, n_iovec); + if (r < 0) + log_error_errno(r, "Failed to log backtrace: %m"); + + finish: + for (i = 0; i < n_to_free; i++) + free(iovec[i].iov_base); + + return r; +} + int main(int argc, char *argv[]) { int r; @@ -1251,9 +1329,12 @@ int main(int argc, char *argv[]) { /* 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) - r = process_kernel(argc, argv); - else if (r == 1) + if (r == 0) { + if (streq_ptr(argv[1], "--backtrace")) + r = process_backtrace(argc, argv); + else + r = process_kernel(argc, argv); + } else if (r == 1) r = process_socket(SD_LISTEN_FDS_START); else { log_error("Received unexpected number of file descriptors."); diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h index db1a21be05..542e900744 100644 --- a/src/systemd/sd-messages.h +++ b/src/systemd/sd-messages.h @@ -41,6 +41,7 @@ _SD_BEGIN_DECLARATIONS; #define SD_MESSAGE_COREDUMP SD_ID128_MAKE(fc,2e,22,bc,6e,e6,47,b6,b9,07,29,ab,34,a2,50,b1) #define SD_MESSAGE_TRUNCATED_CORE SD_ID128_MAKE(5a,ad,d8,e9,54,dc,4b,1a,8c,95,4d,63,fd,9e,11,37) +#define SD_MESSAGE_BACKTRACE SD_ID128_MAKE(1f,4e,0a,44,a8,86,49,93,9a,ae,a3,4f,c6,da,8c,95) #define SD_MESSAGE_SESSION_START SD_ID128_MAKE(8d,45,62,0c,1a,43,48,db,b1,74,10,da,57,c6,0c,66) #define SD_MESSAGE_SESSION_STOP SD_ID128_MAKE(33,54,93,94,24,b4,45,6d,98,02,ca,83,33,ed,42,4a) |