kernel: Add option to ensure writable pages are not executable
This adds CONFIG_EXECUTE_XOR_WRITE, which is enabled by default on systems that support controlling whether a page can contain executable code. This is also known as W^X[1]. Trying to add a memory domain with a page that is both executable and writable, either for supervisor mode threads, or for user mode threads, will result in a kernel panic. There are few cases where a writable page should also be executable (JIT compilers, which are most likely out of scope for Zephyr), so an option is provided to disable the check. Since the memory domain APIs are executed in supervisor mode, a determined person could bypass these checks with ease. This is seen more as a way to avoid people shooting themselves in the foot. [1] https://en.wikipedia.org/wiki/W%5EX Signed-off-by: Leandro Pereira <leandro.pereira@intel.com>
This commit is contained in:
parent
36adf4e432
commit
b007b64d30
5 changed files with 82 additions and 1 deletions
|
@ -8,10 +8,21 @@
|
|||
#include <kernel.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <nano_internal.h>
|
||||
|
||||
#include <misc/__assert.h>
|
||||
|
||||
static u8_t max_partitions;
|
||||
|
||||
static void ensure_w_xor_x(u32_t attrs)
|
||||
{
|
||||
#if defined(CONFIG_EXECUTE_XOR_WRITE) && __ASSERT_ON
|
||||
bool writable = K_MEM_PARTITION_IS_WRITABLE(attrs);
|
||||
bool executable = K_MEM_PARTITION_IS_EXECUTABLE(attrs);
|
||||
|
||||
__ASSERT(writable != executable, "writable page not executable");
|
||||
#else
|
||||
ARG_UNUSED(attrs);
|
||||
#endif
|
||||
}
|
||||
|
||||
void k_mem_domain_init(struct k_mem_domain *domain, u32_t num_parts,
|
||||
struct k_mem_partition *parts[])
|
||||
|
@ -31,6 +42,9 @@ void k_mem_domain_init(struct k_mem_domain *domain, u32_t num_parts,
|
|||
|
||||
for (i = 0; i < num_parts; i++) {
|
||||
__ASSERT(parts[i], "");
|
||||
|
||||
ensure_w_xor_x(parts[i]->attr);
|
||||
|
||||
domain->partitions[i] = *parts[i];
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +83,8 @@ void k_mem_domain_add_partition(struct k_mem_domain *domain,
|
|||
__ASSERT(domain && part, "");
|
||||
__ASSERT(part->start + part->size > part->start, "");
|
||||
|
||||
ensure_w_xor_x(part->attr);
|
||||
|
||||
key = irq_lock();
|
||||
|
||||
for (p_idx = 0; p_idx < max_partitions; p_idx++) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue