Skip to content

Commit

Permalink
ldelf: Add support for mapping ELF executable sections as guarded
Browse files Browse the repository at this point in the history
Introduce LDELF_MAP_FLAG_BTI to indicate if ELF supports BTI. A
BTI instruction is used to guard against the execution of instructions
that are not the intended target of a branch. The executable pages need
to be marked as guarded to ensure that BTI doesn't execute as NOP.

Signed-off-by: Ruchika Gupta <[email protected]>
Acked-by: Jerome Forissier <[email protected]>
Acked-by: Jens Wiklander <[email protected]>
  • Loading branch information
ruchi393 authored and jforissier committed Dec 22, 2021
1 parent e84a7da commit 0d482f8
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 0 deletions.
6 changes: 6 additions & 0 deletions core/kernel/ldelf_syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ TEE_Result ldelf_syscall_map_bin(vaddr_t *va, size_t num_bytes,
uint32_t prot = 0;
const uint32_t accept_flags = LDELF_MAP_FLAG_SHAREABLE |
LDELF_MAP_FLAG_WRITEABLE |
LDELF_MAP_FLAG_BTI |
LDELF_MAP_FLAG_EXECUTABLE;

if (!sys_ctx)
Expand Down Expand Up @@ -304,6 +305,8 @@ TEE_Result ldelf_syscall_map_bin(vaddr_t *va, size_t num_bytes,
prot |= TEE_MATTR_UW | TEE_MATTR_PW;
if (flags & LDELF_MAP_FLAG_EXECUTABLE)
prot |= TEE_MATTR_UX;
if (flags & LDELF_MAP_FLAG_BTI)
prot |= TEE_MATTR_GUARDED;

offs_pages = offs_bytes >> SMALL_PAGE_SHIFT;
if (ROUNDUP_OVERFLOW(num_bytes, SMALL_PAGE_SIZE, &num_rounded_bytes))
Expand Down Expand Up @@ -453,6 +456,7 @@ TEE_Result ldelf_syscall_set_prot(unsigned long va, size_t num_bytes,
uint32_t vm_flags = 0;
vaddr_t end_va = 0;
const uint32_t accept_flags = LDELF_MAP_FLAG_WRITEABLE |
LDELF_MAP_FLAG_BTI |
LDELF_MAP_FLAG_EXECUTABLE;

if ((flags & accept_flags) != flags)
Expand All @@ -461,6 +465,8 @@ TEE_Result ldelf_syscall_set_prot(unsigned long va, size_t num_bytes,
prot |= TEE_MATTR_UW | TEE_MATTR_PW;
if (flags & LDELF_MAP_FLAG_EXECUTABLE)
prot |= TEE_MATTR_UX;
if (flags & LDELF_MAP_FLAG_BTI)
prot |= TEE_MATTR_GUARDED;

/*
* The vm_get_flags() and vm_unmap() are supposed to detect or handle
Expand Down
1 change: 1 addition & 0 deletions ldelf/include/ldelf.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ struct dl_entry_arg {
#define LDELF_MAP_FLAG_SHAREABLE BIT32(0)
#define LDELF_MAP_FLAG_WRITEABLE BIT32(1)
#define LDELF_MAP_FLAG_EXECUTABLE BIT32(2)
#define LDELF_MAP_FLAG_BTI BIT32(3)

#endif /*!__ASSEMBLER__*/

Expand Down
23 changes: 23 additions & 0 deletions ldelf/ta_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,23 @@ static void populate_segments(struct ta_elf *elf)
}
}

static void ta_elf_add_bti(struct ta_elf *elf)
{
TEE_Result res = TEE_SUCCESS;
struct segment *seg = NULL;
uint32_t flags = LDELF_MAP_FLAG_EXECUTABLE | LDELF_MAP_FLAG_BTI;

TAILQ_FOREACH(seg, &elf->segs, link) {
vaddr_t va = elf->load_addr + seg->vaddr;

if (seg->flags & PF_X) {
res = sys_set_prot(va, seg->memsz, flags);
if (res)
err(res, "sys_set_prot");
}
}
}

static void parse_property_segment(struct ta_elf *elf)
{
char *desc = NULL;
Expand Down Expand Up @@ -1139,6 +1156,9 @@ static void load_main(struct ta_elf *elf)
save_symtab(elf);
close_handle(elf);
set_tls_offset(elf);
parse_property_segment(elf);
if (elf->bti_enabled)
ta_elf_add_bti(elf);

elf->head = (struct ta_head *)elf->load_addr;
if (elf->head->depr_entry != UINT64_MAX) {
Expand Down Expand Up @@ -1246,6 +1266,9 @@ void ta_elf_load_dependency(struct ta_elf *elf, bool is_32bit)
save_symtab(elf);
close_handle(elf);
set_tls_offset(elf);
parse_property_segment(elf);
if (elf->bti_enabled)
ta_elf_add_bti(elf);
}

void ta_elf_finalize_mappings(struct ta_elf *elf)
Expand Down

0 comments on commit 0d482f8

Please sign in to comment.