On Tue, May 24, 2022 at 08:22:30PM +0000, Sean Christopherson wrote: > On Sun, May 22, 2022, Hyeonggon Yoo wrote: > > On Mon, May 16, 2022 at 07:04:32AM -0700, Dave Hansen wrote: > > > I was thinking of something more along the lines of taking the > > > set_memory.c code and ensuring that it never sets (or even observes) > > > _PAGE_BIT_GLOBAL on a _PAGE_USER mapping. > > > > Yeah that would be a bit more explicit solution. > > > > > There was also a question of > > > if set_memory.c is ever used on userspace mappings. It would be good to > > > validate whether it's possible in-tree today and if not, enforce that > > > _PAGE_USER PTEs should never even be observed with set_memory.c. > > > > Simply adding dump_stack() tells me my kernel on my machine does not use > > set_memory.c for userspace mappings but Hmm I'll take a look. > > vc_slow_virt_to_phys() uses lookup_address_in_pgd() with user mappings, but that > code is all but guaranteed to be buggy, e.g. doesn't guard against concurrent > modifications to user mappings. > > show_fault_oops() can also call into lookup_address_in_pgd() with a user mapping, > though at that point the kernel has bigger problems since it's executing from user > memory. > > And up until commits 44187235cbcc ("KVM: x86/mmu: fix potential races when walking > host page table") and 643d95aac59a ("Revert "x86/mm: Introduce lookup_address_in_mm()""), > KVM had a similar bug. Thanks for your helpful insight. I was curious if set_memory*() helpers are used for user mappings. with some quick look ptrace() and uprobes (where updating application's text is needed) use kmap + memcpy or replace_page() instead of set_memory*() API. _lookup_address_cpa() uses init_mm.pgd when cpa.pgd is not specified and the only place that passes pgd is efi subsystem (efi_mm.pgd), which is not a userspace. So it is *obvious* that set_memory*() functions should not be used for user mappings. because that will only result in updating only init_mm's page table. Therefore answering to the first question ('do we really need to unset _PAGE_GLOBAL when we're clearing _PAGE_PRESENT in set_memory.c to avoid confusing it as _PAGE_PROTNONE?'): we don't need to consider PROT_NONE semantics in set_memory.c because we don't (shouldn't) change user mappings in it and _PAGE_PROTNONE is not used for kernel mappings. > Generally speaking, set_memory.c is not equipped to play nice with user mappings. > It mostly "works", but there are races galore. IMO, hardening set_memory.c to scream > if it's handed a user address or encounters _PAGE_USER PTEs would be a very good thing. I agree that would be a good thing too. Thanks, Hyeonggon