]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
cgroups: allow cgroup fd batch retrieval
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 22 Feb 2021 21:45:36 +0000 (22:45 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 23 Feb 2021 15:15:31 +0000 (16:15 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/cgroups/cgfsng.c
src/lxc/commands.c

index 22b7f4fe99bc56e1d1c28aba8cb74891ebf4aa49..a20b9d1c98c12435a5695742954077716861b66f 100644 (file)
@@ -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;
index 787565a8b206617672a663bf3f0f9377a9688de1..cb26f68317e3257952df2a7454803433142abd7a 100644 (file)
@@ -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;
 }