From fec603eb6cbba4ea03ef01e3ad48fa85a4812a9c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 22 Jul 2016 17:39:47 +0200 Subject: coredump: truncate overly long coredump metadata fields (#3780) Fixes: #3573 Replaces: #3588 --- src/coredump/coredump.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'src/coredump') 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); -- cgit v1.2.3-54-g00ecf