From: Namjae Jeon Date: Mon, 6 Jul 2026 03:00:00 +0000 (+0900) Subject: ntfs: sanitize MFT references returned from ntfs_lookup_inode_by_name() X-Git-Tag: v7.2-rc3~20^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d97a36bae86a9a4021562ded2987f904e6bcb1d7;p=thirdparty%2Fkernel%2Flinux.git ntfs: sanitize MFT references returned from ntfs_lookup_inode_by_name() ntfs_lookup_inode_by_name() returns MFT references read from directory index entries on disk. These values are untrusted, but the function can currently return an error-marked MFT reference to its callers without validating it. Callers later decode lookup failures with MREF_ERR(). A crafted NTFS image can set the MREF error bit while leaving the low bits as an arbitrary value, causing callers to consume a bogus pseudo-errno instead of treating the lookup result as corrupted on-disk metadata. Fix this at the source by normalizing every error-marked MFT reference returned from ntfs_lookup_inode_by_name() to ERR_MREF(-EIO). Apply this to all four directory lookup return paths so every caller gets a validated result without needing additional checks or an API change. This keeps the sanitization in the common lookup helper, which is cleaner than duplicating validation in each caller. Fixes: 1e9ea7e04472 ("Revert "fs: Remove NTFS classic"") Cc: stable@vger.kernel.org Reported-by: Hongling Zeng Signed-off-by: Namjae Jeon --- diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index 4b6bd5f30c65..6fa9ae3377cb 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c @@ -23,6 +23,13 @@ __le16 I30[5] = { cpu_to_le16('$'), cpu_to_le16('I'), cpu_to_le16('3'), cpu_to_le16('0'), 0 }; +static inline u64 ntfs_check_mref(u64 mref) +{ + if (IS_ERR_MREF(mref)) + return ERR_MREF(-EIO); + return mref; +} + /* * ntfs_lookup_inode_by_name - find an inode in a directory given its name * @dir_ni: ntfs inode of the directory in which to search for the name @@ -178,7 +185,7 @@ found_it: mref = le64_to_cpu(ie->data.dir.indexed_file); ntfs_attr_put_search_ctx(ctx); unmap_mft_record(dir_ni); - return mref; + return ntfs_check_mref(mref); } /* * For a case insensitive mount, we also perform a case @@ -273,7 +280,7 @@ found_it: if (name) { ntfs_attr_put_search_ctx(ctx); unmap_mft_record(dir_ni); - return name->mref; + return ntfs_check_mref(name->mref); } ntfs_debug("Entry not found."); err = -ENOENT; @@ -413,7 +420,7 @@ found_it2: mref = le64_to_cpu(ie->data.dir.indexed_file); kfree(kaddr); iput(ia_vi); - return mref; + return ntfs_check_mref(mref); } /* * For a case insensitive mount, we also perform a case @@ -538,7 +545,7 @@ found_it2: if (name) { kfree(kaddr); iput(ia_vi); - return name->mref; + return ntfs_check_mref(name->mref); } ntfs_debug("Entry not found."); err = -ENOENT;