summaryrefslogtreecommitdiff
path: root/src/coredump/coredump.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/coredump/coredump.c')
-rw-r--r--src/coredump/coredump.c97
1 files changed, 89 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.");