CVE-2026-45864
Description
In the Linux kernel, the following vulnerability has been resolved:
fs/ntfs3: prevent infinite loops caused by the next valid being the same
When processing valid within the range [valid : pos), if valid cannot be retrieved correctly, for example, if the retrieved valid value is always the same, this can trigger a potential infinite loop, similar to the hung problem reported by syzbot [1].
Adding a check for the valid value within the loop body, and terminating the loop and returning -EINVAL if the value is the same as the current value, can prevent this.
[1] INFO: task syz.4.21:6056 blocked for more than 143 seconds. Call Trace: rwbase_write_lock+0x14f/0x750 kernel/locking/rwbase_rt.c:244 inode_lock include/linux/fs.h:1027 [inline] ntfs_file_write_iter+0xe6/0x870 fs/ntfs3/file.c:1284
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A flaw in the Linux NTFS3 driver can cause an infinite loop when processing valid data references, leading to a system hang.
Vulnerability
In the Linux kernel's fs/ntfs3 filesystem driver, a vulnerability exists in the processing of valid data ranges. When handling the range [valid : pos), if the retrieved valid value is incorrect and remains the same across iterations, the driver enters an infinite loop. This loop can block critical kernel resources, leading to a system hang. The affected versions include all current kernels with the NTFS3 driver active; the fix is in the stable tree but has not been widely released yet [1].
Exploitation
An attacker requires a way to trigger malformed NTFS3 metadata that causes the kernel to repeatedly fetch the same valid value while processing a file write operation. The syzbot report confirms that the hang is triggered via ntfs_file_write_iter, which requires only a local user with write access to a NTFS3 volume. No special privileges or race conditions are needed beyond the ability to write to such a filesystem [1].
Impact
A successful exploitation results in a denial of service (DoS): the calling process (and possibly the entire system) hangs indefinitely due to the infinite loop. The kernel lock (rwbase_write_lock) is never released, blocking the inode lock and preventing any further write operations on the filesystem. This can render the system unresponsive [1].
Mitigation
A fix has been committed to the Linux kernel stable tree in commit 6d93239b4fc479c0a412dd196ec0ca2672d14a, which adds a check for repeated valid values and returns -EINVAL to break out of the loop. As of the advisory date, updating to a kernel containing this commit (expected in stable releases shortly) resolves the issue. No workaround is available for unpatched kernels; users should avoid writing to NTFS3 volumes or disable the NTFS3 driver if possible [1].
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
1471c8b966ec56fs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index a7fe2e02c32ee6..212737a816d7af 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -901,8 +901,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index a7fe2e02c32ee6..212737a816d7af 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -901,8 +901,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
b97e371e5d1cfs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 23a637cdb0810c..3f144a049d7109 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1045,8 +1045,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 23a637cdb0810c..3f144a049d7109 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1045,8 +1045,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
4bf3bafb8e06fs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 3e61eaf28e0885..cd7aaeef45fe9a 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1012,8 +1012,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 3e61eaf28e0885..cd7aaeef45fe9a 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1012,8 +1012,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
a47a2bb9aa64fs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 732260087066d7..5120bd78516946 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1077,8 +1077,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 732260087066d7..5120bd78516946 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1077,8 +1077,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
27b75ca4e51efs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 58fa4da114bbe9..1be77f865d78f4 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1016,8 +1016,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 58fa4da114bbe9..1be77f865d78f4 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1016,8 +1016,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
50c822fcb367fs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index ffb31420085f4c..25788df25deeb1 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -932,8 +932,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index ffb31420085f4c..25788df25deeb1 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -932,8 +932,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
6d93239b4fc4fs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 6d9c1dfe9b1b64..f2d1df2c988a98 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -870,8 +870,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 6d9c1dfe9b1b64..f2d1df2c988a98 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -870,8 +870,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
50c822fcb367fs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index ffb31420085f4c..25788df25deeb1 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -932,8 +932,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index ffb31420085f4c..25788df25deeb1 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -932,8 +932,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
27b75ca4e51efs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 58fa4da114bbe9..1be77f865d78f4 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1016,8 +1016,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 58fa4da114bbe9..1be77f865d78f4 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1016,8 +1016,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
4bf3bafb8e06fs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 3e61eaf28e0885..cd7aaeef45fe9a 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1012,8 +1012,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 3e61eaf28e0885..cd7aaeef45fe9a 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1012,8 +1012,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
71c8b966ec56fs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index a7fe2e02c32ee6..212737a816d7af 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -901,8 +901,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index a7fe2e02c32ee6..212737a816d7af 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -901,8 +901,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
b97e371e5d1cfs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 23a637cdb0810c..3f144a049d7109 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1045,8 +1045,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 23a637cdb0810c..3f144a049d7109 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1045,8 +1045,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
a47a2bb9aa64fs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 732260087066d7..5120bd78516946 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1077,8 +1077,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 732260087066d7..5120bd78516946 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -1077,8 +1077,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
6d93239b4fc4fs/ntfs3: prevent infinite loops caused by the next valid being the same
2 files changed · +12 −6
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 6d9c1dfe9b1b64..f2d1df2c988a98 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -870,8 +870,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
fs/ntfs3/file.c+6 −3 modifieddiff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 6d9c1dfe9b1b64..f2d1df2c988a98 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -870,8 +870,12 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from) goto out; if (lcn == SPARSE_LCN) { - ni->i_valid = valid = - frame_vbo + ((u64)clen << sbi->cluster_bits); + valid = frame_vbo + ((u64)clen << sbi->cluster_bits); + if (ni->i_valid == valid) { + err = -EINVAL; + goto out; + } + ni->i_valid = valid; continue; } -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing loop-progress check in ntfs_compress_write allows infinite loop when the computed valid value equals the current i_valid value."
Attack vector
An attacker can trigger this vulnerability by performing a write operation on a specially crafted NTFS3 filesystem that causes the `ntfs_compress_write` function to repeatedly retrieve the same `valid` value when processing sparse clusters. This results in an infinite loop where `ni->i_valid` never advances, causing the task to block indefinitely while holding the inode lock. The syzbot report shows the task blocked for over 143 seconds in `ntfs_file_write_iter` [patch_id=2661959]. The attack requires the ability to mount and write to a malicious NTFS3 filesystem image.
Affected code
The vulnerability is in the `ntfs_compress_write` function in `fs/ntfs3/file.c` [patch_id=2661959]. The fault lies in the loop that processes valid data within the range `[valid : pos)` when handling sparse logical cluster numbers (LCN == SPARSE_LCN).
What the fix does
The patch separates the computation of the `valid` value from the assignment to `ni->i_valid`. Previously, the code was `ni->i_valid = valid = frame_vbo + ...` which simultaneously updated both. The fix first computes `valid` into a local variable, then checks if `ni->i_valid == valid` — if the new value equals the current value, the loop would never make progress, so the function returns `-EINVAL` and exits. This breaks the infinite loop by detecting the stuck condition [patch_id=2661959].
Preconditions
- configAttacker must be able to mount a crafted NTFS3 filesystem image
- inputAttacker must be able to perform a write operation (ntfs_file_write_iter) on a file within that filesystem
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- git.kernel.org/stable/c/27b75ca4e51e3e4554dc85dbf1a0246c66106fd3nvd
- git.kernel.org/stable/c/4bf3bafb8e0635ed93e3cd4156dcbcc0fb960cb4nvd
- git.kernel.org/stable/c/50c822fcb36768f1fb356f05b02a2248ef81936dnvd
- git.kernel.org/stable/c/6d93239b4fc479f7c0a412dd196ec0ca2672d14anvd
- git.kernel.org/stable/c/71c8b966ec56e13c02388c1312910588bb49be7anvd
- git.kernel.org/stable/c/a47a2bb9aa6455d5cee1045814a60c749309c92bnvd
- git.kernel.org/stable/c/b97e371e5d1c13d722335d46eb8bc1a22b272a0envd
News mentions
0No linked articles in our index yet.