]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf: refactor transient procfs mounting
authorChristian Brauner <christian.brauner@ubuntu.com>
Wed, 3 Feb 2021 20:31:03 +0000 (21:31 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Wed, 3 Feb 2021 20:54:52 +0000 (21:54 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/conf.c
src/lxc/conf.h

index 1bf33a78d30f985982940d5cc1f9e28456d5ffa6..893485de2ab0705c49da29339b13f683c1f393fe 100644 (file)
@@ -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. */
index 2fd9b783df4cc15fc5de0627a22be074357f2c4c..ab0a2bacca8323beb095d0f14d9ff9bd2b71b035 100644 (file)
@@ -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 */