From: Lizhi Xu lizhi.xu@windriver.com
[ Upstream commit 2d91b3765cd05016335cd5df5e5c6a29708ec058 ]
The fileset value of the inode copy from the disk by the reproducer is AGGR_RESERVED_I. When executing evict, its hard link number is 0, so its inode pages are not truncated. This causes the bugon to be triggered when executing clear_inode() because nrpages is greater than 0.
Reported-by: syzbot+6e516bb515d93230bc7b@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=6e516bb515d93230bc7b Signed-off-by: Lizhi Xu lizhi.xu@windriver.com Signed-off-by: Dave Kleikamp dave.kleikamp@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
**Backport Status: YES**
This commit should be backported to stable kernel trees based on the following extensive analysis:
## Critical Bug Fix Nature
This commit fixes a kernel BUG_ON() crash that can be triggered in production systems. Looking at the code changes and commit message:
1. **The Bug**: When JFS evicts an inode with `fileset == AGGR_RESERVED_I` and hard link count of 0, the inode pages were not being truncated. This leads to a BUG_ON() trigger in `clear_inode()` at fs/inode.c when checking `BUG_ON(inode->i_data.nrpages)`.
2. **Root Cause**: The original code only called `truncate_inode_pages_final()` for inodes with `fileset == FILESYSTEM_I`, missing other fileset types like `AGGR_RESERVED_I`. This left pages in memory when they should have been freed.
## Fix Characteristics
The fix is ideal for stable backporting:
1. **Minimal and Contained**: The change is just moving one line of code - `truncate_inode_pages_final(&inode->i_data)` is moved outside the `if (JFS_IP(inode)->fileset == FILESYSTEM_I)` condition block, ensuring it runs for ALL inodes with 0 hard links, not just FILESYSTEM_I inodes.
2. **Low Risk**: The change ensures proper cleanup for all inode types during eviction, which is the expected behavior. The function `truncate_inode_pages_final()` is safe to call for any inode being evicted with no links.
3. **Clear Bug Report**: This fixes a syzbot-reported crash with a reproducible test case (syzbot+6e516bb515d93230bc7b@syzkaller.appspotmail.com).
## Impact Analysis
- **User Impact**: Without this fix, users can experience kernel panics/crashes when specific JFS inode conditions occur - **Security**: Prevents potential denial-of-service through triggerable BUG_ON() - **Regression Risk**: Minimal - the change ensures proper cleanup that should have been happening all along
## Historical Context
Looking at related commits: - Similar eviction-related fixes have been backported (e.g., e0e1958f4c36 "jfs: fix uaf in jfs_evict_inode") - JFS has had multiple stability fixes in the eviction path that were deemed stable-worthy - The subsystem maintainer (Dave Kleikamp) signed off on this fix
The commit clearly meets stable kernel criteria: it fixes a real bug that causes system crashes, the fix is minimal and correct, and there's no risk of introducing new features or architectural changes.
fs/jfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 60fc92dee24d..81e6b18e81e1 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -145,9 +145,9 @@ void jfs_evict_inode(struct inode *inode) if (!inode->i_nlink && !is_bad_inode(inode)) { dquot_initialize(inode);
+ truncate_inode_pages_final(&inode->i_data); if (JFS_IP(inode)->fileset == FILESYSTEM_I) { struct inode *ipimap = JFS_SBI(inode->i_sb)->ipimap; - truncate_inode_pages_final(&inode->i_data);
if (test_cflag(COMMIT_Freewmap, inode)) jfs_free_zero_link(inode);