All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dennis Tighe <dennis.tighe@gmail.com>
To: Namjae Jeon <linkinjeon@kernel.org>, Hyunchul Lee <hyc.lee@gmail.com>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] ntfs: prevent out-of-bounds write from a corrupt runlist
Date: Fri, 14 Aug 2026 23:41:46 -0700	[thread overview]
Message-ID: <bcdd72e1-707c-4bcd-94cc-572ba781d00a@gmail.com> (raw)

For the cluster bitmap ($Bitmap), __ntfs_bitmap_set_bits_in_run() uses a
cluster number as an index into vol->lcn_empty_bits_per_page[] via
ntfs_set_lcn_empty_bits(), with no upper bound on the index.  On the
deallocation path that cluster number is read from an on-disk runlist, so a
corrupted runlist naming a cluster beyond the end of the volume writes past
the end of the array into adjacent memory when a file is freed.

Reject cluster ranges outside the volume before updating the array,
mirroring the nr_clusters check already used in ntfs_trim_fs().

Fixes: 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Dennis Tighe <dennis.tighe@gmail.com>
---
  fs/ntfs/bitmap.c | 15 +++++++++++++++
  1 file changed, 15 insertions(+)

diff --git a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c
index b1436b3..fb65bce 100644
--- a/fs/ntfs/bitmap.c
+++ b/fs/ntfs/bitmap.c
@@ -138,6 +138,21 @@ int __ntfs_bitmap_set_bits_in_run(struct inode *vi, 
const s64 start_bit,
      if (start_bit < 0 || cnt < 0 || value > 1)
          return -EINVAL;

+    /*
+     * For $Bitmap, @start_bit is a cluster number that comes from an
+     * on-disk runlist on the free path.  A corrupt runlist can name a
+     * cluster past the end of the volume and index
+     * vol->lcn_empty_bits_per_page[] out of bounds below, so reject it.
+     */
+    if (ni->mft_no == FILE_Bitmap &&
+        (start_bit >= vol->nr_clusters || cnt > vol->nr_clusters - 
start_bit)) {
+        ntfs_error(vi->i_sb,
+               "Cluster range (0x%llx+0x%llx) outside volume 0x%llx; 
corrupt runlist.",
+               (unsigned long long)start_bit, (unsigned long long)cnt,
+               (unsigned long long)vol->nr_clusters);
+        return -EIO;
+    }
+
      /*
       * Calculate the indices for the pages containing the first and last
       * bits, i.e. @start_bit and @start_bit + @cnt - 1, respectively.
-- 
2.47.3


                 reply	other threads:[~2026-08-15  6:41 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bcdd72e1-707c-4bcd-94cc-572ba781d00a@gmail.com \
    --to=dennis.tighe@gmail.com \
    --cc=hyc.lee@gmail.com \
    --cc=linkinjeon@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.