kernel: prevent modules from being loaded multiple times
This commit is contained in:
parent
01765b3e5e
commit
045431b2de
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user