[lxc-devel] [lxc/master] af_unix: abstract lxc_abstract_unix_{send, recv}_fd

brauner on Github lxc-bot at linuxcontainers.org
Sun Jun 4 06:10:56 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 583 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170604/94dd48a6/attachment.bin>
-------------- next part --------------
From ae467c546bb15f16cad3a83b958c19136cdd7e91 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 4 Jun 2017 07:04:27 +0200
Subject: [PATCH] af_unix: abstract lxc_abstract_unix_{send,recv}_fd

- Enable lxc_abstract_unix_{send,recv}_fd() to send and receive multiple fds at
  once.
- lxc_abstract_unix_{send,recv}_fd() -> lxc_abstract_unix_{send,recv}_fds()
- Send tty fds from child to parent all at once.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/af_unix.c  | 74 +++++++++++++++++++++++++++++++++---------------------
 src/lxc/af_unix.h  |  8 ++++--
 src/lxc/attach.c   |  4 +--
 src/lxc/commands.c |  4 +--
 src/lxc/conf.c     | 65 +++++++++++++++++++++--------------------------
 src/lxc/start.c    | 57 +++++++++++++++++++++--------------------
 6 files changed, 111 insertions(+), 101 deletions(-)

diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c
index ac839943e..074fabb44 100644
--- a/src/lxc/af_unix.c
+++ b/src/lxc/af_unix.c
@@ -22,6 +22,8 @@
  */
 #include "config.h"
 
+#include <stdio.h>
+#include <stdlib.h>
 #include <stddef.h>
 #include <string.h>
 #include <unistd.h>
@@ -133,49 +135,66 @@ int lxc_abstract_unix_connect(const char *path)
 	return fd;
 }
 
-int lxc_abstract_unix_send_fd(int fd, int sendfd, void *data, size_t size)
+int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
+			       void *data, size_t size)
 {
-	struct msghdr msg = { 0 };
+	int ret;
+	struct msghdr msg;
 	struct iovec iov;
-	struct cmsghdr *cmsg;
-	char cmsgbuf[CMSG_SPACE(sizeof(int))] = {0};
+	struct cmsghdr *cmsg = NULL;
 	char buf[1] = {0};
-	int *val;
+	char *cmsgbuf;
+	size_t cmsgbufsize = CMSG_SPACE(num_sendfds * sizeof(int));
+
+	memset(&msg, 0, sizeof(msg));
+	memset(&iov, 0, sizeof(iov));
+
+	cmsgbuf = malloc(cmsgbufsize);
+	if (!cmsgbuf)
+		return -1;
 
 	msg.msg_control = cmsgbuf;
-	msg.msg_controllen = sizeof(cmsgbuf);
+	msg.msg_controllen = cmsgbufsize;
 
 	cmsg = CMSG_FIRSTHDR(&msg);
-	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
 	cmsg->cmsg_level = SOL_SOCKET;
 	cmsg->cmsg_type = SCM_RIGHTS;
-	val = (int *)(CMSG_DATA(cmsg));
-	*val = sendfd;
+	cmsg->cmsg_len = CMSG_LEN(num_sendfds * sizeof(int));
 
-	msg.msg_name = NULL;
-	msg.msg_namelen = 0;
+	msg.msg_controllen = cmsg->cmsg_len;
+
+	memcpy(CMSG_DATA(cmsg), sendfds, num_sendfds * sizeof(int));
 
 	iov.iov_base = data ? data : buf;
 	iov.iov_len = data ? size : sizeof(buf);
 	msg.msg_iov = &iov;
 	msg.msg_iovlen = 1;
 
-	return sendmsg(fd, &msg, MSG_NOSIGNAL);
+	ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
+	free(cmsgbuf);
+	return ret;
 }
 
