CVE-2026-46062
Description
In the Linux kernel, the following vulnerability has been resolved:
ntfs3: fix integer overflow in run_unpack() volume boundary check
The volume boundary check lcn + len > sbi->used.bitmap.nbits uses raw addition which can wrap around for large lcn and len values, bypassing the validation. Use check_add_overflow() as is already done for the adjacent prev_lcn + dlcn and vcn64 + len checks added by commit 3ac37e100385 ("ntfs3: Fix integer overflow in run_unpack()").
Found by fuzzing with a source-patched harness (LibAFL + QEMU).
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Integer overflow in ntfs3 run_unpack() volume boundary check bypasses validation, leading to potential memory corruption.
Vulnerability
In the Linux kernel's ntfs3 filesystem driver, an integer overflow vulnerability exists in the run_unpack() function's volume boundary check. The condition lcn + len > sbi->used.bitmap.nbits uses raw addition, which can wrap around for large lcn and len values, allowing an attacker to bypass the validation. This was discovered through fuzzing. The affected versions include those prior to the fix commit [1], which backports the use of check_add_overflow() as already done for similar checks in commit 3ac37e100385.
Exploitation
An attacker with the ability to mount a crafted NTFS filesystem image (e.g., through local access or physical media) can trigger the overflow by supplying specially crafted run data. No authentication is required if the attacker can cause the kernel to parse the malicious image. The exploitation involves providing large values that cause the addition to wrap, bypassing the boundary check and potentially allowing out-of-bounds access.
Impact
Successful exploitation could lead to memory corruption, potentially resulting in information disclosure or denial of service. The exact impact depends on the kernel memory layout, but the vulnerability could be used to escalate privileges or cause a system crash. The fix ensures proper overflow checking using check_add_overflow().
Mitigation
The fix is included in Linux kernel version 6.13.3 and later (as indicated by the stable commit [1]). Users should update their kernel to the latest stable version. If patching is not immediately possible, users can avoid mounting untrusted NTFS filesystems. There is no known workaround for the vulnerability itself.
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
2Patches
10a954061b334entfs3: fix integer overflow in run_unpack() volume boundary check
2 files changed · +18 −8
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 568ce7ce4f00e1..f2451eaf928af8 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1018,9 +1018,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 568ce7ce4f00e1..f2451eaf928af8 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1018,9 +1018,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
f1af27cec07antfs3: fix integer overflow in run_unpack() volume boundary check
2 files changed · +18 −8
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 087c13a60c2057..de9081be462e59 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1020,9 +1020,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 087c13a60c2057..de9081be462e59 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1020,9 +1020,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
6175d09c23bentfs3: fix integer overflow in run_unpack() volume boundary check
2 files changed · +18 −8
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 29817ecb1c7d4f..1ce7d92fb27482 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1065,9 +1065,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 29817ecb1c7d4f..1ce7d92fb27482 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1065,9 +1065,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
984a415f0195ntfs3: fix integer overflow in run_unpack() volume boundary check
2 files changed · +18 −8
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 29817ecb1c7d4f..1ce7d92fb27482 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1065,9 +1065,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 29817ecb1c7d4f..1ce7d92fb27482 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1065,9 +1065,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
60dab3e2931fntfs3: fix integer overflow in run_unpack() volume boundary check
2 files changed · +18 −8
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 9f7e2eae03dcf6..744c1a317f8e67 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1020,9 +1020,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 9f7e2eae03dcf6..744c1a317f8e67 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1020,9 +1020,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
984a415f0195ntfs3: fix integer overflow in run_unpack() volume boundary check
2 files changed · +18 −8
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 29817ecb1c7d4f..1ce7d92fb27482 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1065,9 +1065,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 29817ecb1c7d4f..1ce7d92fb27482 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1065,9 +1065,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
f1af27cec07antfs3: fix integer overflow in run_unpack() volume boundary check
2 files changed · +18 −8
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 087c13a60c2057..de9081be462e59 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1020,9 +1020,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 087c13a60c2057..de9081be462e59 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1020,9 +1020,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
a954061b334entfs3: fix integer overflow in run_unpack() volume boundary check
2 files changed · +18 −8
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 568ce7ce4f00e1..f2451eaf928af8 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1018,9 +1018,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 568ce7ce4f00e1..f2451eaf928af8 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1018,9 +1018,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
6175d09c23bentfs3: fix integer overflow in run_unpack() volume boundary check
2 files changed · +18 −8
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 29817ecb1c7d4f..1ce7d92fb27482 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1065,9 +1065,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 29817ecb1c7d4f..1ce7d92fb27482 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1065,9 +1065,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
60dab3e2931fntfs3: fix integer overflow in run_unpack() volume boundary check
2 files changed · +18 −8
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 9f7e2eae03dcf6..744c1a317f8e67 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1020,9 +1020,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
fs/ntfs3/run.c+9 −4 modifieddiff --git a/fs/ntfs3/run.c b/fs/ntfs3/run.c index 9f7e2eae03dcf6..744c1a317f8e67 100644 --- a/fs/ntfs3/run.c +++ b/fs/ntfs3/run.c @@ -1020,9 +1020,15 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino, return -EOPNOTSUPP; } #endif - if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits) { - /* LCN range is out of volume. */ - return -EINVAL; + if (lcn != SPARSE_LCN64) { + u64 lcn_end; + + if (check_add_overflow(lcn, len, &lcn_end)) + return -EINVAL; + if (lcn_end > sbi->used.bitmap.nbits) { + /* LCN range is out of volume. */ + return -EINVAL; + } } if (!run) -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Integer overflow in run_unpack() volume boundary check due to raw addition of lcn and len without overflow detection."
Attack vector
An attacker can craft a malicious NTFS volume image containing an attribute run with a large logical cluster number (LCN) and length (len) such that `lcn + len` wraps around a 64-bit integer. Because the original check uses raw addition without overflow detection, the wrapped result may appear to be within the volume bitmap bounds, bypassing the validation. The attacker must be able to mount the crafted NTFS image, which triggers `run_unpack()` during file system operations.
Affected code
The vulnerability is in the `run_unpack()` function in `fs/ntfs3/run.c` [patch_id=2660035]. The flawed code is the volume boundary check at the line `if (lcn != SPARSE_LCN64 && lcn + len > sbi->used.bitmap.nbits)`.
What the fix does
The patch replaces the raw addition `lcn + len` with `check_add_overflow(lcn, len, &lcn_end)`, which detects if the addition overflows and returns true if so. If overflow is detected, the function returns `-EINVAL`. Otherwise, the computed `lcn_end` is compared against `sbi->used.bitmap.nbits`. This mirrors the overflow-safe pattern already used for the adjacent `prev_lcn + dlcn` and `vcn64 + len` checks added by an earlier fix [patch_id=2660035].
Preconditions
- inputAttacker must supply a crafted NTFS volume image with malicious run data.
- configThe target system must mount the crafted NTFS image, triggering run_unpack().
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/60dab3e2931f3d792438a77a6cb0cb731c43300bnvd
- git.kernel.org/stable/c/6175d09c23bec4b60860ee9a0170308ff4b56e10nvd
- git.kernel.org/stable/c/984a415f019536ea2d24de9010744e5302a9a948nvd
- git.kernel.org/stable/c/a954061b334ec67c79ae9d0cadd83fa521396487nvd
- git.kernel.org/stable/c/f1af27cec07a9fd0847166bdb23c99e86b05bfdcnvd
News mentions
0No linked articles in our index yet.