DF-3391 / df3391.c
/* DF-3391: ip_fw3_ctl discards ip_fw3_ctl_x() error in its IP_FW_X case * (ip_fw3.c:1058-1059). Reach it with a NESTED opcode: payload opcode 49 * (IP_FW_X) makes ip_fw3_ctl re-enter ip_fw3_ctl_x, whose inner failure * (invalid innermost opcode -> EINVAL, console "ip_fw3_ctl invalid option") * is dropped and setsockopt returns 0. A flat invalid opcode via the glue * path propagates correctly (control case). */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> #define IP_FW_X_DF 49 int main(void) { int s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (s < 0) { perror("socket"); return 1; } /* control: flat invalid opcode through the glue - error propagates */ struct { unsigned short opcode; unsigned short pad; char payload[4]; } a; a.opcode = 0xbeef; a.pad = 0; memset(a.payload, 0, 4); errno = 0; int rc1 = setsockopt(s, IPPROTO_IP, IP_FW_X_DF, &a, sizeof(a)); printf("[control] flat invalid opcode: rc=%d errno=%d (%s)\n", rc1, errno, rc1 ? strerror(errno) : "SUCCESS?!"); /* bug case: nested IP_FW_X opcode -> ip_fw3_ctl case IP_FW_X drops it */ struct { unsigned short opcode; unsigned short pad; unsigned short inner; unsigned short innerpad; } b; b.opcode = IP_FW_X_DF; b.pad = 0; b.inner = 0xbeef; b.innerpad = 0; errno = 0; int rc2 = setsockopt(s, IPPROTO_IP, IP_FW_X_DF, &b, sizeof(b)); printf("[bugcase] nested IP_FW_X opcode: rc=%d errno=%d (%s)\n", rc2, errno, rc2 ? strerror(errno) : "SUCCESS despite inner EINVAL"); close(s); return (rc2 == 0) ? 2 : 0; /* rc2==0 == bug reproduced */ } |