diff options
author | Himbeer <himbeer@disroot.org> | 2024-07-08 16:21:49 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-07-08 16:21:49 +0200 |
commit | c20f8ceeba73e68f5db1619c287283a739a95755 (patch) | |
tree | 50cd59fa041e67987e2e7a988ed457a076feb94b /src/lib/process.zig | |
parent | 862678c2323a57005a2ed55417a0d2b00bcf1d7c (diff) |
vfs: Provide drivers with secure copies of caller buffers
Fixes #45.
Diffstat (limited to 'src/lib/process.zig')
-rw-r--r-- | src/lib/process.zig | 57 |
1 files changed, 56 insertions, 1 deletions
diff --git a/src/lib/process.zig b/src/lib/process.zig index c155243..aa3568c 100644 --- a/src/lib/process.zig +++ b/src/lib/process.zig @@ -58,11 +58,18 @@ pub const Info = struct { pages: []align(paging.page_size) u8, stack: []align(paging.page_size) u8, pc: usize, + cleanup_hook: ?CleanupHook, term_hook: ?TermHook, page_table: *paging.Table, state: State, rds: std.AutoArrayHashMap(usize, vfs.ResourceDescriptor), + pub const CleanupHook = struct { + cleanupFn: *const fn (proc: *const Info, buffer: []u8, copy: []const u8) void, + buffer: []u8, + copy: []const u8, + }; + pub const TermHook = struct { hookFn: *const fn (context: *anyopaque, proc: *const Info) void, context: *anyopaque, @@ -122,6 +129,7 @@ pub const Info = struct { .pages = self.pages, .stack = stack, .pc = self.pc, + .cleanup_hook = null, .term_hook = null, .page_table = self.page_table, .state = .suspended, @@ -135,7 +143,7 @@ pub const Info = struct { return &proc_node.data; } - pub fn call(self: *Info, function: usize, args: anytype, term_hook: ?TermHook) noreturn { + pub fn call(self: *Info, function: usize, args: anytype, cleanup_hook: ?CleanupHook, term_hook: ?TermHook) noreturn { const Container = struct { fn terminate() linksection(".rethooks") callconv(.Naked) noreturn { // Syscall #100011 is "terminate". @@ -147,6 +155,7 @@ pub const Info = struct { }; self.pc = function; + self.cleanup_hook = cleanup_hook; self.term_hook = term_hook; self.trap_frame.general_purpose_registers[1] = @intFromPtr(&Container.terminate); inline for (args, 0..) |arg, i| { @@ -184,6 +193,9 @@ pub const Info = struct { self.rds.deinit(); } + if (self.cleanup_hook) |cleanup_hook| { + cleanup_hook.cleanupFn(self, cleanup_hook.buffer, cleanup_hook.copy); + } if (self.term_hook) |term_hook| { term_hook.hookFn(term_hook.context, self); } @@ -196,6 +208,48 @@ pub const Info = struct { fn shouldRemoveThread(self: *const Info, candidate: *const Info) bool { return candidate.thread_id == self.thread_id or self.thread_id == 0; } + + pub fn copyBytes(self: *const Info, bytes: []const u8) ![]align(paging.page_size) const u8 { + const aligned_len = std.mem.alignForward(usize, bytes.len, paging.page_size); + const num_pages = @divExact(aligned_len, paging.page_size); + + const copy = try paging.zeroedAlloc(num_pages); + errdefer paging.free(copy); + + var addr = @intFromPtr(copy.ptr); + const limit = addr + copy.len; + while (addr < limit) : (addr += paging.page_size) { + try self.page_table.map(addr, addr, paging.EntryFlags.userReadOnly, 0); + errdefer self.page_table.unmapEntry(addr); + } + + paging.setUserMemoryAccess(true); + defer paging.setUserMemoryAccess(false); + + @memcpy(copy[0..bytes.len], bytes); + return copy[0..bytes.len]; + } + + pub fn copyBuffer(self: *const Info, buffer: []u8) ![]align(paging.page_size) u8 { + const aligned_len = std.mem.alignForward(usize, buffer.len, paging.page_size); + const num_pages = @divExact(aligned_len, paging.page_size); + + const copy = try paging.zeroedAlloc(num_pages); + errdefer paging.free(copy); + + var addr = @intFromPtr(copy.ptr); + const limit = addr + copy.len; + while (addr < limit) : (addr += paging.page_size) { + try self.page_table.map(addr, addr, paging.EntryFlags.userReadWrite, 0); + errdefer self.page_table.unmapEntry(addr); + } + + paging.setUserMemoryAccess(true); + defer paging.setUserMemoryAccess(false); + + @memcpy(copy[0..buffer.len], buffer); + return copy[0..buffer.len]; + } }; pub fn next() ?*Info { @@ -344,6 +398,7 @@ pub fn create(allocator: std.mem.Allocator, elf_buf: []align(@alignOf(elf.Elf64_ .pages = pages, .stack = @ptrCast(stack), .pc = hdr.entry, + .cleanup_hook = null, .term_hook = null, .page_table = procmem, .state = .waiting, |