]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fs: allow mount namespace fd
authorChristian Brauner <brauner@kernel.org>
Fri, 19 Jul 2024 11:41:49 +0000 (13:41 +0200)
committerChristian Brauner <brauner@kernel.org>
Fri, 9 Aug 2024 10:44:49 +0000 (12:44 +0200)
We already allow a mount namespace id, enable mount namespace file
descriptors as well.

Link: https://lore.kernel.org/r/20240719-work-mount-namespace-v1-2-834113cab0d2@kernel.org
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/namespace.c

index 221db9de472967132a682097e213ebec642df486..1a0b9e3089a275d7ece4bc49f07c72a551777466 100644 (file)
@@ -5243,12 +5243,37 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req,
  * that, or if not simply grab a passive reference on our mount namespace and
  * return that.
  */
-static struct mnt_namespace *grab_requested_mnt_ns(u64 mnt_ns_id)
+static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq)
 {
-       if (mnt_ns_id)
-               return lookup_mnt_ns(mnt_ns_id);
-       refcount_inc(&current->nsproxy->mnt_ns->passive);
-       return current->nsproxy->mnt_ns;
+       struct mnt_namespace *mnt_ns;
+
+       if (kreq->mnt_ns_id && kreq->spare)
+               return ERR_PTR(-EINVAL);
+
+       if (kreq->mnt_ns_id)
+               return lookup_mnt_ns(kreq->mnt_ns_id);
+
+       if (kreq->spare) {
+               struct ns_common *ns;
+
+               CLASS(fd, f)(kreq->spare);
+               if (!f.file)
+                       return ERR_PTR(-EBADF);
+
+               if (!proc_ns_file(f.file))
+                       return ERR_PTR(-EINVAL);
+
+               ns = get_proc_ns(file_inode(f.file));
+               if (ns->ops->type != CLONE_NEWNS)
+                       return ERR_PTR(-EINVAL);
+
+               mnt_ns = to_mnt_ns(ns);
+       } else {
+               mnt_ns = current->nsproxy->mnt_ns;
+       }
+
+       refcount_inc(&mnt_ns->passive);
+       return mnt_ns;
 }
 
 SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
@@ -5269,7 +5294,7 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
        if (ret)
                return ret;
 
-       ns = grab_requested_mnt_ns(kreq.mnt_ns_id);
+       ns = grab_requested_mnt_ns(&kreq);
        if (!ns)
                return -ENOENT;
 
@@ -5396,7 +5421,7 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req,
        if (!kmnt_ids)
                return -ENOMEM;
 
-       ns = grab_requested_mnt_ns(kreq.mnt_ns_id);
+       ns = grab_requested_mnt_ns(&kreq);
        if (!ns)
                return -ENOENT;