Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

boot: convert paging from assembly to Zig (take 2) #23

Merged
merged 54 commits into from
May 3, 2024
Merged
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
897e7ef
zasm: add util functions for control and model specific registers
mewmew May 23, 2022
82dc1ae
zasm: update Zig syntax to version 0.11.0
mewmew Apr 15, 2024
23378ed
boot: rewrite assembly version of enable_paging in Zig
mewmew Apr 15, 2024
6460ab1
boot: remove unused print32.asm
mewmew May 23, 2022
ea38491
boot: remove unused protected_mode.asm
mewmew May 23, 2022
0b9c138
boot: remove unused print.asm
mewmew May 23, 2022
7602dd5
zasm: add PageTableEntry and PageTableFlags from x86_64 repo
mewmew May 23, 2022
95adbb1
zasm: update Zig syntax to version 0.11.0 (part 2)
mewmew Apr 15, 2024
4cf2039
boot: ensure that no MMX instructions are used in 32-bit boot code
mewmew May 23, 2022
57f6361
boot: rewrite assembly version of map_frame_buffer in Zig
mewmew May 23, 2022
9428ed1
boot: rewrite assembly version of map_kernel_stack in Zig
mewmew May 23, 2022
03341c2
boot: use dedicated functions to map kernel code and data segment pages
mewmew May 23, 2022
11fa41f
boot: rewrite assembly version of set_up_page_tables in Zig
mewmew May 23, 2022
cef2b14
boot: make paging constants public and move into dedicated source file
mewmew May 24, 2022
da51fe0
makefile: add TODO to remove objcopy hack
mewmew May 25, 2022
1c8db56
boot: add TODO to remove 4xNOP hack in init_long_mode
mewmew May 25, 2022
2ccf788
boot/paging: use const instead of var where applicable
mewmew May 25, 2022
a7453f2
boot/paging: move load of P4 table (Cr3) closer to enable paging code…
mewmew May 25, 2022
1a46edc
boot/paging: assert that long mode active is set after enable_paging
mewmew May 25, 2022
3ced6de
zasm: add TODO to re-enable assert in setAddr
mewmew May 25, 2022
7ffb38c
notes: add logbook entry for ld bug
mewmew May 26, 2022
79fde45
boot: make kernel_data_seg executable for userland code and data (TEMP!)
mewmew Apr 15, 2024
6c37760
update to use Zig 0.12
mewmew Apr 26, 2024
c64bd0b
add TODO for adding guard page in between kernel memory and heap
mewmew Apr 26, 2024
233741f
paging: remove user access from kernel stack and framebuffer
mewmew Apr 26, 2024
ff3a207
map userland
mewmew Apr 26, 2024
4621476
make kernel heap address less hard-coded
mewmew Apr 26, 2024
d1be613
copy userland code into userland segment
mewmew Apr 26, 2024
26d6a3c
switch to userland stack
mewmew Apr 26, 2024
f231798
remove user accessability from kernel code segment
mewmew Apr 27, 2024
20227f4
remove user accessibility from kernel data segment, userland now in u…
mewmew Apr 27, 2024
c4bb0c1
fix C compiler warnings
mewmew Apr 27, 2024
3319c06
tss64: dynamically updated tss64 addr
karlek Apr 27, 2024
35ef412
make: Remove bin/fat32.img remnants
karlek Apr 29, 2024
aa33d53
paging: nice virtual ASCII memory mappings.
karlek Apr 29, 2024
bb9344c
run/debug: Increase memory demands from 128M -> 4G
karlek Apr 29, 2024
9827d8c
debug: ctrl-c now possible in gdb
karlek Apr 29, 2024
ebb27d7
ci: add lld dependency
karlek Apr 29, 2024
cbe7ff0
lint: appease the CI gods
karlek Apr 29, 2024
2c03749
make: Remove last bin/fat32.img sneaky boi
karlek Apr 29, 2024
b1e3739
paging: bootstrap is chonky
karlek May 1, 2024
2c9377c
debug: remove debug.py and use gef-remote
karlek May 1, 2024
eb47f68
qemu: add +smep and +smap capabilities to cpu
karlek May 1, 2024
2b9cc92
long_mode: Actually use the stack..
karlek May 1, 2024
f94d6ca
idt: save _all_ registers and flags
karlek May 1, 2024
42c6374
malloc: print heap status and size on oom
karlek May 1, 2024
687f330
kernel/heap: enable smep
karlek May 1, 2024
5b06ee0
debug: tidy up debug.sh
karlek May 2, 2024
c99bd02
elf2: handle file->data in kernel for SMEP
karlek May 2, 2024
5ff1444
kernel_userland: correctly handle syscalls
karlek May 2, 2024
a539b8d
userland: syscall with system v calling convention
karlek May 2, 2024
9c197c1
kernel_userland: bring userland mem into kernel
karlek May 2, 2024
a989439
userland: actually call sys_print
karlek May 2, 2024
866baf8
kernel: Enable SMAP
karlek May 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
elf2: handle file->data in kernel for SMEP
We parse and handle the ELF file as long as possible in kernel memory
before calling `userland_malloc` and `userland_memcpy`. It quickly gets
murky when mixing kernel & userland objects.
karlek committed May 2, 2024
commit c99bd02811939f76f5249db5533b8db5368c440b
106 changes: 57 additions & 49 deletions src/kernel/elf2.c
Original file line number Diff line number Diff line change
@@ -11,9 +11,9 @@ uint64_t read_uint64(uint8_t* buf, uint64_t* cur) {
return ret;
}

