David Higgs recently reported an incorrect usage of uvm_map_protect(9):
  https://marc.info/?l=openbsd-tech&m=174001772620750&w=2

It turns out there's another one in exec_sigcode_map(), fixed by the
diff below.  Currently the uvm_map_protect(9) calls has no effect and
returns EINVAL.

However, on amd64, with the diff applied the kernel faults when writing
to curproc.  In the trace below tatclock+0x108 corresponds to
tu_enter(&p->p_tu) in statclock().

panic(ffffffff81d89ec1) at panic+0xdd
witness_checkorder(ffffffff820236d0,1,0) at witness_checkorder+0x8ae
rw_do_enter_read(ffffffff820236b8,0) at rw_do_enter_read+0x4c
uvmfault_lookup(ffff800003aa1810,0) at uvmfault_lookup+0x8a
uvm_fault_check(ffff800003aa1810,ffff800003aa1848,ffff800003aa1878,0) at uvm_fa
ult_check+0x38
uvm_fault(ffffffff820235d0,ffff8000fffff000,0,2) at uvm_fault+0xed
kpageflttrap(ffff800003aa1990,ffff8000fffff8a8) at kpageflttrap+0x158
kerntrap(ffff800003aa1990) at kerntrap+0xaf
alltraps_kern_meltdown() at alltraps_kern_meltdown+0x7b
statclock(ffffffff81fd8dc8,ffff800003aa1bb0,0) at statclock+0x108
clockintr_dispatch(ffff800003aa1bb0) at clockintr_dispatch+0x249
clockintr(ffff800003aa1bb0) at clockintr+0x59
intr_handler(ffff800003aa1bb0,ffff80000008fe80) at intr_handler+0x91
Xintr_legacy0_untramp() at Xintr_legacy0_untramp+0x1a3
pmap_write_protect(ffffffff82022a20,ffff800003b14000,ffff800003b15000,1) at pma
p_write_protect+0x13f
uvm_map_protect(ffffffff820235d0,ffff800003b14000,ffff800003b15000,1,0,0,56f497
690e6c544a) at uvm_map_protect+0x47a
exec_sigcode_map(ffff800003aa7288) at exec_sigcode_map+0x22e
sys_execve(ffff8000fffff710,ffff800003aa2330,ffff800003aa23e0) at sys_execve+0x
11db       
start_init(ffff8000fffff710) at start_init+0x2e8

On arm64 the kernel works fine with this diff.

Any idea of what is happening?

Index: kern/exec_subr.c
===================================================================
RCS file: /cvs/src/sys/kern/exec_subr.c,v
diff -u -p -r1.68 exec_subr.c
--- kern/exec_subr.c    2 Nov 2024 10:02:23 -0000       1.68
+++ kern/exec_subr.c    10 Mar 2025 19:26:50 -0000
@@ -260,7 +260,7 @@ vmcmd_map_readvn(struct proc *p, struct 
                 * uvm_map_protect() to fix up the protection.  ICK.
                 */
                error = (uvm_map_protect(&p->p_vmspace->vm_map,
-                   cmd->ev_addr, round_page(cmd->ev_len),
+                   cmd->ev_addr, round_page(cmd->ev_addr + cmd->ev_len),
                    prot, 0, FALSE, TRUE));
        }
        if (error == 0) {
Index: kern/kern_exec.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exec.c,v
diff -u -p -r1.262 kern_exec.c
--- kern/kern_exec.c    17 Feb 2025 10:07:10 -0000      1.262
+++ kern/kern_exec.c    25 Mar 2025 13:56:34 -0000
@@ -874,12 +874,11 @@ exec_sigcode_map(struct process *pr)
                int r;
 
                sigobject = uao_create(sz, 0);
-               uao_reference(sigobject);       /* permanent reference */
-
                if ((r = uvm_map(kernel_map, &va, round_page(sz), sigobject,
                    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | 
PROT_WRITE,
                    MAP_INHERIT_SHARE, MADV_RANDOM, 0)))) {
                        uao_detach(sigobject);
+                       sigobject = NULL;
                        return (ENOMEM);
                }
 
@@ -890,9 +889,13 @@ exec_sigcode_map(struct process *pr)
                        left -= chunk;
                }
                memcpy((caddr_t)va, sigcode, sz);
-
-               (void) uvm_map_protect(kernel_map, va, round_page(sz),
+               r = uvm_map_protect(kernel_map, va, round_page(va + sz),
                    PROT_READ, 0, FALSE, FALSE);
+               if (r) {
+                       uao_detach(sigobject);
+                       sigobject = NULL;
+                       return (r);
+               }
                sigcode_va = va;
                sigcode_sz = round_page(sz);
        }
@@ -927,8 +930,6 @@ exec_timekeep_map(struct process *pr)
                vaddr_t va = 0;
 
                timekeep_object = uao_create(timekeep_sz, 0);
-               uao_reference(timekeep_object);
-
                if (uvm_map(kernel_map, &va, timekeep_sz, timekeep_object,
                    0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | 
PROT_WRITE,
                    MAP_INHERIT_SHARE, MADV_RANDOM, 0))) {


Reply via email to