Linux KVM/arm64 development list
 help / color / mirror / Atom feed
From: Tian Zheng <zhengtian10@huawei.com>
To: <sashiko-reviews@lists.linux.dev>
Cc: <kvm@vger.kernel.org>, <kvmarm@lists.linux.dev>,
	Oliver Upton <oupton@kernel.org>, Marc Zyngier <maz@kernel.org>
Subject: Re: [PATCH v4 6/6] KVM: arm64: Add auto HDBSS enable/disable on dirty logging change
Date: Mon, 31 Aug 2026 20:23:26 +0800	[thread overview]
Message-ID: <8a593c94-3fa5-4504-bbd3-4f9bbaf78264@huawei.com> (raw)
In-Reply-To: <20260709113436.951C81F000E9@smtp.kernel.org>



On 7/9/2026 7:34 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 8 potential issue(s) to consider:
> - [Critical] Freeing HDBSS buffers synchronously in `kvm_arm_disable_hdbss_global()` without kicking vCPUs causes a hardware Use-After-Free and host memory corruption.
> - [High] The patch fails to enforce eager page table splitting when `KVM_DIRTY_LOG_INITIALLY_SET` is used, violating the HDBSS requirement.
> - [High] Global enable/disable functions mutate per-vCPU HDBSS state across all vCPUs without proper locking or KVM request mechanisms.
> - [High] Missing `kvm_unshare_hyp()` on the vCPU creation error path breaks pKVM memory ownership.
> - [High] Memslots are accessed without SRCU protection when flushing the HDBSS buffer.
> - [Medium] The dynamically calculated HDBSS buffer order is never saved, causing newly created vCPUs to allocate incorrect 1-page buffers.
> - [Medium] A conditional check in `kvm_arm_vcpu_destroy` leaks HDBSS buffers if a TOCTOU race left a vCPU with an allocated buffer while `enable_hdbss` is false.
> - [Medium] Missing immediate Context Synchronization Events (ISB) for control-plane system registers.
> --
> 
> --- Patch [6]: [PATCH v4 6/6] KVM: arm64: Add auto HDBSS enable/disable on dirty logging change ---
> commit c993a05c79f4338df277681c6534d32f65490e56
> Author: eillon <yezhenyu2@huawei.com>
> 
> KVM: arm64: Add auto HDBSS enable/disable on dirty logging change
> 
> This commit adds VM-level HDBSS enable/disable support tied to dirty logging
> changes. It automatically enables HDBSS when dirty logging starts and disables
> it when all memslots stop dirty logging.
> 
>> diff --git a/arch/arm64/kvm/dirty_bit.c b/arch/arm64/kvm/dirty_bit.c
>> index 002366337637c..c5bf866c23ef2 100644
>> --- a/arch/arm64/kvm/dirty_bit.c
>> +++ b/arch/arm64/kvm/dirty_bit.c
> [ ... ]
>> +static int kvm_arm_enable_hdbss_global(struct kvm *kvm)
>> +{
>> +	int err;
>> +	unsigned long i;
>> +	unsigned int order;
>> +	struct kvm_vcpu *vcpu;
> [ ... ]
>> +	/* Turn it on */
>> +	order = hdbss_auto_select_order(kvm);
>> +	kvm_for_each_vcpu(i, vcpu, kvm) {
>> +		err = kvm_arm_vcpu_alloc_hdbss(vcpu, order);
> 
> [Severity: Medium]
> Will newly created vCPUs allocate buffers of the correct size?
> 
> The optimal HDBSS buffer order is calculated here based on memslot sizes and
> used to allocate buffers for currently online vCPUs, but the value doesn't
> seem to be saved to kvm->arch.hdbss_order.
> 
> When a new vCPU is created later, it appears kvm_arch_vcpu_create() allocates
> its buffer using the uninitialized kvm->arch.hdbss_order:
> 
> arch/arm64/kvm/arm.c:kvm_arch_vcpu_create() {
>      ...
>      err = kvm_arm_vcpu_alloc_hdbss(vcpu, vcpu->kvm->arch.hdbss_order);
>      ...
> }
> 
> Could this cause new vCPUs to receive order-0 buffers instead of the
> dynamically selected size, leading to mismatched sizes and excessive
> buffer-full exits?
> 

Addressed by redesign in v5. The dynamic order calculation is removed.
The buffer size is now stored in kvm->arch.hdbss_buffer_size (bytes),
set either by the user via KVM_CAP_ARM_HDBSS_BUFFER_SIZE (before vCPU
creation), or by kvm_arch_dirty_ring_size_updated() when dirty-ring is
configured, or defaults to PAGE_SIZE. Since it is stored in kvm->arch
before any vCPU exists, all vCPUs — including later-created ones —
allocate a consistent size.

> [Severity: High]
> Is it safe to directly mutate per-vCPU HDBSS state across all vCPUs from the
> thread handling the memslot ioctl?
> 
> This loop directly calls kvm_arm_vcpu_alloc_hdbss() to mutate vcpu->arch.hdbss
> without holding vcpu->mutex or using the KVM vCPU requests framework.
> 
> Could concurrently running vCPUs undergoing a context switch (like
> __load_hdbss) or fault path read partially updated, torn, or freed state,
> leading to unpredictable hardware register programming?
> 
>> +		if (err)
>> +			goto error_alloc;
>> +	}
> [ ... ]
>> +void kvm_arm_disable_hdbss_global(struct kvm *kvm)
>> +{
>> +	unsigned long i;
>> +	struct kvm_vcpu *vcpu;
>> +
>> +	if (!kvm->arch.enable_hdbss) /* Already Off */
>> +		return;
>> +
>> +	/* Turn it off */
>> +	kvm->arch.mmu.vtcr &= ~(VTCR_EL2_HD | VTCR_EL2_HDBSS | VTCR_EL2_HA);
>> +
>> +	kvm_for_each_vcpu(i, vcpu, kvm)
>> +		kvm_arm_vcpu_free_hdbss(vcpu);
> 

Addressed by redesign in v5. Enable/disable no longer touch any per-vCPU 
state. Buffers are pre-allocated at vCPU creation, and enable/disable 
only flips VTCR bits in kvm->arch.mmu.vtcr (a VM-level field written 
only from the memslot-ioctl path under slots_lock) followed by a kick. 
vCPUs pick up the new VTCR when __load_stage2() reprograms vtcr_el2 on 
re-entry.


> [Severity: Critical]
> Does this code risk hardware use-after-free and host memory corruption?
> 
> When dirty logging is disabled, the enable_hdbss flag and VTCR_EL2 bits are
> cleared, and the physical pages are immediately freed. Since this occurs under
> kvm->slots_lock, which does not prevent vCPUs from executing in guest mode,
> running vCPUs could continue executing with their hardware VTCR_EL2 and
> HDBSSBR_EL2 registers still active.
> 
> Should this function force running vCPUs to exit (e.g., via kvm_vcpu_kick() or
> a KVM request) before freeing the physical pages to prevent the hardware MMU
> from asynchronously writing dirty page records into newly freed memory?
> 
>> +
>> +	kvm->arch.enable_hdbss = false;
>> +}
> [ ... ]
>> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
>> index 949fb895add6a..484f48dae0003 100644
>> --- a/arch/arm64/kvm/mmu.c
>> +++ b/arch/arm64/kvm/mmu.c
>> @@ -2588,6 +2588,9 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
>>   {
>>   	bool log_dirty_pages = new && new->flags & KVM_MEM_LOG_DIRTY_PAGES;
> [ ... ]
>>   	if (log_dirty_pages) {
>>   
>>   		if (change == KVM_MR_DELETE)
>>   			return;
>>   
>>   		/*
>>   		 * Huge and normal pages are write-protected and split
>>   		 * on either of these two cases:
>>   		 *
>>   		 * 1. with initial-all-set: gradually with CLEAR ioctls,
>>   		 */
>>   		if (kvm_dirty_log_manual_protect_and_init_set(kvm))
>>   			return;
> 

Valid point, addressed by redesign in v5. kvm_arm_disable_hdbss_global() 
no longer frees buffers at all — it only clears the VTCR HDBSS bits and 
kicks vCPUs out of guest mode via KVM_REQ_OUTSIDE_GUEST_MODE. Buffers 
are allocated at vCPU creation and freed only at vCPU destruction 
(PML-style), so there is no window where the MMU can write into freed 
memory.

> [Severity: High]
> Does this early return violate the HDBSS requirement for eager page table
> splitting?
> 
> The commit message states that enabling HDBSS requires disabling lazy split so
> that all block mappings are eagerly broken down before the buffer starts
> recording. However, if userspace utilizes KVM_DIRTY_LOG_INITIALLY_SET, this
> path returns early without calling kvm_mmu_split_memory_region().
> 
> Since HDBSS was already globally enabled earlier in this function, could it
> now operate on block mappings instead of page-granularity tables, defeating
> the hardware expectation and corrupting the dirty log state?
> 

Not an issue in the v5 design. With KVM_DIRTY_LOG_INITIALLY_SET, 
userspace clears the bitmap via CLEAR ioctls; the clear path 
write-protects, and v5's wrprotect strips DBM from blocks (->RO) so the 
first write faults and triggers the split, while level-3 pages go WC 
(DBM=1, S2AP_W=0) and are re-tracked by HDBSS. Since v5 supports lazy 
split in the HDBSS flow, the early return on INITIALLY_SET does not 
break dirty tracking.


> [Severity: Medium]
> Can a Time-of-Check to Time-of-Use (TOCTOU) race leak HDBSS buffers during
> vCPU destruction?
> 
> Looking at kvm_arm_vcpu_destroy() in arch/arm64/kvm/reset.c:
> 
> kvm_arm_vcpu_destroy() {
>      ...
>      if (vcpu->kvm->arch.enable_hdbss)
>          kvm_arm_vcpu_free_hdbss(vcpu);
>      ...
> }
> 
> If KVM_CREATE_VCPU allocates an HDBSS buffer but kvm_arm_disable_hdbss_global()
> runs before the vCPU is added to online_vcpus, the global disable loop would
> miss the vCPU and clear enable_hdbss. When the VM is destroyed, the condition
> would evaluate to false, skipping the cleanup.
> 
> Since kvm_arm_vcpu_free_hdbss() natively checks for the existence of the
> buffer, is the outer check against enable_hdbss necessary?
> 

Addressed in v5. kvm_arm_vcpu_destroy() calls kvm_arm_vcpu_free_hdbss() 
unconditionally (the function itself checks for buffer existence), and 
the enable_hdbss conditional — along with the flag itself — no longer 
exists.

> [Severity: High]
> Does the vCPU creation error path break pKVM memory ownership by missing a
> call to kvm_unshare_hyp()?
> 
> In arch/arm64/kvm/arm.c, kvm_arch_vcpu_create() shares the vCPU struct memory
> with the hypervisor. If the new allocation fails, the function cleans up and
> returns the error:
> 
> kvm_arch_vcpu_create() {
>      ...
>      if (vcpu->kvm->arch.enable_hdbss) {
>          err = kvm_arm_vcpu_alloc_hdbss(vcpu, vcpu->kvm->arch.hdbss_order);
>          if (err)
>              kvm_vgic_vcpu_destroy(vcpu);
>      }
> 
>      return err;
> }
> 
> Could the memory for the vcpu struct be subsequently freed back to the host
> allocator while still marked as shared with the hypervisor, violating pKVM
> trust boundaries and triggering a hypervisor panic upon reuse?
> 

Not applicable. HDBSS is VHE-only. The error path does not touch pKVM 
ownership — it simply cleans up the local allocation. pKVM support is 
explicitly out of scope and left as future work.

> [Severity: High]
> Does flushing the HDBSS buffer access memslots without SRCU protection?
> 
> kvm_flush_hdbss_buffer() processes dirty pages by resolving GFNs via
> kvm_vcpu_mark_page_dirty():
> 
> arch/arm64/kvm/dirty_bit.c:kvm_flush_hdbss_buffer() {
>      ...
>      kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
>      ...
> }
> 
> This internal function requires srcu_read_lock(&kvm->srcu) to safely access
> the KVM memslots array. However, kvm_flush_hdbss_buffer() is invoked from
> kvm_arch_vcpu_put() and check_vcpu_requests(), neither of which hold the SRCU
> read lock.
> 
> Could this create a use-after-free risk when memslots are concurrently
> modified?
> 

Valid point, addressed in v5. kvm_flush_hdbss_buffer() now holds 
srcu_read_lock(&kvm->srcu) around the loop that resolves GFNs through 
the memslots, and releases it before resetting HDBSSPROD_EL2.

> [Severity: Medium]
> Are immediate Context Synchronization Events (ISB) missing for control-plane
> system registers?
> 
> The ARM64 subsystem rules require that every write to a control-plane system
> register must be followed by an isb() as the very next instruction.
> 
> In arch/arm64/kvm/dirty_bit.c, a memory store executes between the write and
> the isb():
> 
> kvm_flush_hdbss_buffer() {
>      ...
>      write_sysreg_s(0, SYS_HDBSSPROD_EL2);
>      vcpu->arch.hdbss.hdbssprod_el2 = 0;
>      isb();
>      ...
> }
> 
> Similarly, in arch/arm64/kvm/hyp/vhe/switch.c, two sysreg writes occur
> back-to-back without an intervening isb():
> 
> __load_hdbss() {
>      ...
>      write_sysreg_s(vcpu->arch.hdbss.hdbssbr_el2, SYS_HDBSSBR_EL2);
>      write_sysreg_s(vcpu->arch.hdbss.hdbssprod_el2, SYS_HDBSSPROD_EL2);
>      ...
> }
> 
> Could these patterns risk observing undefined pipeline state?
>


Duplicate of the ISB comments on patches 4/5.

Thanks!
Tian



  reply	other threads:[~2026-08-31 12:23 UTC|newest]

Thread overview: 90+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-09 10:40 [PATCH v4 0/6] Support the FEAT_HDBSS introduced in Armv9.5 Tian Zheng
2026-07-09 10:40 ` [PATCH v4 1/6] KVM: arm64: Enable eager hugepage splitting if HDBSS is available Tian Zheng
2026-07-09 11:03   ` sashiko-bot
2026-08-31  8:52     ` Tian Zheng
2026-07-09 10:40 ` [PATCH v4 2/6] KVM: arm64: Add support for FEAT_HDBSS Tian Zheng
2026-07-09 11:00   ` sashiko-bot
2026-08-31  8:55     ` Tian Zheng
2026-07-09 10:40 ` [PATCH v4 3/6] KVM: arm64: Add auto DBM support for hardware dirty tracking Tian Zheng
2026-07-09 11:14   ` sashiko-bot
2026-08-31  9:14     ` Tian Zheng
2026-07-13 11:17   ` Leonardo Bras
2026-07-14  1:14     ` Tian Zheng
2026-07-14  7:23       ` Marc Zyngier
2026-07-14  7:44         ` Tian Zheng
2026-07-14 10:20           ` Leonardo Bras
2026-07-16  7:39   ` Oliver Upton
2026-07-17  3:58     ` Tian Zheng
2026-07-17 15:21       ` Leonardo Bras
2026-07-20 12:58         ` Leonardo Bras
2026-07-29  8:51           ` Tian Zheng
2026-07-29 15:16             ` Leonardo Bras
2026-08-03  1:33               ` Tian Zheng
2026-08-03  4:04                 ` Tian Zheng
2026-08-03 10:21                   ` Leonardo Bras
2026-08-03 13:57                     ` Tian Zheng
2026-08-03 16:32                       ` Leonardo Bras
2026-08-03 16:34                         ` Leonardo Bras
2026-08-04  4:54                         ` Tian Zheng
2026-08-04 11:10                           ` Leonardo Bras
2026-08-05  3:41                             ` Tian Zheng
2026-08-10 11:01                               ` Leonardo Bras
2026-08-21 15:58                                 ` Leonardo Bras
2026-08-31 12:36                                   ` Tian Zheng
2026-09-01 17:22                                     ` Leonardo Bras
2026-09-07  3:17                                       ` Tian Zheng
2026-09-07 10:50                                         ` Leonardo Bras
2026-08-31 12:33                                 ` Tian Zheng
2026-08-05  3:43                             ` Tian Zheng
2026-07-28  8:49         ` Tian Zheng
2026-07-09 10:40 ` [PATCH v4 4/6] KVM: arm64: Add HDBSS per-vCPU buffer management Tian Zheng
2026-07-09 11:15   ` sashiko-bot
2026-08-31  9:37     ` Tian Zheng
2026-07-13 13:39   ` Leonardo Bras
2026-07-14  7:15     ` Tian Zheng
2026-07-14 10:47       ` Leonardo Bras
2026-07-15  9:16         ` Tian Zheng
2026-07-15 14:28           ` Leonardo Bras
2026-07-17  4:06             ` Tian Zheng
2026-07-09 10:40 ` [PATCH v4 5/6] KVM: arm64: Add HDBSS fault handling and buffer flush Tian Zheng
2026-07-09 11:26   ` sashiko-bot
2026-08-31 13:57     ` Tian Zheng
2026-07-13 14:06   ` Leonardo Bras
2026-07-14  7:38     ` Tian Zheng
2026-07-14 10:50       ` Leonardo Bras
2026-07-14 13:27         ` Tian Zheng
2026-07-14 14:19           ` Leonardo Bras
2026-07-17  6:51             ` Tian Zheng
2026-07-17 15:44               ` Leonardo Bras
2026-07-21  8:53                 ` Inochi Amaoto
2026-07-21 14:18                   ` Leonardo Bras
2026-07-22  5:14                     ` Inochi Amaoto
2026-07-22 11:04                       ` Leonardo Bras
2026-07-23  1:17                         ` Inochi Amaoto
2026-07-28  7:52                     ` Tian Zheng
2026-07-29 15:30                       ` Leonardo Bras
2026-08-03  3:15                         ` Tian Zheng
2026-08-03 10:43                           ` Leonardo Bras
2026-08-04  8:26                             ` Tian Zheng
2026-08-03  3:22                 ` Tian Zheng
2026-08-03 10:24                   ` Leonardo Bras
2026-07-09 10:40 ` [PATCH v4 6/6] KVM: arm64: Add auto HDBSS enable/disable on dirty logging change Tian Zheng
2026-07-09 11:34   ` sashiko-bot
2026-08-31 12:23     ` Tian Zheng [this message]
2026-07-13 14:50   ` Leonardo Bras
2026-07-14  8:58     ` Tian Zheng
2026-07-14 11:16       ` Leonardo Bras
2026-07-14 14:33         ` Leonardo Bras
2026-07-16  8:37           ` Tian Zheng
2026-07-17  7:23         ` Tian Zheng
2026-07-17 15:50           ` Leonardo Bras
2026-07-16  7:15     ` Tian Zheng
2026-07-17 15:53       ` Leonardo Bras
2026-07-13 10:31 ` [PATCH v4 0/6] Support the FEAT_HDBSS introduced in Armv9.5 Leonardo Bras
2026-07-13 16:27   ` Leonardo Bras
2026-07-14 10:39     ` Tian Zheng
2026-07-14 11:20       ` Leonardo Bras
2026-07-14 13:29         ` Tian Zheng
2026-07-14  9:37   ` Tian Zheng
2026-07-14 10:19     ` Leonardo Bras
2026-07-14 13:34       ` Tian Zheng

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=8a593c94-3fa5-4504-bbd3-4f9bbaf78264@huawei.com \
    --to=zhengtian10@huawei.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.linux.dev \
    --cc=maz@kernel.org \
    --cc=oupton@kernel.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox