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

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) ===
Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From ea2a070bc5666ef7b3fc23023c3a5214b0dafc9c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brau...@ubuntu.com>
Date: Wed, 11 Mar 2020 12:02:10 +0100
Subject: [PATCH] commands: add ability to audit fd connection and cleanup path

Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
---
 src/lxc/commands.c       | 145 +++++++++++++++++++++------------------
 src/lxc/commands.h       |   7 ++
 src/lxc/commands_utils.c |   3 +-
 src/lxc/lxccontainer.c   |  14 ++--
 4 files changed, 94 insertions(+), 75 deletions(-)

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index 1feae25aab..b11c3c7fc8 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -284,6 +284,9 @@ static int lxc_cmd(const char *name, struct lxc_cmd_rr 
*cmd, int *stopped,
        if (ret < 0 && errno == ECONNRESET)
                *stopped = 1;
 
+       TRACE("Opened new command socket connection fd %d for command \"%s\"",
+             client_fd, lxc_cmd_str(cmd->req.cmd));
+
        if (stay_connected && ret > 0)
                cmd->rsp.ret = move_fd(client_fd);
 
@@ -357,11 +360,16 @@ static int lxc_cmd_get_init_pid_callback(int fd, struct 
lxc_cmd_req *req,
                                         struct lxc_handler *handler,
                                         struct lxc_epoll_descr *descr)
 {
+       int ret;
        struct lxc_cmd_rsp rsp = {
                .data = PID_TO_PTR(handler->pid)
        };
 
-       return lxc_cmd_rsp_send(fd, &rsp);
+       ret = lxc_cmd_rsp_send(fd, &rsp);
+       if (ret < 0)
+               return LXC_CMD_REAP_CLIENT_FD;
+
+       return 0;
 }
 
 /*
@@ -392,11 +400,16 @@ static int lxc_cmd_get_clone_flags_callback(int fd, 
struct lxc_cmd_req *req,
                                            struct lxc_handler *handler,
                                            struct lxc_epoll_descr *descr)
 {
+       int ret;
        struct lxc_cmd_rsp rsp = {
                .data = INT_TO_PTR(handler->ns_clone_flags),
        };
 
-       return lxc_cmd_rsp_send(fd, &rsp);
+       ret = lxc_cmd_rsp_send(fd, &rsp);
+       if (ret < 0)
+               return LXC_CMD_REAP_CLIENT_FD;
+
+       return 0;
 }
 
 /*
@@ -445,6 +458,7 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct 
lxc_cmd_req *req,
                                       struct lxc_handler *handler,
                                       struct lxc_epoll_descr *descr)
 {
+       int ret;
        const char *path;
        struct lxc_cmd_rsp rsp;
        struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
@@ -460,7 +474,11 @@ static int lxc_cmd_get_cgroup_callback(int fd, struct 
lxc_cmd_req *req,
        rsp.datalen = strlen(path) + 1;
        rsp.data = (char *)path;
 
-       return lxc_cmd_rsp_send(fd, &rsp);
+       ret = lxc_cmd_rsp_send(fd, &rsp);
+       if (ret < 0)
+               return LXC_CMD_REAP_CLIENT_FD;
+
+       return 0;
 }
 
 /*
@@ -525,7 +543,11 @@ static int lxc_cmd_get_config_item_callback(int fd, struct 
lxc_cmd_req *req,
 err1:
        rsp.ret = -1;
 out:
-       return lxc_cmd_rsp_send(fd, &rsp);
+       cilen = lxc_cmd_rsp_send(fd, &rsp);
+       if (cilen < 0)
+               return LXC_CMD_REAP_CLIENT_FD;
+
+       return 0;
 }
 
 /*
@@ -564,11 +586,16 @@ static int lxc_cmd_get_state_callback(int fd, struct 
lxc_cmd_req *req,
                                      struct lxc_handler *handler,
                                      struct lxc_epoll_descr *descr)
 {
+       int ret;
        struct lxc_cmd_rsp rsp = {
                .data = INT_TO_PTR(handler->state),
        };
 
-       return lxc_cmd_rsp_send(fd, &rsp);
+       ret = lxc_cmd_rsp_send(fd, &rsp);
+       if (ret < 0)
+               return LXC_CMD_REAP_CLIENT_FD;
+
+       return 0;
 }
 
 /*
@@ -613,6 +640,7 @@ static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req 
*req,
        struct lxc_cmd_rsp rsp;
        int stopsignal = SIGKILL;
        struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
+       int ret;
 
        if (handler->conf->stopsignal)
                stopsignal = handler->conf->stopsignal;
@@ -629,7 +657,11 @@ static int lxc_cmd_stop_callback(int fd, struct 
lxc_cmd_req *req,
                rsp.ret = -errno;
        }
 
-       return lxc_cmd_rsp_send(fd, &rsp);
+       ret = lxc_cmd_rsp_send(fd, &rsp);
+       if (ret < 0)
+               return LXC_CMD_REAP_CLIENT_FD;
+
+       return 0;
 }
 
 /*
@@ -706,24 +738,18 @@ static int lxc_cmd_console_callback(int fd, struct 
lxc_cmd_req *req,
 
        masterfd = lxc_terminal_allocate(handler->conf, fd, &ttynum);
        if (masterfd < 0)
-               goto out_close;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        memset(&rsp, 0, sizeof(rsp));
        rsp.data = INT_TO_PTR(ttynum);
        ret = lxc_abstract_unix_send_fds(fd, &masterfd, 1, &rsp, sizeof(rsp));
        if (ret < 0) {
-               SYSERROR("Failed to send tty to client");
                lxc_terminal_free(handler->conf, fd);
-               goto out_close;
+               return log_error_errno(LXC_CMD_REAP_CLIENT_FD, errno,
+                                      "Failed to send tty to client");
        }
 
        return 0;
-
-out_close:
-       /* Special indicator to lxc_cmd_handler() to close the fd and do
-        * related cleanup.
-        */
-       return 1;
 }
 
 /*
@@ -756,6 +782,7 @@ static int lxc_cmd_get_name_callback(int fd, struct 
lxc_cmd_req *req,
                                     struct lxc_handler *handler,
                                     struct lxc_epoll_descr *descr)
 {
+       int ret;
        struct lxc_cmd_rsp rsp;
 
        memset(&rsp, 0, sizeof(rsp));
@@ -764,7 +791,11 @@ static int lxc_cmd_get_name_callback(int fd, struct 
lxc_cmd_req *req,
        rsp.datalen = strlen(handler->name) + 1;
        rsp.ret = 0;
 
-       return lxc_cmd_rsp_send(fd, &rsp);
+       ret = lxc_cmd_rsp_send(fd, &rsp);
+       if (ret < 0)
+               return LXC_CMD_REAP_CLIENT_FD;
+
+       return 0;
 }
 
 /*
@@ -797,13 +828,18 @@ static int lxc_cmd_get_lxcpath_callback(int fd, struct 
lxc_cmd_req *req,
                                        struct lxc_handler *handler,
                                        struct lxc_epoll_descr *descr)
 {
+       int ret;
        struct lxc_cmd_rsp rsp = {
                .ret            = 0,
                .data           = (char *)handler->lxcpath,
                .datalen        = strlen(handler->lxcpath) + 1,
        };
 
-       return lxc_cmd_rsp_send(fd, &rsp);
+       ret = lxc_cmd_rsp_send(fd, &rsp);
+       if (ret < 0)
+               return LXC_CMD_REAP_CLIENT_FD;
+
+       return 0;
 }
 
 int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
@@ -844,7 +880,8 @@ int lxc_cmd_add_state_client(const char *name, const char 
*lxcpath,
                return log_trace(state, "Container is already in requested 
state %s", lxc_state2str(state));
 
        *state_client_fd = move_fd(clientfd);
-       return log_trace(MAX_STATE, "Added state client %d to state client 
list", *state_client_fd);
+       TRACE("State connection fd %d ready to listen for container state 
changes", *state_client_fd);
+       return MAX_STATE;
 }
 
 static int lxc_cmd_add_state_client_callback(__owns int fd, struct lxc_cmd_req 
*req,
@@ -855,31 +892,25 @@ static int lxc_cmd_add_state_client_callback(__owns int 
fd, struct lxc_cmd_req *
        struct lxc_cmd_rsp rsp = {0};
 
        if (req->datalen < 0)
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        if (req->datalen != (sizeof(lxc_state_t) * MAX_STATE))
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        if (!req->data)
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        rsp.ret = lxc_add_state_client(fd, handler, (lxc_state_t *)req->data);
        if (rsp.ret < 0)
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        rsp.data = INT_TO_PTR(rsp.ret);
 
        ret = lxc_cmd_rsp_send(fd, &rsp);
        if (ret < 0)
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        return 0;
-
-reap_client_fd:
-       /* Special indicator to lxc_cmd_handler() to close the fd and do related
-        * cleanup.
-        */
-       return 1;
 }
 
 int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath,
