On Thu, Sep 16, 2021 at 10:40 AM Christopher M. Riedl <c...@bluescreens.de> wrote: > > On Tue Sep 14, 2021 at 11:24 PM CDT, Jordan Niethe wrote: > > On Sat, Sep 11, 2021 at 12:39 PM Christopher M. Riedl > > <c...@bluescreens.de> wrote: > > > ... > > > +/* > > > + * This can be called for kernel text or a module. > > > + */ > > > +static int map_patch_mm(const void *addr, struct patch_mapping > > > *patch_mapping) > > > +{ > > > + struct page *page; > > > + struct mm_struct *patching_mm = __this_cpu_read(cpu_patching_mm); > > > + unsigned long patching_addr = __this_cpu_read(cpu_patching_addr); > > > + > > > + if (is_vmalloc_or_module_addr(addr)) > > > + page = vmalloc_to_page(addr); > > > + else > > > + page = virt_to_page(addr); > > > + > > > + patch_mapping->ptep = get_locked_pte(patching_mm, patching_addr, > > > + &patch_mapping->ptl); > > > + if (unlikely(!patch_mapping->ptep)) { > > > + pr_warn("map patch: failed to allocate pte for > > > patching\n"); > > > + return -1; > > > + } > > > + > > > + set_pte_at(patching_mm, patching_addr, patch_mapping->ptep, > > > + pte_mkdirty(mk_pte(page, PAGE_KERNEL))); > > > > I think because switch_mm_irqs_off() will not necessarily have a > > barrier so a ptesync would be needed. > > A spurious fault here from __patch_instruction() would not be handled > > correctly. > > Sorry I don't quite follow - can you explain this to me in a bit more > detail?
radix__set_pte_at() skips calling ptesync as an optimization. If there is no ordering between changing the pte and then accessing the page with __patch_instruction(), a spurious fault could be raised. I think such a fault would end up being causing bad_kernel_fault() -> true and would not be fixed up. I thought there might be a barrier in switch_mm_irqs_off() that would provide this ordering but afaics that is not always the case. So I think that we need to have a ptesync after set_pte_at().