From: Christian Brauner Date: Wed, 3 Feb 2021 20:31:03 +0000 (+0100) Subject: conf: refactor transient procfs mounting X-Git-Tag: lxc-5.0.0~302^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=952b5031b78b5de0716a6c4de6f35b81eb334d98;p=thirdparty%2Flxc.git conf: refactor transient procfs mounting Signed-off-by: Christian Brauner --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 1bf33a78d..893485de2 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2643,8 +2643,7 @@ struct lxc_conf *lxc_conf_init(void) new->lsm_se_context = NULL; new->lsm_se_keyring_context = NULL; new->keyring_disable_session = false; - new->tmp_umount_proc = false; - new->tmp_umount_proc = 0; + new->transient_procfs_mnt = false; new->shmount.path_host = NULL; new->shmount.path_cont = NULL; @@ -2957,69 +2956,68 @@ again: * my own. This is needed to have a known-good proc mount for setting * up LSMs both at container startup and attach. * - * @rootfs : the rootfs where proc should be mounted - * - * Returns < 0 on failure, 0 if the correct proc was already mounted - * and 1 if a new proc was mounted. - * * NOTE: not to be called from inside the container namespace! */ -static int lxc_mount_proc_if_needed(const char *rootfs) +static int lxc_transient_proc(struct lxc_rootfs *rootfs) { - char path[PATH_MAX] = {0}; - int link_to_pid, linklen, mypid, ret; - char link[INTTYPE_TO_STRLEN(pid_t)] = {0}; + __do_close int fd_proc = -EBADF; + int link_to_pid, link_len, pid_self, ret; + char link[INTTYPE_TO_STRLEN(pid_t) + 1]; - ret = snprintf(path, PATH_MAX, "%s/proc/self", rootfs); - if (ret < 0 || ret >= PATH_MAX) { - SYSERROR("The name of proc path is too long"); - return -1; - } - - linklen = readlink(path, link, sizeof(link)); + link_len = readlinkat(rootfs->mntpt_fd, "proc/self", link, sizeof(link)); + if (link_len < 0) { + ret = mkdirat(rootfs->mntpt_fd, "proc", 0000); + if (ret < 0 && errno != EEXIST) + return log_error_errno(-errno, errno, "Failed to create %d(proc)", rootfs->mntpt_fd); - ret = snprintf(path, PATH_MAX, "%s/proc", rootfs); - if (ret < 0 || ret >= PATH_MAX) { - SYSERROR("The name of proc path is too long"); - return -1; + goto domount; + } else if (link_len >= sizeof(link)) { + return log_error_errno(-EIO, EIO, "Truncated link target"); } + link[link_len] = '\0'; - /* /proc not mounted */ - if (linklen < 0) { - if (mkdir(path, 0755) && errno != EEXIST) - return -1; + pid_self = lxc_raw_getpid(); + INFO("Caller's PID is %d; /proc/self points to %s", pid_self, link); - goto domount; - } else if (linklen >= sizeof(link)) { - link[linklen - 1] = '\0'; - ERROR("Readlink returned truncated content: \"%s\"", link); - return -1; - } + ret = lxc_safe_int(link, &link_to_pid); + if (ret) + return log_error_errno(-ret, ret, "Failed to parse %s", link); - mypid = lxc_raw_getpid(); - INFO("I am %d, /proc/self points to \"%s\"", mypid, link); + /* Correct procfs is already mounted. */ + if (link_to_pid == pid_self) + return log_trace(0, "Correct procfs instance mounted"); - if (lxc_safe_int(link, &link_to_pid) < 0) - return -1; + fd_proc = open_at(rootfs->mntpt_fd, "proc", PROTECT_OPATH_DIRECTORY, + PROTECT_LOOKUP_BENEATH_XDEV, 0); + if (fd_proc < 0) + return log_error_errno(-errno, errno, "Failed to open transient procfs mountpoint"); - /* correct procfs is already mounted */ - if (link_to_pid == mypid) - return 0; + ret = snprintf(rootfs->buf, sizeof(rootfs->buf), "/proc/self/fd/%d", fd_proc); + if (ret < 0 || (size_t)ret >= sizeof(rootfs->buf)) + return ret_errno(EIO); - ret = umount2(path, MNT_DETACH); + ret = umount2(rootfs->buf, MNT_DETACH); if (ret < 0) - SYSWARN("Failed to umount \"%s\" with MNT_DETACH", path); + SYSWARN("Failed to umount \"%s\" with MNT_DETACH", rootfs->buf); domount: /* rootfs is NULL */ - if (!strcmp(rootfs, "")) - ret = mount("proc", path, "proc", 0, NULL); - else - ret = safe_mount("proc", path, "proc", 0, NULL, rootfs); + if (!rootfs->path) { + ret = mount("proc", rootfs->buf, "proc", 0, NULL); + } else { + ret = safe_mount_beneath_at(rootfs->mntpt_fd, "none", "proc", "proc", 0, NULL); + if (ret < 0) { + ret = snprintf(rootfs->buf, sizeof(rootfs->buf), "%s/proc", rootfs->path ? rootfs->mount : ""); + if (ret < 0 || (size_t)ret >= sizeof(rootfs->buf)) + return ret_errno(EIO); + + ret = safe_mount("proc", rootfs->buf, "proc", 0, NULL, rootfs->mount); + } + } if (ret < 0) - return -1; + return log_error_errno(-1, errno, "Failed to mount temporary procfs"); - INFO("Mounted /proc in container for security transition"); + INFO("Created transient procfs mount"); return 1; } @@ -3028,14 +3026,13 @@ static int lxc_create_tmp_proc_mount(struct lxc_conf *conf) { int mounted; - mounted = lxc_mount_proc_if_needed(conf->rootfs.path ? conf->rootfs.mount : ""); + mounted = lxc_transient_proc(&conf->rootfs); if (mounted == -1) { - SYSERROR("Failed to mount proc in the container"); /* continue only if there is no rootfs */ if (conf->rootfs.path) - return -1; + return log_error_errno(-EPERM, EPERM, "Failed to create transient procfs mount"); } else if (mounted == 1) { - conf->tmp_umount_proc = true; + conf->transient_procfs_mnt = true; } return 0; @@ -3043,11 +3040,10 @@ static int lxc_create_tmp_proc_mount(struct lxc_conf *conf) void tmp_proc_unmount(struct lxc_conf *lxc_conf) { - if (!lxc_conf->tmp_umount_proc) - return; - - (void)umount2("/proc", MNT_DETACH); - lxc_conf->tmp_umount_proc = false; + if (lxc_conf->transient_procfs_mnt) { + (void)umount2("/proc", MNT_DETACH); + lxc_conf->transient_procfs_mnt = false; + } } /* Walk /proc/mounts and change any shared entries to dependent mounts. */ diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 2fd9b783d..ab0a2bacc 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -183,6 +183,7 @@ struct lxc_tty_info { * optionals pivot_root, rootfs mount paths * @path : the rootfs source (directory or device) * @mount : where it is mounted + * @buf : static buffer to construct paths * @bev_type : optional backing store type * @options : mount options * @mountflags : the portion of @options that are flags @@ -196,6 +197,7 @@ struct lxc_rootfs { int dev_mntpt_fd; char *path; char *mount; + char buf[PATH_MAX]; char *bdev_type; char *options; unsigned long mountflags; @@ -360,7 +362,7 @@ struct lxc_conf { char *lsm_se_context; char *lsm_se_keyring_context; bool keyring_disable_session; - bool tmp_umount_proc; + bool transient_procfs_mnt; struct lxc_seccomp seccomp; int maincmd_fd; unsigned int autodev; /* if 1, mount and fill a /dev at start */