Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Vikash Garodia" <vikash.garodia@oss.qualcomm.com>
Cc: virtualization@lists.linux.dev, devicetree@vger.kernel.org,
	robh@kernel.org, conor+dt@kernel.org,
	"Michael S. Tsirkin" <mst@redhat.com>,
	"Eugenio Perez" <eperezma@redhat.com>
Subject: Re: [PATCH v6 2/2] of: Add support for "iommu-ranges" on a device node
Date: Tue, 03 Nov 2026 15:49:58 +0000	[thread overview]
Message-ID: <sashiko-outbox-195658@kernel.org> (raw)
In-Reply-To: <20261103-add_iommu_ranges-v6-2-361f3921a133@oss.qualcomm.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] iommu: of_iommu_derive_resv_regions() corrupts iovad->anchor on 32-bit LPAE
- [High] iommu: of_iommu_derive_resv_regions() PHYS_ADDR_MAX end overflows merge
--

commit 138d9a14b5fdb2f77facac6b1fa8a670c0862071
Author: Vikash Garodia <vikash.garodia@oss.qualcomm.com>

of: Add support for "iommu-ranges" on a device node

This commit adds support for parsing the "iommu-ranges" device tree property
on a device node to derive reserved IOVA regions outside the usable ranges,
and restricts "iommu-addresses" on reserved-memory nodes to identity mappings
backed by a "reg" property.

> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index 5c266511db789..0428ceb50dec5 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -185,11 +185,118 @@ iommu_resv_region_get_type(struct device *dev,

[ ... ]

> +static void of_iommu_derive_resv_regions(struct device *dev, struct list_head *list)
> +{

[ ... ]

> +	list_for_each_entry_safe(pos, next_range, &ranges, node) {
> +		if (pos->start > next) {
> +			region = iommu_alloc_resv_region(next, pos->start - next, prot,
> +							 IOMMU_RESV_RESERVED, GFP_KERNEL);
> +			if (region)
> +				list_add_tail(&region->list, list);
> +		}
> +
> +		if (pos->end == PHYS_ADDR_MAX)
> +			goto exit;
> +
> +		if (pos->end >= next)
> +			next = pos->end + 1;
> +
> +		list_del(&pos->node);
> +		kfree(pos);
> +	}
> +
> +	region = iommu_alloc_resv_region(next, PHYS_ADDR_MAX - next + 1,
> +					 prot, IOMMU_RESV_RESERVED, GFP_KERNEL);
> +	if (region)
> +		list_add_tail(&region->list, list);

[Severity: Critical]
On 32-bit systems with 64-bit phys_addr_t and dma_addr_t (such as ARM LPAE
with CONFIG_PHYS_ADDR_T_64BIT=y), can reserving this trailing region up to
PHYS_ADDR_MAX corrupt iovad->anchor and lead to slab corruption when the
IOVA domain is freed?

In of_iommu_derive_resv_regions(), the trailing reserved region is allocated
with start = next and length = PHYS_ADDR_MAX - next + 1, giving it an
inclusive end address of 0xffffffffffffffffULL.

When a device attaches to a DMA domain, iova_reserve_iommu_regions() in
drivers/iommu/dma-iommu.c reserves each region:

    lo = iova_pfn(iovad, region->start);
    hi = iova_pfn(iovad, region->start + region->length - 1);
    reserve_iova(iovad, lo, hi);

Because iova_pfn() returns an unsigned long (32-bit on 32-bit architectures),
shifting 0xffffffffffffffffULL right by iova_shift(iovad) and truncating to
unsigned long yields hi = 0xffffffffUL, which is IOVA_ANCHOR (~0UL).

In drivers/iommu/iova.c:reserve_iova(), the upper-bound check compares
32-bit unsigned long values against (ULLONG_MAX >> iova_shift(iovad)), which
does not trigger on 32-bit LPAE. The rbtree walk then finds &iovad->anchor
(where pfn_lo = pfn_hi = IOVA_ANCHOR):

    for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) {
        if (__is_range_overlap(node, pfn_lo, pfn_hi)) {
            iova = to_iova(node);
            __adjust_overlap_range(iova, &pfn_lo, &pfn_hi);

__adjust_overlap_range() overwrites iovad->anchor.pfn_lo with lo. Later, when
put_iova_domain() tears down the domain and calls free_iova_mem(&iovad->anchor),
iova->pfn_lo != IOVA_ANCHOR is true and kmem_cache_free(iova_cache, &iovad->anchor)
is called on the anchor embedded inside struct iommu_dma_cookie.

[Severity: High]
Does setting the trailing reserved region's end to PHYS_ADDR_MAX also cause
unsigned integer wraparound in iommu_insert_resv_region() when merging
group reserved regions?

When iommu_get_group_resv_regions() merges device reserved regions through
iommu_insert_device_resv_regions() -> iommu_insert_resv_region() in
drivers/iommu/iommu.c:

    top_end = top->start + top->length - 1;

    if (iter->start > top_end + 1) {
        list_move_tail(&iter->list, &stack);
    } else {
        top->length = max(top_end, iter_end) - top->start + 1;

First, when top is a reserved region ending at top_end == PHYS_ADDR_MAX,
top_end + 1 wraps around to 0 in phys_addr_t arithmetic. Any subsequent
overlapping IOMMU_RESV_RESERVED region with iter->start > 0 satisfies
iter->start > 0 and fails to merge.

Second, if a reserved region starting at top->start == 0 is merged with an
overlapping or adjacent region ending at iter_end == PHYS_ADDR_MAX (for
instance, when two devices in the same IOMMU group have disjoint usable
iommu-ranges), max(top_end, iter_end) - top->start + 1 evaluates
PHYS_ADDR_MAX - 0 + 1, wrapping top->length around to 0.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261103-add_iommu_ranges-v6-0-361f3921a133@oss.qualcomm.com?part=2

      reply	other threads:[~2026-11-03 15:49 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-03 15:29 [PATCH v6 0/2] of_iommu: add support for "iommu-ranges" Vikash Garodia
2026-11-03 15:29 ` [PATCH v6 1/2] iommu: use resource_size_t for reserved region length Vikash Garodia
2026-11-03 15:46   ` sashiko-bot
2026-11-03 15:29 ` [PATCH v6 2/2] of: Add support for "iommu-ranges" on a device node Vikash Garodia
2026-11-03 15:49   ` sashiko-bot [this message]

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-195658@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=eperezma@redhat.com \
    --cc=mst@redhat.com \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vikash.garodia@oss.qualcomm.com \
    --cc=virtualization@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox