]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
statmount: don't call path_put() under namespace semaphore
authorChristian Brauner <brauner@kernel.org>
Fri, 19 Sep 2025 15:03:51 +0000 (17:03 +0200)
committerChristian Brauner <brauner@kernel.org>
Fri, 26 Sep 2025 08:16:06 +0000 (10:16 +0200)
Massage statmount() and make sure we don't call path_put() under the
namespace semaphore. If we put the last reference we're fscked.

Fixes: 46eae99ef733 ("add statmount(2) syscall")
Cc: stable@vger.kernel.org # v6.8+
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/namespace.c

index ba3e5215b6362d3c592b3f016a79cc1e415e95d7..993983a768536110e4cd133ae9c4812522cfb0ed 100644 (file)
@@ -5708,7 +5708,6 @@ static int grab_requested_root(struct mnt_namespace *ns, struct path *root)
 static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
                        struct mnt_namespace *ns)
 {
-       struct path root __free(path_put) = {};
        struct mount *m;
        int err;
 
@@ -5720,7 +5719,7 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
        if (!s->mnt)
                return -ENOENT;
 
-       err = grab_requested_root(ns, &root);
+       err = grab_requested_root(ns, &s->root);
        if (err)
                return err;
 
@@ -5729,7 +5728,7 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
         * mounts to show users.
         */
        m = real_mount(s->mnt);
-       if (!is_path_reachable(m, m->mnt.mnt_root, &root) &&
+       if (!is_path_reachable(m, m->mnt.mnt_root, &s->root) &&
            !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
                return -EPERM;
 
@@ -5737,8 +5736,6 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id,
        if (err)
                return err;
 
-       s->root = root;
-
        /*
         * Note that mount properties in mnt->mnt_flags, mnt->mnt_idmap
         * can change concurrently as we only hold the read-side of the
@@ -5960,6 +5957,7 @@ retry:
        if (!ret)
                ret = copy_statmount_to_user(ks);
        kvfree(ks->seq.buf);
+       path_put(&ks->root);
        if (retry_statmount(ret, &seq_size))
                goto retry;
        return ret;