Loading arch/arm/mm/init.c +54 −4 Original line number Original line Diff line number Diff line Loading @@ -630,6 +630,9 @@ struct section_perm { pmdval_t mask; pmdval_t mask; pmdval_t prot; pmdval_t prot; pmdval_t clear; pmdval_t clear; pteval_t ptemask; pteval_t pteprot; pteval_t pteclear; }; }; /* First section-aligned location at or after __start_rodata. */ /* First section-aligned location at or after __start_rodata. */ Loading @@ -643,6 +646,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)_stext, .end = (unsigned long)_stext, .mask = ~PMD_SECT_XN, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, }, /* Make init RW (set NX). */ /* Make init RW (set NX). */ { { Loading @@ -651,6 +656,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)_sdata, .end = (unsigned long)_sdata, .mask = ~PMD_SECT_XN, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, }, /* Make rodata NX (set RO in ro_perms below). */ /* Make rodata NX (set RO in ro_perms below). */ { { Loading @@ -659,6 +666,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)__init_begin, .end = (unsigned long)__init_begin, .mask = ~PMD_SECT_XN, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, }, }; }; Loading @@ -676,6 +685,8 @@ static struct section_perm ro_perms[] = { .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, .clear = PMD_SECT_AP_WRITE, .clear = PMD_SECT_AP_WRITE, #endif #endif .ptemask = ~L_PTE_RDONLY, .pteprot = L_PTE_RDONLY, }, }, }; }; Loading @@ -684,6 +695,35 @@ static struct section_perm ro_perms[] = { * copied into each mm). During startup, this is the init_mm. Is only * copied into each mm). During startup, this is the init_mm. Is only * safe to be called with preemption disabled, as under stop_machine(). * safe to be called with preemption disabled, as under stop_machine(). */ */ struct pte_data { pteval_t mask; pteval_t val; }; static int __pte_update(pte_t *ptep, pgtable_t token, unsigned long addr, void *d) { struct pte_data *data = d; pte_t pte = *ptep; pte = __pte((pte_val(*ptep) & data->mask) | data->val); set_pte_ext(ptep, pte, 0); return 0; } static inline void pte_update(unsigned long addr, pteval_t mask, pteval_t prot, struct mm_struct *mm) { struct pte_data data; data.mask = mask; data.val = prot; apply_to_page_range(mm, addr, SECTION_SIZE, __pte_update, &data); flush_tlb_kernel_range(addr, addr + SECTION_SIZE); } static inline void section_update(unsigned long addr, pmdval_t mask, static inline void section_update(unsigned long addr, pmdval_t mask, pmdval_t prot, struct mm_struct *mm) pmdval_t prot, struct mm_struct *mm) { { Loading Loading @@ -732,11 +772,21 @@ void set_section_perms(struct section_perm *perms, int n, bool set, for (addr = perms[i].start; for (addr = perms[i].start; addr < perms[i].end; addr < perms[i].end; addr += SECTION_SIZE) addr += SECTION_SIZE) { pmd_t *pmd; pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr); if (pmd_bad(*pmd)) section_update(addr, perms[i].mask, section_update(addr, perms[i].mask, set ? perms[i].prot : perms[i].clear, mm); set ? perms[i].prot : perms[i].clear, mm); else pte_update(addr, perms[i].ptemask, set ? perms[i].pteprot : perms[i].pteclear, mm); } } } } } static void update_sections_early(struct section_perm perms[], int n) static void update_sections_early(struct section_perm perms[], int n) Loading Loading
arch/arm/mm/init.c +54 −4 Original line number Original line Diff line number Diff line Loading @@ -630,6 +630,9 @@ struct section_perm { pmdval_t mask; pmdval_t mask; pmdval_t prot; pmdval_t prot; pmdval_t clear; pmdval_t clear; pteval_t ptemask; pteval_t pteprot; pteval_t pteclear; }; }; /* First section-aligned location at or after __start_rodata. */ /* First section-aligned location at or after __start_rodata. */ Loading @@ -643,6 +646,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)_stext, .end = (unsigned long)_stext, .mask = ~PMD_SECT_XN, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, }, /* Make init RW (set NX). */ /* Make init RW (set NX). */ { { Loading @@ -651,6 +656,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)_sdata, .end = (unsigned long)_sdata, .mask = ~PMD_SECT_XN, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, }, /* Make rodata NX (set RO in ro_perms below). */ /* Make rodata NX (set RO in ro_perms below). */ { { Loading @@ -659,6 +666,8 @@ static struct section_perm nx_perms[] = { .end = (unsigned long)__init_begin, .end = (unsigned long)__init_begin, .mask = ~PMD_SECT_XN, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, .prot = PMD_SECT_XN, .ptemask = ~L_PTE_XN, .pteprot = L_PTE_XN, }, }, }; }; Loading @@ -676,6 +685,8 @@ static struct section_perm ro_perms[] = { .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, .prot = PMD_SECT_APX | PMD_SECT_AP_WRITE, .clear = PMD_SECT_AP_WRITE, .clear = PMD_SECT_AP_WRITE, #endif #endif .ptemask = ~L_PTE_RDONLY, .pteprot = L_PTE_RDONLY, }, }, }; }; Loading @@ -684,6 +695,35 @@ static struct section_perm ro_perms[] = { * copied into each mm). During startup, this is the init_mm. Is only * copied into each mm). During startup, this is the init_mm. Is only * safe to be called with preemption disabled, as under stop_machine(). * safe to be called with preemption disabled, as under stop_machine(). */ */ struct pte_data { pteval_t mask; pteval_t val; }; static int __pte_update(pte_t *ptep, pgtable_t token, unsigned long addr, void *d) { struct pte_data *data = d; pte_t pte = *ptep; pte = __pte((pte_val(*ptep) & data->mask) | data->val); set_pte_ext(ptep, pte, 0); return 0; } static inline void pte_update(unsigned long addr, pteval_t mask, pteval_t prot, struct mm_struct *mm) { struct pte_data data; data.mask = mask; data.val = prot; apply_to_page_range(mm, addr, SECTION_SIZE, __pte_update, &data); flush_tlb_kernel_range(addr, addr + SECTION_SIZE); } static inline void section_update(unsigned long addr, pmdval_t mask, static inline void section_update(unsigned long addr, pmdval_t mask, pmdval_t prot, struct mm_struct *mm) pmdval_t prot, struct mm_struct *mm) { { Loading Loading @@ -732,11 +772,21 @@ void set_section_perms(struct section_perm *perms, int n, bool set, for (addr = perms[i].start; for (addr = perms[i].start; addr < perms[i].end; addr < perms[i].end; addr += SECTION_SIZE) addr += SECTION_SIZE) { pmd_t *pmd; pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr); if (pmd_bad(*pmd)) section_update(addr, perms[i].mask, section_update(addr, perms[i].mask, set ? perms[i].prot : perms[i].clear, mm); set ? perms[i].prot : perms[i].clear, mm); else pte_update(addr, perms[i].ptemask, set ? perms[i].pteprot : perms[i].pteclear, mm); } } } } } static void update_sections_early(struct section_perm perms[], int n) static void update_sections_early(struct section_perm perms[], int n) Loading