From: Jinyu Tang <jinyu.tang@linux.dev>
To: Anup Patel <anup@brainfault.org>,
Anup Patel <apatel@ventanamicro.com>,
Atish Patra <atish.patra@linux.dev>
Cc: kvm@vger.kernel.org, kvm-riscv@lists.infradead.org,
linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org,
Paolo Bonzini <pbonzini@redhat.com>,
Sean Christopherson <seanjc@google.com>,
Paul Walmsley <pjw@kernel.org>,
Paul Walmsley <paul.walmsley@sifive.com>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>,
Alexandre Ghiti <alex@ghiti.fr>,
Andrew Jones <andrew.jones@oss.qualcomm.com>,
Conor Dooley <conor.dooley@microchip.com>,
Yong-Xuan Wang <yongxuan.wang@sifive.com>,
Nutty Liu <nutty.liu@hotmail.com>, Jinyu Tang <tjytimi@163.com>,
Jinyu Tang <jinyu.tang@linux.dev>,
Sashiko <sashiko-bot@kernel.org>
Subject: [PATCH] KVM: riscv: Avoid overwriting existing G-stage tables with huge leaves
Date: Fri, 14 Aug 2026 06:57:52 -0400 [thread overview]
Message-ID: <20260814105752.565325-1-jinyu.tang@linux.dev> (raw)
RISC-V KVM can overwrite an existing G-stage table entry when installing
a huge leaf mapping. If the target huge range already has a lower-level
page table, kvm_riscv_gstage_set_pte() can replace the non-leaf entry
with a leaf PTE. This disconnects the lower-level page table and can
change guest-visible mappings or leak the page-table page.
Reject replacing a valid non-leaf PTE with a leaf PTE. If huge-page
installation hits such a conflict, fall back to a 4K mapping for the
faulting GPA and leave the existing page-table structure intact.
Suggested-by: Sashiko <sashiko-bot@kernel.org>
Fixes: 9d05c1fee837 ("RISC-V: KVM: Implement stage2 page table programming")
Signed-off-by: Jinyu Tang <jinyu.tang@linux.dev>
---
arch/riscv/kvm/gstage.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kvm/gstage.c b/arch/riscv/kvm/gstage.c
index e5002cb9cbef..23cb35e36073 100644
--- a/arch/riscv/kvm/gstage.c
+++ b/arch/riscv/kvm/gstage.c
@@ -174,6 +174,12 @@ int kvm_riscv_gstage_set_pte(struct kvm_gstage *gstage,
if (pte_val(*ptep) != pte_val(map->pte)) {
bool was_invalid = !pte_val(*ptep);
+
+ /* Avoid replacing an existing lower-level table with a leaf mapping. */
+ if (!gstage_pte_leaf(ptep) && !was_invalid &&
+ gstage_pte_leaf(&map->pte))
+ return -EEXIST;
+
set_pte(ptep, map->pte);
if (gstage_pte_leaf(ptep) &&
!(was_invalid && riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC)))
@@ -211,12 +217,13 @@ int kvm_riscv_gstage_map_page(struct kvm_gstage *gstage,
struct kvm_gstage_mapping *out_map)
{
bool found_leaf;
+ phys_addr_t huge_page_offset;
u32 ptep_level;
pgprot_t prot;
pte_t *ptep;
int ret;
- out_map->addr = gpa;
+ out_map->addr = gpa & PAGE_MASK;
out_map->level = 0;
ret = gstage_page_size_to_level(gstage, page_size, &out_map->level);
@@ -287,7 +294,18 @@ int kvm_riscv_gstage_map_page(struct kvm_gstage *gstage,
out_map->pte = pfn_pte(PFN_DOWN(hpa), prot);
out_map->pte = pte_mkdirty(out_map->pte);
- return kvm_riscv_gstage_set_pte(gstage, pcache, out_map);
+ ret = kvm_riscv_gstage_set_pte(gstage, pcache, out_map);
+ if (ret == -EEXIST) {
+ huge_page_offset = out_map->addr & (page_size - 1);
+ hpa += huge_page_offset;
+ out_map->level = 0;
+ out_map->pte = pfn_pte(PFN_DOWN(hpa), prot);
+ out_map->pte = pte_mkdirty(out_map->pte);
+
+ ret = kvm_riscv_gstage_set_pte(gstage, pcache, out_map);
+ }
+
+ return ret;
}
static inline unsigned long make_child_pte(unsigned long huge_pte, int index,
--
2.43.0
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
reply other threads:[~2026-08-14 10:58 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=20260814105752.565325-1-jinyu.tang@linux.dev \
--to=jinyu.tang@linux.dev \
--cc=alex@ghiti.fr \
--cc=andrew.jones@oss.qualcomm.com \
--cc=anup@brainfault.org \
--cc=aou@eecs.berkeley.edu \
--cc=apatel@ventanamicro.com \
--cc=atish.patra@linux.dev \
--cc=conor.dooley@microchip.com \
--cc=kvm-riscv@lists.infradead.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=nutty.liu@hotmail.com \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.com \
--cc=pbonzini@redhat.com \
--cc=pjw@kernel.org \
--cc=sashiko-bot@kernel.org \
--cc=seanjc@google.com \
--cc=tjytimi@163.com \
--cc=yongxuan.wang@sifive.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