DF-2527 / fix.diff
--- /home/maxx/dfbsd/dfbsd/sys/dev/disk/vn/vn.c 2026-07-22 23:04:24.321615409 +0000 +++ sys/dev/disk/vn/vn.c 2026-10-24 09:12:56.265938105 +0000 @@ -123,6 +123,7 @@ int sc_flags; /* flags */ u_int64_t sc_size; /* size of vn, sc_secsize scale */ int sc_secsize; /* sector size */ + struct lwkt_token sc_iotok; /* serialize I/O vs vnclear */ struct disk sc_disk; struct vnode *sc_vp; /* vnode if not NULL */ vm_object_t sc_object; /* backing object if not NULL */ @@ -301,7 +302,21 @@ /* * Use the translated nbio from this point on */ - if (vn->sc_vp && bp->b_cmd == BUF_CMD_FREEBLKS) { + struct vnode *vp_snap; + int inited_snap; + + /* + * Snapshot the backing-store state under the token so a + * concurrent vnclear (detach) cannot free sc_vp between the + * test and the use. (Full lifetime safety additionally needs + * a held vnode reference across the I/O.) + */ + lwkt_gettoken(&vn->sc_iotok); + vp_snap = vn->sc_vp; + inited_snap = (vn->sc_flags & VNF_INITED) != 0; + lwkt_reltoken(&vn->sc_iotok); + + if (vp_snap && bp->b_cmd == BUF_CMD_FREEBLKS) { /* * Freeblks is not handled for vnode-backed elements yet. */ @@ -556,6 +571,10 @@ * If the size is specified, override the file attributes. Note that * the vn_size argument is in PAGE_SIZE sized blocks. */ + if (vio->vn_size < 0 || vio->vn_size > INT64_MAX / PAGE_SIZE) { + error = EDOM; /* same range guard the swap path applies */ + goto done; + } if (vio->vn_size) vn->sc_size = vio->vn_size * PAGE_SIZE / vn->sc_secsize; else @@ -857,6 +876,7 @@ ret_dev = dev = disk_create(unit, &vn->sc_disk, &vn_ops); } vninitvn(vn, dev); + lwkt_token_init(&vn->sc_iotok, "vniotok"); bzero(&info, sizeof(struct disk_info)); info.d_media_blksize = 512; |