提交 23840187 编写于 作者: Y yangerkun 提交者: Yang Yingliang

jbd2: protect jh by grab a ref in jbd2_journal_forget

hulk inclusion
category: bugfix
bugzilla: 176007
CVE: NA
---------------------------

jbd2_journal_put_journal_head protect jh with jbd_lock_bh_journal_head.
jbd2_journal_forget protect jh with jbd_lock_bh_state. This two function
can happen parallel, and this can lead the follow bug:

[ 1140.658593] kasan: GPF could be caused by NULL-ptr deref or user memory access
...
[ 1140.660011] general protection fault: 0000 [#1] SMP KASAN
...
[ 1140.664723] RIP: 0010:__jbd2_journal_remove_checkpoint+0x7b/0x6a0
[ 1140.683008] Call Trace:
[ 1140.683570]  jbd2_journal_forget+0x564/0x840
[ 1140.684348]  jbd2_journal_revoke+0x248/0x5b0
[ 1140.685101]  __ext4_forget+0x341/0x5d0
[ 1140.685802]  ext4_free_blocks+0x1233/0x1970
[ 1140.692235]  ext4_ext_remove_space+0x1aaf/0x34b0
[ 1140.694614]  ext4_ext_truncate+0x192/0x1e0
[ 1140.695320]  ext4_truncate+0xad0/0x1020
[ 1140.698187]  ext4_evict_inode+0xac6/0x15c0
[ 1140.700377]  evict+0x2f6/0x650
[ 1140.701586]  iput+0x3aa/0x740
[ 1140.702084]  dentry_unlink_inode+0x2ff/0x3b0
[ 1140.702799]  d_delete+0x1dd/0x240
[ 1140.703366]  vfs_rmdir+0x2d5/0x430
[ 1140.703933]  do_rmdir+0x2e1/0x380
[ 1140.705848]  do_syscall_64+0xbd/0x3d0
[ 1140.707384]  entry_SYSCALL_64_after_hwframe+0x44/0xa9

Fix it by grab jh in jbd2_journal_forget, and put it at the end of
jbd2_journal_forget.

It is a part for 46417064 ("jbd2: Make state lock a spinlock").
Signed-off-by: Nyangerkun <yangerkun@huawei.com>
Reviewed-by: NZhang Yi <yi.zhang@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 a2fcd456
......@@ -1580,11 +1580,13 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
BUFFER_TRACE(bh, "entry");
jbd_lock_bh_state(bh);
jh = jbd2_journal_grab_journal_head(bh);
if (!jh) {
__bforget(bh);
return 0;
}
if (!buffer_jbd(bh))
goto not_jbd;
jh = bh2jh(bh);
jbd_lock_bh_state(bh);
/* Critical error: attempting to delete a bitmap buffer, maybe?
* Don't do any jbd operations, and return an error. */
......@@ -1704,18 +1706,14 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
spin_unlock(&journal->j_list_lock);
}
drop:
jbd_unlock_bh_state(bh);
__brelse(bh);
jbd_unlock_bh_state(bh);
jbd2_journal_put_journal_head(jh);
if (drop_reserve) {
/* no need to reserve log space for this block -bzzz */
handle->h_total_credits++;
}
return err;
not_jbd:
jbd_unlock_bh_state(bh);
__bforget(bh);
goto drop;
}
/**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册