DF-3260 / poc_regression.c
/* DF-3260 fix regression check: valid rules must still install & work */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define O_IP_SRC 1 #define O_PROBE_STATE 36 #define O_KEEP_STATE 37 #define O_LOG 40 #define O_ACCEPT 43 #define IP_FW_ADD 50 #define IP_FW_GET 54 struct ioc_rule { uint16_t act_ofs, cmd_len, rulenum; uint8_t set, usr_flags; uint32_t set_disable, static_count, static_len; uint64_t pcnt, bcnt; uint32_t timestamp; uint8_t reserved[16]; uint32_t cmd[64]; }; #define INSN(op, len, arg1) ((op) | ((len) << 8) | ((arg1) << 16)) int main(void) { static unsigned char buf[65536]; struct ioc_rule r; struct sockaddr_in src, dst; socklen_t len; int s, us, i, nvalid = 0; s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (s < 0) { perror("raw"); exit(1); } /* 1. same shape as PoC1 rule, but act_ofs=4 (the O_ACCEPT) */ memset(&r, 0, sizeof(r)); r.rulenum = 1000; r.cmd_len = 5; r.act_ofs = 4; r.cmd[0] = INSN(O_PROBE_STATE, 1, 0); r.cmd[1] = INSN(O_IP_SRC, 2, 0); r.cmd[2] = 0xffff007f; r.cmd[3] = INSN(O_KEEP_STATE, 1, 0); r.cmd[4] = INSN(O_ACCEPT, 1, 0); i = setsockopt(s, IPPROTO_IP, IP_FW_ADD, &r, 60 + 20); printf("[%c] rule 1000 (act_ofs=4, action boundary): %s\n", i ? '-' : '+', i ? "REJECTED (regression!)" : "installed"); if (i == 0) nvalid++; /* 2. log rule with act_ofs=0 (the O_LOG boundary) */ memset(&r, 0, sizeof(r)); r.rulenum = 2000; r.cmd_len = 4; r.act_ofs = 0; r.cmd[0] = INSN(O_LOG, 3, 0); r.cmd[1] = 0x00000128; r.cmd[2] = 0x00000128; r.cmd[3] = INSN(O_ACCEPT, 1, 0); i = setsockopt(s, IPPROTO_IP, IP_FW_ADD, &r, 60 + 16); printf("[%c] rule 2000 (log rule, act_ofs=0): %s\n", i ? '-' : '+', i ? "REJECTED (regression!)" : "installed"); if (i == 0) nvalid++; /* 3. traffic still flows & state rule works (2 pkts, no panic) */ us = socket(AF_INET, SOCK_DGRAM, 0); memset(&src, 0, sizeof(src)); src.sin_family = AF_INET; src.sin_port = htons(54321); src.sin_addr.s_addr = inet_addr("127.0.255.255"); memset(&dst, 0, sizeof(dst)); dst.sin_family = AF_INET; dst.sin_port = htons(9); dst.sin_addr.s_addr = inet_addr("127.0.0.1"); if (bind(us, (struct sockaddr *)&src, sizeof(src)) != 0) { /* alias missing: fall back to 127.0.0.1 (rule won't match, * but traffic must still pass) */ src.sin_addr.s_addr = inet_addr("127.0.0.1"); bind(us, (struct sockaddr *)&src, sizeof(src)); } for (i = 0; i < 2; i++) sendto(us, buf, 8, 0, (struct sockaddr *)&dst, sizeof(dst)); close(us); sleep(1); len = sizeof(buf); if (getsockopt(s, IPPROTO_IP, IP_FW_GET, buf, &len) == 0) printf("[+] IP_FW_GET ok (%u bytes) -- kernel alive, " "no panic, no wedge\n", (unsigned)len); else printf("[-] IP_FW_GET failed\n"); printf("%s\n", nvalid == 2 ? "PASS: valid rules accepted, traffic flows" : "FAIL: valid rule rejected (regression)"); return nvalid == 2 ? 0 : 1; } |