All of lore.kernel.org
 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: 88+ 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-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 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.