DF-3169 / fake_daemon.c
/* * fake_daemon.c — DF-3169 variant B: production-shaped automountd stand-in. * * plays automountd(8): opens /dev/autofs, loops on the AUTOFSREQUEST * ioctl, and for every received request spawns a mkdir storm on * <mountpoint>/<key> inside the autofs mount (automountd really does * mkdir the key node via vop_nmkdir -> sys/vfs/autofs/autofs_vnops.c:245). * It never completes the requests (the kernel timeout reaps them), * so triggers keep retrying -- exactly the automountd behavior that * widens the umount -f race window to seconds. * * Build: cc -O2 -o fake_daemon fake_daemon.c * Run (root): ./fake_daemon /df3169b_mp */ #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <pthread.h> #include <errno.h> #include "autofs_ioctl.h" static const char *g_mp; static void * mkdir_storm(void *arg) { char *path = arg; int i; for (i = 0; i < 4000; i++) { if (mkdir(path, 0755) == -1 && errno == ENOENT) break; /* mount gone */ rmdir(path); } free(path); return (NULL); } int main(int argc, char **argv) { struct autofs_daemon_request req; pthread_t t; int fd; if (argc != 2) { fprintf(stderr, "usage: %s <autofs-mountpoint>\n", argv[0]); return (1); } g_mp = argv[1]; if (setsid() == -1) { perror("setsid"); return (1); } fd = open("/dev/autofs", O_RDWR); if (fd < 0) { perror("open /dev/autofs (kldload autofs first)"); return (1); } fprintf(stderr, "fake_daemon: ready on %s (sid=%d)\n", g_mp, getsid(0)); for (;;) { pthread_t *pt = &t; memset(&req, 0, sizeof(req)); if (ioctl(fd, AUTOFSREQUEST, &req) == -1) { if (errno == EINTR) continue; perror("AUTOFSREQUEST"); return (1); } fprintf(stderr, "fake_daemon: request id=%d path=%s key=%s\n", req.adr_id, req.adr_path, req.adr_key); /* mkdir storm <mp>/<key> -- vop_nmkdir on the autofs mount */ { char *path = malloc(strlen(g_mp) + strlen(req.adr_key) + 2); sprintf(path, "%s/%s", g_mp, req.adr_key); if (pthread_create(pt, NULL, mkdir_storm, path) != 0) pt = NULL; } /* deliberately no AUTOFSDONE: kernel timeout reaps it */ } } |