x86,c_traps: avoid PC corruption in kernel lock
When we back out of the lock via IPI stall in ipiStallCoreCallback(), the FaultIP/NextIP are not updated yet and the lock exit code will set the wrong program counter. Moving the FaultIP/NextIP before the lock makes sure that all exit paths will restore to the correct program counter. Even though this write happens outside the lock, it does not introduce a race. The only possible interference would be a TCBWriteRegisters syscall from another core along the lines of the following: other core enters syscall, current core gets to lock, makes FaultIP adjustment, other core exists syscall, current core overwrites effect. This path is not possible, because the TCBWriteRegisters call on the other core first leads to a stall on this core before it proceeds, which means this core will be on idle and cannot attempt to enter the lock. Signed-off-by: Gerwin Klein <gerwin.klein@proofcraft.systems>
This commit is contained in:
parent
eba3cc75f9
commit
d0e0a6a5a2
1 changed files with 10 additions and 8 deletions
|
|
@ -147,6 +147,16 @@ void VISIBLE NORETURN c_handle_syscall(word_t cptr, word_t msgInfo, syscall_t sy
|
|||
x86_enable_ibrs();
|
||||
}
|
||||
|
||||
/* Must happen before NODE_LOCK_SYS so that lock exit via IPI stall restores
|
||||
the correct program counter. */
|
||||
if (config_set(CONFIG_SYSENTER)) {
|
||||
/* increment NextIP to skip sysenter */
|
||||
NODE_STATE(ksCurThread)->tcbArch.tcbContext.registers[NextIP] += 2;
|
||||
} else {
|
||||
/* set FaultIP */
|
||||
setRegister(NODE_STATE(ksCurThread), FaultIP, getRegister(NODE_STATE(ksCurThread), NextIP) - 2);
|
||||
}
|
||||
|
||||
NODE_LOCK_SYS;
|
||||
|
||||
c_entry_hook();
|
||||
|
|
@ -156,14 +166,6 @@ void VISIBLE NORETURN c_handle_syscall(word_t cptr, word_t msgInfo, syscall_t sy
|
|||
ksKernelEntry.is_fastpath = 1;
|
||||
#endif /* TRACK_KERNEL_ENTRIES */
|
||||
|
||||
if (config_set(CONFIG_SYSENTER)) {
|
||||
/* increment NextIP to skip sysenter */
|
||||
NODE_STATE(ksCurThread)->tcbArch.tcbContext.registers[NextIP] += 2;
|
||||
} else {
|
||||
/* set FaultIP */
|
||||
setRegister(NODE_STATE(ksCurThread), FaultIP, getRegister(NODE_STATE(ksCurThread), NextIP) - 2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FASTPATH
|
||||
if (syscall == (syscall_t)SysCall) {
|
||||
fastpath_call(cptr, msgInfo);
|
||||
|
|
|
|||
Loading…
Reference in a new issue