From: Christian Brauner Date: Mon, 22 Feb 2021 21:45:36 +0000 (+0100) Subject: cgroups: allow cgroup fd batch retrieval X-Git-Tag: lxc-5.0.0~273^2~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2092492ca613349a88aeb6199126fc610bf43ecf;p=thirdparty%2Flxc.git cgroups: allow cgroup fd batch retrieval Signed-off-by: Christian Brauner --- diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index 22b7f4fe9..a20b9d1c9 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -3345,23 +3345,14 @@ struct cgroup_ops *cgroup_ops_init(struct lxc_conf *conf) return move_ptr(cgfsng_ops); } -int cgroup_attach(const struct lxc_conf *conf, const char *name, - const char *lxcpath, pid_t pid) +static int __unified_attach_fd(const struct lxc_conf *conf, int fd_unified, pid_t pid) { - __do_close int unified_fd = -EBADF; int ret; - if (!conf || is_empty_string(name) || is_empty_string(lxcpath) || pid <= 0) - return ret_errno(EINVAL); - - unified_fd = lxc_cmd_get_cgroup2_fd(name, lxcpath); - if (unified_fd < 0) - return ret_errno(ENOCGROUP2); - if (!lxc_list_empty(&conf->id_map)) { struct userns_exec_unified_attach_data args = { .conf = conf, - .unified_fd = unified_fd, + .unified_fd = fd_unified, .pid = pid, }; @@ -3375,7 +3366,70 @@ int cgroup_attach(const struct lxc_conf *conf, const char *name, cgroup_unified_attach_child_wrapper, &args); } else { - ret = cgroup_attach_leaf(conf, unified_fd, pid); + ret = cgroup_attach_leaf(conf, fd_unified, pid); + } + + return ret; +} + +static int __cgroup_attach_many(const struct lxc_conf *conf, const char *name, + const char *lxcpath, pid_t pid) +{ + call_cleaner(put_unix_fds) struct unix_fds *fds = &(struct unix_fds){}; + int ret; + char pidstr[INTTYPE_TO_STRLEN(pid_t)]; + ssize_t pidstr_len; + + ret = lxc_cmd_get_cgroup_fd(name, lxcpath, NULL, true, fds); + if (ret < 0) + return ret_errno(ENOSYS); + + pidstr_len = strnprintf(pidstr, sizeof(pidstr), "%d", pid); + if (pidstr_len < 0) + return pidstr_len; + + for (size_t idx = 0; idx < fds->fd_count_ret; idx++) { + int dfd_con = fds->fd[idx]; + + if (unified_cgroup_fd(dfd_con)) + ret = __unified_attach_fd(conf, dfd_con, pid); + else + ret = lxc_writeat(dfd_con, "cgroup.procs", pidstr, pidstr_len); + if (ret) + return syserrno(ret, "Failed to attach to cgroup fd %d", dfd_con); + else + TRACE("Attached to cgroup fd %d", dfd_con); + } + + return log_trace(0, "Attached to cgroups"); +} + +static int __cgroup_attach_unified(const struct lxc_conf *conf, const char *name, + const char *lxcpath, pid_t pid) +{ + __do_close int dfd_unified = -EBADF; + + if (!conf || is_empty_string(name) || is_empty_string(lxcpath) || pid <= 0) + return ret_errno(EINVAL); + + dfd_unified = lxc_cmd_get_cgroup2_fd(name, lxcpath); + if (dfd_unified < 0) + return ret_errno(ENOCGROUP2); + + return __unified_attach_fd(conf, dfd_unified, pid); +} + +int cgroup_attach(const struct lxc_conf *conf, const char *name, + const char *lxcpath, pid_t pid) +{ + int ret; + + ret = __cgroup_attach_many(conf, name, lxcpath, pid); + if (ret < 0) { + if (ret != ENOSYS) + return ret; + + ret = __cgroup_attach_unified(conf, name, lxcpath, pid); } return ret; diff --git a/src/lxc/commands.c b/src/lxc/commands.c index 787565a8b..cb26f6831 100644 --- a/src/lxc/commands.c +++ b/src/lxc/commands.c @@ -166,25 +166,25 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd) rsp->data = rspdata; } - if (cmd->req.cmd == LXC_CMD_GET_CGROUP2_FD || - cmd->req.cmd == LXC_CMD_GET_LIMITING_CGROUP2_FD) { - int cgroup2_fd = move_fd(fds->fd[0]); - rsp->data = INT_TO_PTR(cgroup2_fd); - } - - if (cmd->req.cmd == LXC_CMD_GET_INIT_PIDFD) { - int init_pidfd = move_fd(fds->fd[0]); - rsp->data = INT_TO_PTR(init_pidfd); - } - - if (cmd->req.cmd == LXC_CMD_GET_DEVPTS_FD) { - int devpts_fd = move_fd(fds->fd[0]); - rsp->data = INT_TO_PTR(devpts_fd); - } - - if (cmd->req.cmd == LXC_CMD_GET_SECCOMP_NOTIFY_FD) { - int seccomp_notify_fd = move_fd(fds->fd[0]); - rsp->data = INT_TO_PTR(seccomp_notify_fd); + switch (cmd->req.cmd) { + case LXC_CMD_GET_CGROUP2_FD: + __fallthrough; + case LXC_CMD_GET_LIMITING_CGROUP2_FD: + __fallthrough; + case LXC_CMD_GET_INIT_PIDFD: + __fallthrough; + case LXC_CMD_GET_DEVPTS_FD: + __fallthrough; + case LXC_CMD_GET_SECCOMP_NOTIFY_FD: + rsp->data = INT_TO_PTR(move_fd(fds->fd[0])); + return log_debug(ret, "Finished processing \"%s\"", lxc_cmd_str(cmd->req.cmd)); + case LXC_CMD_GET_CGROUP_FD: + rsp->data = move_ptr(fds); + rsp->datalen = sizeof(struct unix_fds); + return log_debug(ret, "Finished processing \"%s\"", lxc_cmd_str(cmd->req.cmd)); + break; + default: + break; } if (rsp->datalen == 0) @@ -594,6 +594,8 @@ int lxc_cmd_get_cgroup_fd(const char *name, const char *lxcpath, if (cmd.rsp.ret < 0) return log_debug_errno(-EBADF, errno, "Failed to receive cgroup fds"); + *ret_fds = *(struct unix_fds *)cmd.rsp.data; + return 0; }