]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ntfs3: Allocate iomap inline_data using alloc_page
authorMihai Brodschi <m.brodschi@gmail.com>
Mon, 11 May 2026 17:19:04 +0000 (20:19 +0300)
committerKonstantin Komarov <almaz.alexandrovich@paragon-software.com>
Tue, 2 Jun 2026 15:02:37 +0000 (17:02 +0200)
This fixes a BUG reported in iomap_write_end_inline:
iomap_inline_data_valid checks that the inline_data fits within
a page. If the inline_data is allocated with kmemdup there's no
guarantee that it's page-aligned, so the check sometimes fails.
Allocate it with alloc_page to ensure it's page-aligned.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221446
Fixes: 099ef9ab9203 ("fs/ntfs3: implement iomap-based file operations")
Signed-off-by: Mihai Brodschi <m.brodschi@gmail.com>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
fs/ntfs3/attrib.c
fs/ntfs3/inode.c

index a85d3ee51091670c0b4df007b586a5293d83f0e0..c621a4c582f9ed47c716622dbd25bbaa6a116d7f 100644 (file)
@@ -1001,6 +1001,7 @@ int attr_data_get_block_locked(struct ntfs_inode *ni, CLST vcn, CLST clen,
        struct ATTRIB *attr, *attr_b;
        struct ATTR_LIST_ENTRY *le, *le_b;
        struct mft_inode *mi, *mi_b;
+       struct page *page;
        CLST hint, svcn, to_alloc, evcn1, next_svcn, asize, end, vcn0;
        CLST alloc, evcn;
        unsigned fr;
@@ -1036,10 +1037,13 @@ again:
                *lcn = RESIDENT_LCN;
                *len = data_size;
                if (res && data_size) {
-                       *res = kmemdup(resident_data(attr_b), data_size,
-                                      GFP_KERNEL);
-                       if (!*res)
+                       page = alloc_page(GFP_KERNEL);
+                       if (!page) {
                                err = -ENOMEM;
+                       } else {
+                               *res = page_address(page);
+                               memcpy(*res, resident_data(attr_b), data_size);
+                       }
                }
                goto out;
        }
index 7423e8c897384132dd241592fb7a3247d8df3899..c43101cc064d53f4327362efa2a28dbb87a3cac9 100644 (file)
@@ -796,7 +796,7 @@ static int ntfs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
 
        if (lcn == RESIDENT_LCN) {
                if (offset >= clen) {
-                       kfree(res);
+                       __free_page(virt_to_page(res));
                        if (flags & IOMAP_REPORT) {
                                /* special code for report. */
                                return -ENOENT;
@@ -920,7 +920,7 @@ static int ntfs_iomap_end(struct inode *inode, loff_t pos, loff_t length,
 
 out:
        if (iomap->type == IOMAP_INLINE) {
-               kfree(iomap->private);
+               __free_page(virt_to_page(iomap->private));
                iomap->private = NULL;
        }