DF-3073 / holder.c
/* * holder.c - unprivileged holder for DF-3073 * * holder <mountpoint> * * 1. opens <mp>/dev - the server-supplied VCHR node (rdev 14:2 = /dev/null) * 2. opens <mp>/slow - a regular file * 3. reads <mp>/slow - the fake server never answers the READ RPC, and the * mount is hard/non-interruptible, so this process * sleeps unkillably with BOTH descriptors open. * * The open /dev vnode keeps VREFCNT>1 across umount -f's kill-retry loop * (SIGINT at retry 3 / SIGKILL at retry 7 cannot be delivered while we are * blocked in the uninterruptible nfs_request tsleep). */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <signal.h> int main(int argc, char **argv) { char path[256]; char buf[8]; int fd1, fd2, n; if (argc != 2) { fprintf(stderr, "usage: holder <mountpoint>\n"); exit(2); } signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGHUP, SIG_IGN); snprintf(path, sizeof(path), "%s/dev", argv[1]); fd1 = open(path, O_RDONLY); if (fd1 < 0) { perror("open dev"); exit(1); } printf("DEV_OPEN_OK\n"); fflush(stdout); snprintf(path, sizeof(path), "%s/slow", argv[1]); fd2 = open(path, O_RDONLY); if (fd2 < 0) { perror("open slow"); exit(1); } printf("SLOW_OPEN_OK\n"); fflush(stdout); printf("READ_BLOCKING\n"); fflush(stdout); /* blocks forever: hard mount, server withholds the reply */ n = read(fd2, buf, sizeof(buf)); /* not reached on a live bug run */ printf("READ_RETURNED n=%d errno=%d\n", n, n < 0 ? 0 : 0); fflush(stdout); pause(); return (0); } |