-int lxc_abstract_unix_recv_fd(int fd, int *recvfd, void *data, size_t size)
+int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
+			       void *data, size_t size)
 {
-	struct msghdr msg = { 0 };
+	int ret;
+	struct msghdr msg;
 	struct iovec iov;
-	struct cmsghdr *cmsg;
-	int ret, *val;
-	char cmsgbuf[CMSG_SPACE(sizeof(int))] = {0};
+	struct cmsghdr *cmsg = NULL;
 	char buf[1] = {0};
+	char *cmsgbuf;
+	size_t cmsgbufsize = CMSG_SPACE(num_recvfds * sizeof(int));
+
+	memset(&msg, 0, sizeof(msg));
+	memset(&iov, 0, sizeof(iov));
+
+	cmsgbuf = malloc(cmsgbufsize);
+	if (!cmsgbuf)
+		return -1;
 
-	msg.msg_name = NULL;
-	msg.msg_namelen = 0;
 	msg.msg_control = cmsgbuf;
-	msg.msg_controllen = sizeof(cmsgbuf);
+	msg.msg_controllen = cmsgbufsize;
 
 	iov.iov_base = data ? data : buf;
 	iov.iov_len = data ? size : sizeof(buf);
@@ -188,17 +207,14 @@ int lxc_abstract_unix_recv_fd(int fd, int *recvfd, void *data, size_t size)
 
 	cmsg = CMSG_FIRSTHDR(&msg);
 
-	/* if the message is wrong the variable will not be
-	 * filled and the peer will notified about a problem */
-	*recvfd = -1;
-
-	if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int)) &&
-			cmsg->cmsg_level == SOL_SOCKET &&
-			cmsg->cmsg_type == SCM_RIGHTS) {
-		val = (int *) CMSG_DATA(cmsg);
-		*recvfd = *val;
+	memset(recvfds, -1, num_recvfds * sizeof(int));
+	if (cmsg && cmsg->cmsg_len == CMSG_LEN(num_recvfds * sizeof(int)) &&
+	    cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+		memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int));
 	}
+
 out:
+	free(cmsgbuf);
 	return ret;
 }
 
diff --git a/src/lxc/af_unix.h b/src/lxc/af_unix.h
index d25a2118a..fafa225b5 100644
--- a/src/lxc/af_unix.h
+++ b/src/lxc/af_unix.h
@@ -24,13 +24,17 @@
 #ifndef __LXC_AF_UNIX_H
 #define __LXC_AF_UNIX_H
 
+#include <stdio.h>
+
 /* does not enforce \0-termination */
 extern int lxc_abstract_unix_open(const char *path, int type, int flags);
 extern int lxc_abstract_unix_close(int fd);
 /* does not enforce \0-termination */
 extern int lxc_abstract_unix_connect(const char *path);
-extern int lxc_abstract_unix_send_fd(int fd, int sendfd, void *data, size_t size);
-extern int lxc_abstract_unix_recv_fd(int fd, int *recvfd, void *data, size_t size);
+extern int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
+				      void *data, size_t size);
+extern int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
+				      void *data, size_t size);
 extern int lxc_abstract_unix_send_credential(int fd, void *data, size_t size);
 extern int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size);
 
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 968301760..eae494067 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -986,7 +986,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
 				goto on_error;
 
 			/* Send child fd of the LSM security module to write to. */
