7.3-stable review patch. If anyone has any objections, please let me know. ------------------ From: Ard Biesheuvel [ Upstream commit 215d7b6622733603751f546b9faf9b84b0c281d4 ] set_permissions() sets PTE_RDONLY for regions that the Memory Attributes Table describes as read-only, but leaves PTE_WRITE set. PTE_WRITE is the DBM bit, so when hardware dirty state management is enabled (TCR_EL1.HD), such a descriptor is writable-clean rather than read-only, and a write by the firmware will be permitted by the hardware (which marks the entry dirty) instead of faulting. Clear PTE_WRITE as well, as pte_wrprotect() does. Cc: stable@vger.kernel.org Signed-off-by: Ard Biesheuvel Signed-off-by: Catalin Marinas Signed-off-by: Sasha Levin --- arch/arm64/kernel/efi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 0ec90fd1754ed..6f34aef3d04ef 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -117,8 +117,14 @@ static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data) const efi_memory_desc_t *md = spd->md; pte_t pte = __ptep_get(ptep); + /* + * Clear PTE_WRITE as well: it doubles as the DBM bit, and leaving it + * set would permit the hardware to make the mapping writable again + * when TCR_EL1.HD is set. + */ if (md->attribute & EFI_MEMORY_RO) - pte = set_pte_bit(pte, __pgprot(PTE_RDONLY)); + pte = set_pte_bit(clear_pte_bit(pte, __pgprot(PTE_WRITE)), + __pgprot(PTE_RDONLY)); if (md->attribute & EFI_MEMORY_XP) pte = set_pte_bit(pte, __pgprot(PTE_PXN)); else if (system_supports_bti_kernel() && spd->has_bti) -- 2.53.0