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:
parent
8351e0323b
commit
1ba93dde2c
2 changed files with 10 additions and 3 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -619,11 +619,11 @@ exec_elf(char *path, struct argsrc *av, struct argsrc *ev)
|
|||
myproc()->tf->rcx = entry;
|
||||
myproc()->tf->rsp = sp;
|
||||
|
||||
// syscall_entry saves user RSP at kstack+PGSIZE-16 (not in the trapframe).
|
||||
// syscall_entry saves user RSP at kstack+KSTACKSIZE-16 (not in the trapframe).
|
||||
// sysretq reads RSP from that slot, so update it to the new stack pointer.
|
||||
// Without this, sysretq returns with the old parent's RSP, causing lksh to
|
||||
// start with an invalid/wrong stack pointer.
|
||||
*(uint64*)((char*)myproc()->kstack + PGSIZE - 16) = sp;
|
||||
*(uint64*)((char*)myproc()->kstack + KSTACKSIZE - 16) = sp;
|
||||
|
||||
// Userspace is running now, so the splash has done its job and the display
|
||||
// becomes a terminal. Only the first exec does anything; every later one
|
||||
|
|
|
|||
Loading…
Reference in a new issue