[PATCH] ntfs: validate error codes from untrusted disk data

From: Hongling Zeng

Date: Tue Jun 30 2026 - 02:04:14 EST


ntfs_lookup_ino_by_name() returns MFT references read directly from
disk, which are untrusted data. The current code extracts error codes
via MREF_ERR() without proper validation, allowing maliciously crafted
NTFS images to trigger kernel panic.

The MFT reference encoding uses bit 47 as an error indicator, but the
lower 32 bits can contain arbitrary values. If a malicious image sets
the error bit with a positive integer (e.g., 1), MREF_ERR() returns
that positive value. Returning ERR_PTR(1) causes VFS to treat it as
a valid dentry pointer since IS_ERR() only recognizes values in
[-MAX_ERRNO, -1] as errors.

This leads to kernel panic when walk_component() → step_into()
dereferences the bogus pointer at:
struct inode *inode = dentry->d_inode;

Fix by strictly validating error codes: only accept negative values
in the valid errno range [-MAX_ERRNO, -1]. Convert all other values
(positive, zero, or out-of-range) to -EIO to indicate disk corruption.

This prevents potential security issues and ensures proper error handling
for corrupted or malicious NTFS filesystems.

Fixes: 1e9ea7e04472 ("Revert "fs: Remove NTFS classic"")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Hongling Zeng <zenghongling@xxxxxxxxxx>
---
fs/ntfs/namei.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index 9c1c36acfad2..e3ec1f2663cc 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -236,7 +236,18 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
}
ntfs_error(vol->sb, "ntfs_lookup_ino_by_name() failed with error code %i.",
-MREF_ERR(mref));
- return ERR_PTR(MREF_ERR(mref));
+ {
+ long err = MREF_ERR(mref);
+
+ if (err < 0 && err >= -MAX_ERRNO) {
+ ntfs_error(vol->sb, "ntfs_lookup_ino_by_name() failed with error code %li.",
+ err);
+ return ERR_PTR(err);
+ }
+ ntfs_error(vol->sb, "ntfs_lookup_ino_by_name() failed with error code %li.",
+ err);
+ return ERR_PTR(-EIO);
+ }
handle_name:
{
struct mft_record *m;
--
2.25.1