Skip to content

Commit b5addc8

Browse files
Nicolas Pitrenashif
authored andcommitted
llext: adjust memory permissions on MMU systems
By default, normal memory is set readable+writable and not executable. Adjust those permissions according to each region: LLEXT_MEM_TEXT --> K_MEM_PERM_EXEC LLEXT_MEM_DATA, LLEXT_MEM_BSS --> K_MEM_PERM_RW LLEXT_MEM_RODATA --> K_MEM_PERM_RO aka 0 This must be done only at the end of an LLEXT load operation as memory needs to remain RW for reloc processing, etc. And while at it, flush/invalidate the cache accordingly. Signed-off-by: Nicolas Pitre <[email protected]>
1 parent c692136 commit b5addc8

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

subsys/llext/llext_load.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,8 @@ int do_llext_load(struct llext_loader *ldr, struct llext *ext,
632632
goto out;
633633
}
634634

635+
llext_adjust_mmu_permissions(ext);
636+
635637
out:
636638
/*
637639
* Free resources only used during loading. Note that this exploits

subsys/llext/llext_mem.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,51 @@ int llext_copy_regions(struct llext_loader *ldr, struct llext *ext)
159159
return 0;
160160
}
161161

162+
void llext_adjust_mmu_permissions(struct llext *ext)
163+
{
164+
#ifdef CONFIG_MMU
165+
void *addr;
166+
size_t size;
167+
uint32_t flags;
168+
169+
for (enum llext_mem mem_idx = 0; mem_idx < LLEXT_MEM_PARTITIONS; mem_idx++) {
170+
addr = ext->mem[mem_idx];
171+
size = ROUND_UP(ext->mem_size[mem_idx], LLEXT_PAGE_SIZE);
172+
if (size == 0) {
173+
continue;
174+
}
175+
switch (mem_idx) {
176+
case LLEXT_MEM_TEXT:
177+
sys_cache_instr_invd_range(addr, size);
178+
flags = K_MEM_PERM_EXEC;
179+
break;
180+
case LLEXT_MEM_DATA:
181+
case LLEXT_MEM_BSS:
182+
/* memory is already K_MEM_PERM_RW by default */
183+
continue;
184+
case LLEXT_MEM_RODATA:
185+
flags = 0;
186+
break;
187+
default:
188+
continue;
189+
}
190+
sys_cache_data_flush_range(addr, size);
191+
k_mem_update_flags(addr, size, flags);
192+
}
193+
#endif
194+
}
195+
162196
void llext_free_regions(struct llext *ext)
163197
{
164198
for (int i = 0; i < LLEXT_MEM_COUNT; i++) {
199+
#ifdef CONFIG_MMU
200+
if (ext->mem_size[i] != 0) {
201+
/* restore default RAM permissions */
202+
k_mem_update_flags(ext->mem[i],
203+
ROUND_UP(ext->mem_size[i], LLEXT_PAGE_SIZE),
204+
K_MEM_PERM_RW);
205+
}
206+
#endif
165207
if (ext->mem_on_heap[i]) {
166208
LOG_DBG("freeing memory region %d", i);
167209
llext_free(ext->mem[i]);

subsys/llext/llext_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct llext_elf_sect_map {
2222
int llext_copy_strings(struct llext_loader *ldr, struct llext *ext);
2323
int llext_copy_regions(struct llext_loader *ldr, struct llext *ext);
2424
void llext_free_regions(struct llext *ext);
25+
void llext_adjust_mmu_permissions(struct llext *ext);
2526

2627
static inline void *llext_alloc(size_t bytes)
2728
{

0 commit comments

Comments
 (0)