aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/features/load.c53
-rw-r--r--kernel/features/mm.c23
-rw-r--r--kernel/inc/load.h82
-rw-r--r--kernel/inc/mm.h1
4 files changed, 145 insertions, 14 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, &section_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, &section, 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;