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,
};
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;
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)
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;
}