[PATCH 2/3] xfs_io: fix TOCTOU in openfile()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;
 




[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux