# git rev-parse -q --verify 9f7853d7609d59172eecfc5e7ccf503bc1b690bd^{commit} 9f7853d7609d59172eecfc5e7ccf503bc1b690bd already have revision, skipping fetch # git checkout -q -f -B kisskb 9f7853d7609d59172eecfc5e7ccf503bc1b690bd # git clean -qxdf # < git log -1 # commit 9f7853d7609d59172eecfc5e7ccf503bc1b690bd # Author: Michael Ellerman # Date: Sun Aug 15 14:10:24 2021 +1000 # # powerpc/mm: Fix set_memory_*() against concurrent accesses # # Laurent reported that STRICT_MODULE_RWX was causing intermittent crashes # on one of his systems: # # kernel tried to execute exec-protected page (c008000004073278) - exploit attempt? (uid: 0) # BUG: Unable to handle kernel instruction fetch # Faulting instruction address: 0xc008000004073278 # Oops: Kernel access of bad area, sig: 11 [#1] # LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA pSeries # Modules linked in: drm virtio_console fuse drm_panel_orientation_quirks ... # CPU: 3 PID: 44 Comm: kworker/3:1 Not tainted 5.14.0-rc4+ #12 # Workqueue: events control_work_handler [virtio_console] # NIP: c008000004073278 LR: c008000004073278 CTR: c0000000001e9de0 # REGS: c00000002e4ef7e0 TRAP: 0400 Not tainted (5.14.0-rc4+) # MSR: 800000004280b033 CR: 24002822 XER: 200400cf # ... # NIP fill_queue+0xf0/0x210 [virtio_console] # LR fill_queue+0xf0/0x210 [virtio_console] # Call Trace: # fill_queue+0xb4/0x210 [virtio_console] (unreliable) # add_port+0x1a8/0x470 [virtio_console] # control_work_handler+0xbc/0x1e8 [virtio_console] # process_one_work+0x290/0x590 # worker_thread+0x88/0x620 # kthread+0x194/0x1a0 # ret_from_kernel_thread+0x5c/0x64 # # Jordan, Fabiano & Murilo were able to reproduce and identify that the # problem is caused by the call to module_enable_ro() in do_init_module(), # which happens after the module's init function has already been called. # # Our current implementation of change_page_attr() is not safe against # concurrent accesses, because it invalidates the PTE before flushing the # TLB and then installing the new PTE. That leaves a window in time where # there is no valid PTE for the page, if another CPU tries to access the # page at that time we see something like the fault above. # # We can't simply switch to set_pte_at()/flush TLB, because our hash MMU # code doesn't handle a set_pte_at() of a valid PTE. See [1]. # # But we do have pte_update(), which replaces the old PTE with the new, # meaning there's no window where the PTE is invalid. And the hash MMU # version hash__pte_update() deals with synchronising the hash page table # correctly. # # [1]: https://lore.kernel.org/linuxppc-dev/87y318wp9r.fsf@linux.ibm.com/ # # Fixes: 1f9ad21c3b38 ("powerpc/mm: Implement set_memory() routines") # Reported-by: Laurent Vivier # Reviewed-by: Christophe Leroy # Reviewed-by: Murilo Opsfelder Araújo # Tested-by: Laurent Vivier # Signed-off-by: Fabiano Rosas # Signed-off-by: Michael Ellerman # Link: https://lore.kernel.org/r/20210818120518.3603172-1-mpe@ellerman.id.au # < /opt/cross/kisskb/br-mipsel-o32-full-2016.08-613-ge98b4dd/bin/mipsel-linux-gcc --version # < /opt/cross/kisskb/br-mipsel-o32-full-2016.08-613-ge98b4dd/bin/mipsel-linux-ld --version # < git log --format=%s --max-count=1 9f7853d7609d59172eecfc5e7ccf503bc1b690bd # < make -s -j 32 ARCH=mips O=/kisskb/build/powerpc-fixes_mips-defconfig_mipsel CROSS_COMPILE=/opt/cross/kisskb/br-mipsel-o32-full-2016.08-613-ge98b4dd/bin/mipsel-linux- defconfig # < make -s -j 32 ARCH=mips O=/kisskb/build/powerpc-fixes_mips-defconfig_mipsel CROSS_COMPILE=/opt/cross/kisskb/br-mipsel-o32-full-2016.08-613-ge98b4dd/bin/mipsel-linux- help # make -s -j 32 ARCH=mips O=/kisskb/build/powerpc-fixes_mips-defconfig_mipsel CROSS_COMPILE=/opt/cross/kisskb/br-mipsel-o32-full-2016.08-613-ge98b4dd/bin/mipsel-linux- olddefconfig # make -s -j 32 ARCH=mips O=/kisskb/build/powerpc-fixes_mips-defconfig_mipsel CROSS_COMPILE=/opt/cross/kisskb/br-mipsel-o32-full-2016.08-613-ge98b4dd/bin/mipsel-linux- Completed OK # rm -rf /kisskb/build/powerpc-fixes_mips-defconfig_mipsel # Build took: 0:01:02.439930