| CVE |
Vendors |
Products |
Updated |
CVSS v3.1 |
| In the Linux kernel, the following vulnerability has been resolved:
ntfs: validate index entries on reading
Validate index entries immediately after reading an index root or index
block from disk. This eliminates repeated checks in lookup and readdir,
and reduce the risk of missing checks in those paths. |
| In the Linux kernel, the following vulnerability has been resolved:
ntfs: detect mapping-pairs LCN accumulator overflow
The NTFS mapping-pairs parser accumulates relative LCN deltas in a
signed integer. A corrupted attribute can drive that addition past
the representable range.
One corrupt runlist shape sets the accumulated LCN to S64_MAX and
then adds a delta of 1 in the next mapping-pairs entry.
Signed overflow is undefined and can turn an invalid runlist into a
different set of physical clusters.
Check the LCN addition for overflow before storing the next run. |
| In the Linux kernel, the following vulnerability has been resolved:
ntfs: validate resident index root values on lookup
Resident $INDEX_ROOT values carry index header fields that callers
consume after lookup. Some callers already validate parts of the layout
before walking entries, but those checks are scattered and do not cover
all root header invariants, such as entries_offset alignment and lower
bound, index_length, and allocated_size consistency.
The resident root resize paths now keep these header fields consistent
while the value size changes: ntfs_ir_truncate() lowers
index.allocated_size before shrinking the resident value, and
ntfs_ir_reparent() grows the resident value before publishing a larger
root header. Lookup-time validation can therefore cover these invariants
without tripping over the driver's own resize paths.
Add $INDEX_ROOT to the minimum resident value size table and validate the
resident index header fields before returning the attribute from lookup.
Require 8-byte aligned index header fields, a sane entries_offset, an
index_length within allocated_size, allocated_size within the resident
value, and enough entry space for at least an index entry header.
The shared validator already rejects non-resident records for
resident-only attribute types, including $INDEX_ROOT. |
| In the Linux kernel, the following vulnerability has been resolved:
ntfs: reject non-resident records for resident-only attributes
The shared lookup-time attribute validator rejects non-resident
$FILE_NAME and $VOLUME_NAME records because their formats require
resident values and callers handle returned records as resident
attributes. Other resident-only attribute types still pass through the
generic non-resident mapping-pairs checks.
That leaves real resident/non-resident union confusion paths. Inode load
looks up $STANDARD_INFORMATION and then reads data.resident.value_offset
without checking a->non_resident. ntfs_inode_sync_standard_information()
does the same when updating the standard information value.
ntfs_write_volume_flags() also looks up $VOLUME_INFORMATION and reads
data.resident.value_offset directly. $INDEX_ROOT callers in dir.c and
index.c depend on the same lookup contract before consuming the resident
index root value.
Reject non-resident records for all resident-only attribute types in the
shared validator. Keep the existing $FILE_NAME and $VOLUME_NAME behavior,
but factor it through a helper and extend it to
$STANDARD_INFORMATION, $OBJECT_ID, $VOLUME_INFORMATION, $INDEX_ROOT, and
$EA_INFORMATION. For $OBJECT_ID and $EA_INFORMATION this is contract
hardening for resident-only formats; this patch only rejects the
non-resident form and does not add new resident value validation for
those types. |
| In the Linux kernel, the following vulnerability has been resolved:
fs/ntfs3: bound DeleteIndexEntryAllocation memmove length
In do_action()'s DeleteIndexEntryAllocation case, e->size comes
from an on-disk INDEX_BUFFER entry. When e->size makes
e + e->size point past hdr + hdr->used,
PtrOffset(e1, Add2Ptr(hdr, used)) returns a negative ptrdiff_t
that is silently cast to a quasi-infinite size_t when passed
to memmove(). The memmove then walks past the destination
buffer.
The sibling DeleteIndexEntryRoot case at fslog.c:3540-3543
already carries the corresponding guard:
if (PtrOffset(e1, Add2Ptr(hdr, used)) < esize ||
Add2Ptr(e, esize) > Add2Ptr(lrh, rec_len) ||
used + esize > le32_to_cpu(hdr->total)) {
goto dirty_vol;
}
Apply the same shape to the allocation-path case. Also reject
esize == 0: memmove(e, e, ...) is a no-op and leaves
hdr->used unchanged, hiding a malformed entry from the
existing check_index_header() walk.
Reproduced under UML+KASAN on mainline 8d90b09e6741 by
mounting a crafted NTFS image: the unguarded memmove takes a
length of 0xffffffffffffff00 and the kernel oopses in
memmove+0x81/0x1a0 on the do_action+0x36a2 frame.
[almaz.alexandrovich@paragon-software.com: clang-formatted the changes] |
| In the Linux kernel, the following vulnerability has been resolved:
fs/ntfs3: bound copy_lcns dp->page_lcns[] index in analysis pass
In log_replay()'s analysis pass, after find_dp() returns a
valid DIR_PAGE_ENTRY for the (target_attr, target_vcn) tuple,
the copy_lcns block walks lrh->lcns_follow further entries:
t16 = le16_to_cpu(lrh->lcns_follow);
for (i = 0; i < t16; i++) {
size_t j = (size_t)(le64_to_cpu(lrh->target_vcn) -
le64_to_cpu(dp->vcn));
dp->page_lcns[j + i] = lrh->page_lcns[i];
}
find_dp() only validates that target_vcn falls within
[dp->vcn, dp->vcn + dp->lcns_follow), i.e., that the FIRST
cluster is covered. The walk through the further entries is
not bounded against dp->lcns_follow. For a malformed LRH
where target_vcn = dp->vcn + dp->lcns_follow - 1 and
lrh->lcns_follow > 1, the i > 0 writes overflow the dp's
allocated page_lcns[] array.
Add the missing j + lrh->lcns_follow <= dp->lcns_follow guard.
Reproduced under UML+KASAN on mainline 8d90b09e6741 as a
slab-out-of-bounds write of size 8 from log_replay+0x68d4 on
the mount path.
This is distinct from Pavitra Jha's 2026-05-02 patch
("fs/ntfs3: validate lcns_follow in log_replay conversion",
<20260502154252.164586-1-jhapavitra98@gmail.com>) which
addresses the separate version-0 dirty-page-table conversion
path's memmove(&dp->vcn, ...) call. The two fixes are
complementary; both should land.
[almaz.alexandrovich@paragon-software.com: clang-formatted the changes,
fixed conflicts] |
| In the Linux kernel, the following vulnerability has been resolved:
fs/ntfs3: bound attr_off in UpdateResidentValue against data_off
In do_action()'s UpdateResidentValue case (fslog.c:3307),
lrh->attr_off and lrh->redo_len come from the on-disk LRH.
When they satisfy aoff + dlen < attr->res.data_off, the
assignment
attr->res.data_size = cpu_to_le32(aoff + dlen - data_off);
underflows to ~4 GiB (e.g. 0xFFFFFFF9 when aoff=0x10, dlen=1,
data_off=0x18). Subsequent code that reads attr->res.data_size
to walk the resident attribute payload would then read up to
4 GiB past the 1024-byte MFT record allocation.
The existing mi_enum_attr() defense in fs/ntfs3/record.c:287
catches the corrupted data_size on the next attribute walk
and fails the mount, but only on the path that walks all
attributes. A read site that picks an attribute by name and
reads its data_size without re-validating is not covered.
Validate aoff against data_off and asize at the source.
Reproduced under UML+KASAN on mainline 8d90b09e6741 via
pr_warn-only probe: with aoff=0x10 and data_off=0x18, the
post-assignment data_size is 0xfffffff9 (mount then fails
at -22 from mi_enum_attr).
[almaz.alexandrovich@paragon-software.com: clang-formatted the changes] |
| In the Linux kernel, the following vulnerability has been resolved:
fs/ntfs3: add depth limit to indx_find_buffer to prevent stack overflow
indx_find_buffer() recursively descends the B+ tree index with no depth
limit. A crafted NTFS image with circular index node references causes
unbounded recursion, overflowing the kernel stack and panicking the
system.
This is reachable by mounting a malicious NTFS filesystem (e.g. from a
USB drive via desktop automount) and deleting a file whose index entry
triggers the rebalancing fallback path in indx_delete_entry().
Add a depth parameter and bail out with -EINVAL when it reaches the
fnd->nodes array bound, matching the constraint already enforced by
fnd_push() in indx_find().
The related function indx_find() was previously patched for a similar
infinite-loop issue (commit 1732053c8a6b), but indx_find_buffer() was
missed. |
| In the Linux kernel, the following vulnerability has been resolved:
ntfs3: bound to_move in indx_insert_into_root before hdr_insert_head
indx_insert_into_root() promotes a full resident $INDEX_ROOT into
$INDEX_ALLOCATION and copies all non-last resident root entries into
a newly allocated INDEX_BUFFER via hdr_insert_head(). The source
byte count 'to_move' is summed from the on-disk resident entry sizes
and is independent of the destination buffer size, which comes from
root->index_block_size (via indx->index_bits).
A crafted NTFS image that keeps a valid, full resident root but
shrinks root->index_block_size down to 512 after the root has been
populated makes hdr_insert_head() memcpy attacker-controlled resident
entry bytes past the end of the kmalloc(1u << indx->index_bits)
allocation returned by indx_new(). For a 512-byte destination and a
resident root whose non-last entries total 560 bytes, the memcpy
overruns by 120 bytes and a following memmove extends the highest
written offset to 136 bytes past the allocation. The overflow bytes
are a direct copy of on-disk entries (via kmemdup), so they are
fully attacker-controlled.
The write is reachable from unprivileged open(O_CREAT) on a mounted
crafted NTFS image: a single sufficiently long create in a directory
whose resident root is already full forces root promotion and
triggers the copy.
This is a controlled out-of-bounds write of 120-136 bytes past a
kmalloc(index_block_size) allocation, with attacker-controlled
content. It is a bounded adjacent-heap corruption primitive; it is
not an arbitrary-address write. Successful exploitation into a named
victim object depends on the surrounding slab layout.
Reject the copy at the sink. The destination's INDEX_HDR already
reports hdr_total (the payload capacity of the new buffer) and
hdr_used (the bytes already consumed by the terminal END entry
installed by indx_new()); require that to_move fits in the remaining
payload before calling hdr_insert_head(). On mismatch, fail with
-EINVAL and mark the filesystem as having a detected on-disk
inconsistency, which is the same behaviour as the surrounding
validation in this function. |
| In the Linux kernel, the following vulnerability has been resolved:
ntfs3: validate split-point offset in indx_insert_into_buffer
indx_insert_into_buffer() computes
used = used1 - to_copy - sp_size;
memmove(de_t, Add2Ptr(sp, sp_size), used - le32_to_cpu(hdr1->de_off));
where sp and sp_size come from hdr_find_split(). hdr_find_split()
walks entries by le16_to_cpu(e->size) without validating that each
step stays within hdr->used or that the size field is at least
sizeof(struct NTFS_DE). index_hdr_check(), the on-load gatekeeper,
only validates header-level fields (used, total, de_off) and does
not walk per-entry sizes.
A crafted NTFS image whose leaf INDEX_HDR reports used == total but
contains one interior NTFS_DE with size = 0xFFF0 therefore passes
validation, descends to indx_insert_into_buffer() through the
ntfs_create() -> indx_insert_entry() path, and makes hdr_find_split()
return an sp whose sp_size (0xFFF0) greatly exceeds the remaining
bytes in the buffer. The u32 subtraction underflows and the memmove
count becomes a near-4-GiB value, producing an out-of-bounds kernel
write that corrupts adjacent allocations and panics the kernel.
Reproduced on 7.0.0-rc7 with UML + KASAN via a crafted image and a
single 'touch' inside the mounted directory; crash site resolves to
fs/ntfs3/index.c at the memmove. Trigger requires only local mount
of an attacker-supplied filesystem image (USB, loopback, or removable
media auto-mount).
Reject the split whenever the chosen sp plus its declared size
already extends past hdr1->used. This is the minimal fix; it
preserves the existing hdr_find_split() contract and relies on the
same out: cleanup path as the pre-existing error returns.
A prior OOB read in the very same indx_insert_into_buffer() memmove
was fixed in commit b8c44949044e ("fs/ntfs3: Fix OOB read in
indx_insert_into_buffer") by tightening hdr_find_e(), but that fix
does not cover the split-point size field path addressed here: sp is
returned by hdr_find_split(), not hdr_find_e(), and the underflow is
driven by sp->size rather than hdr->used exceeding hdr->total. |
| In the Linux kernel, the following vulnerability has been resolved:
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. |
| In the Linux kernel, the following vulnerability has been resolved:
ntfs: make system files immutable to prevent corruption
When a system file such as $Bitmap is exposed via show_sys_files and
written from userspace, the volume is corrupted and, because the cluster
allocator scans $Bitmap through the same inode's page cache, a write to
$Bitmap also deadlocks writeback against the folio it already holds locked.
These files are maintained by the driver itself and have no valid reason
to be written through the file interface. Mark base metadata files
(mft_no < FILE_first_user) as immutable during inode read so the VFS
rejects write, mmap, truncate and unlink with -EPERM. Directories are
skipped so the root and $Extend remain usable. Internal metadata updates
do not go through the VFS write path and are unaffected. |
| In the Linux kernel, the following vulnerability has been resolved:
ntfs: fix WARN_ON for resident attribute in ntfs_map_runlist_nolock()
When ntfs_map_runlist_nolock() needs to look up the attribute extent
containing a target VCN (ctx_needs_reset == true), it calls
ntfs_attr_lookup() and then expects the result to be a non-resident
attribute, since only non-resident attributes have a mapping pairs
array to decompress.
A crafted NTFS image can place a resident attribute where a non-resident
one is expected, causing ntfs_attr_lookup() to succeed but return a
resident attribute record. Previously this was caught only by a
WARN_ON(), which does not stop execution. The code then falls through to
read a->data.non_resident.highest_vcn from what is actually a resident
attribute, accessing the wrong union member and corrupting the VCN range
check.
The caller path triggering this warning during mount is:
ntfs_map_runlist_nolock
ntfs_empty_logfile
load_system_files
ntfs_fill_super
In this path ctx is NULL, so ntfs_map_runlist_nolock() allocates a
temporary search context internally and sets ctx_needs_reset = true.
The existing resident-attribute guard in the ctx != NULL branch already
returns -EIO silently for the same condition; make the ctx_needs_reset
path consistent by replacing the WARN_ON() with the same -EIO error
return.
This causes the crafted image to be rejected with a mount error instead
of triggering a kernel warning. |
| In the Linux kernel, the following vulnerability has been resolved:
landlock: Fix LANDLOCK_SCOPE_SIGNAL bypass on the SIGIO path
LANDLOCK_SCOPE_SIGNAL must prevent a sandboxed process from signaling
processes outside its Landlock domain. It can be bypassed through the
asynchronous SIGIO delivery path.
A sandboxed process that owns any file or socket can arm it with
fcntl(fd, F_SETOWN, -pgid), fcntl(fd, F_SETSIG, SIGKILL) and O_ASYNC, so
that an I/O event makes the kernel deliver the chosen signal to the
whole process group. As the head of its process group's task list (the
default position right after fork()) that group can also hold the
non-sandboxed process that launched it, e.g. a supervisor or a security
monitor. The sandbox can thus kill or signal the processes
LANDLOCK_SCOPE_SIGNAL is meant to protect from it.
The scope is enforced in hook_file_send_sigiotask() against the Landlock
domain recorded at F_SETOWN time, not the live domain of the sender.
control_current_fowner() decides whether to record that domain and skips
recording it when the fowner target is in the caller's thread group,
which is safe only for a single-task target (PIDTYPE_PID, PIDTYPE_TGID).
For a process group (PIDTYPE_PGID) pid_task() returns only one member;
recording is skipped whenever that member shares the caller's thread
group, and hook_file_send_sigiotask() then lets the signal fan out to
the whole group unchecked.
Record the domain for every non single-process target so the scope is
enforced against each group member at delivery time.
That recording is necessary but not sufficient on its own: the kernel
signals a process group through its members' thread-group leaders, and
the leader of the registrant's own process can carry a different
Landlock domain than the sibling thread that armed the owner.
domain_is_scoped() would then deny that leader, even though commit
18eb75f3af40 ("landlock: Always allow signals between threads of the
same process") requires same-process delivery to be allowed.
hook_task_kill() avoids this by evaluating same_thread_group() live, per
recipient; the SIGIO path instead delegates the whole decision to a
single registration-time check, which a process-group fan-out cannot
honor.
So also record the registrant's thread group next to its domain and
exempt it at delivery: hook_file_send_sigiotask() allows the signal
whenever the recipient belongs to the registrant's own process,
restoring the same-process guarantee while keeping out-of-domain group
members blocked. The direct kill() path (hook_task_kill) already
evaluates the live domain and is unaffected.
[mic: Check pid_type earlier and improve comment, fix commit message,
fix comment formatting] |
| In the Linux kernel, the following vulnerability has been resolved:
mips: sched: Fix CPUMASK_OFFSTACK memory corruption
This patch addresses a critical memory management flaw. When
CONFIG_CPUMASK_OFFSTACK is enabled, cpumask_var_t is a pointer.
Consequently, sizeof(new_mask) evaluates to the pointer size, causing
copy_from_user() to clobber the mask pointer. Furthermore, the old
logic performed copy_from_user() before allocating the mask.
Fix this by allocating new_mask first. To handle variable-sized user
masks correctly, use cpumask_size() to truncate overly large user masks
or pad undersized masks with zeros before copying the data directly into
the allocated buffer. |
| In the Linux kernel, the following vulnerability has been resolved:
fs/proc/task_mmu: fix make_uffd_wp_huge_pte() prot-update race
Patch series "userfaultfd/pagemap: pre-existing fixes".
These are pre-existing bug fixes that were carried at the front of the
userfaultfd RWP working-set-tracking series up to v5 [1]. Per review
feedback that fixes should not sit in the middle of a feature series, they
are split out and sent on their own; the RWP series is reposted rebased on
top of this.
All six were flagged by the Sashiko AI review of the RWP series and carry
independent of RWP, apply to mm-new directly, and carry Cc: stable@.
1: fs/proc/task_mmu: a missing huge_ptep_modify_prot_start() in
make_uffd_wp_huge_pte() can lose hardware Dirty/Accessed updates
when PAGEMAP_SCAN write-protects a hugetlb PTE.
2: fs/proc/task_mmu: pagemap_scan_hugetlb_entry() compares the range
against HPAGE_SIZE rather than the hstate page size, so it never
write-protects gigantic hugetlb pages.
3: fs/proc/task_mmu: PAGEMAP_SCAN with PM_SCAN_WP_MATCHING over an
unpopulated hugetlb range self-deadlocks -- pagemap_scan_pte_hole()
calls uffd_wp_range() while walk_hugetlb_range() holds the hugetlb
vma lock for read, and hugetlb_change_protection() then takes it
for write. Install the marker inline instead.
4: mm/huge_memory: change_non_present_huge_pmd() drops pmd_swp_uffd_wp
on a device-private PMD permission downgrade, silently losing the
uffd-wp marker.
5: userfaultfd: must_wait() applies pte_write() to a locklessly read
PTE without checking pte_present(), so swap/migration entries
decode random offset bits and a thread can stay parked on a stale
fault.
6: userfaultfd: __VMA_UFFD_FLAGS feeds VMA_UFFD_MINOR_BIT (41) to
mk_vma_flags() unconditionally, an out-of-bounds write into the
single-word vma_flags_t on 32-bit. Build the mask from config-gated
per-mode masks so an unavailable bit is never materialised.
This patch (of 6):
make_uffd_wp_huge_pte() arms the UFFD_WP bit on a present HugeTLB PTE by
calling huge_ptep_modify_prot_commit() with a ptent snapshot that was
fetched without the corresponding huge_ptep_modify_prot_start(). The
start helper is what atomically clears the entry so the kernel-owned
snapshot stays consistent until the commit; without it, the hardware may
set Dirty or Accessed in the live PTE between the original read and the
commit, and huge_ptep_modify_prot_commit() (whose generic implementation
just calls set_huge_pte_at()) then writes the stale snapshot back over the
live hardware bits, losing the update.
The non-hugetlb sibling make_uffd_wp_pte() does this correctly via
ptep_modify_prot_start() / ptep_modify_prot_commit(). Mirror that pattern
for the present-PTE branch. The migration case stays as-is -- migration
entries are non-present, so there's no hardware update to race against. |
| In the Linux kernel, the following vulnerability has been resolved:
mm/mm_init: fix uninitialized struct pages for ZONE_DEVICE
If DAX memory is hotplugged into an unoccupied subsection of an early
section, section_activate() reuses the unoptimized boot memmap. However,
compound_nr_pages() still assumes that vmemmap optimization is in effect
and initializes only the reduced number of struct pages. As a result, the
remaining tail struct pages are left uninitialized, which can later lead
to unexpected behavior or crashes.
Fix this by treating early sections as unoptimized when calculating how
many struct pages to initialize. |
| In the Linux kernel, the following vulnerability has been resolved:
mtd: slram: remove failed entries from the device list
register_device() links a new slram_mtdlist entry before allocating all
of the state needed by the entry. If a later allocation, memremap(), or
mtd_device_register() fails, the partially initialized entry remains on
the global list. A later cleanup can then dereference or free invalid
state from that failed entry.
Unwind the partially initialized entry and clear the list tail on each
failure path after the entry has been linked. |
| In the Linux kernel, the following vulnerability has been resolved:
9p: skip nlink update in cacheless mode to fix WARN_ON
v9fs_dec_count() unconditionally calls drop_nlink() on regular files,
even when the inode's nlink is already zero. In cacheless mode the
client refetches inode metadata from the server (the source of truth)
on every operation, so by the time v9fs_remove() returns, the locally
cached nlink may already reflect the post-unlink value:
1. Client initiates unlink, server processes it and sets nlink to 0
2. Client refetches inode metadata (nlink=0) before unlink returns
3. Client's v9fs_remove() completes successfully
4. Client calls v9fs_dec_count() which calls drop_nlink() on nlink=0
This race is easily triggered under heavy unlink workloads, such as
stress-ng's unlink stressor, producing the following warning:
WARNING: fs/inode.c:417 at drop_nlink+0x4c/0xc8
Call trace:
drop_nlink+0x4c/0xc8
v9fs_remove+0x1e0/0x250 [9p]
v9fs_vfs_unlink+0x20/0x38 [9p]
vfs_unlink+0x13c/0x258
...
In cacheless mode the server is authoritative and the inode is on its
way out, so locally adjusting nlink buys nothing. Skip v9fs_dec_count()
entirely when neither CACHE_META nor CACHE_LOOSE is set, which both
avoids the warning and removes a class of nlink races (two concurrent
unlinkers observing nlink > 0 and both calling drop_nlink()) that an
nlink == 0 guard alone would only narrow rather than close. |
| In the Linux kernel, the following vulnerability has been resolved:
mtd: rawnand: fix condition in 'nand_select_target()'
'cs' here must be in range [0:nanddev_ntargets[. |