From: sashiko-bot@kernel.org
To: jianyungao89@gmail.com
Cc: nvdimm@lists.linux.dev
Subject: Re: [PATCH] dax: fix wrong size passed to dax_iomap_direct_access() in dax_range_compare_iter()
Date: Sat, 10 Oct 2026 07:35:06 +0000 [thread overview]
Message-ID: <sashiko-outbox-166309@kernel.org> (raw)
In-Reply-To: <20261010071453.6028-1-jianyungao89@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] fsdax: dax_range_compare_iter() memcmp ignores page-in-page offset
- [High] fsdax: out-of-bounds access due to bypassed length check in dax_iomap_direct_access()
--
commit 05244bba82891c8d959214ace5da854f182c9e20
Author: Jianyun Gao <jianyungao89@gmail.com>
dax: fix wrong size passed to dax_iomap_direct_access() in dax_range_compare_iter()
dax_range_compare_iter() passes ALIGN(pos + len, PAGE_SIZE) as the size
argument to dax_iomap_direct_access(), but this 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), leading to unnecessarily large access ranges and
potential spurious -EHWPOISON from driver badblock scans.
> diff --git a/fs/dax.c b/fs/dax.c
> index 08adeaed2baf1..fb12d0c0dcd49 100644
> --- a/fs/dax.c
> +++ b/fs/dax.c
> @@ -2190,6 +2190,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));
> @@ -2205,13 +2206,13 @@ 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 + (pos1 & ~PAGE_MASK), PAGE_SIZE);
> + ret = dax_iomap_direct_access(smap, pos1, size1, &saddr, NULL);
[Severity: High]
Does this code risk an out-of-bounds access in the subsequent memcmp() if the
underlying physical DAX memory mapped is shorter than requested?
Looking at dax_iomap_direct_access(), it bypasses the length validation when
the pfnp argument is NULL:
fs/dax.c:dax_iomap_direct_access() {
...
if (!pfnp)
goto out_check_addr;
rc = -EINVAL;
if (PFN_PHYS(length) < size)
goto out;
...
}
If the iomap extent crosses a device mapper target boundary, such as on
dm-linear, dm_dax_direct_access() truncates the mapping length and returns
fewer pages than requested.
Because dax_iomap_direct_access() is called here with a NULL pfnp, it skips
the length check and returns success even for short mappings.
Could this regression cause the subsequent memcmp() to read beyond the
physically contiguous mapped memory?
> if (ret < 0)
> goto out_unlock;
>
> - ret = dax_iomap_direct_access(dmap, pos2, ALIGN(pos2 + len, PAGE_SIZE),
> - &daddr, NULL);
> + size2 = ALIGN(len + (pos2 & ~PAGE_MASK), PAGE_SIZE);
> + ret = dax_iomap_direct_access(dmap, pos2, size2, &daddr, NULL);
> if (ret < 0)
> goto out_unlock;
>
[Severity: High]
Is it possible that the memcmp() that follows compares the wrong file data
because it ignores the page-in-page offset?
The dax_iomap_direct_access() function translates a file offset to a kernel
virtual address, but the returned pointers saddr and daddr are strictly
page-aligned, ignoring any page-in-page offset (pos & ~PAGE_MASK).
When filesystem block sizes are smaller than the architecture's page size,
deduplication requests can be block-aligned but not page-aligned.
If memcmp() is called directly on saddr and daddr without adding the
pos1 & ~PAGE_MASK and pos2 & ~PAGE_MASK offsets:
fs/dax.c:dax_range_compare_iter() {
...
*same = !memcmp(saddr, daddr, len);
...
}
Will this regression compare memory starting from the page boundary instead of
the actual file offset? Could this lead to FIDEDUPERANGE incorrectly
deduplicating non-identical blocks and causing data corruption?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261010071453.6028-1-jianyungao89@gmail.com?part=1
next prev parent reply other threads:[~2026-10-10 7:35 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-10 7:14 [PATCH] dax: fix wrong size passed to dax_iomap_direct_access() in dax_range_compare_iter() jianyungao89
2026-10-10 7:35 ` sashiko-bot [this message]
2026-10-11 6:35 ` Jianyun Gao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-166309@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=jianyungao89@gmail.com \
--cc=nvdimm@lists.linux.dev \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.