Skip to content

Commit b15e431

Browse files
ea1daviskleikamp
authored andcommitted
jfs: Set the lbmDone flag at the end of lbmIODone
In lbmRead(), the I/O event waited for by wait_event() finishes before it goes to sleep, and the lbmIODone() prematurely sets the flag to lbmDONE, thus ending the wait. This causes wait_event() to return before lbmREAD is cleared (because lbmDONE was set first), the premature return of wait_event() leads to the release of lbuf before lbmIODone() returns, thus triggering the use-after-free vulnerability reported in [1]. Moving the operation of setting the lbmDONE flag to after clearing lbmREAD in lbmIODone() avoids the use-after-free vulnerability reported in [1]. [1] BUG: KASAN: slab-use-after-free in rt_spin_lock+0x88/0x3e0 kernel/locking/spinlock_rt.c:56 Call Trace: blk_update_request+0x57e/0xe60 block/blk-mq.c:1007 blk_mq_end_request+0x3e/0x70 block/blk-mq.c:1169 blk_complete_reqs block/blk-mq.c:1244 [inline] blk_done_softirq+0x10a/0x160 block/blk-mq.c:1249 Allocated by task 6101: lbmLogInit fs/jfs/jfs_logmgr.c:1821 [inline] lmLogInit+0x3d0/0x19e0 fs/jfs/jfs_logmgr.c:1269 open_inline_log fs/jfs/jfs_logmgr.c:1175 [inline] lmLogOpen+0x4e1/0xfa0 fs/jfs/jfs_logmgr.c:1069 jfs_mount_rw+0xe9/0x670 fs/jfs/jfs_mount.c:257 jfs_fill_super+0x754/0xd80 fs/jfs/super.c:532 Freed by task 6101: kfree+0x1bd/0x900 mm/slub.c:6876 lbmLogShutdown fs/jfs/jfs_logmgr.c:1864 [inline] lmLogInit+0x1137/0x19e0 fs/jfs/jfs_logmgr.c:1415 open_inline_log fs/jfs/jfs_logmgr.c:1175 [inline] lmLogOpen+0x4e1/0xfa0 fs/jfs/jfs_logmgr.c:1069 jfs_mount_rw+0xe9/0x670 fs/jfs/jfs_mount.c:257 jfs_fill_super+0x754/0xd80 fs/jfs/super.c:532 Reported-by: syzbot+1d38eedcb25a3b5686a7@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=1d38eedcb25a3b5686a7 Signed-off-by: Edward Adam Davis <eadavis@qq.com> Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
1 parent 3c778ec commit b15e431

1 file changed

Lines changed: 7 additions & 11 deletions

File tree

fs/jfs/jfs_logmgr.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2180,8 +2180,6 @@ static void lbmIODone(struct bio *bio)
21802180

21812181
LCACHE_LOCK(flags); /* disable+lock */
21822182

2183-
bp->l_flag |= lbmDONE;
2184-
21852183
if (bio->bi_status) {
21862184
bp->l_flag |= lbmERROR;
21872185

@@ -2196,12 +2194,10 @@ static void lbmIODone(struct bio *bio)
21962194
if (bp->l_flag & lbmREAD) {
21972195
bp->l_flag &= ~lbmREAD;
21982196

2199-
LCACHE_UNLOCK(flags); /* unlock+enable */
2200-
22012197
/* wakeup I/O initiator */
22022198
LCACHE_WAKEUP(&bp->l_ioevent);
22032199

2204-
return;
2200+
goto out;
22052201
}
22062202

22072203
/*
@@ -2225,8 +2221,7 @@ static void lbmIODone(struct bio *bio)
22252221

22262222
if (bp->l_flag & lbmDIRECT) {
22272223
LCACHE_WAKEUP(&bp->l_ioevent);
2228-
LCACHE_UNLOCK(flags);
2229-
return;
2224+
goto out;
22302225
}
22312226

22322227
tail = log->wqueue;
@@ -2278,8 +2273,6 @@ static void lbmIODone(struct bio *bio)
22782273
* leave buffer for i/o initiator to dispose
22792274
*/
22802275
if (bp->l_flag & lbmSYNC) {
2281-
LCACHE_UNLOCK(flags); /* unlock+enable */
2282-
22832276
/* wakeup I/O initiator */
22842277
LCACHE_WAKEUP(&bp->l_ioevent);
22852278
}
@@ -2290,6 +2283,7 @@ static void lbmIODone(struct bio *bio)
22902283
else if (bp->l_flag & lbmGC) {
22912284
LCACHE_UNLOCK(flags);
22922285
lmPostGC(bp);
2286+
LCACHE_LOCK(flags); /* disable+lock */
22932287
}
22942288

22952289
/*
@@ -2302,9 +2296,11 @@ static void lbmIODone(struct bio *bio)
23022296
assert(bp->l_flag & lbmRELEASE);
23032297
assert(bp->l_flag & lbmFREE);
23042298
lbmfree(bp);
2305-
2306-
LCACHE_UNLOCK(flags); /* unlock+enable */
23072299
}
2300+
2301+
out:
2302+
bp->l_flag |= lbmDONE;
2303+
LCACHE_UNLOCK(flags);
23082304
}
23092305

23102306
int jfsIOWait(void *arg)

0 commit comments

Comments
 (0)