DF-0724 / rfcomm_race_test.c
/* * DF-0724 โ Unsynchronized timer-vs-caller double-close race in * rfcomm_dlc_close (sys/netbt/rfcomm_dlc.c:151-183). * * Trigger attempt: create an RFCOMM socket, bind, and try to connect * to a (nonexistent) remote Bluetooth peer. If a session could be * established, the DLC timer (rd_timeout, 20s) would be armed, and a * DISC frame from the peer arriving at the timer-expiry window would * race rfcomm_dlc_close between the softclock handler * (rfcomm_dlc_timeout, rfcomm_dlc.c:195) and the network-input path * (rfcomm_session.c:784/819/876/911), causing a double-LIST_REMOVE, * double disconnected callback, and double session-expiry scheduling. * * RESULT on this guest: socket() and bind() succeed (after netbt.ko * is loaded by root), but connect() fails with EHOSTUNREACH ("No route * to host") because there is NO Bluetooth adapter / HCI unit on the * QEMU guest. Without an HCI unit, no L2CAP link, no RFCOMM session, * no DLC timer โ the race path is unreachable. This is a code-level * race confirmed by source tracing (see VERDICT.md) but not exercisable * on this guest. */ #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <netbt/bluetooth.h> #include <netbt/rfcomm.h> int main(void) { int s; struct sockaddr_bt laddr, raddr; s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (s < 0) { printf("socket(RFCOMM) FAIL errno=%d (%s)\n", errno, strerror(errno)); printf("=> netbt.ko not loaded; AF_BLUETOOTH domain " "unregistered\n"); return 1; } printf("socket(RFCOMM) = %d OK\n", s); memset(&laddr, 0, sizeof(laddr)); laddr.bt_len = sizeof(laddr); laddr.bt_family = AF_BLUETOOTH; /* bt_bdaddr = all-zeros = BDADDR_ANY */ if (bind(s, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) { printf("bind FAIL errno=%d (%s)\n", errno, strerror(errno)); } else { printf("bind OK\n"); } memset(&raddr, 0, sizeof(raddr)); raddr.bt_len = sizeof(raddr); raddr.bt_family = AF_BLUETOOTH; raddr.bt_channel = 1; raddr.bt_bdaddr.b[0] = 0x01; /* arbitrary non-zero peer */ if (connect(s, (struct sockaddr *)&raddr, sizeof(raddr)) < 0) { printf("connect FAIL errno=%d (%s)\n", errno, strerror(errno)); printf("=> no HCI unit / BT adapter; L2CAP link cannot be " "established; RFCOMM session unreachable\n"); } else { printf("connect OK โ session established (unexpected!)\n"); /* If we got here, the DLC timer would be armed (20s). * Closing the socket now would race against the timer. * But this path is not reached on this guest. */ } close(s); printf("done\n"); return 0; } |