• Christophe Leroy's avatar
    powerpc/book3e: Fix set_memory_x() and set_memory_nx() · b6cb20fd
    Christophe Leroy authored
    set_memory_x() calls pte_mkexec() which sets _PAGE_EXEC.
    set_memory_nx() calls pte_exprotec() which clears _PAGE_EXEC.
    
    Book3e has 2 bits, UX and SX, which defines the exec rights
    resp. for user (PR=1) and for kernel (PR=0).
    
    _PAGE_EXEC is defined as UX only.
    
    An executable kernel page is set with either _PAGE_KERNEL_RWX
    or _PAGE_KERNEL_ROX, which both have SX set and UX cleared.
    
    So set_memory_nx() call for an executable kernel page does
    nothing because UX is already cleared.
    
    And set_memory_x() on a non-executable kernel page makes it
    executable for the user and keeps it non-executable for kernel.
    
    Also, pte_exec() always returns 'false' on kernel pages, because
    it checks _PAGE_EXEC which doesn't include SX, so for instance
    the W+X check doesn't work.
    
    To fix this:
      - change tlb_low_64e.S to use _PAGE_BAP_UX instead of _PAGE_USER
      - sets both UX and SX in _PAGE_EXEC so that pte_exec() returns
        true whenever one of the two bits is set and pte_exprotect()
        clears both bits.
      - Define a book3e specific version of pte_mkexec() which sets
        either SX or UX based on UR.
    
    Fixes: 1f9ad21c ("powerpc/mm: Implement set_memory() routines")
    Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
    Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
    Link: https://lore.kernel.org/r/c41100f9c144dc5b62e5a751b810190c6b5d42fd.1635226743.git.christophe.leroy@csgroup.eu
    b6cb20fd
tlb_low_64e.S 34.6 KB