summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-07-22 17:39:47 +0200
committerGitHub <noreply@github.com>2016-07-22 17:39:47 +0200
commitfec603eb6cbba4ea03ef01e3ad48fa85a4812a9c (patch)
tree50e2fd774e50956134cd7b4ad77284abbf82779c
parente08ab37902bbd6e46ad1365f8ffa87fd700683e2 (diff)
coredump: truncate overly long coredump metadata fields (#3780)
Fixes: #3573 Replaces: #3588
-rw-r--r--src/coredump/coredump.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 82a54968e7..998b047c29 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -852,12 +852,42 @@ static int send_iovec(const struct iovec iovec[], size_t n_iovec, int input_fd)
return log_error_errno(errno, "Failed to connect to coredump service: %m");
for (i = 0; i < n_iovec; i++) {
- ssize_t n;
- assert(iovec[i].iov_len > 0);
+ struct msghdr mh = {
+ .msg_iov = (struct iovec*) iovec + i,
+ .msg_iovlen = 1,
+ };
+ struct iovec copy[2];
+
+ for (;;) {
+ if (sendmsg(fd, &mh, MSG_NOSIGNAL) >= 0)
+ break;
+
+ if (errno == EMSGSIZE && mh.msg_iov[0].iov_len > 0) {
+ /* This field didn't fit? That's a pity. Given that this is just metadata,
+ * let's truncate the field at half, and try again. We append three dots, in
+ * order to show that this is truncated. */
+
+ if (mh.msg_iov != copy) {
+ /* We don't want to modify the caller's iovec, hence let's create our
+ * own array, consisting of two new iovecs, where the first is a
+ * (truncated) copy of what we want to send, and the second one
+ * contains the trailing dots. */
+ copy[0] = iovec[i];
+ copy[1] = (struct iovec) {
+ .iov_base = (char[]) { '.', '.', '.' },
+ .iov_len = 3,
+ };
+
+ mh.msg_iov = copy;
+ mh.msg_iovlen = 2;
+ }
+
+ copy[0].iov_len /= 2; /* halve it, and try again */
+ continue;
+ }
- n = send(fd, iovec[i].iov_base, iovec[i].iov_len, MSG_NOSIGNAL);
- if (n < 0)
return log_error_errno(errno, "Failed to send coredump datagram: %m");
+ }
}
r = send_one_fd(fd, input_fd, 0);