Re: [PATCH] KVM: have hva_to_pfn_remapped write-upgrade PTEs

Sergio Lopez Pascual <[email protected]> Thu, 30 Jul 2026 04:36:52 -0400
Newsgroups dev.linux.lists.sashiko-reviews,org.kernel.vger.kvm
Message-ID <CAAiTLFVTN-KWF3hzPxB-RR6SuLF+9JAWbrLA2um7ZkgXUcdxAw@mail.gmail.com>
[email protected] writes:

> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] Incomplete fix for VM_PFNMAP write-upgrades, bypassing already-populated read-only PTEs
> --
>
> --- Patch [1]: [PATCH] KVM: have hva_to_pfn_remapped write-upgrade PTEs ---
> commit 8ea7b308a68b0aabea9b703efac8ec9af51170aa
> Author: Sergio Lopez <[email protected]>
> Subject: KVM: have hva_to_pfn_remapped write-upgrade PTEs
>
> This patch introduces a second fixup_user_fault call to handle
> write-upgrades for VM_PFNMAP mappings that install read-only PTEs on
> write faults (such as DRM GEM BOs).
>
>> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
>> index b4baa69a55402..b7fb9278f198b 100644
>> --- a/virt/kvm/kvm_main.c
>> +++ b/virt/kvm/kvm_main.c
>> @@ -2958,6 +2958,8 @@ static int hva_to_pfn_remapped(struct vm_area_struct *vma,
> [ ... ]
>>  	r = follow_pfnmap_start(&args);
>>  	if (r) {
>>  		/*
>>  		 * get_user_pages fails for VM_IO and VM_PFNMAP vmas and does
>>  		 * not call the fault handler, so do it here.
>>  		 */
>>  		bool unlocked = false;
>> +		bool write_upgrade = false;
>> +do_write_upgrade:
>>  		r = fixup_user_fault(current->mm, kfp->hva,
>>  				     (write_fault ? FAULT_FLAG_WRITE : 0),
>>  				     &unlocked);
>> @@ -2969,6 +2971,17 @@ static int hva_to_pfn_remapped(struct vm_area_struct *vma,
>>  		r = follow_pfnmap_start(&args);
>>  		if (r)
>>  			return r;
>> +
>> +		if (write_fault && !args.writable && !write_upgrade) {
>> +			/*
>> +			 * VM_PFNMAP fault handlers may install read-only PTEs
>> +			 * via vmf_insert_pfn(), deferring the write upgrade to
>> +			 * a second fault. Trigger that upgrade now.
>> +			 */
>> +			write_upgrade = true;
>> +			follow_pfnmap_end(&args);
>> +			goto do_write_upgrade;
>> +		}
>>  	}
>>
>>  	if (write_fault && !args.writable) {
>         ^^^^
>
> [Severity: High]
> This is a pre-existing issue, but does this placement miss the case where
> the PTE is already populated but read-only?
>
> If a guest first reads from the DRM GEM BO, triggering a read fault, the
> DRM GEM fault handler installs a read-only PTE. If the guest later attempts
> to write to the same page, hva_to_pfn_remapped() calls follow_pfnmap_start(),
> which finds the read-only PTE and returns 0 (success).
>
> Since r == 0, the entire if (r) block containing the new write upgrade logic
> is bypassed. The code then reaches this check and incorrectly returns
> KVM_PFN_ERR_RO_FAULT instead of performing the write upgrade.
>
> Should the upgrade logic be placed outside of the if (r) block so it can also
> handle already-populated read-only PTEs?

Yes, I've confirmed this scenario is possible. I'll send a v2.

Thanks,
Sergio.