DF-5814 / fix.diff
--- a/sys/vm/vm_pageout.c 2026-10-13 03:47:49.422426023 +0000 +++ b/sys/vm/vm_pageout.c 2026-10-13 03:51:24.815615288 +0000 @@ -1244,6 +1244,7 @@ */ if (object->type == OBJT_VNODE) { int flags; + int mightbedirty; vp = object->handle; flags = LK_EXCLUSIVE; @@ -1251,6 +1252,15 @@ flags |= LK_NOWAIT; else flags |= LK_TIMELOCK; + /* + * Sample OBJ_MIGHTBEDIRTY while (m) is still busied: + * the object is provably alive under the page busy. + * After the wakeup/vget window below the object can + * have been terminated and freed (vget failure leaves + * us holding no vnode reference), making any later + * 'object->flags' dereference a use-after-free read. + */ + mightbedirty = (object->flags & OBJ_MIGHTBEDIRTY) != 0; vm_page_hold(m); vm_page_wakeup(m); @@ -1262,7 +1272,7 @@ if (vget(vp, flags) != 0) { *vpfailedp = vp; ++pageout_lock_miss; - if (object->flags & OBJ_MIGHTBEDIRTY) + if (mightbedirty) ++*vnodes_skippedp; vm_page_unhold(m); return 0; @@ -1278,7 +1288,7 @@ if (m->queue - m->pc != PQ_INACTIVE || m->object != object || object->handle != vp) { - if (object->flags & OBJ_MIGHTBEDIRTY) + if (mightbedirty) ++*vnodes_skippedp; vput(vp); vm_page_unhold(m); |