From 25c659d5000190c1d96b36a8ed935181fc99e65d Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 29 Jan 2021 15:13:51 +0100 Subject: [PATCH] attach: move to file descriptor only namespace interactions Signed-off-by: Christian Brauner --- src/lxc/attach.c | 67 +++++++++++++++++++++++---------------------- src/lxc/namespace.c | 16 +++++------ src/lxc/namespace.h | 1 + 3 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 4ac4979b6..ea9a018b9 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -58,7 +58,8 @@ static lxc_attach_options_t attach_static_default_options = LXC_ATTACH_OPTIONS_D struct attach_context { int init_pid; - int dfd_pid; + int dfd_init_pid; + int dfd_self_pid; char *lsm_label; struct lxc_container *container; signed long personality; @@ -116,7 +117,7 @@ static int get_personality(const char *name, const char *lxcpath, static int get_attach_context(struct attach_context *ctx, struct lxc_container *container) { - __do_close int fd_status = -EBADF; + __do_close int dfd_self_pid = -EBADF, dfd_init_pid = -EBADF, fd_status = -EBADF; __do_free char *line = NULL; __do_fclose FILE *f_status = NULL; int ret; @@ -130,15 +131,23 @@ static int get_attach_context(struct attach_context *ctx, if (ctx->init_pid < 0) return log_error(-1, "Failed to get init pid"); + ret = snprintf(path, sizeof(path), "/proc/%d", lxc_raw_getpid()); + if (ret < 0 || ret >= sizeof(path)) + return ret_errno(EIO); + + dfd_self_pid = openat(-EBADF, path, O_CLOEXEC | O_NOCTTY | O_NOFOLLOW | O_PATH | O_DIRECTORY); + if (dfd_self_pid < 0) + return -errno; + ret = snprintf(path, sizeof(path), "/proc/%d", ctx->init_pid); if (ret < 0 || ret >= sizeof(path)) return ret_errno(EIO); - ctx->dfd_pid = openat(-EBADF, path, O_CLOEXEC | O_NOCTTY | O_NOFOLLOW | O_PATH | O_DIRECTORY); - if (ctx->dfd_pid < 0) + dfd_init_pid = openat(-EBADF, path, O_CLOEXEC | O_NOCTTY | O_NOFOLLOW | O_PATH | O_DIRECTORY); + if (dfd_init_pid < 0) return -errno; - fd_status = openat(ctx->dfd_pid, "status", O_CLOEXEC | O_NOCTTY | O_NOFOLLOW | O_RDONLY); + fd_status = openat(dfd_init_pid, "status", O_CLOEXEC | O_NOCTTY | O_NOFOLLOW | O_RDONLY); if (fd_status < 0) return -errno; @@ -162,6 +171,7 @@ static int get_attach_context(struct attach_context *ctx, ctx->lsm_ops = lsm_init_static(); + /* Move to file descriptor-only lsm label retrieval. */ ctx->lsm_label = ctx->lsm_ops->process_label_get(ctx->lsm_ops, ctx->init_pid); ctx->ns_inherited = 0; for (int i = 0; i < LXC_NS_MAX; i++) @@ -177,38 +187,27 @@ static int get_attach_context(struct attach_context *ctx, return log_error_errno(-ENOMEM, ENOMEM, "Failed to allocate new lxc config"); } + ctx->dfd_init_pid = move_fd(dfd_init_pid); + ctx->dfd_self_pid = move_fd(dfd_self_pid); return 0; } -/** - * in_same_namespace - Check whether two processes are in the same namespace. - * @pid1 - PID of the first process. - * @pid2 - PID of the second process. - * @ns - Name of the namespace to check. Must correspond to one of the names - * for the namespaces as shown in /proc/namespaces & ns_info[i].clone_flag) - ctx->ns_fd[i] = lxc_preserve_ns(ctx->init_pid, ns_info[i].proc_name); + ctx->ns_fd[i] = openat(ctx->dfd_init_pid, ns_info[i].proc_path, O_CLOEXEC | O_NOCTTY | O_RDONLY); else if (ctx->ns_inherited & ns_info[i].clone_flag) - ctx->ns_fd[i] = in_same_namespace(pid_self, ctx->init_pid, ns_info[i].proc_name); + ctx->ns_fd[i] = in_same_namespace(ctx->dfd_self_pid, ctx->dfd_init_pid, ns_info[i].proc_path); else continue; @@ -248,13 +245,13 @@ static int get_attach_context_nsfds(struct attach_context *ctx, continue; if (ctx->ns_fd[i] == -EINVAL) { - DEBUG("Inheriting %s namespace from %d", ns_info[i].proc_name, pid_self); + DEBUG("Inheriting %s namespace", ns_info[i].proc_name); ctx->ns_inherited &= ~ns_info[i].clone_flag; continue; } /* We failed to preserve the namespace. */ - SYSERROR("Failed to attach to %s namespace of %d", ns_info[i].proc_name, pid_self); + SYSERROR("Failed to preserve %s namespace of %d", ns_info[i].proc_name, ctx->init_pid); /* Close all already opened file descriptors before we return an * error, so we don't leak them. @@ -278,7 +275,7 @@ static void put_attach_context(struct attach_context *ctx) { if (ctx) { free_disarm(ctx->lsm_label); - close_prot_errno_disarm(ctx->dfd_pid); + close_prot_errno_disarm(ctx->dfd_init_pid); if (ctx->container) { lxc_container_put(ctx->container); @@ -318,9 +315,13 @@ static int attach_context_container(struct attach_context *ctx) static bool attach_context_security_barrier(struct attach_context *ctx) { if (ctx) { - if (close(ctx->dfd_pid)) + if (close(ctx->dfd_self_pid)) + return false; + ctx->dfd_self_pid = -EBADF; + + if (close(ctx->dfd_init_pid)) return false; - ctx->dfd_pid = -EBADF; + ctx->dfd_init_pid = -EBADF; } return true; diff --git a/src/lxc/namespace.c b/src/lxc/namespace.c index a46923078..5a1b3206c 100644 --- a/src/lxc/namespace.c +++ b/src/lxc/namespace.c @@ -38,14 +38,14 @@ lxc_log_define(namespace, lxc); * linux/fs/namespace.c:mntns_install(). */ const struct ns_info ns_info[LXC_NS_MAX] = { - [LXC_NS_USER] = { "user", CLONE_NEWUSER, "CLONE_NEWUSER", "LXC_USER_NS" }, - [LXC_NS_MNT] = { "mnt", CLONE_NEWNS, "CLONE_NEWNS", "LXC_MNT_NS" }, - [LXC_NS_PID] = { "pid", CLONE_NEWPID, "CLONE_NEWPID", "LXC_PID_NS" }, - [LXC_NS_UTS] = { "uts", CLONE_NEWUTS, "CLONE_NEWUTS", "LXC_UTS_NS" }, - [LXC_NS_IPC] = { "ipc", CLONE_NEWIPC, "CLONE_NEWIPC", "LXC_IPC_NS" }, - [LXC_NS_NET] = { "net", CLONE_NEWNET, "CLONE_NEWNET", "LXC_NET_NS" }, - [LXC_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP", "LXC_CGROUP_NS" }, - [LXC_NS_TIME] = { "time", CLONE_NEWTIME, "CLONE_NEWTIME", "LXC_TIME_NS" }, + [LXC_NS_USER] = { "user", "ns/user", CLONE_NEWUSER, "CLONE_NEWUSER", "LXC_USER_NS" }, + [LXC_NS_MNT] = { "mnt", "ns/mnt", CLONE_NEWNS, "CLONE_NEWNS", "LXC_MNT_NS" }, + [LXC_NS_PID] = { "pid", "ns/pid", CLONE_NEWPID, "CLONE_NEWPID", "LXC_PID_NS" }, + [LXC_NS_UTS] = { "uts", "ns/uts", CLONE_NEWUTS, "CLONE_NEWUTS", "LXC_UTS_NS" }, + [LXC_NS_IPC] = { "ipc", "ns/ipc", CLONE_NEWIPC, "CLONE_NEWIPC", "LXC_IPC_NS" }, + [LXC_NS_NET] = { "net", "ns/net", CLONE_NEWNET, "CLONE_NEWNET", "LXC_NET_NS" }, + [LXC_NS_CGROUP] = { "cgroup", "ns/cgroup", CLONE_NEWCGROUP, "CLONE_NEWCGROUP", "LXC_CGROUP_NS" }, + [LXC_NS_TIME] = { "time", "ns/time", CLONE_NEWTIME, "CLONE_NEWTIME", "LXC_TIME_NS" }, }; int lxc_namespace_2_cloneflag(const char *namespace) diff --git a/src/lxc/namespace.h b/src/lxc/namespace.h index 4e3fc3dfc..6dd83be14 100644 --- a/src/lxc/namespace.h +++ b/src/lxc/namespace.h @@ -23,6 +23,7 @@ enum { __hidden extern const struct ns_info { const char *proc_name; + const char *proc_path; int clone_flag; const char *flag_name; const char *env_name; -- 2.47.2