[Bug 283938] panic due to race between ether_output() and ng_ether_detach()
Date: Wed, 08 Jan 2025 20:21:10 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=283938 Bug ID: 283938 Summary: panic due to race between ether_output() and ng_ether_detach() Product: Base System Version: CURRENT Hardware: Any OS: Any Status: New Severity: Affects Some People Priority: --- Component: kern Assignee: bugs@FreeBSD.org Reporter: chs@FreeBSD.org while running the freebsd kyua test suite in a loop, I hit this panic: Fatal trap 12: page fault while in kernel mode cpuid = 4; apic id = 04 fault virtual address = 0x30 fault code = supervisor read data, page not present instruction pointer = 0x20:0xffffffff83a5ca9f stack pointer = 0x28:0xfffffe02f90df790 frame pointer = 0x28:0xfffffe02f90df7b0 code segment = base 0x0, limit 0xfffff, type 0x1b = DPL 0, pres 1, long 1, def32 0, gran 1 processor eflags = interrupt enabled, resume, IOPL = 0 current process = 0 (netlink_socket (PID) rdi: fffff805a7b0c000 rsi: fffffe02f90df7c8 rdx: 9c58ffffffffffff rcx: fffffe02f90df8c0 r8: 0608504e00fc9c58 r9: fffff811b4eff060 rax: 0000000000000000 rbx: fffff805a7b0c000 rbp: fffffe02f90df7b0 r10: 0000000000000000 r11: 0000000082e34944 r12: 000000000000000e r13: 0000000000000000 r14: fffffe02f90df8c0 r15: fffff805a7b0c000 trap number = 12 panic: page fault cpuid = 4 time = 1733106093 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe02f90df480 vpanic() at vpanic+0x136/frame 0xfffffe02f90df5b0 panic() at panic+0x43/frame 0xfffffe02f90df610 trap_fatal() at trap_fatal+0x40b/frame 0xfffffe02f90df670 trap_pfault() at trap_pfault+0x46/frame 0xfffffe02f90df6c0 calltrap() at calltrap+0x8/frame 0xfffffe02f90df6c0 --- trap 0xc, rip = 0xffffffff83a5ca9f, rsp = 0xfffffe02f90df790, rbp = 0xfffffe02f90df7b0 --- ng_ether_output() at ng_ether_output+0xf/frame 0xfffffe02f90df7b0 ether_output() at ether_output+0x68d/frame 0xfffffe02f90df840 arprequest_internal() at arprequest_internal+0x394/frame 0xfffffe02f90df950 arp_ifinit() at arp_ifinit+0x6a/frame 0xfffffe02f90df9b0 ether_ioctl() at ether_ioctl+0x169/frame 0xfffffe02f90df9f0 tunifioctl() at tunifioctl+0x275/frame 0xfffffe02f90dfa30 in_control_ioctl() at in_control_ioctl+0xaff/frame 0xfffffe02f90dfad0 rtnl_handle_addr() at rtnl_handle_addr+0x412/frame 0xfffffe02f90dfcd0 rtnl_handle_message() at rtnl_handle_message+0x195/frame 0xfffffe02f90dfd30 nl_taskqueue_handler() at nl_taskqueue_handler+0x48e/frame 0xfffffe02f90dfe40 taskqueue_run_locked() at taskqueue_run_locked+0x182/frame 0xfffffe02f90dfec0 taskqueue_thread_loop() at taskqueue_thread_loop+0xc2/frame 0xfffffe02f90dfef0 fork_exit() at fork_exit+0x7b/frame 0xfffffe02f90dff30 fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe02f90dff30 --- trap 0, rip = 0, rsp = 0x3fc2a3a098be, rbp = 0x4 --- KDB: enter: panic [ thread pid 0 tid 812581 ] Stopped at kdb_enter+0x33: movq $0,0x10510c2(%rip) kgdb showed: (kgdb) up #8 ng_ether_output (ifp=0xfffff805a7b0c000, mp=0xfffffe02f90df7c8) at /usr/src/sys/netgraph/ng_ether.c:284 284 const priv_p priv = NG_NODE_PRIVATE(node); (kgdb) p node $3 = (const node_p) 0x0 (kgdb) p ifp $4 = (struct ifnet *) 0xfffff805a7b0c000 (kgdb) p ifp->if_l2com $7 = (void *) 0x0 the code in ether_output() is /* Handle ng_ether(4) processing, if any */ if (ifp->if_l2com != NULL) { KASSERT(ng_ether_output_p != NULL, ("ng_ether_output_p is NULL")); if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) { and then ng_ether_output() does #define IFP2NG(ifp) ((ifp)->if_l2com) static int ng_ether_output(struct ifnet *ifp, struct mbuf **mp) { const node_p node = IFP2NG(ifp); const priv_p priv = NG_NODE_PRIVATE(node); so ifp->if_l2com must have been non-NULL a few instructions earlier or we wouldn't have called ng_ether_output(), but then it was NULL by the time that ng_ether_output() looked at it. this looks like a race between ether_output() and something that cleared ifp->if_l2com, and the only functions that clear ifp->if_l2com are ng_ether_detach() and ng_ether_shutdown(). and indeed, ng_ether_detach() has a comment noting this race: IFP2NG(ifp) = NULL; priv->ifp = NULL; /* XXX race if interrupted an output packet */ I can reproduce this panic in less than a day by running the entire kyua test suite in a loop, but it would probably trigger much more quickly if the non-network parts of the tests were skipped. skipping the "sys/netgraph" tests and just running the rest of the test suite in a loop results in this crash not being triggered. -- You are receiving this mail because: You are the assignee for the bug.