]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fs/ntfs3: add depth limit to indx_find_buffer to prevent stack overflow
authorMichael Bommarito <michael.bommarito@gmail.com>
Mon, 13 Apr 2026 13:31:17 +0000 (09:31 -0400)
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Thu, 30 Apr 2026 11:55:07 +0000 (13:55 +0200)
indx_find_buffer() recursively descends the B+ tree index with no depth
limit.  A crafted NTFS image with circular index node references causes
unbounded recursion, overflowing the kernel stack and panicking the
system.

This is reachable by mounting a malicious NTFS filesystem (e.g. from a
USB drive via desktop automount) and deleting a file whose index entry
triggers the rebalancing fallback path in indx_delete_entry().

Add a depth parameter and bail out with -EINVAL when it reaches the
fnd->nodes array bound, matching the constraint already enforced by
fnd_push() in indx_find().

The related function indx_find() was previously patched for a similar
infinite-loop issue (commit 1732053c8a6b), but indx_find_buffer() was
missed.

Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-6
Assisted-by: Codex:gpt-5-4
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3/index.c

index 5344b29b0577f53c592e7b1a585ae39df38823e3..dbf5ec00b2376f7d4f986e03e6433ec50f2ee32f 100644 (file)
@@ -2022,13 +2022,21 @@ out1:
 static struct indx_node *indx_find_buffer(struct ntfs_index *indx,
                                          struct ntfs_inode *ni,
                                          const struct INDEX_ROOT *root,
-                                         __le64 vbn, struct indx_node *n)
+                                         __le64 vbn, struct indx_node *n,
+                                         int depth)
 {
        int err;
        const struct NTFS_DE *e;
        struct indx_node *r;
        const struct INDEX_HDR *hdr = n ? &n->index->ihdr : &root->ihdr;
 
+       /*
+        * Limit recursion depth to prevent stack overflow from crafted
+        * images.  Use the same bound as the fnd->nodes array (20).
+        */
+       if (depth > ARRAY_SIZE(((struct ntfs_fnd *)NULL)->nodes))
+               return ERR_PTR(-EINVAL);
+
        /* Step 1: Scan one level. */
        for (e = hdr_first_de(hdr);; e = hdr_next_de(hdr, e)) {
                if (!e)
@@ -2049,7 +2057,8 @@ static struct indx_node *indx_find_buffer(struct ntfs_index *indx,
                        if (err)
                                return ERR_PTR(err);
 
-                       r = indx_find_buffer(indx, ni, root, vbn, n);
+                       r = indx_find_buffer(indx, ni, root, vbn, n,
+                                            depth + 1);
                        if (r)
                                return r;
                }
@@ -2462,7 +2471,7 @@ int indx_delete_entry(struct ntfs_index *indx, struct ntfs_inode *ni,
 
                fnd_clear(fnd);
 
-               in = indx_find_buffer(indx, ni, root, sub_vbn, NULL);
+               in = indx_find_buffer(indx, ni, root, sub_vbn, NULL, 0);
                if (IS_ERR(in)) {
                        err = PTR_ERR(in);
                        goto out;