untrusted comment: verify with openbsd-80-base.pub RWSMSt0erHTcte/DOGd1aYsyG1WQQj7QS1lEHbE6MrGQ3t2o2YYrVmNc2+EXKkfULevmVHfqwRoO41g7OKtSIhXj9EDlNw5bDgc= OpenBSD 8.0 errata 014, November 14, 2026: Fix a local root exploit through a reference count race in the vnode pager that can be triggered with kbind(2). Apply by doing: signify -Vep /etc/signify/openbsd-80-base.pub -x 014_kbind.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install a new kernel: KK=`sysctl -n kern.osversion | cut -d# -f1` cd /usr/src/sys/arch/`machine`/compile/$KK make obj make config make make install Index: sys/uvm/uvm_vnode.c =================================================================== RCS file: /cvs/src/sys/uvm/uvm_vnode.c,v diff -u -p -r1.151 uvm_vnode.c --- sys/uvm/uvm_vnode.c 29 Dec 2025 16:07:14 -0000 1.151 +++ sys/uvm/uvm_vnode.c 6 Nov 2026 22:15:41 -0000 @@ -46,6 +46,7 @@ */ #include +#include #include #include #include @@ -207,14 +208,12 @@ uvn_attach(struct vnode *vp, vm_prot_t a if (uvn->u_flags & UVM_VNODE_VALID) { /* already active? */ /* regain vref if we were persisting */ - if (uvn->u_obj.uo_refs == 0) { + if (atomic_inc_int_nv(&uvn->u_obj.uo_refs) == 1) vref(vp); - } - uvn->u_obj.uo_refs++; /* bump uvn ref! */ } else { /* now set up the uvn. */ KASSERT(uvn->u_obj.uo_refs == 0); - uvn->u_obj.uo_refs++; + atomic_inc_int(&uvn->u_obj.uo_refs); uvn->u_flags = UVM_VNODE_VALID|UVM_VNODE_CANPERSIST; uvn->u_nio = 0; uvn->u_size = used_vnode_size; @@ -269,7 +268,7 @@ uvn_reference(struct uvm_object *uobj) panic("uvn_reference: invalid state"); } #endif - uobj->uo_refs++; + atomic_inc_int(&uobj->uo_refs); rw_exit(uobj->vmobjlock); } @@ -289,14 +288,14 @@ uvn_detach(struct uvm_object *uobj) struct vnode *vp; int oldflags; + KERNEL_LOCK(); rw_enter(uobj->vmobjlock, RW_WRITE); - uobj->uo_refs--; /* drop ref! */ - if (uobj->uo_refs) { /* still more refs */ + if (atomic_dec_int_nv(&uobj->uo_refs) != 0) { rw_exit(uobj->vmobjlock); + KERNEL_UNLOCK(); return; } - KERNEL_LOCK(); /* get other pointers ... */ uvn = (struct uvm_vnode *) uobj; vp = uvn->u_vnode; @@ -1355,7 +1354,7 @@ uvm_vnp_uncache(struct vnode *vp) * it so that we can call uvn_detach to kill the uvn. */ vref(vp); /* seems ok, even with VOP_LOCK */ - uvn->u_obj.uo_refs++; /* value is now 1 */ + atomic_inc_int(&uvn->u_obj.uo_refs); /* value is now 1 */ rw_exit(uobj->vmobjlock); #ifdef VFSLCKDEBUG @@ -1473,11 +1472,11 @@ uvm_vnp_sync(struct mount *mp) /* * gain reference. watch out for persisting uvns (need to - * regain vnode REF). + * regain vnode REF). uvn_reference() can take another + * reference without the kernel lock. */ - if (uvn->u_obj.uo_refs == 0) + if (atomic_inc_int_nv(&uvn->u_obj.uo_refs) == 1) vref(vp); - uvn->u_obj.uo_refs++; SIMPLEQ_INSERT_HEAD(&uvn_sync_q, uvn, u_syncq); }