void parse_ident(uint8_t* userland_obj, uint64_t* cur, uint8_t* e_ident) {
void parse_ident(uint8_t* kernel_obj, uint64_t* cur, uint8_t* e_ident) {
uint8_t magic[4] = {0};
read(userland_obj, 4, cur, magic);
read(kernel_obj, 4, cur, magic);
debug("ELF magic: %x %x %x %x", magic[0], magic[1], magic[2], magic[3]);
debug("ELF magic: %x %x %x %x", ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3);
if (streqn(magic, ELFMAG, 4)) {
@@ -24,38 +24,38 @@ void parse_ident(uint8_t* userland_obj, uint64_t* cur, uint8_t* e_ident) {
e_ident[EI_MAG2] = magic[2];
e_ident[EI_MAG3] = magic[3];

uint8_t bitness = read_uint8(userland_obj, cur);
uint8_t bitness = read_uint8(kernel_obj, cur);
debug("ELF class (bitness): %d", bitness);
if (bitness != ELFCLASS64) {
debug("not implemented!");
return;
}
e_ident[EI_CLASS] = bitness;

uint8_t endianess = read_uint8(userland_obj, cur);
uint8_t endianess = read_uint8(kernel_obj, cur);
debug("ELF endianess: %d", endianess);
e_ident[EI_DATA] = endianess;

uint8_t elf_version = read_uint8(userland_obj, cur);
uint8_t elf_version = read_uint8(kernel_obj, cur);
debug("ELF version: %d", elf_version);
e_ident[EI_VERSION] = elf_version;

uint8_t os_abi = read_uint8(userland_obj, cur);
uint8_t os_abi = read_uint8(kernel_obj, cur);
debug("ELF os_abi: %d", os_abi);
e_ident[EI_OSABI] = os_abi;

uint8_t abi_version = read_uint8(userland_obj, cur);
uint8_t abi_version = read_uint8(kernel_obj, cur);
debug("ELF abi_version: %d", abi_version);
e_ident[EI_ABIVERSION] = abi_version;

uint8_t padding[7] = {0};
read(userland_obj, 7, cur, padding);
read(kernel_obj, 7, cur, padding);
debug("ELF padding: %x %x %x %x %x %x %x", padding[0], padding[1], padding[2], padding[3], padding[4], padding[5], padding[6]);
}

Elf64_Ehdr *parse_elf_header(uint8_t* userland_obj, uint64_t* cur) {
Elf64_Ehdr *parse_elf_header(uint8_t* kernel_obj, uint64_t* cur) {
uint8_t* e_ident = malloc(EI_NIDENT);
parse_ident(userland_obj, cur, e_ident);
parse_ident(kernel_obj, cur, e_ident);
if (e_ident[EI_CLASS] != ELFCLASS64) {
debug("not implemented!");
return NULL;
@@ -64,120 +64,120 @@ Elf64_Ehdr *parse_elf_header(uint8_t* userland_obj, uint64_t* cur) {
Elf64_Ehdr *header = malloc(sizeof(Elf64_Ehdr));
*header->e_ident = *e_ident;

header->e_type = read_uint16(userland_obj, cur);
header->e_type = read_uint16(kernel_obj, cur);
debug("ELF type: %d", header->e_type);

header->e_machine = read_uint16(userland_obj, cur);
header->e_machine = read_uint16(kernel_obj, cur);
debug("ELF machine: %d", header->e_machine);

header->e_version = read_uint32(userland_obj, cur);
header->e_version = read_uint32(kernel_obj, cur);
debug("ELF version: %d", header->e_version);

header->e_entry = read_uint64(userland_obj, cur);
header->e_entry = read_uint64(kernel_obj, cur);
debug("ELF entry: 0x%llx", header->e_entry);

header->e_phoff = read_uint64(userland_obj, cur);
header->e_phoff = read_uint64(kernel_obj, cur);
debug("ELF phoff: 0x%llx", header->e_phoff);

header->e_shoff = read_uint64(userland_obj, cur);
header->e_shoff = read_uint64(kernel_obj, cur);
debug("ELF shoff: 0x%llx", header->e_shoff);

header->e_flags = read_uint32(userland_obj, cur);
header->e_flags = read_uint32(kernel_obj, cur);
debug("ELF flags: 0x%x", header->e_flags);

header->e_ehsize = read_uint16(userland_obj, cur);
header->e_ehsize = read_uint16(kernel_obj, cur);
debug("ELF ehsize: 0x%x", header->e_ehsize);

header->e_phentsize = read_uint16(userland_obj, cur);
header->e_phentsize = read_uint16(kernel_obj, cur);
debug("ELF phentsize: 0x%x", header->e_phentsize);

header->e_phnum = read_uint16(userland_obj, cur);
header->e_phnum = read_uint16(kernel_obj, cur);
debug("ELF phnum: 0x%x", header->e_phnum);

header->e_shentsize = read_uint16(userland_obj, cur);
header->e_shentsize = read_uint16(kernel_obj, cur);
debug("ELF shentsize: 0x%x", header->e_shentsize);

header->e_shnum = read_uint16(userland_obj, cur);
header->e_shnum = read_uint16(kernel_obj, cur);
debug("ELF qtySectionHeaders: 0x%x", header->e_shnum);

header->e_shstrndx = read_uint16(userland_obj, cur);
header->e_shstrndx = read_uint16(kernel_obj, cur);
debug("ELF sectionNamesIndex: 0x%x", header->e_shstrndx);

return header;
}

Elf64_Phdr *parse_program_segment_header(uint8_t* userland_obj, uint64_t* cur) {
Elf64_Phdr *parse_program_segment_header(uint8_t* kernel_obj, uint64_t* cur) {
Elf64_Phdr *program_segment_header = malloc(sizeof(Elf64_Shdr));

program_segment_header->p_type = read_uint32(userland_obj, cur);
program_segment_header->p_type = read_uint32(kernel_obj, cur);
debug("Segment type: %d", program_segment_header->p_type);

program_segment_header->p_flags = read_uint32(userland_obj, cur);
program_segment_header->p_flags = read_uint32(kernel_obj, cur);
debug("Segment flags: %d", program_segment_header->p_flags);

program_segment_header->p_offset = read_uint64(userland_obj, cur);
program_segment_header->p_offset = read_uint64(kernel_obj, cur);
debug("Segment offset: 0x%llx", program_segment_header->p_offset);

program_segment_header->p_vaddr = read_uint64(userland_obj, cur);
program_segment_header->p_vaddr = read_uint64(kernel_obj, cur);
debug("Segment virtual addr: 0x%llx", program_segment_header->p_vaddr);

program_segment_header->p_paddr = read_uint64(userland_obj, cur);
program_segment_header->p_paddr = read_uint64(kernel_obj, cur);
debug("Segment physical addr: 0x%llx", program_segment_header->p_paddr);

program_segment_header->p_filesz = read_uint64(userland_obj, cur);
program_segment_header->p_filesz = read_uint64(kernel_obj, cur);
debug("Segment size in file: 0x%llx", program_segment_header->p_filesz);

program_segment_header->p_memsz = read_uint64(userland_obj, cur);
program_segment_header->p_memsz = read_uint64(kernel_obj, cur);
debug("Segment size in memory: 0x%llx", program_segment_header->p_memsz);

program_segment_header->p_align = read_uint64(userland_obj, cur);
program_segment_header->p_align = read_uint64(kernel_obj, cur);
debug("Segment alignment: 0x%llx", program_segment_header->p_align);

return program_segment_header;
}

Elf64_Shdr *parse_section_header(uint8_t* userland_obj, uint64_t* cur) {
Elf64_Shdr *parse_section_header(uint8_t* kernel_obj, uint64_t* cur) {
Elf64_Shdr *section_header = malloc(sizeof(Elf64_Shdr));

section_header->sh_name = read_uint32(userland_obj, cur);
section_header->sh_name = read_uint32(kernel_obj, cur);
debug("Section name: %d", section_header->sh_name);

section_header->sh_type = read_uint32(userland_obj, cur);
section_header->sh_type = read_uint32(kernel_obj, cur);
/* debug("Section type: 0x%x", section_header->sh_type); */

section_header->sh_flags = read_uint64(userland_obj, cur);
section_header->sh_flags = read_uint64(kernel_obj, cur);
/* debug("Section flags: 0x%llx", section_header->sh_flags); */

section_header->sh_addr = read_uint64(userland_obj, cur);
section_header->sh_addr = read_uint64(kernel_obj, cur);
/* debug("Section addr: 0x%llx", section_header->sh_addr); */

section_header->sh_offset = read_uint64(userland_obj, cur);
section_header->sh_offset = read_uint64(kernel_obj, cur);
/* debug("Section offset: 0x%llx", section_header->sh_offset); */

section_header->sh_size = read_uint64(userland_obj, cur);
section_header->sh_size = read_uint64(kernel_obj, cur);
/* debug("Section size: 0x%llx", section_header->sh_size); */

section_header->sh_link = read_uint32(userland_obj, cur);
section_header->sh_link = read_uint32(kernel_obj, cur);
/* debug("Section link: 0x%x", section_header->sh_link); */

section_header->sh_info = read_uint32(userland_obj, cur);
section_header->sh_info = read_uint32(kernel_obj, cur);
/* debug("Section info: 0x%x", section_header->sh_info); */

section_header->sh_addralign = read_uint64(userland_obj, cur);
section_header->sh_addralign = read_uint64(kernel_obj, cur);
/* debug("Section addralign: 0x%llx", section_header->sh_addralign); */

section_header->sh_entsize = read_uint64(userland_obj, cur);
section_header->sh_entsize = read_uint64(kernel_obj, cur);
/* debug("Section entsize: 0x%llx", section_header->sh_entsize); */

return section_header;
}

extern void enter_userland(void *entry_point);

void run_userland(uint8_t* userland_obj, size_t userland_obj_size) {
void run_userland(uint8_t* kernel_obj, size_t kernel_obj_size) {
uint64_t cur = 0;

Elf64_Ehdr *header = parse_elf_header(userland_obj, &cur);
Elf64_Ehdr *header = parse_elf_header(kernel_obj, &cur);
if (header == NULL) {
debug("header is null");
return;
@@ -187,12 +187,12 @@ void run_userland(uint8_t* userland_obj, size_t userland_obj_size) {
uint16_t num_sections = 19;
cur = header->e_shoff;
for (int i = 0; i < header->e_shnum; i++) {
Elf64_Shdr *section_header = parse_section_header(userland_obj, &cur);
Elf64_Shdr *section_header = parse_section_header(kernel_obj, &cur);
}

cur = header->e_phoff;
for (int i = 0; i < header->e_phnum; i++) {
Elf64_Phdr *program_segment_header = parse_program_segment_header(userland_obj, &cur);
Elf64_Phdr *program_segment_header = parse_program_segment_header(kernel_obj, &cur);
if (program_segment_header->p_type != 1) {
debug("not implemented!");
continue;
@@ -201,12 +201,20 @@ void run_userland(uint8_t* userland_obj, size_t userland_obj_size) {

debug("file size: 0x%llx", program_segment_header->p_filesz);
debug("pseg_cur: %d", pseg_cur);
uint8_t *userland_code = userland_malloc(program_segment_header->p_filesz);
read(userland_obj, program_segment_header->p_filesz, &pseg_cur, userland_code);
uint8_t *kernel_code = malloc(program_segment_header->p_filesz);
debug("kernel_code: %p", kernel_code);
debug("size: %p", program_segment_header->p_filesz);
read(kernel_obj, program_segment_header->p_filesz, &pseg_cur, kernel_code);
debug("pseg_cur: %d", pseg_cur);

// debug_buffer(userland_code, program_segment_header->p_filesz);
uint8_t* userland_code = userland_malloc(program_segment_header->p_filesz);
userland_memcpy(userland_code, kernel_code, program_segment_header->p_filesz);

kernel_code += header->e_entry - program_segment_header->p_paddr;
userland_code += header->e_entry - program_segment_header->p_paddr;
debug("kernel_code: %p", kernel_code);
debug("userland_code: %p", userland_code);
enter_userland(userland_code);
return;
}