From: Eric Biggers Date: Tue, 11 Jun 2024 18:29:28 +0000 (-0700) Subject: xfs_io: fix mread with length 1 mod page size X-Git-Tag: v6.9.0~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7ea701ffc7cf306a903f2966519b3f5aedfb77ea;p=thirdparty%2Fxfsprogs-dev.git xfs_io: fix mread with length 1 mod page size Fix a weird bug in mread where if you passed it a length that was 1 modulo the page size, for example xfs_io -r file -c "mmap -r 0 8192" -c "mread -v 0 4097" ... it never reset its pointer into the buffer into which it copies the data from the memory map. This caused an out-of-bounds write, which depending on the length passed could be very large and reliably segfault. Also nothing was printed, despite the use of -v option. (I don't know if this case gets reached by any existing xfstest, but presumably not. I noticed it while working on a patch to an xfstest.) Signed-off-by: Eric Biggers Reviewed-by: Darrick J. Wong --- diff --git a/io/mmap.c b/io/mmap.c index 85087f57..4c03e3d5 100644 --- a/io/mmap.c +++ b/io/mmap.c @@ -471,34 +471,26 @@ mread_f( dumplen = pagesize; if (rflag) { - for (tmp = length - 1, c = 0; tmp >= 0; tmp--, c = 1) { - *bp = *(((char *)mapping->addr) + dumpoffset + tmp); - cnt++; - if (c && cnt == dumplen) { + for (tmp = length - 1; tmp >= 0; tmp--) { + bp[cnt++] = ((char *)mapping->addr)[dumpoffset + tmp]; + if (cnt == dumplen) { if (dump) { dump_buffer(printoffset, dumplen); printoffset += dumplen; } - bp = (char *)io_buffer; dumplen = pagesize; cnt = 0; - } else { - bp++; } } } else { - for (tmp = 0, c = 0; tmp < length; tmp++, c = 1) { - *bp = *(((char *)mapping->addr) + dumpoffset + tmp); - cnt++; - if (c && cnt == dumplen) { + for (tmp = 0; tmp < length; tmp++) { + bp[cnt++] = ((char *)mapping->addr)[dumpoffset + tmp]; + if (cnt == dumplen) { if (dump) dump_buffer(printoffset + tmp - (dumplen - 1), dumplen); - bp = (char *)io_buffer; dumplen = pagesize; cnt = 0; - } else { - bp++; } } }