-			ret = lxc_abstract_unix_send_fd(ipc_sockets[0], labelfd, NULL, 0);
+			ret = lxc_abstract_unix_send_fds(ipc_sockets[0], &labelfd, 1, NULL, 0);
 			saved_errno = errno;
 			close(labelfd);
 			if (ret <= 0) {
@@ -1273,7 +1273,7 @@ static int attach_child_main(void* data)
 	if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
 		int on_exec;
 		/* Receive fd for LSM security module. */
-		ret = lxc_abstract_unix_recv_fd(ipc_socket, &lsm_labelfd, NULL, 0);
+		ret = lxc_abstract_unix_recv_fds(ipc_socket, &lsm_labelfd, 1, NULL, 0);
 		if (ret <= 0) {
 			ERROR("Expected to receive file descriptor: %s.", strerror(errno));
 			shutdown(ipc_socket, SHUT_RDWR);
diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index 85e7b0c9d..bb354a505 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -171,7 +171,7 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
 	int ret,rspfd;
 	struct lxc_cmd_rsp *rsp = &cmd->rsp;
 
-	ret = lxc_abstract_unix_recv_fd(sock, &rspfd, rsp, sizeof(*rsp));
+	ret = lxc_abstract_unix_recv_fds(sock, &rspfd, 1, rsp, sizeof(*rsp));
 	if (ret < 0) {
 		WARN("Command %s failed to receive response: %s.",
 		     lxc_cmd_str(cmd->req.cmd), strerror(errno));
@@ -756,7 +756,7 @@ static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
 
 	memset(&rsp, 0, sizeof(rsp));
 	rsp.data = INT_TO_PTR(ttynum);
-	if (lxc_abstract_unix_send_fd(fd, masterfd, &rsp, sizeof(rsp)) < 0) {
+	if (lxc_abstract_unix_send_fds(fd, &masterfd, 1, &rsp, sizeof(rsp)) < 0) {
 		ERROR("Failed to send tty to client.");
 		lxc_console_free(handler->conf, fd);
 		goto out_close;
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 2490e5cf6..44f15c482 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -4093,55 +4093,46 @@ static bool verify_start_hooks(struct lxc_conf *conf)
 	return true;
 }
 
-static int send_fd(int sock, int fd)
+static int lxc_send_ttys_to_parent(struct lxc_handler *handler)
 {
-	int ret = lxc_abstract_unix_send_fd(sock, fd, NULL, 0);
-
-
-	if (ret < 0) {
-		SYSERROR("Error sending tty fd to parent");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int send_ttys_to_parent(struct lxc_handler *handler)
-{
-	int i, ret;
+	int i;
+	int *ttyfds;
+	struct lxc_pty_info *pty_info;
 	struct lxc_conf *conf = handler->conf;
 	const struct lxc_tty_info *tty_info = &conf->tty_info;
 	int sock = handler->ttysock[0];
+	int ret = -1;
+	size_t num_ttyfds = (2 * conf->tty);
 
-	for (i = 0; i < tty_info->nbtty; i++) {
-		struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
-		ret = send_fd(sock, pty_info->slave);
-		if (ret >= 0)
-			send_fd(sock, pty_info->master);
-		TRACE("sending pty \"%s\" with master fd %d and slave fd %d to "
+	ttyfds = malloc(num_ttyfds * sizeof(int));
+	if (!ttyfds)
+		return -1;
+
+	for (i = 0; i < num_ttyfds; i++) {
+		pty_info = &tty_info->pty_info[i / 2];
+		ttyfds[i++] = pty_info->slave;
+		ttyfds[i] = pty_info->master;
+		TRACE("send pty \"%s\" with master fd %d and slave fd %d to "
 		      "parent",
 		      pty_info->name, pty_info->master, pty_info->slave);
-		close(pty_info->slave);
-		pty_info->slave = -1;
-		close(pty_info->master);
-		pty_info->master = -1;
-		if (ret < 0) {
-			ERROR("failed to send pty \"%s\" with master fd %d and "
-			      "slave fd %d to parent : %s",
-			      pty_info->name, pty_info->master, pty_info->slave,
-			      strerror(errno));
-			goto bad;
-		}
 	}
 
+	ret = lxc_abstract_unix_send_fds(sock, ttyfds, num_ttyfds, NULL, 0);
+	if (ret < 0)
+		ERROR("failed to send %d ttys to parent: %s", conf->tty,
+		      strerror(errno));
+	else
+		TRACE("sent %d ttys to parent", conf->tty);
+
 	close(handler->ttysock[0]);
 	close(handler->ttysock[1]);
 
-	return 0;
+	for (i = 0; i < num_ttyfds; i++)
+		close(ttyfds[i]);
 
-bad:
-	ERROR("Error writing tty fd to parent");
-	return -1;
+	free(ttyfds);
+
+	return ret;
 }
 
 int lxc_setup(struct lxc_handler *handler)
@@ -4260,7 +4251,7 @@ int lxc_setup(struct lxc_handler *handler)
 		return -1;
 	}
 
-	if (send_ttys_to_parent(handler) < 0) {
+	if (lxc_send_ttys_to_parent(handler) < 0) {
 		ERROR("failure sending console info to parent");
 		return -1;
 	}
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 6d932038d..c0a7be5f0 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1008,23 +1008,16 @@ static int save_phys_nics(struct lxc_conf *conf)
 	return 0;
 }
 
-static int recv_fd(int sock, int *fd)
+static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
 {
-	if (lxc_abstract_unix_recv_fd(sock, fd, NULL, 0) < 0) {
-		SYSERROR("Error receiving tty file descriptor from child process.");
-		return -1;
-	}
-	if (*fd == -1)
-		return -1;
-	return 0;
-}
-
-static int recv_ttys_from_child(struct lxc_handler *handler)
-{
-	int i, ret;
+	int i;
+	int *ttyfds;
+	struct lxc_pty_info *pty_info;
+	int ret = -1;
 	int sock = handler->ttysock[1];
 	struct lxc_conf *conf = handler->conf;
 	struct lxc_tty_info *tty_info = &conf->tty_info;
+	size_t num_ttyfds = (2 * conf->tty);
 
 	if (!conf->tty)
 		return 0;
@@ -1033,25 +1026,31 @@ static int recv_ttys_from_child(struct lxc_handler *handler)
 	if (!tty_info->pty_info)
 		return -1;
 
-	for (i = 0; i < conf->tty; i++) {
-		struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
+	ttyfds = malloc(num_ttyfds * sizeof(int));
+	if (!ttyfds)
+		return -1;
+
+	ret = lxc_abstract_unix_recv_fds(sock, ttyfds, num_ttyfds, NULL, 0);
+	for (i = 0; (ret >= 0 && *ttyfds != -1) && (i < num_ttyfds); i++) {
+		pty_info = &tty_info->pty_info[i / 2];
 		pty_info->busy = 0;
-		ret = recv_fd(sock, &pty_info->slave);
-		if (ret >= 0)
-			recv_fd(sock, &pty_info->master);
-		if (ret < 0) {
-			ERROR("failed to receive pty with master fd %d and "
-			      "slave fd %d from child: %s",
-			      pty_info->master, pty_info->slave,
-			      strerror(errno));
-			return -1;
-		}
-		TRACE("received pty with master fd %d and slave fd %d from child",
-		      pty_info->master, pty_info->slave);
+		pty_info->slave = ttyfds[i++];
+		pty_info->master = ttyfds[i];
+		TRACE("received pty with master fd %d and slave fd %d from "
+		      "parent", pty_info->master, pty_info->slave);
 	}
+
 	tty_info->nbtty = conf->tty;
 
-	return 0;
+	free(ttyfds);
+
+	if (ret < 0)
+		ERROR("failed to receive %d ttys from child: %s", conf->tty,
+		      strerror(errno));
+	else
+		TRACE("received %d ttys from child", conf->tty);
+
+	return ret;
 }
 
 void resolve_clone_flags(struct lxc_handler *handler)
@@ -1294,7 +1293,7 @@ static int lxc_spawn(struct lxc_handler *handler)
 	cgroups_connected = false;
 
 	/* Read tty fds allocated by child. */
-	if (recv_ttys_from_child(handler) < 0) {
+	if (lxc_recv_ttys_from_child(handler) < 0) {
 		ERROR("Failed to receive tty info from child process.");
 		goto out_delete_net;
 	}


More information about the lxc-devel mailing list