From 0162d9cafc2c9b14fe6f319d1fbca74b26bd0b3d Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Sat, 3 Apr 2021 18:33:26 +0200 Subject: Added readonly remap of readonly elf sections --- kernel/features/load.c | 53 +++++++++++++++++++++++++++++++- kernel/features/mm.c | 23 ++++++++++++++ kernel/inc/load.h | 82 ++++++++++++++++++++++++++++++++++++++++++-------- kernel/inc/mm.h | 1 + 4 files changed, 145 insertions(+), 14 deletions(-) (limited to 'kernel') 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; diff --git a/kernel/inc/load.h b/kernel/inc/load.h index 365da79..af59cce 100644 --- a/kernel/inc/load.h +++ b/kernel/inc/load.h @@ -41,6 +41,7 @@ #define ELF_ETYPE_EXEC 2 #define ELF_ETYPE_DYN 3 #define ELF_ETYPE_CORE 4 +#define ELF_ETYPE_NUM 5 #define ELF_MACHINE_NONE 0 #define ELF_MACHINE_SPARC 2 @@ -49,19 +50,18 @@ #define ELF_MACHINE_SPARCV9 43 #define ELF_MACHINE_AMD64 62 -#define ELF_FLAG_SPARC_EXT_MASK 0xffff00 -#define ELF_FLAG_SPARC_32PLUS 0x000100 -#define ELF_FLAG_SPARC_SUN_US1 0x000200 -#define ELF_FLAG_SPARC_HAL_R1 0x000400 -#define ELF_FLAG_SPARC_SUN_US3 0x000800 -#define ELF_FLAG_SPARCV9_MM 0x3 -#define ELF_FLAG_SPARCV9_TSO 0x0 -#define ELF_FLAG_SPARCV9_PSO 0x1 -#define ELF_FLAG_SPARCV9_RMO 0x2 +#define ELF_PROGRAM_TYPE_NULL 0 +#define ELF_PROGRAM_TYPE_LOAD 1 +#define ELF_PROGRAM_TYPE_DYNAMIC 2 +#define ELF_PROGRAM_TYPE_INTERP 3 +#define ELF_PROGRAM_TYPE_NOTE 4 +#define ELF_PROGRAM_TYPE_SHLIB 5 +#define ELF_PROGRAM_TYPE_PHDR 6 +#define ELF_PROGRAM_TYPE_TLS 7 -#define ELF_PROGRAM_X 0x1 -#define ELF_PROGRAM_W 0x2 -#define ELF_PROGRAM_R 0x4 +#define ELF_PROGRAM_FLAG_X 0x1 +#define ELF_PROGRAM_FLAG_W 0x2 +#define ELF_PROGRAM_FLAG_R 0x4 #define ELF_SECTION_TYPE_NULL 0 #define ELF_SECTION_TYPE_PROGBITS 1 @@ -77,6 +77,40 @@ #define ELF_SECTION_TYPE_DYNSYM 11 #define ELF_SECTION_TYPE_COUNT 12 +#define ELF_SECTION_FLAG_WRITE 0x1 +#define ELF_SECTION_FLAG_ALLOC 0x2 +#define ELF_SECTION_FLAG_EXEC 0x3 +#define ELF_SECTION_FLAG_MERGE 0x10 +#define ELF_SECTION_FLAG_STRINGS 0x20 +#define ELF_SECTION_FLAG_INFO_LINK 0x40 +#define ELF_SECTION_FLAG_LINK_ORDER 0x80 +#define ELF_SECTION_FLAG_OS_SPECIAL 0x100 +#define ELF_SECTION_FLAG_GROUP 0x200 +#define ELF_SECTION_FLAG_TLS 0x400 +#define ELF_SECTION_FLAG_COMPRESSED 0x800 + +#define ELF_BSS ".bss" +#define ELF_DATA ".data" +#define ELF_DEBUG ".debug" +#define ELF_DYNAMIC ".dynamic" +#define ELF_DYNSTR ".dynstr" +#define ELF_DYNSYM ".dynsym" +#define ELF_FINI ".fini" +#define ELF_GOT ".got" +#define ELF_HASH ".hash" +#define ELF_INIT ".init" +#define ELF_REL_DATA ".rel.data" +#define ELF_REL_FINI ".rel.fini" +#define ELF_REL_INIT ".rel.init" +#define ELF_REL_DYN ".rel.dyn" +#define ELF_REL_RODATA ".rel.rodata" +#define ELF_REL_TEXT ".rel.text" +#define ELF_RODATA ".rodata" +#define ELF_SHSTRTAB ".shstrtab" +#define ELF_STRTAB ".strtab" +#define ELF_SYMTAB ".symtab" +#define ELF_TEXT ".text" + struct PACKED elf_header { u8 ident[ELF_IDENT_COUNT]; u16 type; @@ -94,7 +128,7 @@ struct PACKED elf_header { u16 shstrndx; }; -struct elf_program { +struct PACKED elf_program { u32 type; u32 offset; u32 vaddr; @@ -105,6 +139,28 @@ struct elf_program { u32 align; }; +struct PACKED elf_section { + u32 name; + u32 type; + u32 flags; + u32 addr; + u32 offset; + u32 size; + u32 link; + u32 info; + u32 addralign; + u32 entsize; +}; + +struct PACKED elf_symbol { + u32 name; + u32 value; + u32 size; + u8 info; + u8 other; + u16 shndx; +}; + res elf_load(const char *path, struct proc *proc) NONNULL; #endif diff --git a/kernel/inc/mm.h b/kernel/inc/mm.h index 7226adb..b7032c8 100644 --- a/kernel/inc/mm.h +++ b/kernel/inc/mm.h @@ -85,6 +85,7 @@ struct page_dir { u8 virtual_present(struct page_dir *dir, u32 vaddr) NONNULL; u32 virtual_to_physical(struct page_dir *dir, u32 vaddr) NONNULL; void virtual_map(struct page_dir *dir, struct memory_range prange, u32 vaddr, u32 flags) NONNULL; +void virtual_remap_readonly(struct page_dir *dir, struct memory_range vrange); struct memory_range virtual_alloc(struct page_dir *dir, struct memory_range physical_range, u32 flags) NONNULL; void virtual_free(struct page_dir *dir, struct memory_range vrange) NONNULL; -- cgit v1.2.3