aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruenba@redhat.com>2017-08-22 10:01:30 -0500
committerEric Sandeen <sandeen@redhat.com>2017-08-22 10:01:30 -0500
commit866d7fcb27924744fa86e07105fbeac34cc2f92c (patch)
tree93a6bdac08e64ec4a1022b9b28f8a061cb50d5a0
parent8d2666e3f66c263946b47155f3764f64ce64d684 (diff)
downloadxfsprogs-dev-866d7fcb27924744fa86e07105fbeac34cc2f92c.tar.gz
xfs_io: add seek consistency checks
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> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
-rw-r--r--io/seek.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/io/seek.c b/io/seek.c
index d06375dc1d..871b47262f 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