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

Commit 82034c23 authored by Laura Abbott's avatar Laura Abbott Committed by Will Deacon
Browse files

arm64: Make sure permission updates happen for pmd/pud



Commit 15122ee2 ("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: 15122ee2 ("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>
parent cc198460
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -933,13 +933,15 @@ int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot)
{
	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);

	/* ioremap_page_range doesn't honour BBM */
	if (pud_present(READ_ONCE(*pudp)))
	/* Only allow permission changes for now */
	if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pudp)),
				   pud_val(new_pud)))
		return 0;

	BUG_ON(phys & ~PUD_MASK);
	set_pud(pudp, pfn_pud(__phys_to_pfn(phys), sect_prot));
	set_pud(pudp, new_pud);
	return 1;
}

@@ -947,13 +949,15 @@ int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot)
{
	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);

	/* ioremap_page_range doesn't honour BBM */
	if (pmd_present(READ_ONCE(*pmdp)))
	/* Only allow permission changes for now */
	if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)),
				   pmd_val(new_pmd)))
		return 0;

	BUG_ON(phys & ~PMD_MASK);
	set_pmd(pmdp, pfn_pmd(__phys_to_pfn(phys), sect_prot));
	set_pmd(pmdp, new_pmd);
	return 1;
}