Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75a1e8d0 authored by Laura Abbott's avatar Laura Abbott Committed by Ashwini Muduganti
Browse files

arm64: Make sure permission updates happen for pmd/pud



Commit 15122ee2c515 ("arm64: Enforce BBM for huge IO/VMAP mappings")
disallowed block mappings for ioremap since that code does not honor
break-before-make. The same APIs are also used for permission updating
though and the extra checks prevent the permission updates from happening,
even though this should be permitted. This results in read-only permissions
not being fully applied. Visibly, this can occasionaly be seen as a failure
on the built in rodata test when the test data ends up in a section or
as an odd RW gap on the page table dump. Fix this by using
pgattr_change_is_safe instead of p*d_present for determining if the
change is permitted.

Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Tested-by: default avatarPeter Robinson <pbrobinson@gmail.com>
Reported-by: default avatarPeter Robinson <pbrobinson@gmail.com>
Fixes: 15122ee2c515 ("arm64: Enforce BBM for huge IO/VMAP mappings")
Signed-off-by: default avatarLaura Abbott <labbott@redhat.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Git-Commit: 82034c23fcbc2389c73d97737f61fa2dd6526413
Git-Repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git


Change-Id: I7cbc0366b5101ade51a527b4c9e72f0a39ea5246
[sudaraja@codeaurora.org: added definition for pfn_pud, merge conflict fixes]
Signed-off-by: default avatarSudarshan Rajagopalan <sudaraja@codeaurora.org>
parent 18c9b991
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -393,6 +393,7 @@ static inline int pmd_protnone(pmd_t pmd)

#define pud_write(pud)		pte_write(pud_pte(pud))
#define pud_pfn(pud)		(((pud_val(pud) & PUD_MASK) & PHYS_MASK) >> PAGE_SHIFT)
#define pfn_pud(pfn,prot)	(__pud(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))

#define set_pmd_at(mm, addr, pmdp, pmd)	set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))

+16 −6
Original line number Diff line number Diff line
@@ -1352,23 +1352,33 @@ int __init arch_ioremap_pmd_supported(void)

int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot)
{
	/* ioremap_page_range doesn't honour BBM */
	if (pud_present(READ_ONCE(*pud)))
	pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT |
					pgprot_val(mk_sect_prot(prot)));
	pud_t new_pud = pfn_pud(__phys_to_pfn(phys), sect_prot);

	/* Only allow permission changes for now */
	if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pud)),
				   pud_val(new_pud)))
		return 0;

	BUG_ON(phys & ~PUD_MASK);
	set_pud(pud, __pud(phys | PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))));
	set_pud(pud, new_pud);
	return 1;
}

int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot)
{
	/* ioremap_page_range doesn't honour BBM */
	if (pmd_present(READ_ONCE(*pmd)))
	pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT |
					pgprot_val(mk_sect_prot(prot)));
	pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), sect_prot);

	/* Only allow permission changes for now */
	if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmd)),
				   pmd_val(new_pmd)))
		return 0;

	BUG_ON(phys & ~PMD_MASK);
	set_pmd(pmd, __pmd(phys | PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))));
	set_pmd(pmd, new_pmd);
	return 1;
}