Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: domains: keep vectors in separate domain

Keep the machine vectors in its own domain to avoid software based
user access control from making the vector code inaccessible, and
thereby deadlocking the machine.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

+16 -3
+3 -1
arch/arm/include/asm/domain.h
··· 43 43 #define DOMAIN_USER 1 44 44 #define DOMAIN_IO 0 45 45 #endif 46 + #define DOMAIN_VECTORS 3 46 47 47 48 /* 48 49 * Domain types ··· 63 62 (domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \ 64 63 domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ 65 64 domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ 66 - domain_val(DOMAIN_IO, DOMAIN_CLIENT)) 65 + domain_val(DOMAIN_IO, DOMAIN_CLIENT) | \ 66 + domain_val(DOMAIN_VECTORS, DOMAIN_CLIENT)) 67 67 68 68 #ifndef __ASSEMBLY__ 69 69
+1
arch/arm/include/asm/pgtable-2level-hwdef.h
··· 23 23 #define PMD_PXNTABLE (_AT(pmdval_t, 1) << 2) /* v7 */ 24 24 #define PMD_BIT4 (_AT(pmdval_t, 1) << 4) 25 25 #define PMD_DOMAIN(x) (_AT(pmdval_t, (x)) << 5) 26 + #define PMD_DOMAIN_MASK PMD_DOMAIN(0x0f) 26 27 #define PMD_PROTECTION (_AT(pmdval_t, 1) << 9) /* v5 */ 27 28 /* 28 29 * - section
+2 -2
arch/arm/mm/mmu.c
··· 291 291 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 292 292 L_PTE_RDONLY, 293 293 .prot_l1 = PMD_TYPE_TABLE, 294 - .domain = DOMAIN_USER, 294 + .domain = DOMAIN_VECTORS, 295 295 }, 296 296 [MT_HIGH_VECTORS] = { 297 297 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | 298 298 L_PTE_USER | L_PTE_RDONLY, 299 299 .prot_l1 = PMD_TYPE_TABLE, 300 - .domain = DOMAIN_USER, 300 + .domain = DOMAIN_VECTORS, 301 301 }, 302 302 [MT_MEMORY_RWX] = { 303 303 .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
+10
arch/arm/mm/pgd.c
··· 84 84 if (!new_pte) 85 85 goto no_pte; 86 86 87 + #ifndef CONFIG_ARM_LPAE 88 + /* 89 + * Modify the PTE pointer to have the correct domain. This 90 + * needs to be the vectors domain to avoid the low vectors 91 + * being unmapped. 92 + */ 93 + pmd_val(*new_pmd) &= ~PMD_DOMAIN_MASK; 94 + pmd_val(*new_pmd) |= PMD_DOMAIN(DOMAIN_VECTORS); 95 + #endif 96 + 87 97 init_pud = pud_offset(init_pgd, 0); 88 98 init_pmd = pmd_offset(init_pud, 0); 89 99 init_pte = pte_offset_map(init_pmd, 0);