ext4_open_balloon() hands userspace a writable fd for the hidden
balloon inode built with alloc_file(). Unlike the normal open path,
alloc_file() does not call ->open, so ext4_file_open()'s
ext4_inode_attach_jinode() for write-opened inodes never runs and
EXT4_I(balloon_ino)->jinode stays NULL.
A subsequent fallocate() (or any write that has to zero a partial
block in the default data=ordered mode) reaches
__ext4_block_zero_page_range() -> ext4_jbd2_inode_add_write() ->
jbd2_journal_inode_ranged_write() with a NULL jinode and oopses:
BUG: kernel NULL pointer dereference, address: 0000000000000028
RIP: jbd2_journal_file_inode+0x5f/0x150 [jbd2]
Call Trace:
__ext4_block_zero_page_range+0x195/0x300 [ext4]
ext4_alloc_file_blocks.isra.0+0x2af/0x380 [ext4]
ext4_do_fallocate+0xab/0x200 [ext4]
ext4_fallocate+0x121/0x160 [ext4]
So an EXT4_IOC_OPEN_BALLOON caller (which needs only CAP_SYS_ADMIN)
can crash the host. Attach the jinode right after alloc_file() when
the balloon was opened for write, mirroring ext4_file_open(), and
fail the open if the attach fails.
Fixes: 55ad5a773877 ("ext4: Provide a balloon nipple for management")
Feature: fs/ext4: fast online shrink support
https://virtuozzo.atlassian.net/browse/VSTOR-137234
Signed-off-by: Konstantin Khorenko <[email protected]>
---
fs/ext4/ioctl.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 954799144751..d8bf99b1f953 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -1269,6 +1269,22 @@ static int ext4_open_balloon(struct super_block *sb,
struct vfsmount *mnt)
goto err_filp;
}
+ /*
+ * alloc_file() does not invoke ->open, so ext4_file_open()'s
+ * jinode setup for write-opened inodes is skipped here. Attach it
+ * ourselves, otherwise a later fallocate()/write() that has to
+ * zero a partial block in data=ordered mode dereferences a NULL
+ * EXT4_I(balloon_ino)->jinode and oopses.
+ */
+ if (!ro) {
+ err = ext4_inode_attach_jinode(balloon_ino);
+ if (err < 0) {
+ fput(filp);
+ put_unused_fd(fd);
+ return err;
+ }
+ }
+
filp->f_flags |= O_LARGEFILE;
fd_install(fd, filp);
return fd;
--
2.47.1
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel