diff mbox

xfs_io: add seek consistency checks

Message ID 1498151028-18433-1-git-send-email-agruenba@redhat.com (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Andreas Gruenbacher June 22, 2017, 5:03 p.m. UTC
When seeking for data and holes, the lseek result must be greater than
or equal to the start offset.  Furthermore, assuming that the file
doesn't change under us, when switching between SEEK_HOLE and SEEK_DATA,
the seek position must increase monotonically.  Warn and abort if this
is not the case.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
 io/seek.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

Comments

Christoph Hellwig June 28, 2017, 4:43 p.m. UTC | #1
Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/io/seek.c b/io/seek.c
index d06375d..871b472 100644
--- a/io/seek.c
+++ b/io/seek.c
@@ -147,7 +147,10 @@  seek_f(
 	 * decide if we want to display that type of entry.
 	 */
 	if (flag & SEEK_HFLAG) {
+		current = HOLE;
 		offset = lseek(file->fd, start, SEEK_HOLE);
+		if (offset != -1 && offset < start)
+			goto bad_result;
 		if ((start == offset) || !(flag & SEEK_DFLAG)) {
 			/*
 			 * this offset is a hole or are only displaying holes.
@@ -155,7 +158,6 @@  seek_f(
 			 * data, then we will fall through below to
 			 * initialize the data search.
 			 */
-			current = HOLE;
 			goto found_hole;
 		}
 	}
@@ -163,6 +165,8 @@  seek_f(
 	/* The offset is not a hole, or we are looking just for data */
 	current = DATA;
 	offset = lseek(file->fd, start, SEEK_DATA);
+	if (offset != -1 && offset < start)
+		goto bad_result;
 
 found_hole:
 	/*
@@ -203,8 +207,15 @@  found_hole:
 		current ^= 1;		/* alternate between data and hole */
 		start = offset;
 		offset = lseek(file->fd, start, seekinfo[current].seektype);
+		if (offset != -1 && offset <= start)
+			goto bad_result;
 	}
 	return 0;
+
+bad_result:
+	fprintf(stderr, "Invalid seek result: lseek(<fd>, %lld, SEEK_%s) = %lld\n",
+		(long long)start, seekinfo[current].name, (long long)offset);
+	return 0;
 }
 
 void