DF-5029 / pcf_dos.c
/* * DF-5029 - pcfclock unkillable ppbreq sleep reproducer. * * Modes: * pcf_dos hold <sec> open /dev/pcfclock0 (blocking) and hold the ppbus * pcf_dos victim open /dev/pcfclock0 (blocking, no O_NONBLOCK); * with the bug this never returns while another * process holds the bus, and the sleeper cannot be * killed (tsleep(ppb, 0, "ppbreq", 0) - no PCATCH). * pcf_dos victim_nb open with O_NONBLOCK -> expect EWOULDBLOCK * pcf_dos read open (bus free) + read(32) -> expect EIO after * the bounded retry/busy-wait sequence */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <time.h> static double now(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec + ts.tv_nsec / 1e9; } int main(int argc, char **argv) { const char *dev = "/dev/pcfclock0"; int fd; if (argc < 2) { fprintf(stderr, "usage: %s hold <sec>|victim|victim_nb|read\n", argv[0]); return 2; } if (!strcmp(argv[1], "hold")) { int sec = argc > 2 ? atoi(argv[2]) : 30; fd = open(dev, O_RDONLY); if (fd < 0) { perror("holder open"); return 3; } printf("holder: pid=%d opened %s fd=%d, holding ppbus for %ds\n", getpid(), dev, fd, sec); fflush(stdout); sleep(sec); printf("holder: closing\n"); close(fd); return 0; } if (!strcmp(argv[1], "victim")) { double t0 = now(); printf("victim: pid=%d opening %s (blocking)...\n", getpid(), dev); fflush(stdout); fd = open(dev, O_RDONLY); printf("victim: open returned fd=%d errno=%d (%s) after %.3fs\n", fd, errno, strerror(errno), now() - t0); fflush(stdout); if (fd >= 0) close(fd); return 0; } if (!strcmp(argv[1], "victim_nb")) { fd = open(dev, O_RDONLY | O_NONBLOCK); printf("victim_nb: open returned fd=%d errno=%d (%s)\n", fd, errno, strerror(errno)); if (fd >= 0) close(fd); return 0; } if (!strcmp(argv[1], "read")) { char buf[32]; ssize_t n; double t0; fd = open(dev, O_RDONLY); if (fd < 0) { perror("reader open"); return 3; } t0 = now(); n = read(fd, buf, sizeof(buf)); printf("reader: read returned %zd errno=%d (%s) after %.3fs\n", n, errno, strerror(errno), now() - t0); close(fd); return 0; } fprintf(stderr, "unknown mode %s\n", argv[1]); return 2; } |