From: Aditya Prakash Srivastava During a buffered write, `ext4_write_inline_data_end()` acquires the xattr lock after preparing the write. If a concurrent page fault (`ext4_page_mkwrite()`) converts the inline data to an extent after the write_end handlers check the state but before `ext4_write_inline_data_end()` acquires the xattr write lock, the subsequent check will trigger a kernel panic via `BUG_ON(!ext4_has_inline_data(inode))`. Replace the `BUG_ON` check with a graceful error-handling retry path. If the inline data is cleared after locking the xattr, we safely release all resources (releasing `iloc.bh`, unlocking/putting the folio, stopping the active journal transaction handle) and return 0 (VFS retry) to let the generic write path retry the operation safely. Reported-by: syzbot+0c89d865531d053abb2d@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=0c89d865531d053abb2d Fixes: 3fdcfb668fd7 ("ext4: add journalled write support for inline data") Suggested-by: Jan Kara Signed-off-by: Aditya Prakash Srivastava --- fs/ext4/inline.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 8045e4ff270c..cfd591dc1d9c 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -812,7 +812,19 @@ int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len, goto out; } ext4_write_lock_xattr(inode, &no_expand); - BUG_ON(!ext4_has_inline_data(inode)); + /* + * We could have raced with ext4_page_mkwrite() converting + * the inode and clearing the inline data flag, so we just + * release resources and retry the whole write. + */ + if (unlikely(!ext4_has_inline_data(inode))) { + ext4_write_unlock_xattr(inode, &no_expand); + brelse(iloc.bh); + folio_unlock(folio); + folio_put(folio); + ext4_journal_stop(handle); + return 0; + } /* * ei->i_inline_off may have changed since -- 2.47.3