kernel: syscalls get the whole kernel stack

syscall_entry put the frame at kstack + 4096 - 16, from when a kernel
stack was one page. It has been two since, so every syscall ran in the
bottom 4 KB while traps used the top, and a deep enough read -- startx
exec'ing through the new compressed ramdisk -- ran over the canary at
kstack[0]. The frame now sits at the top of KSTACKSIZE, where allocproc
and the TSS already put it, and exec's user-rsp slot moves with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-24 21:17:02 +02:00
commit 1ba93dde2c
2 changed files with 10 additions and 3 deletions

View file

@ -1,3 +1,4 @@
#include "core/param.h" /* KSTACKSIZE */
# trapasm.S — kernel/user entry/exit with FS_BASE swapping for TLS
#
# The kernel uses __thread struct cpu *cpu and __thread struct proc *proc,
@ -209,7 +210,13 @@ syscall_entry:
movq %rax, %fs:(8) # save rax in per-CPU scratch slot
movq %gs:24, %rax # proc pointer (PERCPU_PROC)
movq 0x10(%rax), %rax # proc->kstack (offset 16)
addq $(4096-16), %rax # point to tf->rsp slot
# The top of the whole stack, where allocproc() put the trapframe and
# where a trap from user mode lands (TSS rsp0). This was $(4096-16) from
# when the stack was one page, and stayed that when it became two: every
# syscall ran in the bottom 4 KB with the top 4 KB unused, and a deep
# enough read -- startx exec'ing through a SCFF chunk unpack -- ran
# through the canary at kstack[0].
addq $(KSTACKSIZE-16), %rax # point to tf->rsp slot
movq %rsp, (%rax) # save user rsp
movq %rax, %rsp # switch to kernel stack
movq %fs:(8), %rax # restore rax