• Gerald Schaefer's avatar
    s390/mm: properly clear _PAGE_NOEXEC bit when it is not supported · ab874f22
    Gerald Schaefer authored
    On older HW or under a hypervisor, w/o the instruction-execution-
    protection (IEP) facility, and also w/o EDAT-1, a translation-specification
    exception may be recognized when bit 55 of a pte is one (_PAGE_NOEXEC).
    
    The current code tries to prevent setting _PAGE_NOEXEC in such cases,
    by removing it within set_pte_at(). However, ptep_set_access_flags()
    will modify a pte directly, w/o using set_pte_at(). There is at least
    one scenario where this can result in an active pte with _PAGE_NOEXEC
    set, which would then lead to a panic due to a translation-specification
    exception (write to swapped out page):
    
    do_swap_page
      pte = mk_pte (with _PAGE_NOEXEC bit)
      set_pte_at   (will remove _PAGE_NOEXEC bit in page table, but keep it
                    in local variable pte)
      vmf->orig_pte = pte (pte still contains _PAGE_NOEXEC bit)
      do_wp_page
        wp_page_reuse
          entry = vmf->orig_pte (still with _PAGE_NOEXEC bit)
          ptep_set_access_flags (writes entry with _PAGE_NOEXEC bit)
    
    Fix this by clearing _PAGE_NOEXEC already in mk_pte_phys(), where the
    pgprot value is applied, so that no pte with _PAGE_NOEXEC will ever be
    visible, if it is not supported. The check in set_pte_at() can then also
    be removed.
    
    Cc: <stable@vger.kernel.org> # 4.11+
    Fixes: 57d7f939 ("s390: add no-execute support")
    Signed-off-by: default avatarGerald Schaefer <gerald.schaefer@de.ibm.com>
    Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
    ab874f22
pgtable.h 48.7 KB