@@ -925,13 +956,13 @@ static int lxc_cmd_add_bpf_device_cgroup_callback(int fd, 
struct lxc_cmd_req *re
        struct bpf_program *devices_old;
 
        if (req->datalen <= 0)
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        if (req->datalen != sizeof(struct device_item))
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        if (!req->data)
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
        device = (struct device_item *)req->data;
 
        rsp.ret = -1;
@@ -978,15 +1009,9 @@ static int lxc_cmd_add_bpf_device_cgroup_callback(int fd, 
struct lxc_cmd_req *re
 respond:
        ret = lxc_cmd_rsp_send(fd, &rsp);
        if (ret < 0)
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        return 0;
-
-reap_client_fd:
-       /* Special indicator to lxc_cmd_handler() to close the fd and do related
-        * cleanup.
-        */
-       return 1;
 #else
        return ret_set_errno(-1, ENOSYS);
 #endif
@@ -1097,20 +1122,13 @@ static int lxc_cmd_serve_state_clients_callback(int fd, 
struct lxc_cmd_req *req,
 
        ret = lxc_serve_state_clients(handler->name, handler, state);
        if (ret < 0)
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        ret = lxc_cmd_rsp_send(fd, &rsp);
        if (ret < 0)
-               goto reap_client_fd;
+               return LXC_CMD_REAP_CLIENT_FD;
 
        return 0;
-
-reap_client_fd:
-       /*
-        * Special indicator to lxc_cmd_handler() to close the fd and do
-        * related cleanup.
-        */
-       return 1;
 }
 
 int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
@@ -1347,7 +1365,7 @@ static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler 
*handler,
                         * No need to walk the whole list. If we found the state
                         * client fd there can't be a second one.
                         */
-                       TRACE("Found state client fd %d in state client list", 
fd);
+                       TRACE("Found state client fd %d in state client list 
for command \"%s\"", fd, lxc_cmd_str(cmd));
                        break;
                }
 
@@ -1357,9 +1375,10 @@ static void lxc_cmd_fd_cleanup(int fd, struct 
lxc_handler *handler,
                 * was already reached by the time we were ready to add it. So
                 * fallthrough and clean it up.
                 */
-               TRACE("Closing state client fd %d", fd);
+               TRACE("Closing state client fd %d for command \"%s\"", fd, 
lxc_cmd_str(cmd));
        }
 
+       TRACE("Closing client fd %d for command \"%s\"", fd, lxc_cmd_str(cmd));
        close(fd);
 }
 
