diff options
author | davidcunado-arm <david.cunado@arm.com> | 2017-05-05 09:50:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-05 09:50:34 +0100 |
commit | 5e6232778649fb1e6c6e0aa4671efe7e559ca78d (patch) | |
tree | b687acdecbb4b7babab57d0f81452d6b83d7603e /lib/xlat_tables | |
parent | f132b4a05b23916c1101add4bd6d973a99983719 (diff) | |
parent | a56402521f80cf1b17e3936abcc6b1772aa91e66 (diff) |
Merge pull request #924 from antonio-nino-diaz-arm/an/fix-xn-bit
Fix execute-never permissions in xlat tables libs
Diffstat (limited to 'lib/xlat_tables')
-rw-r--r-- | lib/xlat_tables/aarch32/xlat_tables.c | 14 | ||||
-rw-r--r-- | lib/xlat_tables/aarch64/xlat_tables.c | 19 | ||||
-rw-r--r-- | lib/xlat_tables/xlat_tables_common.c | 14 | ||||
-rw-r--r-- | lib/xlat_tables/xlat_tables_private.h | 11 |
4 files changed, 53 insertions, 5 deletions
diff --git a/lib/xlat_tables/aarch32/xlat_tables.c b/lib/xlat_tables/aarch32/xlat_tables.c index 03caf36f..3c9051c3 100644 --- a/lib/xlat_tables/aarch32/xlat_tables.c +++ b/lib/xlat_tables/aarch32/xlat_tables.c @@ -69,6 +69,20 @@ static unsigned long long get_max_supported_pa(void) } #endif /* ENABLE_ASSERTIONS */ +int xlat_arch_current_el(void) +{ + /* + * If EL3 is in AArch32 mode, all secure PL1 modes (Monitor, System, + * SVC, Abort, UND, IRQ and FIQ modes) execute at EL3. + */ + return 3; +} + +uint64_t xlat_arch_get_xn_desc(int el __unused) +{ + return UPPER_ATTRS(XN); +} + void init_xlat_tables(void) { unsigned long long max_pa; diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c index 2126180e..309cb9bd 100644 --- a/lib/xlat_tables/aarch64/xlat_tables.c +++ b/lib/xlat_tables/aarch64/xlat_tables.c @@ -122,6 +122,25 @@ static unsigned long long get_max_supported_pa(void) } #endif /* ENABLE_ASSERTIONS */ +int xlat_arch_current_el(void) +{ + int el = GET_EL(read_CurrentEl()); + + assert(el > 0); + + return el; +} + +uint64_t xlat_arch_get_xn_desc(int el) +{ + if (el == 3) { + return UPPER_ATTRS(XN); + } else { + assert(el == 1); + return UPPER_ATTRS(PXN); + } +} + void init_xlat_tables(void) { unsigned long long max_pa; diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c index f322a9af..17e7e6e0 100644 --- a/lib/xlat_tables/xlat_tables_common.c +++ b/lib/xlat_tables/xlat_tables_common.c @@ -40,6 +40,8 @@ static unsigned next_xlat; static unsigned long long xlat_max_pa; static uintptr_t xlat_max_va; +static uint64_t execute_never_mask; + /* * Array of all memory regions stored in order of ascending base address. * The list is terminated by the first entry with size == 0. @@ -213,7 +215,8 @@ static uint64_t mmap_desc(mmap_attr_t attr, unsigned long long addr_pa, * fetch, which could be an issue if this memory region * corresponds to a read-sensitive peripheral. */ - desc |= UPPER_ATTRS(XN); + desc |= execute_never_mask; + } else { /* Normal memory */ /* * Always map read-write normal memory as execute-never. @@ -221,7 +224,7 @@ static uint64_t mmap_desc(mmap_attr_t attr, unsigned long long addr_pa, * R/W memory is reserved for data storage, which must not be * executable.) * Note that setting the XN bit here is for consistency only. - * The enable_mmu_elx() function sets the SCTLR_EL3.WXN bit, + * The function that enables the MMU sets the SCTLR_ELx.WXN bit, * which makes any writable memory region to be treated as * execute-never, regardless of the value of the XN bit in the * translation table. @@ -229,8 +232,9 @@ static uint64_t mmap_desc(mmap_attr_t attr, unsigned long long addr_pa, * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER * attribute to figure out the value of the XN bit. */ - if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER)) - desc |= UPPER_ATTRS(XN); + if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER)) { + desc |= execute_never_mask; + } if (mem_type == MT_MEMORY) { desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH); @@ -377,7 +381,7 @@ void init_xlation_table(uintptr_t base_va, uint64_t *table, int level, uintptr_t *max_va, unsigned long long *max_pa) { - + execute_never_mask = xlat_arch_get_xn_desc(xlat_arch_current_el()); init_xlation_table_inner(mmap, base_va, table, level); *max_va = xlat_max_va; *max_pa = xlat_max_pa; diff --git a/lib/xlat_tables/xlat_tables_private.h b/lib/xlat_tables/xlat_tables_private.h index d568dc0d..92078525 100644 --- a/lib/xlat_tables/xlat_tables_private.h +++ b/lib/xlat_tables/xlat_tables_private.h @@ -65,6 +65,17 @@ CASSERT(IS_POWER_OF_TWO(PLAT_PHY_ADDR_SPACE_SIZE), #endif /* AARCH32 */ void print_mmap(void); + +/* Returns the current Exception Level. The returned EL must be 1 or higher. */ +int xlat_arch_current_el(void); + +/* + * Returns the bit mask that has to be ORed to the rest of a translation table + * descriptor so that execution of code is prohibited at the given Exception + * Level. + */ +uint64_t xlat_arch_get_xn_desc(int el); + void init_xlation_table(uintptr_t base_va, uint64_t *table, int level, uintptr_t *max_va, unsigned long long *max_pa); |