From: Dan Carpenter <dan@cryspen.com>
To: Eric Auger <eric.auger@redhat.com>
Cc: "Marc Zyngier" <maz@kernel.org>,
"Oliver Upton" <oupton@kernel.org>,
"Fuad Tabba" <fuad.tabba@linux.dev>,
"Joey Gouly" <joey.gouly@arm.com>,
"Steffen Eiden" <seiden@linux.ibm.com>,
"Suzuki K Poulose" <suzuki.poulose@arm.com>,
"Zenghui Yu" <yuzenghui@huawei.com>,
"Catalin Marinas" <catalin.marinas@arm.com>,
"Will Deacon" <will@kernel.org>,
"Mark Rutland" <mark.rutland@arm.com>,
"Sascha Bischoff" <Sascha.Bischoff@arm.com>,
"Timothy Hayes" <timothy.hayes@arm.com>,
"Jonathan Cameron" <jic23@kernel.org>,
"Christoffer Dall" <cdall@linaro.org>,
linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
linux-kernel@vger.kernel.org,
"Karthik Bhargavan" <karthik@pereq.eu>,
"Clément Blaudeau" <clement@cryspen.com>
Subject: [PATCH v2] KVM: arm64: vgic: Don't truncate offsets in vgic_find_mmio_region()
Date: Wed, 11 Nov 2026 14:02:04 +0300 [thread overview]
Message-ID: <avRLLMOiudnKoSlk@stanley.mountain> (raw)
In vgic_its_has_attr_regs() and vgic_its_attr_regs_access() we take a
u64 "offset" from the user and pass it to vgic_find_mmio_region() to
find the correct region. The problem is that vgic_find_mmio_region()
truncates the "offset" to 32 bits so we might find a region even
though really we shouldn't.
Later the untruncated offset is used to calculate "addr".
addr = its->vgic_its_base + offset;
For example, an offset of 0x100000084 finds the 64-bit GITS_CBASER
register at 0x80, and the write reaches update_64bit_reg() with an
offset of 4 into the register and a length of 8. It exhibits as a
UBSAN warning.
[ 183.796046] UBSAN: shift-out-of-bounds in arch/arm64/kvm/vgic/vgic-mmio-v3.c:35:10
[ 183.796198] shift exponent 18446744073709551584 is too large for 64-bit type 'long long unsigned int'
The GICv5 IRS code has the same problem in vgic_v5_has_attr_regs() and
vgic_v5_irs_attr_regs_access().
Make vgic_find_mmio_region() and match_region() take the offset as a
u64, so an offset of 2^32 or more no longer matches any region. The
other callers only pass offsets which fit in 32 bits so they are not
affected.
Fortunately the effect of this bug is very minor. The worst case is that
the VMM accesses an emulated register and sets something nonsensical
and users are already allowed to do that without the bug.
Fixes: 8331c23c28e8 ("KVM: arm64: vgic-its: Implement vgic_its_has_attr_regs and attr_regs_access")
Fixes: 71091136d145 ("KVM: arm64: gic-v5: Handle userspace accesses to IRS MMIO region")
Signed-off-by: Dan Carpenter <dan@cryspen.com>
---
v2: Change vgic_find_mmio_region() to take a u64 instead of rejecting
large offsets in the ITS callers, as Marc suggested. This also
fixes the GICv5 IRS code which my previous patch didn't. Drop the
Cc: stable.
arch/arm64/kvm/vgic/vgic-mmio.c | 4 ++--
arch/arm64/kvm/vgic/vgic-mmio.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c
index fddb9da0403d..59bdec495cd7 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio.c
@@ -820,7 +820,7 @@ void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
static int match_region(const void *key, const void *elt)
{
- const unsigned int offset = (unsigned long)key;
+ const u64 offset = (unsigned long)key;
const struct vgic_register_region *region = elt;
if (offset < region->reg_offset)
@@ -834,7 +834,7 @@ static int match_region(const void *key, const void *elt)
const struct vgic_register_region *
vgic_find_mmio_region(const struct vgic_register_region *regions,
- int nr_regions, unsigned int offset)
+ int nr_regions, u64 offset)
{
return bsearch((void *)(uintptr_t)offset, regions, nr_regions,
sizeof(regions[0]), match_region);
diff --git a/arch/arm64/kvm/vgic/vgic-mmio.h b/arch/arm64/kvm/vgic/vgic-mmio.h
index 38ed730d68ac..6c3c4de6883e 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio.h
+++ b/arch/arm64/kvm/vgic/vgic-mmio.h
@@ -228,6 +228,6 @@ u64 vgic_sanitise_field(u64 reg, u64 field_mask, int field_shift,
/* Find the proper register handler entry given a certain address offset */
const struct vgic_register_region *
vgic_find_mmio_region(const struct vgic_register_region *regions,
- int nr_regions, unsigned int offset);
+ int nr_regions, u64 offset);
#endif
--
2.53.0
reply other threads:[~2026-11-11 11:02 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=avRLLMOiudnKoSlk@stanley.mountain \
--to=dan@cryspen.com \
--cc=Sascha.Bischoff@arm.com \
--cc=catalin.marinas@arm.com \
--cc=cdall@linaro.org \
--cc=clement@cryspen.com \
--cc=eric.auger@redhat.com \
--cc=fuad.tabba@linux.dev \
--cc=jic23@kernel.org \
--cc=joey.gouly@arm.com \
--cc=karthik@pereq.eu \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=seiden@linux.ibm.com \
--cc=suzuki.poulose@arm.com \
--cc=timothy.hayes@arm.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/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
all inboxes | Powered by JetHome®