--- a/sys/kern/kern_syscalls.c +++ b/sys/kern/kern_syscalls.c @@ -65,15 +65,31 @@ return EEXIST; *old_sysent = sysent[*offset]; - sysent[*offset] = *new_sysent; + /* + * Publish in a defined order (sy_narg first, sy_call last) so a + * racing dispatcher never sees the new sy_call with a stale narg. + * (Full in-flight quiesce still requires a dispatch epoch.) + */ + sysent[*offset].sy_narg = new_sysent->sy_narg; + sysent[*offset].sy_rsize = new_sysent->sy_rsize; + cpu_ccfence(); + sysent[*offset].sy_abort = new_sysent->sy_abort; + cpu_ccfence(); + sysent[*offset].sy_call = new_sysent->sy_call; return 0; } int syscall_deregister(int *offset, struct sysent *old_sysent) { - if (*offset) - sysent[*offset] = *old_sysent; + if (*offset) { + /* Retract sy_call FIRST so no new dispatch enters it. */ + sysent[*offset].sy_call = (sy_call_t *)sys_lkmnosys; + cpu_ccfence(); + sysent[*offset].sy_narg = old_sysent->sy_narg; + sysent[*offset].sy_rsize = old_sysent->sy_rsize; + sysent[*offset].sy_abort = old_sysent->sy_abort; + } return 0; }