core: Add "tokens" to determine what processes can call which syscalls

This commit is contained in:
Gabriel 2025-02-22 20:11:07 +01:00
parent 6fa70693a5
commit c24bc8ed27
9 changed files with 95 additions and 2 deletions

View File

@ -1,4 +1,5 @@
const std = @import("std"); const std = @import("std");
const system = @import("system");
const easyboot = @cImport(@cInclude("easyboot.h")); const easyboot = @cImport(@cInclude("easyboot.h"));
const debug = @import("arch/debug.zig"); const debug = @import("arch/debug.zig");
const cpu = @import("arch/cpu.zig"); const cpu = @import("arch/cpu.zig");
@ -70,6 +71,7 @@ export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn {
init.address_space = space; init.address_space = space;
init.user_priority = 255; init.user_priority = 255;
init.tokens = @intFromEnum(system.kernel.Token.Root);
thread.arch.initUserRegisters(&init.regs); thread.arch.initUserRegisters(&init.regs);
thread.arch.setArguments(&init.regs, base, space.phys.address); thread.arch.setArguments(&init.regs, base, space.phys.address);

View File

@ -1,8 +1,15 @@
const system = @import("system");
const platform = @import("../arch/platform.zig"); const platform = @import("../arch/platform.zig");
const sys = @import("syscall.zig"); const sys = @import("syscall.zig");
const pmm = @import("../pmm.zig"); const pmm = @import("../pmm.zig");
const cpu = @import("../arch/cpu.zig");
const thread = @import("../thread.zig");
const vmm = @import("../arch/vmm.zig");
pub fn allocFrame(_: *platform.Registers, _: *sys.Arguments, retval: *isize) anyerror!void { pub fn allocFrame(_: *platform.Registers, _: *sys.Arguments, retval: *isize) anyerror!void {
const core = cpu.thisCore();
if (!sys.checkToken(core, system.kernel.Token.PhysicalMemory)) return error.NotAuthorized;
const allocator = pmm.lockGlobalAllocator(); const allocator = pmm.lockGlobalAllocator();
defer pmm.unlockGlobalAllocator(); defer pmm.unlockGlobalAllocator();
@ -12,6 +19,9 @@ pub fn allocFrame(_: *platform.Registers, _: *sys.Arguments, retval: *isize) any
} }
pub fn freeFrame(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { pub fn freeFrame(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
const core = cpu.thisCore();
if (!sys.checkToken(core, system.kernel.Token.PhysicalMemory)) return error.NotAuthorized;
const allocator = pmm.lockGlobalAllocator(); const allocator = pmm.lockGlobalAllocator();
defer pmm.unlockGlobalAllocator(); defer pmm.unlockGlobalAllocator();
@ -19,8 +29,20 @@ pub fn freeFrame(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerr
} }
pub fn lockFrame(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { pub fn lockFrame(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
const core = cpu.thisCore();
if (!sys.checkToken(core, system.kernel.Token.PhysicalMemory)) return error.NotAuthorized;
const allocator = pmm.lockGlobalAllocator(); const allocator = pmm.lockGlobalAllocator();
defer pmm.unlockGlobalAllocator(); defer pmm.unlockGlobalAllocator();
try pmm.lockFrame(allocator, args.arg0); try pmm.lockFrame(allocator, args.arg0);
} }
pub fn setAddressSpace(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
const core = cpu.thisCore();
if (!sys.checkToken(core, system.kernel.Token.VirtualMemory)) return error.NotAuthorized;
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
target.address_space = vmm.AddressSpace.create(.{ .address = args.arg1 }, vmm.PHYSICAL_MAPPING_BASE);
}

View File

@ -12,6 +12,7 @@ const RingBuffer = system.ring_buffer.RingBuffer;
const SyscallError = error{ const SyscallError = error{
NoSuchThread, NoSuchThread,
ThreadQueueAlreadySet, ThreadQueueAlreadySet,
NotAuthorized,
}; };
pub fn yield(regs: *platform.Registers, _: *sys.Arguments, _: *isize) anyerror!void { pub fn yield(regs: *platform.Registers, _: *sys.Arguments, _: *isize) anyerror!void {
@ -23,6 +24,9 @@ pub fn yield(regs: *platform.Registers, _: *sys.Arguments, _: *isize) anyerror!v
pub fn setPriority(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { pub fn setPriority(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
const core = cpu.thisCore(); const core = cpu.thisCore();
if (!sys.checkToken(core, system.kernel.Token.ThreadPriority)) return error.NotAuthorized;
core.current_thread.user_priority = @truncate(args.arg0); core.current_thread.user_priority = @truncate(args.arg0);
} }
@ -36,6 +40,8 @@ pub fn sleep(regs: *platform.Registers, args: *sys.Arguments, _: *isize) anyerro
} }
pub fn setEventQueue(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void { pub fn setEventQueue(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
const core = cpu.thisCore();
if (!sys.checkToken(core, system.kernel.Token.EventQueue)) return error.NotAuthorized;
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread; const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
if (target.event_queue) |_| return error.ThreadQueueAlreadySet; if (target.event_queue) |_| return error.ThreadQueueAlreadySet;

View File

@ -1,8 +1,11 @@
const std = @import("std"); const std = @import("std");
const system = @import("system");
const platform = @import("../arch/platform.zig"); const platform = @import("../arch/platform.zig");
const print = @import("print.zig"); const print = @import("print.zig");
const mem = @import("mem.zig"); const mem = @import("mem.zig");
const sched = @import("sched.zig"); const sched = @import("sched.zig");
const tokens = @import("token.zig");
const cpu = @import("../arch/cpu.zig");
pub const Arguments = struct { pub const Arguments = struct {
arg0: usize, arg0: usize,
@ -15,7 +18,18 @@ pub const Arguments = struct {
const SystemCall = *const fn (frame: *platform.Registers, args: *Arguments, retval: *isize) anyerror!void; const SystemCall = *const fn (frame: *platform.Registers, args: *Arguments, retval: *isize) anyerror!void;
const syscalls = [_]SystemCall{ print.print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield, sched.setPriority, sched.getPriority, sched.sleep, sched.setEventQueue }; const syscalls = [_]SystemCall{
print.print,
mem.allocFrame,
mem.lockFrame,
mem.freeFrame,
sched.yield,
sched.setPriority,
sched.getPriority,
sched.sleep,
sched.setEventQueue,
tokens.setTokens,
};
pub fn invokeSyscall(number: usize, frame: *platform.Registers, args: *Arguments, retval: *isize) void { pub fn invokeSyscall(number: usize, frame: *platform.Registers, args: *Arguments, retval: *isize) void {
if (number >= syscalls.len) { if (number >= syscalls.len) {
@ -28,3 +42,7 @@ pub fn invokeSyscall(number: usize, frame: *platform.Registers, args: *Arguments
return; return;
}; };
} }
pub fn checkToken(core: *cpu.arch.Core, token: system.kernel.Token) bool {
return (core.current_thread.tokens & @intFromEnum(token)) > 0;
}

14
core/src/sys/token.zig Normal file
View File

@ -0,0 +1,14 @@
const system = @import("system");
const platform = @import("../arch/platform.zig");
const sys = @import("syscall.zig");
const cpu = @import("../arch/cpu.zig");
const thread = @import("../thread.zig");
pub fn setTokens(_: *platform.Registers, args: *sys.Arguments, _: *isize) anyerror!void {
const core = cpu.thisCore();
if (!sys.checkToken(core, system.kernel.Token.Root)) return error.NotAuthorized;
const target = thread.lookupThreadById(args.arg0) orelse return error.NoSuchThread;
target.tokens = args.arg1;
}

View File

@ -24,6 +24,7 @@ pub const ThreadControlBlock = struct {
state: ThreadState, state: ThreadState,
user_priority: u8, user_priority: u8,
event_queue: ?RingBuffer, event_queue: ?RingBuffer,
tokens: u64,
// Managed by addThreadToGlobalList(), no need to set manually. // Managed by addThreadToGlobalList(), no need to set manually.
tag: GlobalThreadList.Node, tag: GlobalThreadList.Node,
@ -151,6 +152,7 @@ pub fn createThreadControlBlock(allocator: *pmm.FrameAllocator) !*ThreadControlB
thread.state = .Inactive; thread.state = .Inactive;
thread.user_priority = 127; thread.user_priority = 127;
thread.event_queue = null; thread.event_queue = null;
thread.tokens = 0;
addThreadToGlobalList(thread); addThreadToGlobalList(thread);

View File

@ -7,17 +7,30 @@ const buffer = system.ring_buffer;
// FIXME: Make arch-specific. // FIXME: Make arch-specific.
const PAGE_SIZE = 4096; const PAGE_SIZE = 4096;
const SELF_PID = 1;
fn setupKernelRingBuffer(base: u64) !buffer.RingBuffer { fn setupKernelRingBuffer(base: u64) !buffer.RingBuffer {
const phys = vm.PhysFrame{ .address = try syscalls.allocFrame() }; const phys = vm.PhysFrame{ .address = try syscalls.allocFrame() };
const data: [*]u8 = @ptrCast(phys.virtualPointer(u8, base)); const data: [*]u8 = @ptrCast(phys.virtualPointer(u8, base));
try syscalls.setEventQueue(1, phys.address); try syscalls.setEventQueue(SELF_PID, phys.address);
return buffer.RingBuffer.init(data, PAGE_SIZE, true); return buffer.RingBuffer.init(data, PAGE_SIZE, true);
} }
fn setTokens() void {
var tokens: u64 = 0;
tokens |= @intFromEnum(system.kernel.Token.Root);
tokens |= @intFromEnum(system.kernel.Token.PhysicalMemory);
tokens |= @intFromEnum(system.kernel.Token.EventQueue);
tokens |= @intFromEnum(system.kernel.Token.VirtualMemory);
syscalls.setTokens(SELF_PID, tokens) catch {};
}
export fn _start(base: u64, address: u64) callconv(.C) noreturn { export fn _start(base: u64, address: u64) callconv(.C) noreturn {
setTokens();
const mapper = vm.MemoryMapper.create(.{ .address = address }, base); const mapper = vm.MemoryMapper.create(.{ .address = address }, base);
syscalls.print(base); syscalls.print(base);

View File

@ -8,9 +8,20 @@ pub const SystemCall = enum(u64) {
GetPriority, GetPriority,
Sleep, Sleep,
SetEventQueue, SetEventQueue,
SetTokens,
SetAddressSpace,
};
pub const Token = enum(u64) {
Root = 1 << 0,
PhysicalMemory = 1 << 1,
ThreadPriority = 1 << 2,
EventQueue = 1 << 3,
VirtualMemory = 1 << 4,
}; };
pub const SystemError = error{ pub const SystemError = error{
OutOfMemory, OutOfMemory,
NoSuchThread, NoSuchThread,
NotAuthorized,
}; };

View File

@ -51,3 +51,8 @@ pub fn setEventQueue(pid: u64, address: u64) !void {
const retval = syscall(.SetEventQueue, pid, address); const retval = syscall(.SetEventQueue, pid, address);
if (retval < 0) return error.NoSuchThread; if (retval < 0) return error.NoSuchThread;
} }
pub fn setTokens(pid: u64, tokens: u64) !void {
const retval = syscall(.SetTokens, pid, tokens);
if (retval < 0) return error.NoSuchThread;
}