From: Greg Kroah-Hartman Date: Mon, 6 Jun 2022 12:16:05 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v5.10.121~103 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0ee7c702e87b5647900a56cfddd6021c080c241d;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: acpi-property-release-subnode-properties-with-data-nodes.patch ext4-avoid-cycles-in-directory-h-tree.patch ext4-fix-bug_on-in-ext4_writepages.patch ext4-fix-use-after-free-in-ext4_rename_dir_prepare.patch ext4-fix-warning-in-ext4_handle_inode_extension.patch ext4-verify-dir-block-before-splitting-it.patch netfilter-nf_tables-disallow-non-stateful-expression-in-sets-earlier.patch --- diff --git a/queue-5.4/acpi-property-release-subnode-properties-with-data-nodes.patch b/queue-5.4/acpi-property-release-subnode-properties-with-data-nodes.patch new file mode 100644 index 00000000000..7272af7d3c8 --- /dev/null +++ b/queue-5.4/acpi-property-release-subnode-properties-with-data-nodes.patch @@ -0,0 +1,70 @@ +From 3bd561e1572ee02a50cd1a5be339abf1a5b78d56 Mon Sep 17 00:00:00 2001 +From: Sakari Ailus +Date: Wed, 6 Apr 2022 16:12:08 +0300 +Subject: ACPI: property: Release subnode properties with data nodes + +From: Sakari Ailus + +commit 3bd561e1572ee02a50cd1a5be339abf1a5b78d56 upstream. + +struct acpi_device_properties describes one source of properties present +on either struct acpi_device or struct acpi_data_node. When properties are +parsed, both are populated but when released, only those properties that +are associated with the device node are freed. + +Fix this by also releasing memory of the data node properties. + +Fixes: 5f5e4890d57a ("ACPI / property: Allow multiple property compatible _DSD entries") +Cc: 4.20+ # 4.20+ +Signed-off-by: Sakari Ailus +Reviewed-by: Andy Shevchenko +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +--- + drivers/acpi/property.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/drivers/acpi/property.c ++++ b/drivers/acpi/property.c +@@ -430,6 +430,16 @@ void acpi_init_properties(struct acpi_de + acpi_extract_apple_properties(adev); + } + ++static void acpi_free_device_properties(struct list_head *list) ++{ ++ struct acpi_device_properties *props, *tmp; ++ ++ list_for_each_entry_safe(props, tmp, list, list) { ++ list_del(&props->list); ++ kfree(props); ++ } ++} ++ + static void acpi_destroy_nondev_subnodes(struct list_head *list) + { + struct acpi_data_node *dn, *next; +@@ -442,22 +452,18 @@ static void acpi_destroy_nondev_subnodes + wait_for_completion(&dn->kobj_done); + list_del(&dn->sibling); + ACPI_FREE((void *)dn->data.pointer); ++ acpi_free_device_properties(&dn->data.properties); + kfree(dn); + } + } + + void acpi_free_properties(struct acpi_device *adev) + { +- struct acpi_device_properties *props, *tmp; +- + acpi_destroy_nondev_subnodes(&adev->data.subnodes); + ACPI_FREE((void *)adev->data.pointer); + adev->data.of_compatible = NULL; + adev->data.pointer = NULL; +- list_for_each_entry_safe(props, tmp, &adev->data.properties, list) { +- list_del(&props->list); +- kfree(props); +- } ++ acpi_free_device_properties(&adev->data.properties); + } + + /** diff --git a/queue-5.4/ext4-avoid-cycles-in-directory-h-tree.patch b/queue-5.4/ext4-avoid-cycles-in-directory-h-tree.patch new file mode 100644 index 00000000000..0795359d346 --- /dev/null +++ b/queue-5.4/ext4-avoid-cycles-in-directory-h-tree.patch @@ -0,0 +1,81 @@ +From 3ba733f879c2a88910744647e41edeefbc0d92b2 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 18 May 2022 11:33:29 +0200 +Subject: ext4: avoid cycles in directory h-tree + +From: Jan Kara + +commit 3ba733f879c2a88910744647e41edeefbc0d92b2 upstream. + +A maliciously corrupted filesystem can contain cycles in the h-tree +stored inside a directory. That can easily lead to the kernel corrupting +tree nodes that were already verified under its hands while doing a node +split and consequently accessing unallocated memory. Fix the problem by +verifying traversed block numbers are unique. + +Cc: stable@vger.kernel.org +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20220518093332.13986-2-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/namei.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -750,12 +750,14 @@ static struct dx_frame * + dx_probe(struct ext4_filename *fname, struct inode *dir, + struct dx_hash_info *hinfo, struct dx_frame *frame_in) + { +- unsigned count, indirect; ++ unsigned count, indirect, level, i; + struct dx_entry *at, *entries, *p, *q, *m; + struct dx_root *root; + struct dx_frame *frame = frame_in; + struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR); + u32 hash; ++ ext4_lblk_t block; ++ ext4_lblk_t blocks[EXT4_HTREE_LEVEL]; + + memset(frame_in, 0, EXT4_HTREE_LEVEL * sizeof(frame_in[0])); + frame->bh = ext4_read_dirblock(dir, 0, INDEX); +@@ -811,6 +813,8 @@ dx_probe(struct ext4_filename *fname, st + } + + dxtrace(printk("Look up %x", hash)); ++ level = 0; ++ blocks[0] = 0; + while (1) { + count = dx_get_count(entries); + if (!count || count > dx_get_limit(entries)) { +@@ -852,15 +856,27 @@ dx_probe(struct ext4_filename *fname, st + dx_get_block(at))); + frame->entries = entries; + frame->at = at; +- if (!indirect--) ++ ++ block = dx_get_block(at); ++ for (i = 0; i <= level; i++) { ++ if (blocks[i] == block) { ++ ext4_warning_inode(dir, ++ "dx entry: tree cycle block %u points back to block %u", ++ blocks[level], block); ++ goto fail; ++ } ++ } ++ if (++level > indirect) + return frame; ++ blocks[level] = block; + frame++; +- frame->bh = ext4_read_dirblock(dir, dx_get_block(at), INDEX); ++ frame->bh = ext4_read_dirblock(dir, block, INDEX); + if (IS_ERR(frame->bh)) { + ret_err = (struct dx_frame *) frame->bh; + frame->bh = NULL; + goto fail; + } ++ + entries = ((struct dx_node *) frame->bh->b_data)->entries; + + if (dx_get_limit(entries) != dx_node_limit(dir)) { diff --git a/queue-5.4/ext4-fix-bug_on-in-ext4_writepages.patch b/queue-5.4/ext4-fix-bug_on-in-ext4_writepages.patch new file mode 100644 index 00000000000..5263dc1b0ce --- /dev/null +++ b/queue-5.4/ext4-fix-bug_on-in-ext4_writepages.patch @@ -0,0 +1,107 @@ +From ef09ed5d37b84d18562b30cf7253e57062d0db05 Mon Sep 17 00:00:00 2001 +From: Ye Bin +Date: Mon, 16 May 2022 20:26:34 +0800 +Subject: ext4: fix bug_on in ext4_writepages + +From: Ye Bin + +commit ef09ed5d37b84d18562b30cf7253e57062d0db05 upstream. + +we got issue as follows: +EXT4-fs error (device loop0): ext4_mb_generate_buddy:1141: group 0, block bitmap and bg descriptor inconsistent: 25 vs 31513 free cls +------------[ cut here ]------------ +kernel BUG at fs/ext4/inode.c:2708! +invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI +CPU: 2 PID: 2147 Comm: rep Not tainted 5.18.0-rc2-next-20220413+ #155 +RIP: 0010:ext4_writepages+0x1977/0x1c10 +RSP: 0018:ffff88811d3e7880 EFLAGS: 00010246 +RAX: 0000000000000000 RBX: 0000000000000001 RCX: ffff88811c098000 +RDX: 0000000000000000 RSI: ffff88811c098000 RDI: 0000000000000002 +RBP: ffff888128140f50 R08: ffffffffb1ff6387 R09: 0000000000000000 +R10: 0000000000000007 R11: ffffed10250281ea R12: 0000000000000001 +R13: 00000000000000a4 R14: ffff88811d3e7bb8 R15: ffff888128141028 +FS: 00007f443aed9740(0000) GS:ffff8883aef00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000020007200 CR3: 000000011c2a4000 CR4: 00000000000006e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + + do_writepages+0x130/0x3a0 + filemap_fdatawrite_wbc+0x83/0xa0 + filemap_flush+0xab/0xe0 + ext4_alloc_da_blocks+0x51/0x120 + __ext4_ioctl+0x1534/0x3210 + __x64_sys_ioctl+0x12c/0x170 + do_syscall_64+0x3b/0x90 + +It may happen as follows: +1. write inline_data inode +vfs_write + new_sync_write + ext4_file_write_iter + ext4_buffered_write_iter + generic_perform_write + ext4_da_write_begin + ext4_da_write_inline_data_begin -> If inline data size too + small will allocate block to write, then mapping will has + dirty page + ext4_da_convert_inline_data_to_extent ->clear EXT4_STATE_MAY_INLINE_DATA +2. fallocate +do_vfs_ioctl + ioctl_preallocate + vfs_fallocate + ext4_fallocate + ext4_convert_inline_data + ext4_convert_inline_data_nolock + ext4_map_blocks -> fail will goto restore data + ext4_restore_inline_data + ext4_create_inline_data + ext4_write_inline_data + ext4_set_inode_state -> set inode EXT4_STATE_MAY_INLINE_DATA +3. writepages +__ext4_ioctl + ext4_alloc_da_blocks + filemap_flush + filemap_fdatawrite_wbc + do_writepages + ext4_writepages + if (ext4_has_inline_data(inode)) + BUG_ON(ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) + +The root cause of this issue is we destory inline data until call +ext4_writepages under delay allocation mode. But there maybe already +convert from inline to extent. To solve this issue, we call +filemap_flush first.. + +Cc: stable@kernel.org +Signed-off-by: Ye Bin +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20220516122634.1690462-1-yebin10@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/inline.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -2013,6 +2013,18 @@ int ext4_convert_inline_data(struct inod + if (!ext4_has_inline_data(inode)) { + ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); + return 0; ++ } else if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { ++ /* ++ * Inode has inline data but EXT4_STATE_MAY_INLINE_DATA is ++ * cleared. This means we are in the middle of moving of ++ * inline data to delay allocated block. Just force writeout ++ * here to finish conversion. ++ */ ++ error = filemap_flush(inode->i_mapping); ++ if (error) ++ return error; ++ if (!ext4_has_inline_data(inode)) ++ return 0; + } + + needed_blocks = ext4_writepage_trans_blocks(inode); diff --git a/queue-5.4/ext4-fix-use-after-free-in-ext4_rename_dir_prepare.patch b/queue-5.4/ext4-fix-use-after-free-in-ext4_rename_dir_prepare.patch new file mode 100644 index 00000000000..1a790269d5f --- /dev/null +++ b/queue-5.4/ext4-fix-use-after-free-in-ext4_rename_dir_prepare.patch @@ -0,0 +1,125 @@ +From 0be698ecbe4471fcad80e81ec6a05001421041b3 Mon Sep 17 00:00:00 2001 +From: Ye Bin +Date: Thu, 14 Apr 2022 10:52:23 +0800 +Subject: ext4: fix use-after-free in ext4_rename_dir_prepare + +From: Ye Bin + +commit 0be698ecbe4471fcad80e81ec6a05001421041b3 upstream. + +We got issue as follows: +EXT4-fs (loop0): mounted filesystem without journal. Opts: ,errors=continue +ext4_get_first_dir_block: bh->b_data=0xffff88810bee6000 len=34478 +ext4_get_first_dir_block: *parent_de=0xffff88810beee6ae bh->b_data=0xffff88810bee6000 +ext4_rename_dir_prepare: [1] parent_de=0xffff88810beee6ae +================================================================== +BUG: KASAN: use-after-free in ext4_rename_dir_prepare+0x152/0x220 +Read of size 4 at addr ffff88810beee6ae by task rep/1895 + +CPU: 13 PID: 1895 Comm: rep Not tainted 5.10.0+ #241 +Call Trace: + dump_stack+0xbe/0xf9 + print_address_description.constprop.0+0x1e/0x220 + kasan_report.cold+0x37/0x7f + ext4_rename_dir_prepare+0x152/0x220 + ext4_rename+0xf44/0x1ad0 + ext4_rename2+0x11c/0x170 + vfs_rename+0xa84/0x1440 + do_renameat2+0x683/0x8f0 + __x64_sys_renameat+0x53/0x60 + do_syscall_64+0x33/0x40 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 +RIP: 0033:0x7f45a6fc41c9 +RSP: 002b:00007ffc5a470218 EFLAGS: 00000246 ORIG_RAX: 0000000000000108 +RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f45a6fc41c9 +RDX: 0000000000000005 RSI: 0000000020000180 RDI: 0000000000000005 +RBP: 00007ffc5a470240 R08: 00007ffc5a470160 R09: 0000000020000080 +R10: 00000000200001c0 R11: 0000000000000246 R12: 0000000000400bb0 +R13: 00007ffc5a470320 R14: 0000000000000000 R15: 0000000000000000 + +The buggy address belongs to the page: +page:00000000440015ce refcount:0 mapcount:0 mapping:0000000000000000 index:0x1 pfn:0x10beee +flags: 0x200000000000000() +raw: 0200000000000000 ffffea00043ff4c8 ffffea0004325608 0000000000000000 +raw: 0000000000000001 0000000000000000 00000000ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff88810beee580: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ffff88810beee600: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +>ffff88810beee680: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ^ + ffff88810beee700: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff + ffff88810beee780: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff +================================================================== +Disabling lock debugging due to kernel taint +ext4_rename_dir_prepare: [2] parent_de->inode=3537895424 +ext4_rename_dir_prepare: [3] dir=0xffff888124170140 +ext4_rename_dir_prepare: [4] ino=2 +ext4_rename_dir_prepare: ent->dir->i_ino=2 parent=-757071872 + +Reason is first directory entry which 'rec_len' is 34478, then will get illegal +parent entry. Now, we do not check directory entry after read directory block +in 'ext4_get_first_dir_block'. +To solve this issue, check directory entry in 'ext4_get_first_dir_block'. + +[ Trigger an ext4_error() instead of just warning if the directory is + missing a '.' or '..' entry. Also make sure we return an error code + if the file system is corrupted. -TYT ] + +Signed-off-by: Ye Bin +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20220414025223.4113128-1-yebin10@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/namei.c | 30 +++++++++++++++++++++++++++--- + 1 file changed, 27 insertions(+), 3 deletions(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -3442,6 +3442,9 @@ static struct buffer_head *ext4_get_firs + struct buffer_head *bh; + + if (!ext4_has_inline_data(inode)) { ++ struct ext4_dir_entry_2 *de; ++ unsigned int offset; ++ + /* The first directory block must not be a hole, so + * treat it as DIRENT_HTREE + */ +@@ -3450,9 +3453,30 @@ static struct buffer_head *ext4_get_firs + *retval = PTR_ERR(bh); + return NULL; + } +- *parent_de = ext4_next_entry( +- (struct ext4_dir_entry_2 *)bh->b_data, +- inode->i_sb->s_blocksize); ++ ++ de = (struct ext4_dir_entry_2 *) bh->b_data; ++ if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, ++ bh->b_size, 0) || ++ le32_to_cpu(de->inode) != inode->i_ino || ++ strcmp(".", de->name)) { ++ EXT4_ERROR_INODE(inode, "directory missing '.'"); ++ brelse(bh); ++ *retval = -EFSCORRUPTED; ++ return NULL; ++ } ++ offset = ext4_rec_len_from_disk(de->rec_len, ++ inode->i_sb->s_blocksize); ++ de = ext4_next_entry(de, inode->i_sb->s_blocksize); ++ if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, ++ bh->b_size, offset) || ++ le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) { ++ EXT4_ERROR_INODE(inode, "directory missing '..'"); ++ brelse(bh); ++ *retval = -EFSCORRUPTED; ++ return NULL; ++ } ++ *parent_de = de; ++ + return bh; + } + diff --git a/queue-5.4/ext4-fix-warning-in-ext4_handle_inode_extension.patch b/queue-5.4/ext4-fix-warning-in-ext4_handle_inode_extension.patch new file mode 100644 index 00000000000..8540de69c8d --- /dev/null +++ b/queue-5.4/ext4-fix-warning-in-ext4_handle_inode_extension.patch @@ -0,0 +1,107 @@ +From f4534c9fc94d22383f187b9409abb3f9df2e3db3 Mon Sep 17 00:00:00 2001 +From: Ye Bin +Date: Sat, 26 Mar 2022 14:53:51 +0800 +Subject: ext4: fix warning in ext4_handle_inode_extension + +From: Ye Bin + +commit f4534c9fc94d22383f187b9409abb3f9df2e3db3 upstream. + +We got issue as follows: +EXT4-fs error (device loop0) in ext4_reserve_inode_write:5741: Out of memory +EXT4-fs error (device loop0): ext4_setattr:5462: inode #13: comm syz-executor.0: mark_inode_dirty error +EXT4-fs error (device loop0) in ext4_setattr:5519: Out of memory +EXT4-fs error (device loop0): ext4_ind_map_blocks:595: inode #13: comm syz-executor.0: Can't allocate blocks for non-extent mapped inodes with bigalloc +------------[ cut here ]------------ +WARNING: CPU: 1 PID: 4361 at fs/ext4/file.c:301 ext4_file_write_iter+0x11c9/0x1220 +Modules linked in: +CPU: 1 PID: 4361 Comm: syz-executor.0 Not tainted 5.10.0+ #1 +RIP: 0010:ext4_file_write_iter+0x11c9/0x1220 +RSP: 0018:ffff924d80b27c00 EFLAGS: 00010282 +RAX: ffffffff815a3379 RBX: 0000000000000000 RCX: 000000003b000000 +RDX: ffff924d81601000 RSI: 00000000000009cc RDI: 00000000000009cd +RBP: 000000000000000d R08: ffffffffbc5a2c6b R09: 0000902e0e52a96f +R10: ffff902e2b7c1b40 R11: ffff902e2b7c1b40 R12: 000000000000000a +R13: 0000000000000001 R14: ffff902e0e52aa10 R15: ffffffffffffff8b +FS: 00007f81a7f65700(0000) GS:ffff902e3bc80000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffffffffff600400 CR3: 000000012db88001 CR4: 00000000003706e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + do_iter_readv_writev+0x2e5/0x360 + do_iter_write+0x112/0x4c0 + do_pwritev+0x1e5/0x390 + __x64_sys_pwritev2+0x7e/0xa0 + do_syscall_64+0x37/0x50 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Above issue may happen as follows: +Assume +inode.i_size=4096 +EXT4_I(inode)->i_disksize=4096 + +step 1: set inode->i_isize = 8192 +ext4_setattr + if (attr->ia_size != inode->i_size) + EXT4_I(inode)->i_disksize = attr->ia_size; + rc = ext4_mark_inode_dirty + ext4_reserve_inode_write + ext4_get_inode_loc + __ext4_get_inode_loc + sb_getblk --> return -ENOMEM + ... + if (!error) ->will not update i_size + i_size_write(inode, attr->ia_size); +Now: +inode.i_size=4096 +EXT4_I(inode)->i_disksize=8192 + +step 2: Direct write 4096 bytes +ext4_file_write_iter + ext4_dio_write_iter + iomap_dio_rw ->return error + if (extend) + ext4_handle_inode_extension + WARN_ON_ONCE(i_size_read(inode) < EXT4_I(inode)->i_disksize); +->Then trigger warning. + +To solve above issue, if mark inode dirty failed in ext4_setattr just +set 'EXT4_I(inode)->i_disksize' with old value. + +Signed-off-by: Ye Bin +Link: https://lore.kernel.org/r/20220326065351.761952-1-yebin10@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/inode.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -5668,6 +5668,7 @@ int ext4_setattr(struct dentry *dentry, + if (attr->ia_valid & ATTR_SIZE) { + handle_t *handle; + loff_t oldsize = inode->i_size; ++ loff_t old_disksize; + int shrink = (attr->ia_size < inode->i_size); + + if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { +@@ -5723,6 +5724,7 @@ int ext4_setattr(struct dentry *dentry, + inode->i_ctime = inode->i_mtime; + } + down_write(&EXT4_I(inode)->i_data_sem); ++ old_disksize = EXT4_I(inode)->i_disksize; + EXT4_I(inode)->i_disksize = attr->ia_size; + rc = ext4_mark_inode_dirty(handle, inode); + if (!error) +@@ -5734,6 +5736,8 @@ int ext4_setattr(struct dentry *dentry, + */ + if (!error) + i_size_write(inode, attr->ia_size); ++ else ++ EXT4_I(inode)->i_disksize = old_disksize; + up_write(&EXT4_I(inode)->i_data_sem); + ext4_journal_stop(handle); + if (error) diff --git a/queue-5.4/ext4-verify-dir-block-before-splitting-it.patch b/queue-5.4/ext4-verify-dir-block-before-splitting-it.patch new file mode 100644 index 00000000000..a881a84eef2 --- /dev/null +++ b/queue-5.4/ext4-verify-dir-block-before-splitting-it.patch @@ -0,0 +1,88 @@ +From 46c116b920ebec58031f0a78c5ea9599b0d2a371 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Wed, 18 May 2022 11:33:28 +0200 +Subject: ext4: verify dir block before splitting it + +From: Jan Kara + +commit 46c116b920ebec58031f0a78c5ea9599b0d2a371 upstream. + +Before splitting a directory block verify its directory entries are sane +so that the splitting code does not access memory it should not. + +Cc: stable@vger.kernel.org +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20220518093332.13986-1-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/namei.c | 32 +++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -273,9 +273,9 @@ static struct dx_frame *dx_probe(struct + struct dx_hash_info *hinfo, + struct dx_frame *frame); + static void dx_release(struct dx_frame *frames); +-static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de, +- unsigned blocksize, struct dx_hash_info *hinfo, +- struct dx_map_entry map[]); ++static int dx_make_map(struct inode *dir, struct buffer_head *bh, ++ struct dx_hash_info *hinfo, ++ struct dx_map_entry *map_tail); + static void dx_sort_map(struct dx_map_entry *map, unsigned count); + static struct ext4_dir_entry_2 *dx_move_dirents(char *from, char *to, + struct dx_map_entry *offsets, int count, unsigned blocksize); +@@ -1205,15 +1205,23 @@ static inline int search_dirblock(struct + * Create map of hash values, offsets, and sizes, stored at end of block. + * Returns number of entries mapped. + */ +-static int dx_make_map(struct inode *dir, struct ext4_dir_entry_2 *de, +- unsigned blocksize, struct dx_hash_info *hinfo, ++static int dx_make_map(struct inode *dir, struct buffer_head *bh, ++ struct dx_hash_info *hinfo, + struct dx_map_entry *map_tail) + { + int count = 0; +- char *base = (char *) de; ++ struct ext4_dir_entry_2 *de = (struct ext4_dir_entry_2 *)bh->b_data; ++ unsigned int buflen = bh->b_size; ++ char *base = bh->b_data; + struct dx_hash_info h = *hinfo; + +- while ((char *) de < base + blocksize) { ++ if (ext4_has_metadata_csum(dir->i_sb)) ++ buflen -= sizeof(struct ext4_dir_entry_tail); ++ ++ while ((char *) de < base + buflen) { ++ if (ext4_check_dir_entry(dir, NULL, de, bh, base, buflen, ++ ((char *)de) - base)) ++ return -EFSCORRUPTED; + if (de->name_len && de->inode) { + ext4fs_dirhash(dir, de->name, de->name_len, &h); + map_tail--; +@@ -1223,8 +1231,7 @@ static int dx_make_map(struct inode *dir + count++; + cond_resched(); + } +- /* XXX: do we need to check rec_len == 0 case? -Chris */ +- de = ext4_next_entry(de, blocksize); ++ de = ext4_next_entry(de, dir->i_sb->s_blocksize); + } + return count; + } +@@ -1848,8 +1855,11 @@ static struct ext4_dir_entry_2 *do_split + + /* create map in the end of data2 block */ + map = (struct dx_map_entry *) (data2 + blocksize); +- count = dx_make_map(dir, (struct ext4_dir_entry_2 *) data1, +- blocksize, hinfo, map); ++ count = dx_make_map(dir, *bh, hinfo, map); ++ if (count < 0) { ++ err = count; ++ goto journal_error; ++ } + map -= count; + dx_sort_map(map, count); + /* Ensure that neither split block is over half full */ diff --git a/queue-5.4/netfilter-nf_tables-disallow-non-stateful-expression-in-sets-earlier.patch b/queue-5.4/netfilter-nf_tables-disallow-non-stateful-expression-in-sets-earlier.patch new file mode 100644 index 00000000000..9aae335148b --- /dev/null +++ b/queue-5.4/netfilter-nf_tables-disallow-non-stateful-expression-in-sets-earlier.patch @@ -0,0 +1,103 @@ +From 520778042ccca019f3ffa136dd0ca565c486cedd Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Wed, 25 May 2022 10:36:38 +0200 +Subject: netfilter: nf_tables: disallow non-stateful expression in sets earlier + +From: Pablo Neira Ayuso + +commit 520778042ccca019f3ffa136dd0ca565c486cedd upstream. + +Since 3e135cd499bf ("netfilter: nft_dynset: dynamic stateful expression +instantiation"), it is possible to attach stateful expressions to set +elements. + +cd5125d8f518 ("netfilter: nf_tables: split set destruction in deactivate +and destroy phase") introduces conditional destruction on the object to +accomodate transaction semantics. + +nft_expr_init() calls expr->ops->init() first, then check for +NFT_STATEFUL_EXPR, this stills allows to initialize a non-stateful +lookup expressions which points to a set, which might lead to UAF since +the set is not properly detached from the set->binding for this case. +Anyway, this combination is non-sense from nf_tables perspective. + +This patch fixes this problem by checking for NFT_STATEFUL_EXPR before +expr->ops->init() is called. + +The reporter provides a KASAN splat and a poc reproducer (similar to +those autogenerated by syzbot to report use-after-free errors). It is +unknown to me if they are using syzbot or if they use similar automated +tool to locate the bug that they are reporting. + +For the record, this is the KASAN splat. + +[ 85.431824] ================================================================== +[ 85.432901] BUG: KASAN: use-after-free in nf_tables_bind_set+0x81b/0xa20 +[ 85.433825] Write of size 8 at addr ffff8880286f0e98 by task poc/776 +[ 85.434756] +[ 85.434999] CPU: 1 PID: 776 Comm: poc Tainted: G W 5.18.0+ #2 +[ 85.436023] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014 + +Fixes: 0b2d8a7b638b ("netfilter: nf_tables: add helper functions for expression handling") +Reported-and-tested-by: Aaron Adams +Signed-off-by: Pablo Neira Ayuso +[Ajay: Regenerated the patch for v5.4.y] +Signed-off-by: Ajay Kaher +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/nf_tables_api.c | 16 ++++++++++------ + net/netfilter/nft_dynset.c | 3 --- + 2 files changed, 10 insertions(+), 9 deletions(-) + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -2267,27 +2267,31 @@ struct nft_expr *nft_expr_init(const str + + err = nf_tables_expr_parse(ctx, nla, &info); + if (err < 0) +- goto err1; ++ goto err_expr_parse; ++ ++ err = -EOPNOTSUPP; ++ if (!(info.ops->type->flags & NFT_EXPR_STATEFUL)) ++ goto err_expr_stateful; + + err = -ENOMEM; + expr = kzalloc(info.ops->size, GFP_KERNEL); + if (expr == NULL) +- goto err2; ++ goto err_expr_stateful; + + err = nf_tables_newexpr(ctx, &info, expr); + if (err < 0) +- goto err3; ++ goto err_expr_new; + + return expr; +-err3: ++err_expr_new: + kfree(expr); +-err2: ++err_expr_stateful: + owner = info.ops->type->owner; + if (info.ops->type->release_ops) + info.ops->type->release_ops(info.ops); + + module_put(owner); +-err1: ++err_expr_parse: + return ERR_PTR(err); + } + +--- a/net/netfilter/nft_dynset.c ++++ b/net/netfilter/nft_dynset.c +@@ -204,9 +204,6 @@ static int nft_dynset_init(const struct + return PTR_ERR(priv->expr); + + err = -EOPNOTSUPP; +- if (!(priv->expr->ops->type->flags & NFT_EXPR_STATEFUL)) +- goto err1; +- + if (priv->expr->ops->type->flags & NFT_EXPR_GC) { + if (set->flags & NFT_SET_TIMEOUT) + goto err1; diff --git a/queue-5.4/series b/queue-5.4/series index 8f902dc827d..dbe34f6db9d 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -220,3 +220,10 @@ efi-do-not-import-certificates-from-uefi-secure-boot-for-t2-macs.patch bfq-split-shared-queues-on-move-between-cgroups.patch bfq-update-cgroup-information-before-merging-bio.patch bfq-track-whether-bfq_group-is-still-online.patch +netfilter-nf_tables-disallow-non-stateful-expression-in-sets-earlier.patch +ext4-fix-use-after-free-in-ext4_rename_dir_prepare.patch +ext4-fix-warning-in-ext4_handle_inode_extension.patch +ext4-fix-bug_on-in-ext4_writepages.patch +ext4-verify-dir-block-before-splitting-it.patch +ext4-avoid-cycles-in-directory-h-tree.patch +acpi-property-release-subnode-properties-with-data-nodes.patch