From 22f46cb26cedf3837cd876d738236f9522ceb355 Mon Sep 17 00:00:00 2001 From: Himbeer Date: Thu, 1 Aug 2024 11:58:57 +0200 Subject: process: Fix ELF physical allocation overrun Fixes #71. --- src/lib/process.zig | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/lib/process.zig b/src/lib/process.zig index c8e6d5e..265d9b3 100644 --- a/src/lib/process.zig +++ b/src/lib/process.zig @@ -47,7 +47,7 @@ pub const Info = struct { id: u16, thread_id: usize, trap_frame: TrapFrame, - pages: []align(paging.page_size) u8, + sections: std.ArrayList([]align(paging.page_size) u8), stack: []align(paging.page_size) u8, pc: usize, page_table: *paging.Table, @@ -116,7 +116,14 @@ pub const Info = struct { if (self.thread_id == 0) { self.page_table.unmap(); paging.free(self.page_table); - paging.free(self.pages); + self.freeSections(); + } + } + + fn freeSections(self: *Info) void { + defer self.sections.deinit(); + for (self.sections.items) |section| { + paging.free(section); } } @@ -225,11 +232,6 @@ pub fn create(allocator: Allocator, elf_buf: []align(@alignOf(elf.Elf64_Ehdr)) c try validateElfHeader(hdr, hdr_buf); - const len_aligned = std.mem.alignForwardLog2(elf_buf.len, paging.log2_page_size); - const num_pages = len_aligned / paging.page_size + 1; - const pages = try paging.zeroedAlloc(num_pages); - errdefer paging.free(pages); - const procmem: *paging.Table = @ptrCast(try paging.zeroedAlloc(1)); errdefer paging.free(procmem); @@ -237,22 +239,31 @@ pub fn create(allocator: Allocator, elf_buf: []align(@alignOf(elf.Elf64_Ehdr)) c const parse_source = std.io.fixedBufferStream(elf_buf); + var sections = std.ArrayList([]align(paging.page_size) u8).init(allocator); + var it = hdr.program_header_iterator(parse_source); while (try it.next()) |phdr| { if (phdr.p_type != elf.PT_LOAD) continue; if (phdr.p_filesz == 0 or phdr.p_memsz == 0) continue; - if (phdr.p_filesz > elf_buf.len or phdr.p_memsz > pages.len) { + if (phdr.p_offset + phdr.p_filesz >= elf_buf.len) { return ExeError.LengthOutOfBounds; } + const offset = paging.offsetOf(phdr.p_vaddr); + const memsz_aligned = std.mem.alignForward(usize, offset + phdr.p_memsz, paging.page_size); + const num_pages = @divExact(memsz_aligned, paging.page_size); + + const pages = try paging.zeroedAlloc(num_pages); + errdefer paging.free(pages); + + try sections.append(pages); + const sz = @min(phdr.p_filesz, phdr.p_memsz); - @memcpy(pages[phdr.p_offset .. phdr.p_offset + sz], elf_buf[phdr.p_offset .. phdr.p_offset + sz]); + @memcpy(pages[offset .. offset + sz], elf_buf[phdr.p_offset .. phdr.p_offset + sz]); - const memsz_aligned = std.mem.alignForwardLog2(phdr.p_memsz, paging.log2_page_size); - const num_mappings = @divExact(memsz_aligned, paging.page_size); - for (0..num_mappings) |page| { + for (0..num_pages) |page| { const vaddr = phdr.p_vaddr + page * paging.page_size; - const paddr = @intFromPtr(pages.ptr) + phdr.p_offset + page * paging.page_size; + const paddr = @intFromPtr(pages.ptr) + page * paging.page_size; const flags = paging.EntryFlags{ .valid = 1, .read = @bitCast(phdr.p_flags & elf.PF_R != 0), @@ -286,7 +297,7 @@ pub fn create(allocator: Allocator, elf_buf: []align(@alignOf(elf.Elf64_Ehdr)) c .id = next_pid, .thread_id = 0, .trap_frame = std.mem.zeroInit(TrapFrame, .{}), - .pages = pages, + .sections = sections, .stack = @ptrCast(stack), .pc = hdr.entry, .page_table = procmem, -- cgit v1.2.3