aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorGuanghui Yang <3497809730@qq.com>2026-07-09 14:41:51 +0000
committerTheodore Ts'o <tytso@mit.edu>2026-07-22 12:25:26 -0400
commit05704335803b69c1bfa8637b7ada942bf2ee8a41 (patch)
treecb007dedf8207f3c92f39e145e7e69d2fee1de9f
parentext4: clear error before retrying inode xattr space fallback (diff)
ext4: fix buffer_head leak in ext4_init_orphan_info
ext4_init_orphan_info() reads orphan file blocks with ext4_bread() and stores the returned buffer_head in oi->of_binfo[i].ob_bh. If ext4_bread() succeeds but the orphan block magic or checksum validation fails, the function jumps to out_free. However, the old out_free loop starts releasing buffers from i - 1, so the current buffer_head at index i is skipped. This leaks the buffer_head reference obtained by ext4_bread() on the bad magic and bad checksum error paths. Fix this by tracking the number of successfully read buffer_heads and releasing exactly those buffer_heads on the error path. Fixes: 02f310fcf47f ("ext4: Speedup ext4 orphan inode handling") Signed-off-by: Guanghui Yang <3497809730@qq.com> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://patch.msgid.link/tencent_B38798612A159E21450ECF959016371B0807@qq.com Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/ext4/orphan.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/ext4/orphan.c b/fs/ext4/orphan.c
index 64ea47624233..7095ba1564f6 100644
--- a/fs/ext4/orphan.c
+++ b/fs/ext4/orphan.c
@@ -572,6 +572,7 @@ int ext4_init_orphan_info(struct super_block *sb)
int i, j;
int ret;
int free;
+ int loaded = 0;
__le32 *bdata;
int inodes_per_ob = ext4_inodes_per_orphan_block(sb);
struct ext4_orphan_block_tail *ot;
@@ -613,6 +614,7 @@ int ext4_init_orphan_info(struct super_block *sb)
ret = -EIO;
goto out_free;
}
+ loaded++;
ot = ext4_orphan_block_tail(sb, oi->of_binfo[i].ob_bh);
if (le32_to_cpu(ot->ob_magic) != EXT4_ORPHAN_BLOCK_MAGIC) {
ext4_error(sb, "orphan file block %d: bad magic", i);
@@ -635,8 +637,10 @@ int ext4_init_orphan_info(struct super_block *sb)
iput(inode);
return 0;
out_free:
- for (i--; i >= 0; i--)
- brelse(oi->of_binfo[i].ob_bh);
+ while (loaded > 0) {
+ loaded--;
+ brelse(oi->of_binfo[loaded].ob_bh);
+ }
kvfree(oi->of_binfo);
out_put:
iput(inode);