Two things in sys_kbind() need an explicit kernel lock. First,
sigexit(). Second, uvm_map_extract(), because the following call
chain panics without it:
panic
assert
uvn_reference
uvm_mapent_clone
uum_map_extract
sys_kbind
syscall
Xsyscall
uvn_reference() does KERNEL_ASSERT_LOCKED().
These are the other routines called from sys_kbind():
copyin
kcopy
trunc_page
vm_map_lock
vm_map_unlock
uvm_unmap_detach
uvm_unmap_remove
copyin/kcopy are safe, trunc_page is safe, vm_map_lock/vm_map_unlock
are safe, uvm_unmap_detach takes the kernel lock as needed, and
uvm_unmap_remove has callees that take the kernel lock as needed.
With this committed we can unlock kbind(2).
Thoughts? ok?
Index: uvm_mmap.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_mmap.c,v
retrieving revision 1.165
diff -u -p -r1.165 uvm_mmap.c
--- uvm_mmap.c 5 Dec 2021 22:00:42 -0000 1.165
+++ uvm_mmap.c 5 Dec 2021 23:57:28 -0000
@@ -1112,10 +1112,12 @@ sys_kbind(struct proc *p, void *v, regis
if (pr->ps_kbind_addr == 0) {
pr->ps_kbind_addr = pc;
pr->ps_kbind_cookie = SCARG(uap, proc_cookie);
- } else if (pc != pr->ps_kbind_addr || pc == BOGO_PC)
- sigexit(p, SIGILL);
- else if (pr->ps_kbind_cookie != SCARG(uap, proc_cookie))
+ } else if (pc != pr->ps_kbind_addr || pc == BOGO_PC ||
+ pr->ps_kbind_cookie != SCARG(uap, proc_cookie)) {
+ KERNEL_LOCK();
sigexit(p, SIGILL);
+ }
+
if (psize < sizeof(struct __kbind) || psize > sizeof(param))
return EINVAL;
if ((error = copyin(paramp, ¶m, psize)))
@@ -1169,8 +1171,11 @@ sys_kbind(struct proc *p, void *v, regis
vm_map_unlock(kernel_map);
kva = 0;
}
- if ((error = uvm_map_extract(&p->p_vmspace->vm_map,
- baseva, PAGE_SIZE, &kva, UVM_EXTRACT_FIXPROT)))
+ KERNEL_LOCK();
+ error = uvm_map_extract(&p->p_vmspace->vm_map,
+ baseva, PAGE_SIZE, &kva, UVM_EXTRACT_FIXPROT);
+ KERNEL_UNLOCK();
+ if (error)
break;
last_baseva = baseva;
}