From: Mihai Brodschi Date: Mon, 11 May 2026 17:19:04 +0000 (+0300) Subject: ntfs3: Allocate iomap inline_data using alloc_page X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=70d3855594cf6e8791970714b65cac3202d6160e;p=thirdparty%2Fkernel%2Flinux.git ntfs3: Allocate iomap inline_data using alloc_page 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 Signed-off-by: Konstantin Komarov --- diff --git a/fs/ntfs3/attrib.c b/fs/ntfs3/attrib.c index a85d3ee51091..c621a4c582f9 100644 --- a/fs/ntfs3/attrib.c +++ b/fs/ntfs3/attrib.c @@ -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; } diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 7423e8c89738..c43101cc064d 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -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; }