Skip to content

Commit 6b22bdd

Browse files
committed
Kernel use-after-free via file descriptor syscalls
A file descriptor can be closed while a thread is blocked in a poll(2) or select(2) call waiting for that descriptor. Because the blocked thread does not hold a reference to the underlying object, this closure may result in the object being freed while the thread remains blocked. In this situation, the kernel must remove the blocked thread from the per-object wait queue prior to freeing the object. In the case of some file descriptor types, the kernel failed to unlink blocked threads from the object before freeing it. When the blocked thread is subsequently woken, it accesses memory that has already been freed resulting in a use-after-free vulnerability. CVE-2026-45251 Obtained from: FreeBSD 14.x Does not include tests
1 parent 26484bf commit 6b22bdd

3 files changed

Lines changed: 4 additions & 8 deletions

File tree

sys/dev/netmap/netmap_freebsd.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ nm_os_selinfo_uninit(NM_SELINFO_T *si)
119119
taskqueue_drain(si->ntfytq, &si->ntfytask);
120120
taskqueue_free(si->ntfytq);
121121
si->ntfytq = NULL;
122+
seldrain(&si->si);
122123
knlist_delete(&si->si.si_note, curthread, /*islocked=*/0);
123124
knlist_destroy(&si->si.si_note);
124125
/* now we don't need the mutex anymore */

sys/kern/sys_procdesc.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ procdesc_free(struct procdesc *pd)
273273
KASSERT((pd->pd_flags & PDF_CLOSED),
274274
("procdesc_free: !PDF_CLOSED"));
275275

276+
seldrain(&pd->pd_selinfo);
276277
knlist_destroy(&pd->pd_selinfo.si_note);
277278
PROCDESC_LOCK_DESTROY(pd);
278279
free(pd, M_PROCDESC);
@@ -315,10 +316,7 @@ procdesc_exit(struct proc *p)
315316
procdesc_free(pd);
316317
return (1);
317318
}
318-
if (pd->pd_flags & PDF_SELECTED) {
319-
pd->pd_flags &= ~PDF_SELECTED;
320-
selwakeup(&pd->pd_selinfo);
321-
}
319+
selwakeup(&pd->pd_selinfo);
322320
KNOTE_LOCKED(&pd->pd_selinfo.si_note, NOTE_EXIT);
323321
PROCDESC_UNLOCK(pd);
324322
return (0);
@@ -433,10 +431,8 @@ procdesc_poll(struct file *fp, int events, struct ucred *active_cred,
433431
PROCDESC_LOCK(pd);
434432
if (pd->pd_flags & PDF_EXITED)
435433
revents |= POLLHUP;
436-
if (revents == 0) {
434+
else
437435
selrecord(td, &pd->pd_selinfo);
438-
pd->pd_flags |= PDF_SELECTED;
439-
}
440436
PROCDESC_UNLOCK(pd);
441437
return (revents);
442438
}

sys/sys/procdesc.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ struct procdesc {
8686
* Flags for the pd_flags field.
8787
*/
8888
#define PDF_CLOSED 0x00000001 /* Descriptor has closed. */
89-
#define PDF_SELECTED 0x00000002 /* Issue selwakeup(). */
9089
#define PDF_EXITED 0x00000004 /* Process exited. */
9190
#define PDF_DAEMON 0x00000008 /* Don't exit when procdesc closes. */
9291

0 commit comments

Comments
 (0)