[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