mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-26 06:33:19 -04:00
arm: mm: program ptes for access restriction
CONFIG_RODATA allows strict kernel mapping permissions to be followed and accordingly maps regions as read-only, not-executable etc. correspondingly. CONFIG_RODATA however assumes all memory regions to be SECTION_SIZE aligned and section mapped for performance reasons. With CONFIG_FORCE_PAGES, we force all kernel mappings as page mapped thus breaking CONFIG_RODATA. Provide provision to apply permissions at page (pte) level, if CONFIG_RODATA does not find section mapping. Change-Id: I8dbf5c3741836bc63a231d8a471cf0306662993b Signed-off-by: Shiraz Hashim <shashim@codeaurora.org> Signed-off-by: Charan Teja Reddy <charante@codeaurora.org> Signed-off-by: Vijayanand Jitta <vjitta@codeaurora.org> Signed-off-by: Qingqing Zhou <qqzhou@codeaurora.org>
This commit is contained in:
parent
b4aefd26a7
commit
629471283e
1 changed files with 53 additions and 4 deletions
|
|
@ -511,6 +511,9 @@ struct section_perm {
|
|||
pmdval_t mask;
|
||||
pmdval_t prot;
|
||||
pmdval_t clear;
|
||||
pteval_t ptemask;
|
||||
pteval_t pteprot;
|
||||
pteval_t pteclear;
|
||||
};
|
||||
|
||||
/* First section-aligned location at or after __start_rodata. */
|
||||
|
|
@ -524,6 +527,8 @@ static struct section_perm nx_perms[] = {
|
|||
.end = (unsigned long)_stext,
|
||||
.mask = ~PMD_SECT_XN,
|
||||
.prot = PMD_SECT_XN,
|
||||
.ptemask = ~L_PTE_XN,
|
||||
.pteprot = L_PTE_XN,
|
||||
},
|
||||
/* Make init RW (set NX). */
|
||||
{
|
||||
|
|
@ -532,6 +537,8 @@ static struct section_perm nx_perms[] = {
|
|||
.end = (unsigned long)_sdata,
|
||||
.mask = ~PMD_SECT_XN,
|
||||
.prot = PMD_SECT_XN,
|
||||
.ptemask = ~L_PTE_XN,
|
||||
.pteprot = L_PTE_XN,
|
||||
},
|
||||
/* Make rodata NX (set RO in ro_perms below). */
|
||||
{
|
||||
|
|
@ -540,6 +547,8 @@ static struct section_perm nx_perms[] = {
|
|||
.end = (unsigned long)__init_begin,
|
||||
.mask = ~PMD_SECT_XN,
|
||||
.prot = PMD_SECT_XN,
|
||||
.ptemask = ~L_PTE_XN,
|
||||
.pteprot = L_PTE_XN,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -557,6 +566,8 @@ static struct section_perm ro_perms[] = {
|
|||
.prot = PMD_SECT_APX | PMD_SECT_AP_WRITE,
|
||||
.clear = PMD_SECT_AP_WRITE,
|
||||
#endif
|
||||
.ptemask = ~L_PTE_RDONLY,
|
||||
.pteprot = L_PTE_RDONLY,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -565,6 +576,34 @@ static struct section_perm ro_perms[] = {
|
|||
* copied into each mm). During startup, this is the init_mm. Is only
|
||||
* 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, 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,
|
||||
pmdval_t prot, struct mm_struct *mm)
|
||||
{
|
||||
|
|
@ -613,11 +652,21 @@ void set_section_perms(struct section_perm *perms, int n, bool set,
|
|||
|
||||
for (addr = perms[i].start;
|
||||
addr < perms[i].end;
|
||||
addr += SECTION_SIZE)
|
||||
section_update(addr, perms[i].mask,
|
||||
set ? perms[i].prot : perms[i].clear, mm);
|
||||
}
|
||||
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,
|
||||
set ? perms[i].prot : perms[i].clear,
|
||||
mm);
|
||||
else
|
||||
pte_update(addr, perms[i].ptemask,
|
||||
set ? perms[i].pteprot : perms[i].pteclear,
|
||||
mm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue