On Thu, Feb 28, 2019 at 02:00:17PM -0700, Jens Axboe wrote: > On 2/26/19 3:51 AM, Carlos Maiolino wrote: > > guard_bio_eod() can truncate a segment in bio to allow it to do IO on > > odd last sectors of a device. > > > > It already checks if the IO starts past EOD, but it does not consider > > the possibility of an IO request starting within device boundaries can > > contain more than one segment past EOD. > > > > In such cases, truncated_bytes can be bigger than PAGE_SIZE, and will > > underflow bvec->bv_len. > > > > Fix this by checking if truncated_bytes is lower than PAGE_SIZE. > > > > This situation has been found on filesystems such as isofs and vfat, > > which doesn't check the device size before mount, if the device is > > smaller than the filesystem itself, a readahead on such filesystem, > > which spans EOD, can trigger this situation, leading a call to > > zero_user() with a wrong size possibly corrupting memory. > > > > I didn't see any crash, or didn't let the system run long enough to > > check if memory corruption will be hit somewhere, but adding > > instrumentation to guard_bio_end() to check truncated_bytes size, was > > enough to see the error. > > > > The following script can trigger the error. > > > > MNT=/mnt > > IMG=./DISK.img > > DEV=/dev/loop0 > > > > mkfs.vfat $IMG > > mount $IMG $MNT > > cp -R /etc $MNT &> /dev/null > > umount $MNT > > > > losetup -D > > > > losetup --find --show --sizelimit 16247280 $IMG > > mount $DEV $MNT > > > > find $MNT -type f -exec cat {} + >/dev/null > > > > Kudos to Eric Sandeen for coming up with the reproducer above > > > > Changelog: > > > > V2: Compare truncated_bytes agains bvec->bv_len instead of > > PAGE_SIZE > > Applied - note I snipped your changelog, that should go below the --- > lines to not end up in the commit message. > Thanks Jens, and my apologies, I'll make sure to add the Changelog below the cutting line next time. > -- > Jens Axboe > -- Carlos