Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Edward Adam Davis and committed by
Dave Kleikamp
b15e4310 3c778ec8

+7 -11
+7 -11
fs/jfs/jfs_logmgr.c
··· 2180 2180 2181 2181 LCACHE_LOCK(flags); /* disable+lock */ 2182 2182 2183 - bp->l_flag |= lbmDONE; 2184 - 2185 2183 if (bio->bi_status) { 2186 2184 bp->l_flag |= lbmERROR; 2187 2185 ··· 2194 2196 if (bp->l_flag & lbmREAD) { 2195 2197 bp->l_flag &= ~lbmREAD; 2196 2198 2197 - LCACHE_UNLOCK(flags); /* unlock+enable */ 2198 - 2199 2199 /* wakeup I/O initiator */ 2200 2200 LCACHE_WAKEUP(&bp->l_ioevent); 2201 2201 2202 - return; 2202 + goto out; 2203 2203 } 2204 2204 2205 2205 /* ··· 2221 2225 2222 2226 if (bp->l_flag & lbmDIRECT) { 2223 2227 LCACHE_WAKEUP(&bp->l_ioevent); 2224 - LCACHE_UNLOCK(flags); 2225 - return; 2228 + goto out; 2226 2229 } 2227 2230 2228 2231 tail = log->wqueue; ··· 2273 2278 * leave buffer for i/o initiator to dispose 2274 2279 */ 2275 2280 if (bp->l_flag & lbmSYNC) { 2276 - LCACHE_UNLOCK(flags); /* unlock+enable */ 2277 - 2278 2281 /* wakeup I/O initiator */ 2279 2282 LCACHE_WAKEUP(&bp->l_ioevent); 2280 2283 } ··· 2283 2290 else if (bp->l_flag & lbmGC) { 2284 2291 LCACHE_UNLOCK(flags); 2285 2292 lmPostGC(bp); 2293 + LCACHE_LOCK(flags); /* disable+lock */ 2286 2294 } 2287 2295 2288 2296 /* ··· 2296 2302 assert(bp->l_flag & lbmRELEASE); 2297 2303 assert(bp->l_flag & lbmFREE); 2298 2304 lbmfree(bp); 2299 - 2300 - LCACHE_UNLOCK(flags); /* unlock+enable */ 2301 2305 } 2306 + 2307 + out: 2308 + bp->l_flag |= lbmDONE; 2309 + LCACHE_UNLOCK(flags); 2302 2310 } 2303 2311 2304 2312 int jfsIOWait(void *arg)