diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2024-11-17 12:21:49 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2024-11-17 12:21:49 +0000 |
commit | 4ecbbc09b86badfd4a091455e0cfb5d77d931c4b (patch) | |
tree | c64dba9695caa935c201672f52501448e4f64ba4 | |
parent | b35763eebd3158c664a4430599eff4543aa370de (diff) |
make sure bpfsdetach is holding a bpf_d ref when invalidating stuff.
when bpfsdetach is called by an interface being destroyed, it
iterates over the bpf descriptors using the interface and calls
vdevgone and klist_invalidate against them. however, i'm not sure
the reference the interface holds against the bpf_d is accounted
for properly, so vdevgone might drop it to 0 and free it, which
makes the klist_invalidate a use after free.
avoid this by taking a bpf_d ref before calling vdevgone and
klist_invalidate so the memory can't be freed out from under the
feet of bpfsdetach.
Reported-by: syzbot+b3927f8ad162452a2f39@syzkaller.appspotmail.com
i wasn't able to reproduce whatever syzkaller did. it's possible
this is a double free, but we'll wait and see if it pops up again.
ok mpi@
-rw-r--r-- | sys/net/bpf.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c index d77ad57ace4..41f62b6584f 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bpf.c,v 1.225 2024/08/15 12:20:20 dlg Exp $ */ +/* $OpenBSD: bpf.c,v 1.226 2024/11/17 12:21:48 dlg Exp $ */ /* $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */ /* @@ -1798,8 +1798,10 @@ bpfsdetach(void *p) break; while ((bd = SMR_SLIST_FIRST_LOCKED(&bp->bif_dlist))) { + bpf_get(bd); vdevgone(maj, bd->bd_unit, bd->bd_unit, VCHR); klist_invalidate(&bd->bd_klist); + bpf_put(bd); } for (tbp = bpf_iflist; tbp; tbp = tbp->bif_next) { |