summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2026-08-19tools/virtio: Remove unsupported --batch option from vhost_net_testYichong Chen
vhost_net_test has --batch in longopts, but not in help. The parser never handles 'b', so --batch hits assert(0). Remove the unsupported option. Signed-off-by: Yichong Chen <chenyichong@uniontech.com> Acked-by: Eugenio Pérez <eperezma@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <E091F15D8FBE8F16+20260618100254.513806-1-chenyichong@uniontech.com>
2026-08-19vhost/net: fix clear_user start address in VHOST_GET_FEATURES_ARRAYYufeng Wang
The clear_user() call in VHOST_GET_FEATURES_ARRAY incorrectly starts at argp, which is the beginning of the features array, overwriting the data just written by copy_to_user(). It should start after the copied elements at argp + copied * sizeof(u64) to only zero the trailing unused space. Use size_mul() for both the offset and length calculations so the arithmetic stays consistent with the surrounding code and remains overflow-safe. Fixes: 333c515d1896 ("vhost-net: allow configuring extended features") Signed-off-by: Yufeng Wang <wangyufeng@kylinos.cn> Acked-by: Eugenio Pérez <eperezma@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260626070438.59149-1-r4o5m6e8o@163.com>
2026-08-19virtio_balloon: warn on failed buffer add in stats_handle_request()Denis V. Lunev
Like tell_host(), stats_handle_request() ignores the return value of virtqueue_add_outbuf() and kicks the queue regardless. The same "we should always be able to add one buffer to an empty queue" assumption does not hold once the virtqueue has been broken (e.g. on device shutdown), where the add fails with -EIO. Unlike tell_host() it does not wait_event() afterwards so it cannot hang, but it still kicks a queue with nothing queued. Warn and bail out on failure, mirroring tell_host() and virtballoon_free_page_report(). Suggested-by: David Hildenbrand <david@kernel.org> Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260624154001.2733242-1-den@openvz.org>
2026-08-19virtio_balloon: warn on failed buffer add in tell_host()Denis V. Lunev
tell_host() ignores the return value of virtqueue_add_outbuf() and goes on to kick the queue and wait_event() for the host's ack. The comment claims "We should always be able to add one buffer to an empty queue", but that does not hold once the virtqueue has been broken (e.g. on device shutdown): the add then fails with -EIO and the following wait_event() would block forever on a buffer the host can never return. Warn and bail out on failure, mirroring virtballoon_free_page_report(). Suggested-by: David Hildenbrand <david@kernel.org> Signed-off-by: Denis V. Lunev <den@openvz.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260624140846.2616797-5-den@openvz.org>
2026-08-19virtio_balloon: quiesce balloon work before device shutdownDenis V. Lunev
Commit 8bd2fa086a04 ("virtio: break and reset virtio devices on device_shutdown()") added a generic virtio bus .shutdown handler that breaks and resets every virtio device during device_shutdown(), i.e. on reboot and kexec. virtio_balloon provides no .shutdown of its own, so that generic path runs while the balloon's asynchronous work is still armed. Once the device has been broken, virtqueue_add_inbuf() in virtballoon_free_page_report() returns -EIO and trips its WARN_ON_ONCE(). On a kernel booted with panic_on_warn that turns an ordinary reboot, for example a kexec based upgrade, into a fatal panic in the middle of device_shutdown(), so the machine never reaches the new kernel. Relaxing that single WARN_ON_ONCE() would only hide the symptom: the inflate/deflate and OOM paths do not warn, they call wait_event(vb->acked, ...) and would instead block forever on a broken queue that can no longer complete. The device has to be quiesced, not just kept quiet. Add a .shutdown handler that quiesces the balloon via the shared virtballoon_quiesce() helper while the device is still alive, and only then breaks and resets it via virtio_device_shutdown(). Unlike virtballoon_remove() the balloon workqueue is not destroyed, as shutdown does not free the device and cancel_work_sync() together with stop_update already prevent any further work from being queued. Fixes: 8bd2fa086a04 ("virtio: break and reset virtio devices on device_shutdown()") Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260624140846.2616797-4-den@openvz.org>
2026-08-19virtio_balloon: factor out virtballoon_quiesce()Denis V. Lunev
virtballoon_remove() stops all of the balloon's asynchronous work (the free page reporting worker, the inflate/deflate and stats workers, the OOM notifier and the free page shrinker) before tearing the device down. A following change needs the same teardown from a .shutdown handler, so move it into a virtballoon_quiesce() helper. No functional change. Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260624140846.2616797-3-den@openvz.org>
2026-08-19virtio: add virtio_device_shutdown() helperDenis V. Lunev
The generic virtio bus .shutdown handler, virtio_dev_shutdown(), breaks and resets a device once it has established that the driver has no .shutdown of its own. A driver that does implement .shutdown, to quiesce its own activity first, still needs the same break and reset afterwards and would otherwise have to open code it. Factor the break + synchronize_cbs + reset sequence out of virtio_dev_shutdown() into an exported virtio_device_shutdown() helper so such drivers can reuse it instead of duplicating the core logic. No functional change. Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260624140846.2616797-2-den@openvz.org>
2026-08-19virtio: Add ID for virtio mediaAlbert Esteve
Add VIRTIO_ID_MEDIA definition for virtio-media. Signed-off-by: Albert Esteve <aesteve@redhat.com> Message-ID: <20260310-virtio-media-id-v1-1-be211bcf682b@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2026-08-19crypto: virtio - fix missing le64_to_cpu() conversionsBen Dooks
There are two cases of sending a __le64 type to a print function so fix this by adding le64_to_cpu() which fixes the following (prototype) sparse warnings: drivers/crypto/virtio/virtio_crypto_skcipher_algs.c:234:17: warning: incorrect type in argument 3 (different base types) drivers/crypto/virtio/virtio_crypto_skcipher_algs.c:234:17: expected unsigned long long drivers/crypto/virtio/virtio_crypto_skcipher_algs.c:234:17: got restricted __le64 [usertype] session_id drivers/crypto/virtio/virtio_crypto_akcipher_algs.c:196:17: warning: incorrect type in argument 3 (different base types) drivers/crypto/virtio/virtio_crypto_akcipher_algs.c:196:17: expected unsigned long long drivers/crypto/virtio/virtio_crypto_akcipher_algs.c:196:17: got restricted __le64 [usertype] session_id Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> Message-ID: <20260622150322.526375-1-ben.dooks@codethink.co.uk> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2026-08-19crypto: virtio - bound the akcipher result lengthBryam Vargas
virtio_crypto_dataq_akcipher_callback() sets the result length from the device-reported response length without bounding it to the destination buffer, which was allocated for the original request length. sg_copy_from_buffer() then reads that many bytes from the destination buffer; a backend reporting a larger length over-reads adjacent kernel heap into the caller's scatterlist (an out-of-bounds read). Clamp the reported length to the originally requested destination length. A conforming device reports no more than that, so valid results are unaffected. Fixes: a36bd0ad9fbf ("virtio-crypto: adjust dst_len at ops callback") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Message-ID: <20260622-b4-disp-3a2c09a8-v2-1-d1a809281db4@proton.me> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2026-08-19vsock/virtio: restore msg_iter on transmission failureOctavian Purdila
When transmission fails in virtio_transport_send_pkt_info, the msg_iter might have been partially advanced. If we don't restore it, the next attempt to send data will use an incorrect iterator state, leading to desync and warnings like "send_pkt() returns 0, but X expected". Specifically, this can happen in the following scenario, triggered by the syzkaller repro: 1. A write-only VMA (PROT_WRITE only) is partially populated by a prior TUN write that failed with -EIO but still faulted in some pages). 2. A vsock sendmmsg call with MSG_ZEROCOPY requests transmission of a buffer from this VMA. 3. The first packet (64KB) is sent successfully because the pages are populated. 4. The second packet allocation fails because GUP fast pins the first page but GUP slow fails on the next unpopulated page due to PROT_WRITE-only permissions. 5. The iterator is advanced by the partially successful GUP (68KB total advanced: 64KB from first packet + 4KB from second), but the send loop breaks and only reports 64KB sent. This creates a 4KB desync. 6. The next retry starts with a non-zero iov_offset, disabling zerocopy and falling back to copy mode. 7. In copy mode, the transmission succeeds for the next packets but exhausts the iterator early because of the desync. 8. The final retry sees an empty iterator but zerocopy is re-enabled (offset resets). It attempts to send the remaining bytes with zerocopy but pins 0 pages, creating an empty packet. 9. The transport sends the empty packet, triggering the warning because the returned bytes (header only) do not match the expected payload size. 10. The loop continues to spin, allocating ubuf_info each time, eventually exhausting sysctl_optmem_max and returning -ENOMEM to userspace. Restore msg_iter to its original state before the packet allocation and transmission attempt if they fail. Fixes: e0718bd82e27 ("vsock: enable setting SO_ZEROCOPY") Reported-by: syzbot+28e5f3d207b14bae122a@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=28e5f3d207b14bae122a Assisted-by: gemini:gemini-3.1-pro Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: Octavian Purdila <tavip@google.com> Message-ID: <20260622222757.2130402-3-tavip@google.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2026-08-19iov_iter: export iov_iter_restoreOctavian Purdila
Export iov_iter_restore so that it can be used by modules. This is needed by the virtio vsock transport (which can be built as a module) to restore the msg_iter state when transmission fails. Acked-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: Octavian Purdila <tavip@google.com> Message-ID: <20260622222757.2130402-2-tavip@google.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2026-08-19vdpa_sim: fix cleanup after worker creation failureLinfeng Sun 
vdpasim_create() leaves vdpasim->worker as an ERR_PTR when kthread_run_worker() fails. The error path then drops the device reference, which releases the partially initialized simulator. vdpasim_free() unconditionally passes the worker pointer to kthread_destroy_worker(), so the ERR_PTR is dereferenced and can trigger a general protection fault. Store the worker error, clear the pointer, and only clean up the worker when it was successfully initialized. Also make the release path tolerate partially initialized objects by guarding virtqueue and IOTLB cleanup, since the same release path can be reached from other initialization failures. I found this bug myself, though the patch was written with AI assistance. Fixes: 76acfa7bc54f ("vdpa_sim: use kthread worker") Assisted-by: OpenAI-Codex:GPT-5 Reviewed-by: Eugenio Pérez <eperezma@redhat.com> Signed-off-by: Linfeng Sun <linfeng.sun.dev@gamil.com> Message-ID: <20260620100959.2070316-1-slf@hdu.edu.cn> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2026-08-19virtio_balloon: disable indirect descriptorsMichael S. Tsirkin
The page reporting callback submits an sg list to the reporting virtqueue. With VIRTIO_RING_F_INDIRECT_DESC negotiated and total_sg > 1 (which it typically is), virtqueue_add reports it to the host by allocating an indirect descriptor via kmalloc(GFP_KERNEL). This is not pretty: the reporting worker isolates potentially hundreds of MB of free pages from the buddy allocator (reported pages are at least pageblock_order, and the sg can contain up to PAGE_REPORTING_CAPACITY entries of varying orders). As the result, very theoretically, the kmalloc might trigger OOM when we have in fact a ton of free memory. Clear VIRTIO_RING_F_INDIRECT_DESC, to avoid using indirect descriptors. Fixes: b0c504f15471 ("virtio-balloon: add support for providing free page reports to host") Assisted-by: Claude:claude-opus-4-6 Acked-by: David Hildenbrand (Arm) <david@kernel.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <73fac8a629fd9aca7bb3265ac243a769c28af25d.1783232420.git.mst@redhat.com>
2026-08-19virtio-mmio: add support for transport version 3Peter Hilber
Virtio MMIO transport version 3 allows device reset to complete asynchronously. Unlike version 2, where writing zero to Status must complete the reset before the write returns, version 3 requires the driver to poll Status until it reads back zero before considering reset complete. Update virtio-mmio accordingly: accept transport version 3 and, during reset, wait for Status to become zero. Keep the polling loop unbounded, consistent with virtio-pci, since the reset callback does not return an error code. Signed-off-by: Peter Hilber <peter.hilber@oss.qualcomm.com> Link: https://github.com/oasis-tcs/virtio-spec/commit/bb1dd2e1fe89b862f38f15873d835a698b196f89 Message-ID: <20260605142921.2824-1-peter.hilber@oss.qualcomm.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2026-08-19ntfs: do not update ctime when setxattr failsBaolin Liu
ntfs_setxattr() updates ctime and marks the inode dirty even when the operation fails. A failed setxattr(2) must not change file metadata. Update ctime only on success. Fixes: fc053f05ca28 ("ntfs: add reparse and ea operations") Signed-off-by: Baolin Liu <liubaolin@kylinos.cn> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: reject invalid MFT LCNs from boot sectorHyunchul Lee
The NTFS boot sector stores the MFT and MFTMirr locations as unsigned 64-bit LCNs, but parse_ntfs_boot_sector() decoded them into an s64. A crafted high-bit value could therefore become negative and pass the existing upper-bound check. The invalid value then propagated into the MFT zone allocator and could result in an out-of-bounds access to lcn_empty_bits_per_page. Fixes: 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator") Reported-by: Robert Morris <rtm@csail.mit.edu> Closes: https://lore.kernel.org/all/57514.1787000602@localhost Cc: stable@vger.kernel.org Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: serialize resident iomap reads with mrec_lockHyeontae Lee
ntfs_read_iomap_begin_resident() walks the MFT record through ntfs_attr_lookup() -> ntfs_attr_find() without taking ni->mrec_lock, while ntfs_attr_record_resize(), ntfs_make_room_for_attr() and ntfs_resident_attr_record_add() memmove() the same base_ni->mrec buffer under that lock. map_mft_record() only takes a reference and does not serialize, so the reader can observe torn attribute length and offset fields while a writer is relocating the records. KCSAN reports the race between the mmap read fault path and both link() and unlink(): BUG: KCSAN: data-race in ntfs_attr_find / ntfs_attr_record_resize write to 0xffff888100af1018 of 4 bytes by task 96 on cpu 1: ntfs_attr_record_resize+0xd2/0x130 ntfs_attr_record_rm+0xad/0x530 ntfs_delete+0x224/0x640 ntfs_unlink+0x14d/0x280 vfs_unlink+0x157/0x520 read to 0xffff888100af1018 of 4 bytes by task 95 on cpu 0: ntfs_attr_find+0x104/0x5b0 ntfs_attr_lookup+0x39c/0x10c0 ntfs_read_iomap_begin_resident+0xc6/0x230 ntfs_read_iomap_begin+0x5d/0xa0 iomap_iter+0x2e2/0x6e0 iomap_read_folio+0x147/0x2a0 ntfs_read_folio+0x108/0x170 filemap_read_folio+0x35/0x100 filemap_fault+0x993/0x1000 value changed: 0x00000250 -> 0x000001f0 The address is mrec + 0x18, i.e. mft_record.bytes_in_use, and the change is the 96 bytes of one $FILE_NAME attribute being removed. Keep base_ni->mrec_lock from the resident read iomap lookup through iomap_end(). This protects both the attribute walk and the subsequent copy from iomap->inline_data, which points into the MFT record. The non-resident path is left alone: ntfs_lookup() already holds the directory inode's mrec_lock when it reads an index folio through read_mapping_folio(), and taking the lock in the shared wrapper deadlocks there with recursive locking on mrec_lock. The comment above the read_mapping_folio() call in fs/ntfs/dir.c notes the same hazard. The seek path uses the same lookup helper but does not dereference iomap->inline_data. Release the lock before returning from that path, whereas the regular read path records base_ni in iomap->private and releases the lock from its iomap_end() callback. Tested with a reproducer that faults in a 16-byte resident file while another thread runs link()/unlink() on it. Before: 40 KCSAN reports in about one second. After: no reports in 180 seconds over 206,090 read iterations and 423,540 link/unlink cycles. A PROVE_LOCKING build shows no lockdep splat with the same reproducer running for 60 seconds. Fixes: b041ca562526 ("ntfs: update iomap and address space operations") Link: https://lore.kernel.org/all/20260725042421.109599-1-wonju345@naver.com/ Signed-off-by: Hyeontae Lee <wonju345@naver.com> Co-developed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: verify run length exceeding volume boundaryHongling Zeng
The mapping pairs decoder validates that the starting LCN is within the volume but does not check if the run extends beyond the volume boundary. A malformed NTFS image with a crafted mapping pairs array could cause the kernel to access memory beyond the volume boundary, potentially leading to memory corruption and privilege escalation. Add validation to ensure lcn + length stays within nr_clusters. Cc: stable@vger.kernel.org Fixes: b4be3a47f8ba4 ("ntfs: bound the free-cluster bitmap scan to the volume") Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: allow index root relocationNamjae Jeon
Allow a resident attribute record to move to an extent MFT record when the base record needs room for an attribute list. Retry the root conversion after creating the list, but do not relocate a root that is already external. Roll the root back to the base record if persisting the attribute list fails, and free extent MFT records left empty by relocation or rollback. Also preserve bitmap allocation errors in index operations. Fixes: af0db57d4293 ("ntfs: update inode operations") Reported-by: yi <691464208@qq.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: validate non-resident attribute offsetsHongling Zeng
ntfs_attr_update_meta() shifts the attribute name when converting between non-sparse and sparse attributes. Converting to sparse also adds the compressed_size field before the name and mapping pairs, requiring eight additional bytes in the attribute record. However, the validator does not check that name_offset is within safe boundaries for these operations or that the additional space is available. A malicious MFT record could set name_offset such that: 1. The name is positioned at the very end of a non-sparse attribute. Converting to sparse would shift the name forward by 8 bytes, writing beyond the attribute boundary. 2. The name overlaps with the mapping pairs, causing corruption during conversion. Add validation to ensure: - For named attributes, name_offset is within valid bounds - Name does not extend beyond the attribute or overlap with mapping pairs - For non-sparse, non-compressed attributes, eight bytes are available after mapping_pairs_offset for the compressed_size field The space check also covers unnamed attributes, for which name_offset = 0 is valid and no name range needs to be checked. Fixes: 7e2a1c554bc4 ("ntfs: Fix min_len for compressed/sparse attributes in ntfs_non_resident_attr_value_is_valid()") Cc: stable@vger.kernel.org Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn> Co-developed-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: simplify ntfs_reparse_set_native_symlink()Dmitry Antipov
Avoid redundant 'strlen()' and use the convenient 'strreplace()' to simplify 'ntfs_reparse_set_native_symlink()'. Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: reject unprivileged writes to reserved $LX* xattrsPisit Preechapramoth
Reject setxattr of the reserved $LXUID, $LXGID, $LXMOD and $LXDEV names from userspace unless the caller has CAP_SYS_ADMIN. Fixes: fc053f05ca28 ("ntfs: add reparse and ea operations") Signed-off-by: Pisit Preechapramoth <kml.delusion501@slmail.me> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: bound the free-cluster bitmap scan to the volumeBryam Vargas
vol->lcn_empty_bits_per_page is sized from vol->nr_clusters at mount, but ntfs_cluster_alloc() bounds its scan of that array by the size of $Bitmap. Those are independent on-disk quantities and the mount-time check only rejects a $Bitmap that is too small, so an image whose $Bitmap covers more clusters than the volume has lets the scan index past the array. A run whose LCN lies in that gap takes the allocator straight there, since the caller passes the file's own last LCN as its locality hint. KASAN reports a slab out-of-bounds read when a file on such a volume is extended. Clamp the scan to what that array covers, mirroring the max_index calculation the mount-time scan already uses, and reject a decoded LCN at or beyond nr_clusters in the mapping pairs decoder. Conforming volumes are unaffected. Fixes: 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: respect per-file chmod mode over mount masksNamjae Jeon
fmask and dmask provide the default permissions for files without WSL metadata. Once chmod stores a mode in $LXMOD, however, that per-file mode must take precedence so selected files can retain permissions such as execute across remounts. Record whether $LXMOD was found while loading an inode and apply the mount masks only when it is absent. Do not remask the in-memory mode after setattr persists it. Continue loading $LXMOD even when optional $LXUID or $LXGID metadata is missing, since chmod may create only $LXMOD. Fixes: fc053f05ca28 ("ntfs: add reparse and ea operations") Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: apply Windows name checks only with windows_namesNamjae Jeon
The windows_names mount option is documented to reject names containing characters forbidden by Windows. However, ntfs_check_bad_windows_name() unconditionally rejects those characters before checking the mount option. Move the character validation after the option check so a default NTFS mount accepts POSIX names such as names containing ':'. Mounts using windows_names retain the existing Windows-compatible validation, including reserved device names and trailing spaces or dots. Fixes: af0db57d4293 ("ntfs: update inode operations") Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: Fix index_root heap OOB write in ntfs_ir_to_ib()Alexandro Calo
ntfs_ir_to_ib copies all entries from index_root into a freshly allocated index_block_size-byte buffer without verifying that the entries fit in the available space. The entries in index_root may be larger than the usable entry space in the index block. This can cause OOB writes past the end of the allocation. The validator ntfs_index_root_inconsistent() checks that entries are self-consistent within the IR value, but never cross-checks them against index_block_size. There is no bounds check in ntfs_ir_to_ib() before the memcpy. Fixing this at the sink in ntfs_ir_to_ib() since ntfs_index_root_inconsistent() validates the logical consistency of index_root as a structure and a root with large entries is a structurally valid root. The bug is a size conflict of ntfs_ir_to_ib(). Also, the validator is called once per inode load in ntfs_read_locked_inode() while ntfs_ir_to_ib() is only called during a reparent, a check there adds no overhead to the common path. Moreover, even a future call path that bypasses the validator would still be protected. With NULL as first parameter of ntfs_error(), the volume error flag is never set by this call, so the device name will be absent from the error message. In any case, that the caller, ntfs_ir_reparent(), prints an error message that includes the device name on NULL returns. I think this is the best solution available without adding 'struct super_block *sb' as a parameter to ntfs_ir_to_ib(). This heap out-of-bounds write is triggered by a crafted filesystem image, which is not in the kernel threat model, anyway, fixing memory errors would be nice to keep things secure. Fixes: 0a8ac0c1fa0b ("ntfs: update directory operations") Signed-off-by: Alexandro Calo <alexandro.calo@nozominetworks.com> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: move attribute payload before shrinking its recordNamjae Jeon
ntfs_new_attr_flags() resizes the non-resident attribute record before moving its name and mapping pairs to their shorter-header offsets when compression or sparse state is cleared. Shrinking the record first moves the following attribute over the tail of the old record. The subsequent memmove() therefore copies bytes from that following attribute instead of the old mapping pairs. Re-enabling compression on an empty file persists those bytes as a malformed mapping pairs array, which ntfsck reports as a missing or invalid run length. Move the payload before shrinking the record, while retaining the existing resize-before-move ordering when growing it. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: fix resident conversion in ntfs_new_attr_flagsHyunchul Lee
When setting sparse/compressed flags on a resident attribute, the function skipped the resident-to-non-resident conversion and terminated. Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: skip reads for full compression unit overwritesNamjae Jeon
ntfs_compress_write() reads every page in a compression unit before copying new data into it. The read is unnecessary when an aligned write replaces every byte covered by the page-cache folios. Detect full page-aligned compression unit overwrites and grab locked cache folios without reading them. Keep the read-modify-write path for partial units and units that cover only part of a large page. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: submit one bio per compressed write unitNamjae Jeon
ntfs_write_cb() allocates a single-vector bio and synchronously submits it whenever another output page cannot be added. A 64 KiB uncompressed unit therefore requires up to sixteen separate bio submissions. Allocate enough vectors for the complete unit, add all output pages, and perform one synchronous submission. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: reuse compression output workspace across write unitsNamjae Jeon
ntfs_write_cb() allocates output pages and creates input and output vmaps for every compression unit. Sequential writes repeatedly pay those allocation and page-table costs even though each unit has the same maximum output size. Allocate and map the output workspace once per write request. Access input sub-blocks with kmap_local_page(), and reuse the output pages and mapping for every compression unit in the request. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: reuse the compression context during writesNamjae Jeon
ntfs_compress_block() allocates and initializes a roughly 40 KiB match finder context for every 4 KiB sub-block. A 64 KiB compression unit thus performs sixteen large allocations even though the calls are serialized. Allocate one context for the complete write request and reset its hash chains for each sub-block as before. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: fix initialized size and page state after compressed writesNamjae Jeon
The write iterator now expands attributes before calling ntfs_compress_write(), so compressed writes must not expand the attribute themselves. However, the compressed path still needs to reject zero-byte iterator copies, advance initialized_size after successful I/O, and invalidate modified folios after a failed compression-unit write. Reject no-progress copies, persist the new initialized size on success, and clear folio uptodate state when the synchronous write fails. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: write compressed data before replacing old clustersNamjae Jeon
ntfs_write_cb() punches the old compression unit and publishes the new mapping before submitting the replacement data. An allocation or I/O failure after the punch loses the previous contents and can leave the mapping pointing at unwritten clusters. Allocate and write the replacement clusters first. Replace the runlist only after the synchronous write succeeds, and free new clusters on failure. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: punch all-zero compressed blocksNamjae Jeon
When a rewritten compression block consists entirely of zeroes, ntfs_write_cb() returns without replacing its existing runlist mapping. The old on-disk contents therefore remain visible after cache eviction. Punch the compression unit so that reads resolve it as a sparse block and release any clusters that held the previous contents. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: support large pages in compressed writesNamjae Jeon
ntfs_compress_write() derives its page count by shifting the compression block size and assumes that every compression block begins at a page boundary. This produces a zero page count for small compression blocks on large-page systems and ignores an in-page compression block offset. Map every page covering the compression block, pass the in-page offset to ntfs_write_cb(), and stage uncompressed output in page-aligned pages. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: propagate compression context allocation errorsNamjae Jeon
ntfs_compress_block() returns -ENOMEM when its compression context cannot be allocated, but its unsigned return type turns the error into a large positive value. ntfs_write_cb() then hides the allocation failure. Use a signed return type and propagate negative errors to the caller. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: dir: use kmemdup() instead of kmalloc() and memcpy()Mohammad Shahid
Use kmemdup() instead of a separate kmalloc() and memcpy() pair, simplifying the code while preserving the existing behavior. This issue was reported by memdup.cocci. Signed-off-by: Mohammad Shahid <mdshahid03@gmail.com> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: mft: use kmemdup() instead of kmalloc() and memcpy()Mohammad Shahid
Use kmemdup() instead of a separate kmalloc() and memcpy() pair, simplifying the code while preserving the existing behavior. This issue was reported by memdup.cocci. Signed-off-by: Mohammad Shahid <mdshahid03@gmail.com> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: reparse: remove redundant NULL checks before kvfree()Mohammad Shahid
kvfree() safely handles NULL pointers, so the explicit NULL checks before calling kvfree() are unnecessary. This issue was reported by ifnullfree.cocci. Signed-off-by: Mohammad Shahid <mdshahid03@gmail.com> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19MAINTAINERS: update mailing list address for ntfsNamjae Jeon
Add the newly created official mailing list for the ntfs. This mailing list will be shared and used for both the kernel driver and the ntfsprogs-plus utility project. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: use pagecache_isize_extended() on size extensionNamjae Jeon
When extending file size, call truncate_pagecache() first, then update i_size, and use pagecache_isize_extended() instead of manual iomap_zero_range(). This ensures the straddling folio is properly marked RO so page_mkwrite() is called and post-EOF area is zeroed. Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: file extension before write submissionNamjae Jeon
Prepare non-resident file allocation and initialized-size extension in ->write_iter() before entering the buffered or direct iomap write paths. Previously, the iomap write callback extended initialized_size. When a direct write started beyond initialized_size, ntfs_extend_initialized_size() used iomap_zero_range() to zero the gap through the page cache. This created dirty folios after iomap DIO had invalidated its target cache range. The bsync path then had to synchronously write back the entire zeroed gap to prevent the post-DIO invalidation from encountering a dirty boundary folio. Move allocation and initialized-size preparation ahead of iomap submission. For DIO, kiocb_invalidate_pages() now sees any dirty boundary folio created by iomap_zero_range(), writes it back when necessary, and invalidates it before the direct I/O is issued. This removes the explicit synchronous writeback of the zeroed gap while preserving the required boundary-folio ordering. Keep compressed writes out of the early initialized-size extension so their existing write path can zero uninitialized data before compression. Move compressed-file allocation expansion to write_iter as well, eliminating the now-redundant expansion from ntfs_compress_write(). Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: fix kmap_local_page() usage in compressNamjae Jeon
Several compressed I/O paths discard the address returned by kmap_local_page() and later access or unmap the page using page_address(). This is invalid for highmem pages, and local mappings must also be unmapped using the address returned by kmap_local_page(). Map each destination page in ntfs_decompress() only while producing the current sub-block. Use memcpy_from_page(), memcpy_to_page(), and memzero_page() for the other page accesses. Remove unnecessary local mappings from ntfs_write_cb(), where pages are accessed through the vmap() mapping. Fixes: 495e90fa3348 ("ntfs: update attrib operations") Reported-by: Matthew Wilcox <willy@infradead.org> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: Remove references to page->__folio_indexMatthew Wilcox (Oracle)
Pages don't have indexes, folios have indexes. Correct this in ntfs_read_compressed_block() and also remove a use of page->mapping while I'm in here. Also convert the calls to unlock_page() and flush_dcache_page(). Fixes: 495e90fa3348 ("ntfs: update attrib operations") Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Christoph Hellwig <hch@lst.de> Cc: Hyunchul Lee <hyc.lee@gmail.com> Cc: Namjae Jeon <linkinjeon@kernel.org> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: Use zero_user_segment() in handle_bounds_compressed_page()Matthew Wilcox (Oracle)
This fixes handle_bounds_compressed_page() on highmem memory as page_address() does not work on memory which has been kmap_local(), only on kmap() memory. Fixes: 495e90fa3348 ("ntfs: update attrib operations") Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: Remove use of __folio_index in handle_bounds_compressed_page()Matthew Wilcox (Oracle)
Nobody is supposed to use page->__folio_index. Use page_offset() instead, and simplify by working exclusively in loff_t instead of mixing up loff_t and pgoff_t. Link: https://lore.kernel.org/all/20260608210618.3437216-3-willy@infradead.org/ Fixes: 495e90fa3348 ("ntfs: update attrib operations") Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Co-developed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: Inline zero_partial_compressed_page()Matthew Wilcox (Oracle)
zero_partial_compressed_page() has one caller and the next commit will make changes to it that make it inelegant to split across two functions. Fixes: 495e90fa3348 ("ntfs: update attrib operations") Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
2026-08-19ntfs: Fix min_len for compressed/sparse attributes in ↵Alexandro Calo
ntfs_non_resident_attr_value_is_valid() Here the attribute validator computes a single min_len = 64 (as the end of initialized_size) for all non-resident attributes regardless of the flags field. This is correct for regular non-resident attributes but for sparse or compressed non-resident attributes the fixed header is 8 bytes longer, it includes a compressed_size field at bytes 64-71, min_len should be 72. Since the validator lets a sparse/compressed attr_record be less than the correct length, caller's accesses to compressed_size (e.g., ntfs_read_locked_inode() or ntfs_attr_update_mapping_pairs()) can extend past the attribute declared boundary. This can cause OOB reads or OOB writes past the MFT record buffer if the attribute is positioned near the end of the MFT record. The compressed_size field is accessed from: - ntfs_read_locked_inode() - ntfs_read_locked_attr_inode() - ntfs_attr_open() - ntfs_attr_update_mapping_pairs() ntfs_attr_make_non_resident() seems to be safe. Fixing this by raising min_len for sparse/compressed attributes in the validator. The OOB reads and the OOB writes require a crafted filesystem image, which is not in the kernel threat model, anyway, fixing memory errors would be nice to keep things secure. Signed-off-by: Alexandro Calo <alexandro.calo@nozominetworks.com> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>