Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
bpf use after free
To:
tech@openbsd.org
Date:
Thu, 12 Jun 2025 19:55:20 +0200

Download raw body.

Thread
Hi,

syzcaller has found this crash in lo(4) calling bpf(4).

https://syzkaller.appspot.com/bug?extid=74f8141966171d61a0ab

panic: kernel diagnostic assertion "nlevel >= IPL_NONE" failed: file "/syzkaller/managers/multicore/kernel/sys/arch/amd64/amd64/intr.c", line 781
Stopped at      db_enter+0x25:  addq    $0x8,%rsp
    TID    PID    UID     PRFLAGS     PFLAGS  CPU  COMMAND
*245945  56013      0     0x14000      0x200    1  softnet1
 316891  13736      0     0x14000 0x40000200    0  softclock
db_enter() at db_enter+0x25 sys/arch/amd64/amd64/db_interface.c:438
panic(ffffffff8346d347) at panic+0x1e5 sys/kern/subr_prf.c:198
__assert(ffffffff83415b99,ffffffff8335e4f5,30d,ffffffff833c132c) at __assert+0x29 sys/kern/subr_prf.c:-1
splraise(deadbeef) at splraise+0xbd sys/arch/amd64/amd64/intr.c:781
mtx_enter_try(ffff8000014e8608) at mtx_enter_try+0x97 sys/kern/kern_lock.c:276
mtx_enter(ffff8000014e8608) at mtx_enter+0x62 sys/kern/kern_lock.c:253
_bpf_mtap(ffff800000064c40,fffffd8068509300,ffff80002a216880,2) at _bpf_mtap+0x2fb sys/net/bpf.c:1410
bpf_mtap_af(ffff800000064c40,18,fffffd8068509300,2) at bpf_mtap_af+0x71 sys/net/bpf.c:1502
if_input_local(ffff800000b2c000,fffffd8068509300,18,ffffffff83970b58) at if_input_local+0xb2 sys/net/if.c:802
loinput(ffff800000b2c000,fffffd8068509300,ffffffff83970b58) at loinput+0x73 sys/net/if_loop.c:254
if_input_process(ffff800000b2c000,ffff80002a216a58,1) at if_input_process+0x1d5 sys/net/if.c:1012
ifiq_process(ffff800000b2d200) at ifiq_process+0xcd sys/net/ifq.c:874
taskq_thread(ffff80000002c100) at taskq_thread+0x157 sys/kern/kern_task.c:446
end trace frame: 0x0, count: 2

The splraise(deadbeef) looks very much like a use after free.

if_input_local() checks ifp->if_bpf and bpfdetach() sets ifp->if_bpf
to NULL.  As if_input_local() runs with shared net lock, bpfdetach()
should be locked exclusively.  As bpf_mtap() may be called by
driver's RX interrupt, we also need splnet().

ok?

bluhm

Index: net/if.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.c,v
diff -u -p -r1.734 if.c
--- net/if.c	9 May 2025 03:12:36 -0000	1.734
+++ net/if.c	12 Jun 2025 17:46:22 -0000
@@ -1205,12 +1205,13 @@ if_detach(struct ifnet *ifp)
 	ifq_barrier(&ifp->if_snd);
 	ifq_clr_oactive(&ifp->if_snd);
 
+	NET_LOCK();
+	s = splnet();
+
 #if NBPFILTER > 0
 	bpfdetach(ifp);
 #endif
 
-	NET_LOCK();
-	s = splnet();
 	ifp->if_ioctl = if_detached_ioctl;
 	ifp->if_watchdog = NULL;