|
|
8b9864 |
From 7f56f583d891859c94b24db0ec38a301c3f3466a Mon Sep 17 00:00:00 2001
|
|
|
8b9864 |
From: David Vossel <dvossel@redhat.com>
|
|
|
8b9864 |
Date: Mon, 23 Feb 2015 14:59:51 -0500
|
|
|
8b9864 |
Subject: [PATCH] High: yield to scheduler during new connection auth
|
|
|
8b9864 |
processing
|
|
|
8b9864 |
|
|
|
8b9864 |
---
|
|
|
8b9864 |
lib/ipc_setup.c | 233 ++++++++++++++++++++++++++++++++++++++------------------
|
|
|
8b9864 |
1 file changed, 159 insertions(+), 74 deletions(-)
|
|
|
8b9864 |
|
|
|
8b9864 |
diff --git a/lib/ipc_setup.c b/lib/ipc_setup.c
|
|
|
8b9864 |
index 1ea085b..144b4c0 100644
|
|
|
8b9864 |
--- a/lib/ipc_setup.c
|
|
|
8b9864 |
+++ b/lib/ipc_setup.c
|
|
|
8b9864 |
@@ -48,6 +48,24 @@ struct ipc_auth_ugp {
|
|
|
8b9864 |
pid_t pid;
|
|
|
8b9864 |
};
|
|
|
8b9864 |
|
|
|
8b9864 |
+struct ipc_auth_data {
|
|
|
8b9864 |
+ int32_t sock;
|
|
|
8b9864 |
+ struct qb_ipcs_service *s;
|
|
|
8b9864 |
+ struct qb_ipc_connection_request msg;
|
|
|
8b9864 |
+ struct msghdr msg_recv;
|
|
|
8b9864 |
+ struct iovec iov_recv;
|
|
|
8b9864 |
+ struct ipc_auth_ugp ugp;
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+ size_t processed;
|
|
|
8b9864 |
+ size_t len;
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+#ifdef SO_PASSCRED
|
|
|
8b9864 |
+ char *cmsg_cred;
|
|
|
8b9864 |
+#endif
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+};
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+
|
|
|
8b9864 |
static int32_t qb_ipcs_us_connection_acceptor(int fd, int revent, void *data);
|
|
|
8b9864 |
|
|
|
8b9864 |
ssize_t
|
|
|
8b9864 |
@@ -83,20 +101,21 @@ retry_send:
|
|
|
8b9864 |
}
|
|
|
8b9864 |
|
|
|
8b9864 |
static ssize_t
|
|
|
8b9864 |
-qb_ipc_us_recv_msghdr(int32_t s, struct msghdr *hdr, char *msg, size_t len)
|
|
|
8b9864 |
+qb_ipc_us_recv_msghdr(struct ipc_auth_data *data)
|
|
|
8b9864 |
{
|
|
|
8b9864 |
+ char *msg = (char *) &data->msg;
|
|
|
8b9864 |
int32_t result;
|
|
|
8b9864 |
- int32_t processed = 0;
|
|
|
8b9864 |
|
|
|
8b9864 |
qb_sigpipe_ctl(QB_SIGPIPE_IGNORE);
|
|
|
8b9864 |
|
|
|
8b9864 |
retry_recv:
|
|
|
8b9864 |
- hdr->msg_iov->iov_base = &msg[processed];
|
|
|
8b9864 |
- hdr->msg_iov->iov_len = len - processed;
|
|
|
8b9864 |
+ data->msg_recv.msg_iov->iov_base = &msg[data->processed];
|
|
|
8b9864 |
+ data->msg_recv.msg_iov->iov_len = data->len - data->processed;
|
|
|
8b9864 |
|
|
|
8b9864 |
- result = recvmsg(s, hdr, MSG_NOSIGNAL | MSG_WAITALL);
|
|
|
8b9864 |
+ result = recvmsg(data->sock, &data->msg_recv, MSG_NOSIGNAL | MSG_WAITALL);
|
|
|
8b9864 |
if (result == -1 && errno == EAGAIN) {
|
|
|
8b9864 |
- goto retry_recv;
|
|
|
8b9864 |
+ qb_sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
|
|
8b9864 |
+ return -EAGAIN;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
if (result == -1) {
|
|
|
8b9864 |
qb_sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
|
|
8b9864 |
@@ -105,18 +124,18 @@ retry_recv:
|
|
|
8b9864 |
if (result == 0) {
|
|
|
8b9864 |
qb_sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
|
|
8b9864 |
qb_util_log(LOG_DEBUG,
|
|
|
8b9864 |
- "recv(fd %d) got 0 bytes assuming ENOTCONN", s);
|
|
|
8b9864 |
+ "recv(fd %d) got 0 bytes assuming ENOTCONN", data->sock);
|
|
|
8b9864 |
return -ENOTCONN;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
|
|
|
8b9864 |
- processed += result;
|
|
|
8b9864 |
- if (processed != len) {
|
|
|
8b9864 |
+ data->processed += result;
|
|
|
8b9864 |
+ if (data->processed != data->len) {
|
|
|
8b9864 |
goto retry_recv;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
qb_sigpipe_ctl(QB_SIGPIPE_DEFAULT);
|
|
|
8b9864 |
- assert(processed == len);
|
|
|
8b9864 |
+ assert(data->processed == data->len);
|
|
|
8b9864 |
|
|
|
8b9864 |
- return processed;
|
|
|
8b9864 |
+ return data->processed;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
|
|
|
8b9864 |
int32_t
|
|
|
8b9864 |
@@ -434,6 +453,7 @@ qb_ipcs_us_withdraw(struct qb_ipcs_service * s)
|
|
|
8b9864 |
(void)s->poll_fns.dispatch_del(s->server_sock);
|
|
|
8b9864 |
shutdown(s->server_sock, SHUT_RDWR);
|
|
|
8b9864 |
close(s->server_sock);
|
|
|
8b9864 |
+ s->server_sock = -1;
|
|
|
8b9864 |
return 0;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
|
|
|
8b9864 |
@@ -541,45 +561,56 @@ send_response:
|
|
|
8b9864 |
return res;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
|
|
|
8b9864 |
-static int32_t
|
|
|
8b9864 |
-qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
|
|
|
8b9864 |
- struct ipc_auth_ugp *ugp)
|
|
|
8b9864 |
+static void
|
|
|
8b9864 |
+destroy_ipc_auth_data(struct ipc_auth_data *data)
|
|
|
8b9864 |
{
|
|
|
8b9864 |
- int32_t res = 0;
|
|
|
8b9864 |
- struct msghdr msg_recv;
|
|
|
8b9864 |
- struct iovec iov_recv;
|
|
|
8b9864 |
+ if (data->s) {
|
|
|
8b9864 |
+ qb_ipcs_unref(data->s);
|
|
|
8b9864 |
+ }
|
|
|
8b9864 |
|
|
|
8b9864 |
#ifdef SO_PASSCRED
|
|
|
8b9864 |
- char cmsg_cred[CMSG_SPACE(sizeof(struct ucred))];
|
|
|
8b9864 |
- int off = 0;
|
|
|
8b9864 |
- int on = 1;
|
|
|
8b9864 |
-#endif
|
|
|
8b9864 |
- msg_recv.msg_iov = &iov_recv;
|
|
|
8b9864 |
- msg_recv.msg_iovlen = 1;
|
|
|
8b9864 |
- msg_recv.msg_name = 0;
|
|
|
8b9864 |
- msg_recv.msg_namelen = 0;
|
|
|
8b9864 |
-#ifdef SO_PASSCRED
|
|
|
8b9864 |
- msg_recv.msg_control = (void *)cmsg_cred;
|
|
|
8b9864 |
- msg_recv.msg_controllen = sizeof(cmsg_cred);
|
|
|
8b9864 |
+ free(data->cmsg_cred);
|
|
|
8b9864 |
#endif
|
|
|
8b9864 |
-#ifdef QB_SOLARIS
|
|
|
8b9864 |
- msg_recv.msg_accrights = 0;
|
|
|
8b9864 |
- msg_recv.msg_accrightslen = 0;
|
|
|
8b9864 |
-#else
|
|
|
8b9864 |
- msg_recv.msg_flags = 0;
|
|
|
8b9864 |
-#endif /* QB_SOLARIS */
|
|
|
8b9864 |
+ free(data);
|
|
|
8b9864 |
+}
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+static int32_t
|
|
|
8b9864 |
+process_auth(int32_t fd, int32_t revents, void *d)
|
|
|
8b9864 |
+{
|
|
|
8b9864 |
+ struct ipc_auth_data *data = (struct ipc_auth_data *) d;
|
|
|
8b9864 |
|
|
|
8b9864 |
- iov_recv.iov_base = msg;
|
|
|
8b9864 |
- iov_recv.iov_len = len;
|
|
|
8b9864 |
+ int32_t res = 0;
|
|
|
8b9864 |
#ifdef SO_PASSCRED
|
|
|
8b9864 |
- setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
|
|
|
8b9864 |
+ int off = 0;
|
|
|
8b9864 |
#endif
|
|
|
8b9864 |
|
|
|
8b9864 |
- res = qb_ipc_us_recv_msghdr(sock, &msg_recv, msg, len);
|
|
|
8b9864 |
- if (res < 0) {
|
|
|
8b9864 |
+ if (data->s->server_sock == -1) {
|
|
|
8b9864 |
+ qb_util_log(LOG_DEBUG, "Closing fd (%d) for server shutdown", fd);
|
|
|
8b9864 |
+ res = -ESHUTDOWN;
|
|
|
8b9864 |
goto cleanup_and_return;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
- if (res != len) {
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+ if (revents & POLLNVAL) {
|
|
|
8b9864 |
+ qb_util_log(LOG_DEBUG, "NVAL conn fd (%d)", fd);
|
|
|
8b9864 |
+ res = -EINVAL;
|
|
|
8b9864 |
+ goto cleanup_and_return;
|
|
|
8b9864 |
+ }
|
|
|
8b9864 |
+ if (revents & POLLHUP) {
|
|
|
8b9864 |
+ qb_util_log(LOG_DEBUG, "HUP conn fd (%d)", fd);
|
|
|
8b9864 |
+ res = -ESHUTDOWN;
|
|
|
8b9864 |
+ goto cleanup_and_return;
|
|
|
8b9864 |
+ }
|
|
|
8b9864 |
+ if ((revents & POLLIN) == 0) {
|
|
|
8b9864 |
+ return 0;
|
|
|
8b9864 |
+ }
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+ res = qb_ipc_us_recv_msghdr(data);
|
|
|
8b9864 |
+ if (res == -EAGAIN) {
|
|
|
8b9864 |
+ /* yield to mainloop, Let mainloop call us again */
|
|
|
8b9864 |
+ return 0;
|
|
|
8b9864 |
+ }
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+ if (res != data->len) {
|
|
|
8b9864 |
res = -EIO;
|
|
|
8b9864 |
goto cleanup_and_return;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
@@ -595,11 +626,11 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
|
|
|
8b9864 |
{
|
|
|
8b9864 |
ucred_t *uc = NULL;
|
|
|
8b9864 |
|
|
|
8b9864 |
- if (getpeerucred(sock, &uc) == 0) {
|
|
|
8b9864 |
+ if (getpeerucred(data->sock, &uc) == 0) {
|
|
|
8b9864 |
res = 0;
|
|
|
8b9864 |
- ugp->uid = ucred_geteuid(uc);
|
|
|
8b9864 |
- ugp->gid = ucred_getegid(uc);
|
|
|
8b9864 |
- ugp->pid = ucred_getpid(uc);
|
|
|
8b9864 |
+ ugp.uid = ucred_geteuid(uc);
|
|
|
8b9864 |
+ ugp.gid = ucred_getegid(uc);
|
|
|
8b9864 |
+ ugp.pid = ucred_getpid(uc);
|
|
|
8b9864 |
ucred_free(uc);
|
|
|
8b9864 |
} else {
|
|
|
8b9864 |
res = -errno;
|
|
|
8b9864 |
@@ -614,7 +645,7 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
|
|
|
8b9864 |
* TODO get the peer's pid.
|
|
|
8b9864 |
* c->pid = ?;
|
|
|
8b9864 |
*/
|
|
|
8b9864 |
- if (getpeereid(sock, &ugp->uid, &ugp->gid) == 0) {
|
|
|
8b9864 |
+ if (getpeereid(data->sock, &ugp.uid, &ugp.gid) == 0) {
|
|
|
8b9864 |
res = 0;
|
|
|
8b9864 |
} else {
|
|
|
8b9864 |
res = -errno;
|
|
|
8b9864 |
@@ -630,33 +661,105 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
|
|
|
8b9864 |
struct cmsghdr *cmsg;
|
|
|
8b9864 |
|
|
|
8b9864 |
res = -EINVAL;
|
|
|
8b9864 |
- for (cmsg = CMSG_FIRSTHDR(&msg_recv); cmsg != NULL;
|
|
|
8b9864 |
- cmsg = CMSG_NXTHDR(&msg_recv, cmsg)) {
|
|
|
8b9864 |
+ for (cmsg = CMSG_FIRSTHDR(&data->msg_recv); cmsg != NULL;
|
|
|
8b9864 |
+ cmsg = CMSG_NXTHDR(&data->msg_recv, cmsg)) {
|
|
|
8b9864 |
if (cmsg->cmsg_type != SCM_CREDENTIALS)
|
|
|
8b9864 |
continue;
|
|
|
8b9864 |
|
|
|
8b9864 |
memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred));
|
|
|
8b9864 |
res = 0;
|
|
|
8b9864 |
- ugp->pid = cred.pid;
|
|
|
8b9864 |
- ugp->uid = cred.uid;
|
|
|
8b9864 |
- ugp->gid = cred.gid;
|
|
|
8b9864 |
+ data->ugp.pid = cred.pid;
|
|
|
8b9864 |
+ data->ugp.uid = cred.uid;
|
|
|
8b9864 |
+ data->ugp.gid = cred.gid;
|
|
|
8b9864 |
break;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
}
|
|
|
8b9864 |
#else /* no credentials */
|
|
|
8b9864 |
- ugp->pid = 0;
|
|
|
8b9864 |
- ugp->uid = 0;
|
|
|
8b9864 |
- ugp->gid = 0;
|
|
|
8b9864 |
+ data->ugp.pid = 0;
|
|
|
8b9864 |
+ data->ugp.uid = 0;
|
|
|
8b9864 |
+ data->ugp.gid = 0;
|
|
|
8b9864 |
res = -ENOTSUP;
|
|
|
8b9864 |
#endif /* no credentials */
|
|
|
8b9864 |
|
|
|
8b9864 |
cleanup_and_return:
|
|
|
8b9864 |
+#ifdef SO_PASSCRED
|
|
|
8b9864 |
+ setsockopt(data->sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off));
|
|
|
8b9864 |
+#endif
|
|
|
8b9864 |
|
|
|
8b9864 |
+ (void)data->s->poll_fns.dispatch_del(data->sock);
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+ if (res < 0) {
|
|
|
8b9864 |
+ close(data->sock);
|
|
|
8b9864 |
+ } else if (data->msg.hdr.id == QB_IPC_MSG_AUTHENTICATE) {
|
|
|
8b9864 |
+ (void)handle_new_connection(data->s, res, data->sock, &data->msg, data->len, &data->ugp);
|
|
|
8b9864 |
+ } else {
|
|
|
8b9864 |
+ close(data->sock);
|
|
|
8b9864 |
+ }
|
|
|
8b9864 |
+ destroy_ipc_auth_data(data);
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+ return 1;
|
|
|
8b9864 |
+}
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+static void
|
|
|
8b9864 |
+qb_ipcs_uc_recv_and_auth(int32_t sock, struct qb_ipcs_service *s)
|
|
|
8b9864 |
+{
|
|
|
8b9864 |
+ int res = 0;
|
|
|
8b9864 |
+ struct ipc_auth_data *data = NULL;
|
|
|
8b9864 |
#ifdef SO_PASSCRED
|
|
|
8b9864 |
- setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off));
|
|
|
8b9864 |
+ int on = 1;
|
|
|
8b9864 |
#endif
|
|
|
8b9864 |
|
|
|
8b9864 |
- return res;
|
|
|
8b9864 |
+ data = calloc(1, sizeof(struct ipc_auth_data));
|
|
|
8b9864 |
+ if (data == NULL) {
|
|
|
8b9864 |
+ close(sock);
|
|
|
8b9864 |
+ /* -ENOMEM */
|
|
|
8b9864 |
+ return;
|
|
|
8b9864 |
+ }
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+ data->s = s;
|
|
|
8b9864 |
+ qb_ipcs_ref(data->s);
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+ data->msg_recv.msg_iov = &data->iov_recv;
|
|
|
8b9864 |
+ data->msg_recv.msg_iovlen = 1;
|
|
|
8b9864 |
+ data->msg_recv.msg_name = 0;
|
|
|
8b9864 |
+ data->msg_recv.msg_namelen = 0;
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+#ifdef SO_PASSCRED
|
|
|
8b9864 |
+ data->cmsg_cred = calloc(1,CMSG_SPACE(sizeof(struct ucred)));
|
|
|
8b9864 |
+ if (data->cmsg_cred == NULL) {
|
|
|
8b9864 |
+ close(sock);
|
|
|
8b9864 |
+ destroy_ipc_auth_data(data);
|
|
|
8b9864 |
+ /* -ENOMEM */
|
|
|
8b9864 |
+ return;
|
|
|
8b9864 |
+ }
|
|
|
8b9864 |
+ data->msg_recv.msg_control = (void *)data->cmsg_cred;
|
|
|
8b9864 |
+ data->msg_recv.msg_controllen = CMSG_SPACE(sizeof(struct ucred));
|
|
|
8b9864 |
+#endif
|
|
|
8b9864 |
+#ifdef QB_SOLARIS
|
|
|
8b9864 |
+ data->msg_recv.msg_accrights = 0;
|
|
|
8b9864 |
+ data->msg_recv.msg_accrightslen = 0;
|
|
|
8b9864 |
+#else
|
|
|
8b9864 |
+ data->msg_recv.msg_flags = 0;
|
|
|
8b9864 |
+#endif /* QB_SOLARIS */
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+ data->len = sizeof(struct qb_ipc_connection_request);
|
|
|
8b9864 |
+ data->iov_recv.iov_base = &data->msg;
|
|
|
8b9864 |
+ data->iov_recv.iov_len = data->len;
|
|
|
8b9864 |
+ data->sock = sock;
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+#ifdef SO_PASSCRED
|
|
|
8b9864 |
+ setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
|
|
|
8b9864 |
+#endif
|
|
|
8b9864 |
+
|
|
|
8b9864 |
+ res = s->poll_fns.dispatch_add(QB_LOOP_MED,
|
|
|
8b9864 |
+ data->sock,
|
|
|
8b9864 |
+ POLLIN | POLLPRI | POLLNVAL,
|
|
|
8b9864 |
+ data, process_auth);
|
|
|
8b9864 |
+ if (res < 0) {
|
|
|
8b9864 |
+ qb_util_log(LOG_DEBUG, "Failed to process AUTH for fd (%d)", data->sock);
|
|
|
8b9864 |
+ close(sock);
|
|
|
8b9864 |
+ destroy_ipc_auth_data(data);
|
|
|
8b9864 |
+ }
|
|
|
8b9864 |
}
|
|
|
8b9864 |
|
|
|
8b9864 |
static int32_t
|
|
|
8b9864 |
@@ -666,8 +769,6 @@ qb_ipcs_us_connection_acceptor(int fd, int revent, void *data)
|
|
|
8b9864 |
int32_t new_fd;
|
|
|
8b9864 |
struct qb_ipcs_service *s = (struct qb_ipcs_service *)data;
|
|
|
8b9864 |
int32_t res;
|
|
|
8b9864 |
- struct qb_ipc_connection_request setup_msg;
|
|
|
8b9864 |
- struct ipc_auth_ugp ugp;
|
|
|
8b9864 |
socklen_t addrlen = sizeof(struct sockaddr_un);
|
|
|
8b9864 |
|
|
|
8b9864 |
if (revent & (POLLNVAL | POLLHUP | POLLERR)) {
|
|
|
8b9864 |
@@ -707,22 +808,6 @@ retry_accept:
|
|
|
8b9864 |
return 0;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
|
|
|
8b9864 |
- res = qb_ipcs_uc_recv_and_auth(new_fd, &setup_msg, sizeof(setup_msg),
|
|
|
8b9864 |
- &ugp;;
|
|
|
8b9864 |
- if (res < 0) {
|
|
|
8b9864 |
- close(new_fd);
|
|
|
8b9864 |
- /* This is an error, but -1 would indicate disconnect
|
|
|
8b9864 |
- * from the poll loop
|
|
|
8b9864 |
- */
|
|
|
8b9864 |
- return 0;
|
|
|
8b9864 |
- }
|
|
|
8b9864 |
-
|
|
|
8b9864 |
- if (setup_msg.hdr.id == QB_IPC_MSG_AUTHENTICATE) {
|
|
|
8b9864 |
- (void)handle_new_connection(s, res, new_fd, &setup_msg,
|
|
|
8b9864 |
- sizeof(setup_msg), &ugp;;
|
|
|
8b9864 |
- } else {
|
|
|
8b9864 |
- close(new_fd);
|
|
|
8b9864 |
- }
|
|
|
8b9864 |
-
|
|
|
8b9864 |
+ qb_ipcs_uc_recv_and_auth(new_fd, s);
|
|
|
8b9864 |
return 0;
|
|
|
8b9864 |
}
|
|
|
8b9864 |
--
|
|
|
8b9864 |
1.8.4.2
|
|
|
8b9864 |
|