diff options
author | Marvin Borner | 2021-04-03 18:33:26 +0200 |
---|---|---|
committer | Marvin Borner | 2021-04-03 18:33:26 +0200 |
commit | 0162d9cafc2c9b14fe6f319d1fbca74b26bd0b3d (patch) | |
tree | ba7bf845e3e4721e5f1645a8c5a261b68ad3d89d /kernel/features | |
parent | bd1ad65704d44e3e06a587a890e8087bfd9abe3b (diff) |
Added readonly remap of readonly elf sections
Diffstat (limited to 'kernel/features')
-rw-r--r-- | kernel/features/load.c | 53 | ||||
-rw-r--r-- | kernel/features/mm.c | 23 |
2 files changed, 75 insertions, 1 deletions
diff --git a/kernel/features/load.c b/kernel/features/load.c index 0439424..de48be4 100644 --- a/kernel/features/load.c +++ b/kernel/features/load.c @@ -49,6 +49,7 @@ res elf_load(const char *path, struct proc *proc) header.version != 1 || header.machine != ELF_MACHINE_386) return -ENOEXEC; + // Loop through programs for (u32 i = 0; i < header.phnum; i++) { struct elf_program program = { 0 }; @@ -61,7 +62,7 @@ res elf_load(const char *path, struct proc *proc) } memory_bypass_disable(); - if (program.vaddr == 0) + if (program.vaddr == 0 || program.type != ELF_PROGRAM_TYPE_LOAD) continue; if (!memory_is_user(program.vaddr)) @@ -87,6 +88,56 @@ res elf_load(const char *path, struct proc *proc) memory_switch_dir(prev); } + // Find section string table + struct elf_section section_strings = { 0 }; + memory_bypass_enable(); + if (vfs_read(path, §ion_strings, header.shoff + header.shentsize * header.shstrndx, + sizeof(section_strings)) != sizeof(section_strings)) { + memory_bypass_disable(); + clac(); + return -ENOEXEC; + } + memory_bypass_disable(); + + if (section_strings.type != ELF_SECTION_TYPE_STRTAB) + return -ENOEXEC; + + // Loop through sections + for (u32 i = 0; i < header.shnum; i++) { + struct elf_section section = { 0 }; + memory_bypass_enable(); + if (vfs_read(path, §ion, header.shoff + header.shentsize * i, + sizeof(section)) != sizeof(section)) { + memory_bypass_disable(); + clac(); + return -ENOEXEC; + } + memory_bypass_disable(); + + // TODO: Use section and symbol name for logging or something? (e.g. in page fault handler) + /* u32 offset = section_strings.offset + section.name; */ + /* if (offset >= s.size) */ + /* return -ENOEXEC; */ + /* memory_bypass_enable(); */ + /* char name[64] = { 0 }; // Max length? */ + /* if (vfs_read(path, &name, offset, sizeof(name)) != sizeof(name)) { */ + /* memory_bypass_disable(); */ + /* clac(); */ + /* return -ENOEXEC; */ + /* } */ + /* memory_bypass_disable(); */ + /* printf("%d\n", section.name); */ + /* if (section.type == ELF_SECTION_TYPE_SYMTAB) { */ + /* } else if (section.type == ELF_SECTION_TYPE_STRTAB && i != header.shstrndx) { */ + /* } */ + + // Remap readonly sections + if (!(section.flags & ELF_SECTION_FLAG_WRITE)) { + struct memory_range range = memory_range_around(section.addr, section.size); + virtual_remap_readonly(proc->page_dir, range); + } + } + struct page_dir *prev; memory_backup_dir(&prev); memory_switch_dir(proc->page_dir); diff --git a/kernel/features/mm.c b/kernel/features/mm.c index 29e07e1..67a5abf 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -257,6 +257,29 @@ void virtual_map(struct page_dir *dir, struct memory_range prange, u32 vaddr, u3 paging_invalidate_tlb(); } +void virtual_remap_readonly(struct page_dir *dir, struct memory_range vrange) +{ + for (u32 i = 0; i < vrange.size / PAGE_SIZE; i++) { + u32 offset = i * PAGE_SIZE; + + u32 pdi = PDI(vrange.base + offset); + union page_dir_entry *dir_entry = &dir->entries[pdi]; + if (!dir_entry->bits.present) + continue; + + struct page_table *table = + (struct page_table *)(dir_entry->bits.address * PAGE_SIZE); + + u32 pti = PTI(vrange.base + offset); + union page_table_entry *table_entry = &table->entries[pti]; + + if (table_entry->bits.present) + table_entry->bits.writable = 0; + } + + paging_invalidate_tlb(); +} + struct memory_range virtual_alloc(struct page_dir *dir, struct memory_range prange, u32 flags) { u8 user = flags & MEMORY_USER; |