DF-2551 / fhopen_probe.c
/* DF-2551 -- fhopen() returns success(0) without installing an fd when * the VREG vnode has v_object == NULL (vfs_syscalls.c:4933-4941 -> bad_drop * with error still 0). Empirical probe: getfh() a file, fhopen() it, * compare returned fd validity. * * usage: fhopen_probe path */ #include <sys/param.h> #include <sys/mount.h> #include <sys/fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> int main(int argc, char **argv) { struct fhandle fh; int fd, rc; if (argc != 2) { fprintf(stderr, "usage: %s path\n", argv[0]); return 2; } memset(&fh, 0, sizeof(fh)); rc = getfh(argv[1], &fh); if (rc < 0) { printf("getfh(%s): %s\n", argv[1], strerror(errno)); return 1; } printf("getfh(%s): ok (fh_len=%zu)\n", argv[1], sizeof(fh)); /* close 0..2 noise: use a known-good base */ fd = fhopen(&fh, O_RDWR); printf("fhopen(O_RDWR) = %d errno=%d (%s)\n", fd, errno, fd >= 0 ? "fd" : strerror(errno)); if (fd >= 3) { char b[16]; ssize_t n = pread(fd, b, sizeof(b), 0); printf(" pread on fd -> %zd (errno %d)\n", n, errno); close(fd); } else if (fd == 0 || fd == 1 || fd == 2) { printf(" !! fd value overlaps std fd %d\n", fd); } else { printf(" !! error %d (%s)\n", fd, strerror(-fd)); } /* read-only open of file opened O_RDWR fh */ fd = fhopen(&fh, O_RDONLY); printf("fhopen(O_RDONLY) = %d errno=%d (%s)\n", fd, errno, fd >= 0 ? "fd" : strerror(errno)); if (fd >= 3) close(fd); /* is the returned descriptor REALLY the file? fd 0 dup probe */ return 0; } |