From: Christian Brauner Date: Sun, 21 Apr 2019 19:03:51 +0000 (+0200) Subject: commands: partially backport seccomp notify X-Git-Tag: lxc-3.0.4~64 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=857147910fb867008870671e5ad032dcd665905c;p=thirdparty%2Flxc.git commands: partially backport seccomp notify This backports seccomp notify into various parts of the codebase as a pure nop to make maintenance easier. Signed-off-by: Christian Brauner --- diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c index 3b00d64fb..06700fac1 100644 --- a/src/lxc/af_unix.c +++ b/src/lxc/af_unix.c @@ -201,7 +201,8 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, struct iovec iov; struct cmsghdr *cmsg = NULL; char buf[1] = {0}; - size_t cmsgbufsize = CMSG_SPACE(num_recvfds * sizeof(int)); + size_t cmsgbufsize = CMSG_SPACE(sizeof(struct ucred)) + + CMSG_SPACE(num_recvfds * sizeof(int)); memset(&msg, 0, sizeof(msg)); memset(&iov, 0, sizeof(iov)); @@ -224,12 +225,20 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, if (ret <= 0) goto out; - cmsg = CMSG_FIRSTHDR(&msg); - - 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)); + /* + * If SO_PASSCRED is set we will always get a ucred message. + */ + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_type != SCM_RIGHTS) + continue; + + memset(recvfds, -1, num_recvfds * sizeof(int)); + if (cmsg && + cmsg->cmsg_len == CMSG_LEN(num_recvfds * sizeof(int)) && + cmsg->cmsg_level == SOL_SOCKET) + memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int)); + break; + } out: return ret; diff --git a/src/lxc/attach.c b/src/lxc/attach.c index f2a1339d3..554a3f957 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -853,7 +853,9 @@ static int attach_child_main(struct attach_clone_payload *payload) if (init_ctx->container && init_ctx->container->lxc_conf && init_ctx->container->lxc_conf->seccomp) { - ret = lxc_seccomp_load(init_ctx->container->lxc_conf); + struct lxc_conf *conf = init_ctx->container->lxc_conf; + + ret = lxc_seccomp_load(conf); if (ret < 0) goto on_error; diff --git a/src/lxc/commands.c b/src/lxc/commands.c index ad2c578e1..ca1cde453 100644 --- a/src/lxc/commands.c +++ b/src/lxc/commands.c @@ -47,6 +47,7 @@ #include "log.h" #include "lxc.h" #include "lxclock.h" +#include "lxcseccomp.h" #include "mainloop.h" #include "memory_utils.h" #include "monitor.h" @@ -97,6 +98,7 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd) [LXC_CMD_ADD_STATE_CLIENT] = "add_state_client", [LXC_CMD_CONSOLE_LOG] = "console_log", [LXC_CMD_SERVE_STATE_CLIENTS] = "serve_state_clients", + [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = "seccomp_notify_add_listener", }; if (cmd >= LXC_CMD_MAX) @@ -244,14 +246,21 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd, if (ret < 0 || (size_t)ret != sizeof(cmd->req)) return -1; - if (cmd->req.datalen <= 0) - return move_fd(client_fd); + if (cmd->req.cmd == LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER) { + int notify_fd = PTR_TO_INT(cmd->req.data); + ret = lxc_abstract_unix_send_fds(client_fd, ¬ify_fd, 1, NULL, 0); + if (ret <= 0) + return -1; + } else { + if (cmd->req.datalen <= 0) + return move_fd(client_fd); - errno = EMSGSIZE; - ret = lxc_send_nointr(client_fd, (void *)cmd->req.data, - cmd->req.datalen, MSG_NOSIGNAL); - if (ret < 0 || ret != (ssize_t)cmd->req.datalen) - return -1; + errno = EMSGSIZE; + ret = lxc_send_nointr(client_fd, (void *)cmd->req.data, + cmd->req.datalen, MSG_NOSIGNAL); + if (ret < 0 || ret != (ssize_t)cmd->req.datalen) + return -1; + } return move_fd(client_fd); } @@ -373,7 +382,8 @@ pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath) } static int lxc_cmd_get_init_pid_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { intmax_t pid = handler->pid; @@ -407,7 +417,8 @@ int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath) } static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->ns_clone_flags) }; @@ -457,7 +468,8 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath, } static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { const char *path; struct lxc_cmd_rsp rsp; @@ -509,7 +521,8 @@ char *lxc_cmd_get_config_item(const char *name, const char *item, } static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { __do_free char *cidata = NULL; int cilen; @@ -575,7 +588,8 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath) } static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->state) }; @@ -622,7 +636,8 @@ int lxc_cmd_stop(const char *name, const char *lxcpath) } static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { struct lxc_cmd_rsp rsp; int stopsignal = SIGKILL; @@ -665,7 +680,8 @@ int lxc_cmd_terminal_winch(const char *name, const char *lxcpath) } static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { /* should never be called */ return -1; @@ -720,7 +736,8 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath) } static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { int masterfd, ret; struct lxc_cmd_rsp rsp; @@ -773,7 +790,8 @@ char *lxc_cmd_get_name(const char *hashed_sock_name) } static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { struct lxc_cmd_rsp rsp; @@ -811,7 +829,8 @@ char *lxc_cmd_get_lxcpath(const char *hashed_sock_name) } static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { struct lxc_cmd_rsp rsp; @@ -872,7 +891,8 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath, } static int lxc_cmd_add_state_client_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { int ret; struct lxc_cmd_rsp rsp = {0}; @@ -943,7 +963,8 @@ int lxc_cmd_console_log(const char *name, const char *lxcpath, } static int lxc_cmd_console_log_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { struct lxc_cmd_rsp rsp; uint64_t buffer_size = handler->conf->console.buffer_size; @@ -1002,7 +1023,8 @@ int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath, } static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { int ret; lxc_state_t state = PTR_TO_INT(req->data); @@ -1025,62 +1047,97 @@ reap_client_fd: return 1; } +int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath, + int fd, + /* unused */ unsigned int command, + /* unused */ unsigned int flags) +{ + return minus_one_set_errno(ENOSYS); +} + +static int lxc_cmd_seccomp_notify_add_listener_callback(int fd, + struct lxc_cmd_req *req, + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) +{ + struct lxc_cmd_rsp rsp = { + .ret = -ENOSYS, + }; + int ret; + + ret = lxc_cmd_rsp_send(fd, &rsp); + if (ret < 0) + goto reap_client_fd; + + return 0; + +reap_client_fd: + /* Special indicator to lxc_cmd_handler() to close the fd and do + * related cleanup. + */ + return 1; +} + static int lxc_cmd_process(int fd, struct lxc_cmd_req *req, - struct lxc_handler *handler) + struct lxc_handler *handler, + struct lxc_epoll_descr *descr) { - typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *); + typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *, + struct lxc_epoll_descr *); callback cb[LXC_CMD_MAX] = { - [LXC_CMD_CONSOLE] = lxc_cmd_console_callback, - [LXC_CMD_TERMINAL_WINCH] = lxc_cmd_terminal_winch_callback, - [LXC_CMD_STOP] = lxc_cmd_stop_callback, - [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback, - [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback, - [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback, - [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback, - [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback, - [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback, - [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback, - [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback, - [LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback, - [LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback, + [LXC_CMD_CONSOLE] = lxc_cmd_console_callback, + [LXC_CMD_TERMINAL_WINCH] = lxc_cmd_terminal_winch_callback, + [LXC_CMD_STOP] = lxc_cmd_stop_callback, + [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback, + [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback, + [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback, + [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback, + [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback, + [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback, + [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback, + [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback, + [LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback, + [LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback, + [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = lxc_cmd_seccomp_notify_add_listener_callback, }; if (req->cmd >= LXC_CMD_MAX) { ERROR("Undefined command id %d", req->cmd); return -1; } - return cb[req->cmd](fd, req, handler); + return cb[req->cmd](fd, req, handler, descr); } static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler, - struct lxc_epoll_descr *descr, - const lxc_cmd_t cmd) + struct lxc_epoll_descr *descr, const lxc_cmd_t cmd) { struct lxc_list *cur, *next; lxc_terminal_free(handler->conf, fd); lxc_mainloop_del_handler(descr, fd); - if (cmd != LXC_CMD_ADD_STATE_CLIENT) { - close(fd); - return; - } - - lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) { - struct lxc_state_client *client = cur->elem; - if (client->clientfd != fd) - continue; - - /* kick client from list */ - lxc_list_del(cur); - close(client->clientfd); - free(cur->elem); - free(cur); - /* No need to walk the whole list. If we found the state client - * fd there can't be a second one. - */ + switch (cmd) { + case LXC_CMD_ADD_STATE_CLIENT: + lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) { + struct lxc_state_client *client = cur->elem; + + if (client->clientfd != fd) + continue; + + /* kick client from list */ + lxc_list_del(cur); + close(client->clientfd); + free(cur->elem); + free(cur); + /* No need to walk the whole list. If we found the state + * client fd there can't be a second one. + */ + break; + } break; + default: + close(fd); } } @@ -1139,7 +1196,7 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data, req.data = reqdata; } - ret = lxc_cmd_process(fd, &req, handler); + ret = lxc_cmd_process(fd, &req, handler, descr); if (ret) { /* This is not an error, but only a request to close fd. */ ret = LXC_MAINLOOP_CONTINUE; diff --git a/src/lxc/commands.h b/src/lxc/commands.h index 2c024b65d..d7d0c6096 100644 --- a/src/lxc/commands.h +++ b/src/lxc/commands.h @@ -46,6 +46,7 @@ typedef enum { LXC_CMD_ADD_STATE_CLIENT, LXC_CMD_CONSOLE_LOG, LXC_CMD_SERVE_STATE_CLIENTS, + LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER, LXC_CMD_MAX, } lxc_cmd_t; @@ -124,5 +125,10 @@ extern int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr, extern int lxc_try_cmd(const char *name, const char *lxcpath); extern int lxc_cmd_console_log(const char *name, const char *lxcpath, struct lxc_console_log *log); +extern int lxc_cmd_seccomp_notify_add_listener(const char *name, + const char *lxcpath, + int fd, + /* unused */ unsigned int command, + /* unused */ unsigned int flags); #endif /* __commands_h */ diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 88997f72b..a1b76e91b 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -4948,6 +4948,28 @@ out: return ret; } +static int do_lxcapi_seccomp_notify(struct lxc_container *c, unsigned int cmd, int fd) +{ +#if HAVE_DECL_SECCOMP_NOTIF_GET_FD + if (!c || !c->lxc_conf) + return minus_one_set_errno(-EINVAL); + + switch (cmd) { + case LXC_SECCOMP_NOTIFY_GET_FD: + if (fd) + return minus_one_set_errno(EINVAL); + + return c->lxc_conf->seccomp_notify_fd; + } + + return minus_one_set_errno(EINVAL); +#else + return minus_one_set_errno(ENOSYS); +#endif +} + +WRAP_API_2(int, lxcapi_seccomp_notify, unsigned int, int) + struct lxc_container *lxc_container_new(const char *name, const char *configpath) { struct lxc_container *c; diff --git a/src/lxc/macro.h b/src/lxc/macro.h index b83e43911..7df3b56f0 100644 --- a/src/lxc/macro.h +++ b/src/lxc/macro.h @@ -407,4 +407,10 @@ enum { __internal_fd__; \ }) +#define minus_one_set_errno(__errno__) \ + ({ \ + errno = __errno__; \ + -1; \ + }) + #endif /* __LXC_MACRO_H */ diff --git a/src/lxc/start.c b/src/lxc/start.c index 6bd799a32..4f1117c6d 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -1085,6 +1085,9 @@ void lxc_abort(const char *name, struct lxc_handler *handler) static int do_start(void *data) { + struct lxc_handler *handler = data; + __do_close_prot_errno int data_sock0 = handler->data_sock[0], + data_sock1 = handler->data_sock[1]; int ret; char path[PATH_MAX]; uid_t new_uid; @@ -1093,7 +1096,6 @@ static int do_start(void *data) uid_t nsuid = 0; gid_t nsgid = 0; int devnull_fd = -1; - struct lxc_handler *handler = data; lxc_sync_fini_parent(handler); @@ -1269,8 +1271,6 @@ static int do_start(void *data) /* Setup the container, ip, names, utsname, ... */ ret = lxc_setup(handler); - close(handler->data_sock[1]); - close(handler->data_sock[0]); if (ret < 0) { ERROR("Failed to setup container \"%s\"", handler->name); goto out_warn_father; @@ -1574,6 +1574,7 @@ static inline int do_share_ns(void *arg) */ static int lxc_spawn(struct lxc_handler *handler) { + __do_close_prot_errno int data_sock0 = -EBADF, data_sock1 = -EBADF; int i, ret; char pidstr[20]; bool wants_to_map_ids; @@ -1606,6 +1607,8 @@ static int lxc_spawn(struct lxc_handler *handler) handler->data_sock); if (ret < 0) goto out_sync_fini; + data_sock0 = handler->data_sock[0]; + data_sock1 = handler->data_sock[1]; ret = resolve_clone_flags(handler); if (ret < 0) @@ -1962,11 +1965,6 @@ int __lxc_start(const char *name, struct lxc_handler *handler, ERROR("Failed to spawn container \"%s\"", name); goto out_detach_blockdev; } - /* close parent side of data socket */ - close(handler->data_sock[0]); - handler->data_sock[0] = -1; - close(handler->data_sock[1]); - handler->data_sock[1] = -1; handler->conf->reboot = REBOOT_NONE;