[Bug 205703] [xfstests generic/461]: BUG: KASAN: use-after-free in iomap_finish_ioend+0x58c/0x5c0

bugzilla-daemon
2019-12-04T15:37:27Z

--- Comment #3 from Zorro Lang (zlang@redhat.com) ---
(In reply to Zorro Lang from comment #2)
> (In reply to Darrick J. Wong from comment #1)
> > Could you please post the source line translations of the iomap functions?
> > I don't have your kernel build.
>
> I tryed to use the faddr2line tool, then it point to a printk_ratelimited()
> function. I'm sure I didn't change the kernel source code, the current
> kernel is installed from it. Is that something wrong?
>
> # ./scripts/faddr2line vmlinux iomap_finish_ioend+0x58c
> iomap_finish_ioend+0x58c/0x5c0:
> iomap_finish_ioend at
> /mnt/tests/kernel/distribution/upstream-kernel/install/kernel/fs/iomap/
> buffered-io.c:1153
>
> # ./scripts/faddr2line vmlinux iomap_finish_ioend+0x168
> iomap_finish_ioend+0x168/0x5c0:
> iomap_finish_ioend at
> /mnt/tests/kernel/distribution/upstream-kernel/install/kernel/fs/iomap/
> buffered-io.c:1133
>
> 1124 static void
> 1125 iomap_finish_ioend(struct iomap_ioend *ioend, int error)
> 1126 {
> 1127 struct inode *inode = ioend->io_inode;
> 1128 struct bio *bio = &ioend->io_inline_bio;
> 1129 struct bio *last = ioend->io_bio, *next;
> 1130 u64 start = bio->bi_iter.bi_sector;
> 1131 bool quiet = bio_flagged(bio, BIO_QUIET);
> 1132
> 1133 for (bio = &ioend->io_inline_bio; bio; bio = next) {
> 1134 struct bio_vec *bv;
> 1135 struct bvec_iter_all iter_all;
> 1136
> 1137 /*
> 1138 * For the last bio, bi_private points to the ioend,
> so we
> 1139 * need to explicitly end the iteration here.
> 1140 */
> 1141 if (bio == last)
> 1142 next = NULL;
> 1143 else
> 1144 next = bio->bi_private;
> 1145
> 1146 /* walk each page on bio, ending page IO on them */
> 1147 bio_for_each_segment_all(bv, bio, iter_all)
> 1148 iomap_finish_page_writeback(inode,
> bv->bv_page, error);
> 1149 bio_put(bio);
> 1150 }
> 1151
> 1152 if (unlikely(error && !quiet)) {
> 1153 printk_ratelimited(KERN_ERR
> 1154 "%s: writeback error on inode %lu, offset %lld, sector %llu",
> 1155 inode->i_sb->s_id, inode->i_ino,
> ioend->io_offset,

The bio_put(bio) might already free the bio. The ioend->io_offset is invalid.
I'll test by saving the offset in a local var at first. If it's the issue, I'll
try to send a patch.

> 1156 start);
> 1157 }
> 1158 }