@@ -1373,12 +1392,13 @@ static int lxc_cmd_handler(int fd, uint32_t events, 
void *data,
 
        ret = lxc_abstract_unix_rcv_credential(fd, &req, sizeof(req));
        if (ret < 0) {
-               SYSERROR("Failed to receive data on command socket for command "
-                        "\"%s\"", lxc_cmd_str(req.cmd));
+               SYSERROR("Failed to receive data on command socket for command 
\"%s\"", lxc_cmd_str(req.cmd));
 
                if (errno == EACCES) {
                        /* We don't care for the peer, just send and close. */
-                       struct lxc_cmd_rsp rsp = {.ret = ret};
+                       struct lxc_cmd_rsp rsp = {
+                               .ret = ret,
+                       };
 
                        lxc_cmd_rsp_send(fd, &rsp);
                }
@@ -1390,16 +1410,13 @@ static int lxc_cmd_handler(int fd, uint32_t events, 
void *data,
                goto out_close;
 
        if (ret != sizeof(req)) {
-               WARN("Failed to receive full command request. Ignoring request "
-                    "for \"%s\"", lxc_cmd_str(req.cmd));
+               WARN("Failed to receive full command request. Ignoring request 
for \"%s\"", lxc_cmd_str(req.cmd));
                ret = -1;
                goto out_close;
        }
 
-       if ((req.datalen > LXC_CMD_DATA_MAX) &&
-           (req.cmd != LXC_CMD_CONSOLE_LOG)) {
-               ERROR("Received command data length %d is too large for "
-                     "command \"%s\"", req.datalen, lxc_cmd_str(req.cmd));
+       if ((req.datalen > LXC_CMD_DATA_MAX) && (req.cmd != 
LXC_CMD_CONSOLE_LOG)) {
+               ERROR("Received command data length %d is too large for command 
\"%s\"", req.datalen, lxc_cmd_str(req.cmd));
                errno = EFBIG;
                ret = -EFBIG;
                goto out_close;
@@ -1409,8 +1426,7 @@ static int lxc_cmd_handler(int fd, uint32_t events, void 
*data,
                reqdata = must_realloc(NULL, req.datalen);
                ret = lxc_recv_nointr(fd, reqdata, req.datalen, 0);
                if (ret != req.datalen) {
-                       WARN("Failed to receive full command request. Ignoring "
-                            "request for \"%s\"", lxc_cmd_str(req.cmd));
+                       WARN("Failed to receive full command request. Ignoring 
request for \"%s\"", lxc_cmd_str(req.cmd));
                        ret = LXC_MAINLOOP_ERROR;
                        goto out_close;
                }
@@ -1455,6 +1471,7 @@ static int lxc_cmd_accept(int fd, uint32_t events, void 
*data,
        if (ret)
                return log_error(ret, "Failed to add command handler");
 
+       TRACE("Accepted new client as fd %d on command server fd %d", 
connection, fd);
        move_fd(connection);
        return ret;
 }
@@ -1487,13 +1504,11 @@ int lxc_cmd_init(const char *name, const char *lxcpath, 
const char *suffix)
 int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
                         struct lxc_handler *handler)
 {
-       __do_close_prot_errno int fd = handler->conf->maincmd_fd;
        int ret;
 
-       ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept, handler);
+       ret = lxc_mainloop_add_handler(descr, handler->conf->maincmd_fd, 
lxc_cmd_accept, handler);
        if (ret < 0)
-               return log_error(ret, "Failed to add handler for command 
socket");
+               return log_error(ret, "Failed to add handler for command socket 
fd %d", handler->conf->maincmd_fd);
 
-       move_fd(fd);
        return ret;
 }
diff --git a/src/lxc/commands.h b/src/lxc/commands.h
index c386c21bef..cd78a61a21 100644
--- a/src/lxc/commands.h
+++ b/src/lxc/commands.h
@@ -11,6 +11,13 @@
 #include "macro.h"
 #include "state.h"
 
+/*
+ * Value command callbacks should return when they want the client fd to be
+ * cleaned up by the main loop. This is most certainly what you want unless you
+ * have specific reasons to keep the file descriptor alive.
+ */
+#define LXC_CMD_REAP_CLIENT_FD 1
+
 typedef enum {
        LXC_CMD_CONSOLE,
        LXC_CMD_TERMINAL_WINCH,
diff --git a/src/lxc/commands_utils.c b/src/lxc/commands_utils.c
index 884a18ea1c..dbc06bf334 100644
--- a/src/lxc/commands_utils.c
+++ b/src/lxc/commands_utils.c
@@ -185,5 +185,6 @@ int lxc_add_state_client(int state_client_fd, struct 
lxc_handler *handler,
 
        move_ptr(newclient);
        move_ptr(tmplist);
-       return log_trace(MAX_STATE, "Added state client %d to state client 
list", state_client_fd);
+       TRACE("Added state client fd %d to state client list", state_client_fd);
+       return MAX_STATE;
 }
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 68e5b3400a..bf0c44d217 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -2064,10 +2064,11 @@ WRAP_API_1(bool, lxcapi_reboot2, int)
 
 static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
 {
+       __do_close_prot_errno int state_client_fd = -EBADF;
+       int haltsignal = SIGPWR;
+       lxc_state_t states[MAX_STATE] = {0};
        int killret, ret;
        pid_t pid;
-       int haltsignal = SIGPWR, state_client_fd = -EBADF;
-       lxc_state_t states[MAX_STATE] = {0};
 
        if (!c)
                return false;
@@ -2107,20 +2108,15 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, 
int timeout)
 
        /* Send shutdown signal to container. */
        killret = kill(pid, haltsignal);
-       if (killret < 0) {
-               if (state_client_fd >= 0)
-                       close(state_client_fd);
+       if (killret < 0)
+               return log_warn(false, "Failed to send signal %d to pid %d", 
haltsignal, pid);
 
-               WARN("Failed to send signal %d to pid %d", haltsignal, pid);
-               return false;
-       }
        TRACE("Sent signal %d to pid %d", haltsignal, pid);
 
        if (timeout == 0)
                return true;
 
        ret = lxc_cmd_sock_rcv_state(state_client_fd, timeout);
-       close(state_client_fd);
        if (ret < 0)
                return false;
 
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to