s390/mm: properly clear _PAGE_NOEXEC bit when it is not supported
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: 57d7f939e7bd ("s390: add no-execute support") Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
2d1fc1eb9b
commit
ab874f22d3
@ -1161,8 +1161,6 @@ void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr);
|
|||||||
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
|
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||||
pte_t *ptep, pte_t entry)
|
pte_t *ptep, pte_t entry)
|
||||||
{
|
{
|
||||||
if (!MACHINE_HAS_NX)
|
|
||||||
pte_val(entry) &= ~_PAGE_NOEXEC;
|
|
||||||
if (pte_present(entry))
|
if (pte_present(entry))
|
||||||
pte_val(entry) &= ~_PAGE_UNUSED;
|
pte_val(entry) &= ~_PAGE_UNUSED;
|
||||||
if (mm_has_pgste(mm))
|
if (mm_has_pgste(mm))
|
||||||
@ -1179,6 +1177,8 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
|
|||||||
{
|
{
|
||||||
pte_t __pte;
|
pte_t __pte;
|
||||||
pte_val(__pte) = physpage + pgprot_val(pgprot);
|
pte_val(__pte) = physpage + pgprot_val(pgprot);
|
||||||
|
if (!MACHINE_HAS_NX)
|
||||||
|
pte_val(__pte) &= ~_PAGE_NOEXEC;
|
||||||
return pte_mkyoung(__pte);
|
return pte_mkyoung(__pte);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user