openfile() stats a path to determine whether it is a pipe, and then opens it with flags based on the type it saw during the stat. It's possible that the file at that path changes in between, and Coverity points this out. Instead, always open O_NONBLOCK, stat the fd we got, and turn the flag back off via fcntl() if it's not a pipe. Addresses-Coverity-ID: 1442788 ("Time of check time of use") Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx> --- diff --git a/io/open.c b/io/open.c index f5fbd2c..856018b 100644 --- a/io/open.c +++ b/io/open.c @@ -62,6 +62,12 @@ openfile( int oflags; oflags = flags & IO_READONLY ? O_RDONLY : O_RDWR; + /* + * In case we've been passed a pipe to open, don't block waiting for a + * reader or writer to appear. We want to either succeed or error out + * immediately. We'll clear O_NONBLOCK if it's not a pipe. + */ + oflags |= O_NONBLOCK; if (flags & IO_APPEND) oflags |= O_APPEND; if (flags & IO_CREAT) @@ -81,18 +87,6 @@ openfile( if (flags & IO_NOFOLLOW) oflags |= O_NOFOLLOW; - /* - * if we've been passed a pipe to open, don't block waiting for a - * reader or writer to appear. We want to either succeed or error out - * immediately. - */ - if (stat(path, &st) < 0 && errno != ENOENT) { - perror("stat"); - return -1; - } - if (S_ISFIFO(st.st_mode)) - oflags |= O_NONBLOCK; - fd = open(path, oflags, mode); if (fd < 0) { if (errno == EISDIR && @@ -112,6 +106,22 @@ openfile( } } + if (fstat(fd, &st) < 0) { + perror("stat"); + close(fd); + return -1; + } + + /* We only want to keep nonblocking behavior for pipes */ + if (!S_ISFIFO(st.st_mode)) { + oflags &= ~O_NONBLOCK; + if (fcntl(fd, F_SETFL, oflags) < 0) { + perror("fcntl"); + close(fd); + return -1; + } + } + if (!geom || !platform_test_xfs_fd(fd)) return fd;