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

Sergio Lopez Pascual <[email protected]>
Newsgroups org.kernel.vger.kvm,org.kernel.vger.linux-kernel
Message-ID <CAAiTLFUFDa5X+Gg6WKeovcs5h3D9kDRaU1MYFRKdspkJSpiusA@mail.gmail.com>
Sean Christopherson <[email protected]> writes:

> On Fri, Jul 31, 2026, Sergio Lopez Pascual wrote:
>> Sean Christopherson <[email protected]> writes:
>>
>> > On Wed, Jul 29, 2026, Sergio Lopez wrote:
>> >> After 28e39181 ("drm/gem-shmem: Track folio accessed/dirty status in
>> >> mmap") was merged, a guest write to an unpopulated PTE from a mapping
>> >> backed by a DRM GEM BO triggers a VM exit with EFAULT, with
>> >> hva_to_pfn_remapped setting p_pfn to KVM_PFN_ERR_RO_FAULT.
>> >>
>> >> This happens because that commit implements pfn_mkwrite for
>> >> drm_gem_shmem_vm_ops. With that function present, vma_wants_writenotify
>> >> returns true in vma_set_page_prot, clearing VM_SHARED and leading to the
>> >> entry to be installed as read-only. This is done on purpose so the
>> >> fault handler gets notified when the entry is going to be written.
>> >>
>> >> In KVM, hva_to_pfn_remapped calls to fixup_user_fault to trigger the
>> >> fault handler but, as seen above, this one might install a read-only PTE
>> >> even with FAULT_FLAG_WRITE present in fault_flags. The check at the end
>> >> of hva_to_pfn_remapped notices that the entry is not writable despite
>> >> this being a write fault and sets p_pfn to KVM_PFN_ERR_RO_FAULT.
>> >>
>> >> To address this issue, have hva_to_pfn_remapped issue a second
>> >> fixup_user_fault call when needed for write-upgrading the PTE.
>> >>
>> >> Signed-off-by: Sergio Lopez <[email protected]>
>> >> ---
>> >
>> > NAK, this doesn't belong in KVM.  Expecting callers of fixup_user_fault() to
>> > retry a FAULT_FLAG_WRITE fault on *success* is absurd.  Either manually do the
>> > retry in fixup_user_fault(), or return VM_FAULT_RETRY so that KVM will naturally
>> > retry.  I assume the latter is the correct approach.
>>
>> The issue goes beyond fixup_user_fault() behavior. If we're faulting on
>> a page which already has a ready-only PTE installed,
>> follow_pfnmap_start() returns success, fixup_user_fault isn't called at
>> all, and we're still hitting the "(write_fault && !args.writable)"
>> condition, setting p_pfn to KVM_PFN_ERR_RO_FAULT.
>>
>> Without this change, KVM can't deal with VM_PFNMAP vmas with read-only
>> PTEs installed.
>
> IMO, that's a bug in the APIs.  If a normal #PF handler looked at a write fault
> and decided a read-only mapping sufficed, that would be a bug.  I don't see why
> this is any different.

In the scenario I've described above, were a read-only PTE has been
installed on a fault generated by a read access, and a second fault is
generated later when writting to the page, we aren't invoking any #PF
handler. The call graph looks (roughly) like this:

          kvm_handle_guest_abort()
            ├─ gfn_to_memslot() → gfn_to_hva()
            └─ user_mem_abort()
                └─ kvm_s2_fault_pin_pfn()
                    └─ __kvm_faultin_pfn()
                        └─ hva_to_pfn()
                            ├─ hva_to_pfn_fast()
                            ├─ hva_to_pfn_slow()
                            └─ hva_to_pfn_remapped()

GUP rejects VM_PFNMAP vmas, and hva_to_pfn_remapped() is not calling
fixup_user_fault() because follow_pfnmap_start() finds the PTE. So no
fault handler is involved in this path.

Thanks,
Sergio.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.