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, &param, 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;
                }

Reply via email to