mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
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: 099ef9ab92 ("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>
This commit is contained in:
parent
723325dc91
commit
70d3855594
|
|
@ -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 @@ int attr_data_get_block_locked(struct ntfs_inode *ni, CLST vcn, CLST clen,
|
|||
*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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user