The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/1613

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
- 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 <[email protected]>
From ae467c546bb15f16cad3a83b958c19136cdd7e91 Mon Sep 17 00:00:00 2001
From: Christian Brauner <[email protected]>
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 <[email protected]>
---
 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;
        }
_______________________________________________
lxc-devel mailing list
[email protected]
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to