kernel: user memory is reached only through a checked copy
A new user-memory module owns every kernel touch of a user buffer: copyFromUser, the new copyToUser, and the resolve behind both. The walk accumulates the U/S and writable bits down all four levels with the MMU's own AND rule — folding a 2 MiB leaf in before it resolves and refusing a 1 GiB leaf outright — so a copy honours what ring 3 itself would be allowed, closing the presence-only trust model the IPC layer carried since bring-up. It then confirms the frame is physmap-backed, because that is how the copy reaches it: an mmio_map'd BAR passes the permission walk and would otherwise fault ring 0 on an alias the physmap never mapped, on the IPC path as much as the new one. The nine stragglers that dereferenced user pointers raw now route through it, so a bad pointer returns -EFAULT where it used to fault the kernel. The write direction restructures its callees around kernel bounce buffers: scheduler and devices-broker enumerate from a slot cursor (a task exiting between chunks can neither duplicate nor lose an entry), klog_read drains the ring in chunks, and fs_node stages headers and names contiguously. fs_resolve copies out before installing the endpoint handle, so a faulting copy cannot strand a capability; its out-capacity bound no longer adds an unbounded ring-3 length to the base, which wrapped and trapped the kernel's own overflow check. debug_write reads the caller's message once. Suite 107/107 (new user-memory case: seven bad pointers refused, each paired with a sound call that must still succeed).
This commit is contained in:
@@ -184,11 +184,16 @@ fn installMount(prefix: []const u8, kind: MountKind, backend: ?*ipc.Endpoint, re
|
||||
|
||||
// --- resolve -----------------------------------------------------------------
|
||||
|
||||
/// Longest rewritten mount-relative path a backend resolution can carry — the
|
||||
/// size `fs_resolve`'s caller has to have room for, so it is named rather than
|
||||
/// spelled out at the one place that builds it.
|
||||
pub const maximum_backend_path = maximum_rewrite + maximum_prefix + 160;
|
||||
|
||||
pub const Resolved = union(enum) {
|
||||
/// Kernel-served: a permanent node token.
|
||||
kernel_node: u64,
|
||||
/// Backend-served: the endpoint plus the rewritten mount-relative path.
|
||||
backend: struct { endpoint: *ipc.Endpoint, path: [maximum_rewrite + maximum_prefix + 160]u8, path_len: usize },
|
||||
backend: struct { endpoint: *ipc.Endpoint, path: [maximum_backend_path]u8, path_len: usize },
|
||||
not_found: void,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user