|
|
803fb7 |
From 6d1ef1fb841a0b3b4c53b560892f3570b3379dc9 Mon Sep 17 00:00:00 2001
|
|
|
803fb7 |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
803fb7 |
Date: Wed, 10 Jun 2015 19:24:58 +0200
|
|
|
803fb7 |
Subject: [PATCH] journald: don't employ inner loop for reading from incoming
|
|
|
803fb7 |
sockets
|
|
|
803fb7 |
|
|
|
803fb7 |
Otherwise, if the socket is constantly busy we will never return to the
|
|
|
803fb7 |
event loop, but we really need to to dispatch other (possibly more
|
|
|
803fb7 |
high-priority) events too. Hence, return after dispatching one message
|
|
|
803fb7 |
to the event handler, and rely on the event loop calling us back
|
|
|
803fb7 |
right-away.
|
|
|
803fb7 |
|
|
|
803fb7 |
Fixes #125
|
|
|
803fb7 |
|
|
|
803fb7 |
Related: #1318994
|
|
|
803fb7 |
Cherry-picked from: a315ac4e076c4ce7ce3e5c95792cf916d5e918c5
|
|
|
803fb7 |
---
|
|
|
803fb7 |
src/journal/journald-server.c | 204 +++++++++++++++++++++---------------------
|
|
|
803fb7 |
1 file changed, 100 insertions(+), 104 deletions(-)
|
|
|
803fb7 |
|
|
|
803fb7 |
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
|
|
|
803fb7 |
index 1eb1394d1..275224dc9 100644
|
|
|
803fb7 |
--- a/src/journal/journald-server.c
|
|
|
803fb7 |
+++ b/src/journal/journald-server.c
|
|
|
803fb7 |
@@ -1103,6 +1103,42 @@ finish:
|
|
|
803fb7 |
|
|
|
803fb7 |
int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
|
|
|
803fb7 |
Server *s = userdata;
|
|
|
803fb7 |
+ struct ucred *ucred = NULL;
|
|
|
803fb7 |
+ struct timeval *tv = NULL;
|
|
|
803fb7 |
+ struct cmsghdr *cmsg;
|
|
|
803fb7 |
+ char *label = NULL;
|
|
|
803fb7 |
+ size_t label_len = 0, m;
|
|
|
803fb7 |
+ struct iovec iovec;
|
|
|
803fb7 |
+ ssize_t n;
|
|
|
803fb7 |
+ int *fds = NULL, v = 0;
|
|
|
803fb7 |
+ unsigned n_fds = 0;
|
|
|
803fb7 |
+
|
|
|
803fb7 |
+ union {
|
|
|
803fb7 |
+ struct cmsghdr cmsghdr;
|
|
|
803fb7 |
+
|
|
|
803fb7 |
+ /* We use NAME_MAX space for the SELinux label
|
|
|
803fb7 |
+ * here. The kernel currently enforces no
|
|
|
803fb7 |
+ * limit, but according to suggestions from
|
|
|
803fb7 |
+ * the SELinux people this will change and it
|
|
|
803fb7 |
+ * will probably be identical to NAME_MAX. For
|
|
|
803fb7 |
+ * now we use that, but this should be updated
|
|
|
803fb7 |
+ * one day when the final limit is known. */
|
|
|
803fb7 |
+ uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
|
|
|
803fb7 |
+ CMSG_SPACE(sizeof(struct timeval)) +
|
|
|
803fb7 |
+ CMSG_SPACE(sizeof(int)) + /* fd */
|
|
|
803fb7 |
+ CMSG_SPACE(NAME_MAX)]; /* selinux label */
|
|
|
803fb7 |
+ } control = {};
|
|
|
803fb7 |
+
|
|
|
803fb7 |
+ union sockaddr_union sa = {};
|
|
|
803fb7 |
+
|
|
|
803fb7 |
+ struct msghdr msghdr = {
|
|
|
803fb7 |
+ .msg_iov = &iovec,
|
|
|
803fb7 |
+ .msg_iovlen = 1,
|
|
|
803fb7 |
+ .msg_control = &control,
|
|
|
803fb7 |
+ .msg_controllen = sizeof(control),
|
|
|
803fb7 |
+ .msg_name = &sa,
|
|
|
803fb7 |
+ .msg_namelen = sizeof(sa),
|
|
|
803fb7 |
+ };
|
|
|
803fb7 |
|
|
|
803fb7 |
assert(s);
|
|
|
803fb7 |
assert(fd == s->native_fd || fd == s->syslog_fd || fd == s->audit_fd);
|
|
|
803fb7 |
@@ -1112,119 +1148,79 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
|
|
|
803fb7 |
return -EIO;
|
|
|
803fb7 |
}
|
|
|
803fb7 |
|
|
|
803fb7 |
- for (;;) {
|
|
|
803fb7 |
- struct ucred *ucred = NULL;
|
|
|
803fb7 |
- struct timeval *tv = NULL;
|
|
|
803fb7 |
- struct cmsghdr *cmsg;
|
|
|
803fb7 |
- char *label = NULL;
|
|
|
803fb7 |
- size_t label_len = 0;
|
|
|
803fb7 |
- struct iovec iovec;
|
|
|
803fb7 |
-
|
|
|
803fb7 |
- union {
|
|
|
803fb7 |
- struct cmsghdr cmsghdr;
|
|
|
803fb7 |
-
|
|
|
803fb7 |
- /* We use NAME_MAX space for the SELinux label
|
|
|
803fb7 |
- * here. The kernel currently enforces no
|
|
|
803fb7 |
- * limit, but according to suggestions from
|
|
|
803fb7 |
- * the SELinux people this will change and it
|
|
|
803fb7 |
- * will probably be identical to NAME_MAX. For
|
|
|
803fb7 |
- * now we use that, but this should be updated
|
|
|
803fb7 |
- * one day when the final limit is known. */
|
|
|
803fb7 |
- uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
|
|
|
803fb7 |
- CMSG_SPACE(sizeof(struct timeval)) +
|
|
|
803fb7 |
- CMSG_SPACE(sizeof(int)) + /* fd */
|
|
|
803fb7 |
- CMSG_SPACE(NAME_MAX)]; /* selinux label */
|
|
|
803fb7 |
- } control = {};
|
|
|
803fb7 |
- union sockaddr_union sa = {};
|
|
|
803fb7 |
- struct msghdr msghdr = {
|
|
|
803fb7 |
- .msg_iov = &iovec,
|
|
|
803fb7 |
- .msg_iovlen = 1,
|
|
|
803fb7 |
- .msg_control = &control,
|
|
|
803fb7 |
- .msg_controllen = sizeof(control),
|
|
|
803fb7 |
- .msg_name = &sa,
|
|
|
803fb7 |
- .msg_namelen = sizeof(sa),
|
|
|
803fb7 |
- };
|
|
|
803fb7 |
-
|
|
|
803fb7 |
- ssize_t n;
|
|
|
803fb7 |
- int *fds = NULL;
|
|
|
803fb7 |
- unsigned n_fds = 0;
|
|
|
803fb7 |
- int v = 0;
|
|
|
803fb7 |
- size_t m;
|
|
|
803fb7 |
-
|
|
|
803fb7 |
- /* Try to get the right size, if we can. (Not all
|
|
|
803fb7 |
- * sockets support SIOCINQ, hence we just try, but
|
|
|
803fb7 |
- * don't rely on it. */
|
|
|
803fb7 |
- (void) ioctl(fd, SIOCINQ, &v);
|
|
|
803fb7 |
-
|
|
|
803fb7 |
- /* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful! */
|
|
|
803fb7 |
- m = PAGE_ALIGN(MAX3((size_t) v + 1,
|
|
|
803fb7 |
- (size_t) LINE_MAX,
|
|
|
803fb7 |
- ALIGN(sizeof(struct nlmsghdr)) + ALIGN((size_t) MAX_AUDIT_MESSAGE_LENGTH)) + 1);
|
|
|
803fb7 |
-
|
|
|
803fb7 |
- if (!GREEDY_REALLOC(s->buffer, s->buffer_size, m))
|
|
|
803fb7 |
- return log_oom();
|
|
|
803fb7 |
-
|
|
|
803fb7 |
- iovec.iov_base = s->buffer;
|
|
|
803fb7 |
- iovec.iov_len = s->buffer_size - 1; /* Leave room for trailing NUL we add later */
|
|
|
803fb7 |
-
|
|
|
803fb7 |
- n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
|
|
803fb7 |
- if (n < 0) {
|
|
|
803fb7 |
- if (errno == EINTR || errno == EAGAIN)
|
|
|
803fb7 |
- return 0;
|
|
|
803fb7 |
-
|
|
|
803fb7 |
- log_error_errno(errno, "recvmsg() failed: %m");
|
|
|
803fb7 |
- return -errno;
|
|
|
803fb7 |
- }
|
|
|
803fb7 |
+ /* Try to get the right size, if we can. (Not all
|
|
|
803fb7 |
+ * sockets support SIOCINQ, hence we just try, but
|
|
|
803fb7 |
+ * don't rely on it. */
|
|
|
803fb7 |
+ (void) ioctl(fd, SIOCINQ, &v);
|
|
|
803fb7 |
|
|
|
803fb7 |
- CMSG_FOREACH(cmsg, &msghdr) {
|
|
|
803fb7 |
-
|
|
|
803fb7 |
- if (cmsg->cmsg_level == SOL_SOCKET &&
|
|
|
803fb7 |
- cmsg->cmsg_type == SCM_CREDENTIALS &&
|
|
|
803fb7 |
- cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
|
|
|
803fb7 |
- ucred = (struct ucred*) CMSG_DATA(cmsg);
|
|
|
803fb7 |
- else if (cmsg->cmsg_level == SOL_SOCKET &&
|
|
|
803fb7 |
- cmsg->cmsg_type == SCM_SECURITY) {
|
|
|
803fb7 |
- label = (char*) CMSG_DATA(cmsg);
|
|
|
803fb7 |
- label_len = cmsg->cmsg_len - CMSG_LEN(0);
|
|
|
803fb7 |
- } else if (cmsg->cmsg_level == SOL_SOCKET &&
|
|
|
803fb7 |
- cmsg->cmsg_type == SO_TIMESTAMP &&
|
|
|
803fb7 |
- cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
|
|
|
803fb7 |
- tv = (struct timeval*) CMSG_DATA(cmsg);
|
|
|
803fb7 |
- else if (cmsg->cmsg_level == SOL_SOCKET &&
|
|
|
803fb7 |
- cmsg->cmsg_type == SCM_RIGHTS) {
|
|
|
803fb7 |
- fds = (int*) CMSG_DATA(cmsg);
|
|
|
803fb7 |
- n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
|
|
|
803fb7 |
- }
|
|
|
803fb7 |
- }
|
|
|
803fb7 |
+ /* Fix it up, if it is too small. We use the same fixed value as auditd here. Awful! */
|
|
|
803fb7 |
+ m = PAGE_ALIGN(MAX3((size_t) v + 1,
|
|
|
803fb7 |
+ (size_t) LINE_MAX,
|
|
|
803fb7 |
+ ALIGN(sizeof(struct nlmsghdr)) + ALIGN((size_t) MAX_AUDIT_MESSAGE_LENGTH)) + 1);
|
|
|
803fb7 |
|
|
|
803fb7 |
- /* And a trailing NUL, just in case */
|
|
|
803fb7 |
- s->buffer[n] = 0;
|
|
|
803fb7 |
+ if (!GREEDY_REALLOC(s->buffer, s->buffer_size, m))
|
|
|
803fb7 |
+ return log_oom();
|
|
|
803fb7 |
|
|
|
803fb7 |
- if (fd == s->syslog_fd) {
|
|
|
803fb7 |
- if (n > 0 && n_fds == 0)
|
|
|
803fb7 |
- server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
|
|
|
803fb7 |
- else if (n_fds > 0)
|
|
|
803fb7 |
- log_warning("Got file descriptors via syslog socket. Ignoring.");
|
|
|
803fb7 |
+ iovec.iov_base = s->buffer;
|
|
|
803fb7 |
+ iovec.iov_len = s->buffer_size - 1; /* Leave room for trailing NUL we add later */
|
|
|
803fb7 |
|
|
|
803fb7 |
- } else if (fd == s->native_fd) {
|
|
|
803fb7 |
- if (n > 0 && n_fds == 0)
|
|
|
803fb7 |
- server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
|
|
|
803fb7 |
- else if (n == 0 && n_fds == 1)
|
|
|
803fb7 |
- server_process_native_file(s, fds[0], ucred, tv, label, label_len);
|
|
|
803fb7 |
- else if (n_fds > 0)
|
|
|
803fb7 |
- log_warning("Got too many file descriptors via native socket. Ignoring.");
|
|
|
803fb7 |
+ n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
|
|
803fb7 |
+ if (n < 0) {
|
|
|
803fb7 |
+ if (errno == EINTR || errno == EAGAIN)
|
|
|
803fb7 |
+ return 0;
|
|
|
803fb7 |
|
|
|
803fb7 |
- } else {
|
|
|
803fb7 |
- assert(fd == s->audit_fd);
|
|
|
803fb7 |
+ return log_error_errno(errno, "recvmsg() failed: %m");
|
|
|
803fb7 |
+ }
|
|
|
803fb7 |
|
|
|
803fb7 |
- if (n > 0 && n_fds == 0)
|
|
|
803fb7 |
- server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen);
|
|
|
803fb7 |
- else if (n_fds > 0)
|
|
|
803fb7 |
- log_warning("Got file descriptors via audit socket. Ignoring.");
|
|
|
803fb7 |
+ CMSG_FOREACH(cmsg, &msghdr) {
|
|
|
803fb7 |
+
|
|
|
803fb7 |
+ if (cmsg->cmsg_level == SOL_SOCKET &&
|
|
|
803fb7 |
+ cmsg->cmsg_type == SCM_CREDENTIALS &&
|
|
|
803fb7 |
+ cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
|
|
|
803fb7 |
+ ucred = (struct ucred*) CMSG_DATA(cmsg);
|
|
|
803fb7 |
+ else if (cmsg->cmsg_level == SOL_SOCKET &&
|
|
|
803fb7 |
+ cmsg->cmsg_type == SCM_SECURITY) {
|
|
|
803fb7 |
+ label = (char*) CMSG_DATA(cmsg);
|
|
|
803fb7 |
+ label_len = cmsg->cmsg_len - CMSG_LEN(0);
|
|
|
803fb7 |
+ } else if (cmsg->cmsg_level == SOL_SOCKET &&
|
|
|
803fb7 |
+ cmsg->cmsg_type == SO_TIMESTAMP &&
|
|
|
803fb7 |
+ cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
|
|
|
803fb7 |
+ tv = (struct timeval*) CMSG_DATA(cmsg);
|
|
|
803fb7 |
+ else if (cmsg->cmsg_level == SOL_SOCKET &&
|
|
|
803fb7 |
+ cmsg->cmsg_type == SCM_RIGHTS) {
|
|
|
803fb7 |
+ fds = (int*) CMSG_DATA(cmsg);
|
|
|
803fb7 |
+ n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
|
|
|
803fb7 |
}
|
|
|
803fb7 |
+ }
|
|
|
803fb7 |
+
|
|
|
803fb7 |
+ /* And a trailing NUL, just in case */
|
|
|
803fb7 |
+ s->buffer[n] = 0;
|
|
|
803fb7 |
+
|
|
|
803fb7 |
+ if (fd == s->syslog_fd) {
|
|
|
803fb7 |
+ if (n > 0 && n_fds == 0)
|
|
|
803fb7 |
+ server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len);
|
|
|
803fb7 |
+ else if (n_fds > 0)
|
|
|
803fb7 |
+ log_warning("Got file descriptors via syslog socket. Ignoring.");
|
|
|
803fb7 |
+
|
|
|
803fb7 |
+ } else if (fd == s->native_fd) {
|
|
|
803fb7 |
+ if (n > 0 && n_fds == 0)
|
|
|
803fb7 |
+ server_process_native_message(s, s->buffer, n, ucred, tv, label, label_len);
|
|
|
803fb7 |
+ else if (n == 0 && n_fds == 1)
|
|
|
803fb7 |
+ server_process_native_file(s, fds[0], ucred, tv, label, label_len);
|
|
|
803fb7 |
+ else if (n_fds > 0)
|
|
|
803fb7 |
+ log_warning("Got too many file descriptors via native socket. Ignoring.");
|
|
|
803fb7 |
|
|
|
803fb7 |
- close_many(fds, n_fds);
|
|
|
803fb7 |
+ } else {
|
|
|
803fb7 |
+ assert(fd == s->audit_fd);
|
|
|
803fb7 |
+
|
|
|
803fb7 |
+ if (n > 0 && n_fds == 0)
|
|
|
803fb7 |
+ server_process_audit_message(s, s->buffer, n, ucred, &sa, msghdr.msg_namelen);
|
|
|
803fb7 |
+ else if (n_fds > 0)
|
|
|
803fb7 |
+ log_warning("Got file descriptors via audit socket. Ignoring.");
|
|
|
803fb7 |
}
|
|
|
803fb7 |
+
|
|
|
803fb7 |
+ close_many(fds, n_fds);
|
|
|
803fb7 |
+ return 0;
|
|
|
803fb7 |
}
|
|
|
803fb7 |
|
|
|
803fb7 |
static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
|