summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2025-09-09 13:22:07 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-10-19 16:37:41 +0200
commit2b9da798ff0f4d026c5f0f815047393ebe7d8859 (patch)
tree6d081f8a74b0b66b705b4a3edad35a7ca10f7d92
parente9663669a5fa1ee5aeb1036fdcfb8ab6aa4bbfbc (diff)
downloadlinux-2b9da798ff0f4d026c5f0f815047393ebe7d8859.tar.gz
linux-2b9da798ff0f4d026c5f0f815047393ebe7d8859.tar.bz2
linux-2b9da798ff0f4d026c5f0f815047393ebe7d8859.zip
ext4: verify orphan file size is not too big
commit 0a6ce20c156442a4ce2a404747bb0fb05d54eeb3 upstream. In principle orphan file can be arbitrarily large. However orphan replay needs to traverse it all and we also pin all its buffers in memory. Thus filesystems with absurdly large orphan files can lead to big amounts of memory consumed. Limit orphan file size to a sane value and also use kvmalloc() for allocating array of block descriptor structures to avoid large order allocations for sane but large orphan files. Reported-by: syzbot+0b92850d68d9b12934f5@syzkaller.appspotmail.com Fixes: 02f310fcf47f ("ext4: Speedup ext4 orphan inode handling") Cc: stable@kernel.org Signed-off-by: Jan Kara <jack@suse.cz> Message-ID: <20250909112206.10459-2-jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/ext4/orphan.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/fs/ext4/orphan.c b/fs/ext4/orphan.c
index 0fbcce67ffd4..33c3a89396b1 100644
--- a/fs/ext4/orphan.c
+++ b/fs/ext4/orphan.c
@@ -583,9 +583,20 @@ int ext4_init_orphan_info(struct super_block *sb)
ext4_msg(sb, KERN_ERR, "get orphan inode failed");
return PTR_ERR(inode);
}
+ /*
+ * This is just an artificial limit to prevent corrupted fs from
+ * consuming absurd amounts of memory when pinning blocks of orphan
+ * file in memory.
+ */
+ if (inode->i_size > 8 << 20) {
+ ext4_msg(sb, KERN_ERR, "orphan file too big: %llu",
+ (unsigned long long)inode->i_size);
+ ret = -EFSCORRUPTED;
+ goto out_put;
+ }
oi->of_blocks = inode->i_size >> sb->s_blocksize_bits;
oi->of_csum_seed = EXT4_I(inode)->i_csum_seed;
- oi->of_binfo = kmalloc_array(oi->of_blocks,
+ oi->of_binfo = kvmalloc_array(oi->of_blocks,
sizeof(struct ext4_orphan_block),
GFP_KERNEL);
if (!oi->of_binfo) {