kernel: prevent modules from being loaded multiple times

This commit is contained in:
K. Lange 2021-11-18 19:47:28 +09:00
parent 01765b3e5e
commit 045431b2de
4 changed files with 56 additions and 7 deletions

View File

@ -36,6 +36,7 @@ union PML * mmu_get_kernel_directory(void);
void * mmu_map_from_physical(uintptr_t frameaddress);
void * mmu_map_mmio_region(uintptr_t physical_address, size_t size);
void * mmu_map_module(size_t size);
void mmu_unmap_module(uintptr_t base_address, size_t size);
size_t mmu_count_user(union PML * from);
size_t mmu_count_shm(union PML * from);

View File

@ -905,6 +905,30 @@ void * mmu_map_module(size_t size) {
return out;
}
void mmu_unmap_module(uintptr_t start_address, size_t size) {
if ((size & PAGE_LOW_MASK) || (start_address & PAGE_LOW_MASK)) {
arch_fatal_prepare();
printf("mmu_unmap_module start and size must be multiple of page size %#zx:%#zx.\n", start_address, size);
arch_dump_traceback();
arch_fatal();
}
spin_lock(module_space_lock);
uintptr_t end_address = start_address + size;
/* Unmap all pages we just allocated */
for (uintptr_t i = start_address; i < end_address; i += 0x1000) {
union PML * p = mmu_get_page(i, 0);
mmu_frame_clear(p->bits.page << 12);
}
/* Reset module base address if it was at the end, to avoid wasting address space */
if (end_address == module_base_address) {
module_base_address = start_address;
}
spin_unlock(module_space_lock);
}
int mmu_validate_user_pointer(void * addr, size_t size, int flags) {
if (addr == NULL && !(flags & MMU_PTR_NULL)) return 0;

View File

@ -28,6 +28,7 @@ extern int system(const char * path, int argc, const char ** argv, const char **
extern void snd_install(void);
extern void net_install(void);
extern void console_initialize(void);
extern void modules_install(void);
void generic_startup(void) {
args_parse(arch_get_cmdline());
@ -45,6 +46,7 @@ void generic_startup(void) {
snd_install();
net_install();
tasking_start();
modules_install();
}
int generic_main(void) {

View File

@ -20,14 +20,22 @@
#include <kernel/ksym.h>
#include <kernel/module.h>
#include <kernel/hashmap.h>
#include <kernel/mutex.h>
static hashmap_t * _modules_table = NULL;
hashmap_t * _modules_table = NULL;
sched_mutex_t * _modules_mutex = NULL;
void modules_install(void) {
_modules_table = hashmap_create(10);
_modules_mutex = mutex_init("module loader");
}
hashmap_t * modules_get_list(void) {
return _modules_table;
}
int elf_module(char ** args) {
int error = 0;
Elf64_Header header;
fs_node_t * file = kopen(args[0],0);
@ -49,14 +57,18 @@ int elf_module(char ** args) {
if (header.e_ident[EI_CLASS] != ELFCLASS64) {
printf("(Wrong Elf class)\n");
close_fs(file);
return -EINVAL;
}
if (header.e_type != ET_REL) {
printf("(Not a relocatable object)\n");
close_fs(file);
return -EINVAL;
}
mutex_acquire(_modules_mutex);
/* Just slap the whole thing into memory, why not... */
char * module_load_address = mmu_map_module(file->length);
read_fs(file, 0, file->length, (void*)module_load_address);
@ -119,8 +131,8 @@ int elf_module(char ** args) {
}
if (!moduleData) {
printf("No module data, bailing.\n");
return -EINVAL;
error = EINVAL;
goto _unmap_module;
}
for (unsigned int i = 0; i < header.e_shnum; ++i) {
@ -149,14 +161,15 @@ int elf_module(char ** args) {
*(uint32_t*)target = symbolTable[ELF64_R_SYM(table[rela].r_info)].st_value + table[rela].r_addend - target;
break;
default:
printf("Unsupported relocation: %ld\n", ELF64_R_TYPE(table[rela].r_info));
return -EINVAL;
error = EINVAL;
goto _unmap_module;
}
}
}
if (!_modules_table) {
_modules_table = hashmap_create(10);
if (hashmap_has(_modules_table, moduleData->name)) {
error = EEXIST;
goto _unmap_module;
}
struct LoadedModule * loadedData = malloc(sizeof(struct LoadedModule));
@ -168,12 +181,21 @@ int elf_module(char ** args) {
close_fs(file);
hashmap_set(_modules_table, moduleData->name, loadedData);
mutex_release(_modules_mutex);
/* Count arguments */
int argc = 0;
for (char ** aa = args; *aa; ++aa) ++argc;
return moduleData->init(argc, args);
_unmap_module:
close_fs(file);
mmu_unmap_module((uintptr_t)module_load_address, (uintptr_t)mmu_map_module(0) - (uintptr_t)module_load_address);
mutex_release(_modules_mutex);
return -error;
}
int elf_exec(const char * path, fs_node_t * file, int argc, const char *const argv[], const char *const env[], int interp) {