mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
dax: fix dax_range_compare_iter() to use correct size and address offset
dax_range_compare_iter() has two bugs in how it calls
dax_iomap_direct_access() and uses the returned addresses:
1. The size argument passed to dax_iomap_direct_access() is
ALIGN(pos + len, PAGE_SIZE), which is an absolute file offset
rather than a length. This causes the underlying dax_direct_access()
to request a massively inflated nr_pages via PHYS_PFN(size).
2. The addresses returned by dax_iomap_direct_access() are page-aligned
starting addresses, but memcmp() compares from saddr/daddr directly
without adding the page-in-page offset of pos1/pos2. When pos1/pos2
are not page-aligned, this compares the wrong data.
Fix the size by computing ALIGN(len + offset_in_page(pos), PAGE_SIZE),
matching the pattern used in dax_iomap_copy_around(). Fix the address
by adding offset_in_page(pos1)/offset_in_page(pos2) to saddr/daddr in
the memcmp() call.
Fixes: 6f7db3894a ("fsdax: dedup file range to use a compare function")
Cc: stable@vger.kernel.org
Signed-off-by: Jianyun Gao <jianyungao89@gmail.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20261011064840.1296-1-jianyungao89@gmail.com
Signed-off-by: Alison Schofield <alison.schofield@intel.com>
This commit is contained in:
parent
4da700e2ca
commit
a4bfbfb4e9
12
fs/dax.c
12
fs/dax.c
|
|
@ -2200,6 +2200,7 @@ static int dax_range_compare_iter(struct iomap_iter *it_src,
|
|||
const struct iomap *dmap = &it_dest->iomap;
|
||||
loff_t pos1 = it_src->pos, pos2 = it_dest->pos;
|
||||
void *saddr, *daddr;
|
||||
size_t size1, size2;
|
||||
int id, ret;
|
||||
|
||||
len = min(len, min(smap->length, dmap->length));
|
||||
|
|
@ -2215,17 +2216,18 @@ static int dax_range_compare_iter(struct iomap_iter *it_src,
|
|||
}
|
||||
|
||||
id = dax_read_lock();
|
||||
ret = dax_iomap_direct_access(smap, pos1, ALIGN(pos1 + len, PAGE_SIZE),
|
||||
&saddr, NULL);
|
||||
size1 = ALIGN(len + offset_in_page(pos1), PAGE_SIZE);
|
||||
ret = dax_iomap_direct_access(smap, pos1, size1, &saddr, NULL);
|
||||
if (ret < 0)
|
||||
goto out_unlock;
|
||||
|
||||
ret = dax_iomap_direct_access(dmap, pos2, ALIGN(pos2 + len, PAGE_SIZE),
|
||||
&daddr, NULL);
|
||||
size2 = ALIGN(len + offset_in_page(pos2), PAGE_SIZE);
|
||||
ret = dax_iomap_direct_access(dmap, pos2, size2, &daddr, NULL);
|
||||
if (ret < 0)
|
||||
goto out_unlock;
|
||||
|
||||
*same = !memcmp(saddr, daddr, len);
|
||||
*same = !memcmp(saddr + offset_in_page(pos1),
|
||||
daddr + offset_in_page(pos2), len);
|
||||
if (!*same)
|
||||
len = 0;
|
||||
dax_read_unlock(id);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user