From d5bfbae280c8377d9a48cc10909292b1289dc2bb Mon Sep 17 00:00:00 2001 From: Michal Kubecek Date: Mar 18 2020 12:15:47 +0000 Subject: Merge branch 'users/jack/SLE15-SP2/for-next' into SLE15-SP2 Pull filesystem and block layer fixes from Jan Kára. --- diff --git a/blacklist.conf b/blacklist.conf index a9af553..c1b36e6 100644 --- a/blacklist.conf +++ b/blacklist.conf @@ -228,3 +228,5 @@ ad808910be68dcf8da5d837d4511d00ad5d3678a # Duplicate of bd95c1445274c5e126ffd899 341c8e03a90a8d084a62fecaf97d31ca24b1d475 # dma/imx: reverting 967a3b85bac91c55eff740e61bf270c2732f48b2 # drm/amdgpu: reverted in below b73b7f48895a6a944a76a2d8cdd7feee72bb1f0b # drm/amdgpu: reverting the above +4d8340d0d4d90e7ca367d18ec16c2fefa89a339c # Coding style fix +d876836204897b6d7d911f942084f69a1e9d5c4d # We miss much more sendmsg / recvmsg fixes - most importantly probably 03b1230ca12a: io_uring: ensure async punted sendmsg/recvmsg requests copy data diff --git a/patches.suse/blktrace-fix-dereference-after-null-check.patch b/patches.suse/blktrace-fix-dereference-after-null-check.patch new file mode 100644 index 0000000..e61f77b --- /dev/null +++ b/patches.suse/blktrace-fix-dereference-after-null-check.patch @@ -0,0 +1,70 @@ +From 153031a301bb07194e9c37466cfce8eacb977621 Mon Sep 17 00:00:00 2001 +From: Cengiz Can +Date: Wed, 4 Mar 2020 13:58:19 +0300 +Subject: [PATCH] blktrace: fix dereference after null check +Git-commit: 153031a301bb07194e9c37466cfce8eacb977621 +Patch-mainline: v5.6-rc5 +References: bsc#1159285 + +There was a recent change in blktrace.c that added a RCU protection to +`q->blk_trace` in order to fix a use-after-free issue during access. + +However the change missed an edge case that can lead to dereferencing of +`bt` pointer even when it's NULL: + +Coverity static analyzer marked this as a FORWARD_NULL issue with CID +1460458. + +``` +/kernel/trace/blktrace.c: 1904 in sysfs_blk_trace_attr_store() +1898 ret = 0; +1899 if (bt == NULL) +1900 ret = blk_trace_setup_queue(q, bdev); +1901 +1902 if (ret == 0) { +1903 if (attr == &dev_attr_act_mask) +>>> CID 1460458: Null pointer dereferences (FORWARD_NULL) +>>> Dereferencing null pointer "bt". +1904 bt->act_mask = value; +1905 else if (attr == &dev_attr_pid) +1906 bt->pid = value; +1907 else if (attr == &dev_attr_start_lba) +1908 bt->start_lba = value; +1909 else if (attr == &dev_attr_end_lba) +``` + +Added a reassignment with RCU annotation to fix the issue. + +Fixes: c780e86dd48 ("blktrace: Protect q->blk_trace with RCU") +Cc: stable@vger.kernel.org +Reviewed-by: Ming Lei +Reviewed-by: Bob Liu +Reviewed-by: Steven Rostedt (VMware) +Signed-off-by: Cengiz Can +Signed-off-by: Jens Axboe +Acked-by: Jan Kara + +--- + kernel/trace/blktrace.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c +index 4560878f0bac..ca39dc3230cb 100644 +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -1896,8 +1896,11 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev, + } + + ret = 0; +- if (bt == NULL) ++ if (bt == NULL) { + ret = blk_trace_setup_queue(q, bdev); ++ bt = rcu_dereference_protected(q->blk_trace, ++ lockdep_is_held(&q->blk_trace_mutex)); ++ } + + if (ret == 0) { + if (attr == &dev_attr_act_mask) +-- +2.16.4 + diff --git a/patches.suse/block-bfq-get-a-ref-to-a-group-when-adding-it-to-a-s.patch b/patches.suse/block-bfq-get-a-ref-to-a-group-when-adding-it-to-a-s.patch new file mode 100644 index 0000000..c3ed04c --- /dev/null +++ b/patches.suse/block-bfq-get-a-ref-to-a-group-when-adding-it-to-a-s.patch @@ -0,0 +1,79 @@ +From db37a34c563bf4692b36990ae89005c031385e52 Mon Sep 17 00:00:00 2001 +From: Paolo Valente +Date: Mon, 3 Feb 2020 11:40:59 +0100 +Subject: [PATCH] block, bfq: get a ref to a group when adding it to a service + tree +Git-commit: db37a34c563bf4692b36990ae89005c031385e52 +Patch-mainline: v5.6-rc1 +References: bsc#1166859 + +BFQ schedules generic entities, which may represent either bfq_queues +or groups of bfq_queues. When an entity is inserted into a service +tree, a reference must be taken, to make sure that the entity does not +disappear while still referred in the tree. Unfortunately, such a +reference is mistakenly taken only if the entity represents a +bfq_queue. This commit takes a reference also in case the entity +represents a group. + +Tested-by: Oleksandr Natalenko +Tested-by: Chris Evich +Signed-off-by: Paolo Valente +Signed-off-by: Jens Axboe +Acked-by: Jan Kara + +--- + block/bfq-cgroup.c | 2 +- + block/bfq-iosched.h | 1 + + block/bfq-wf2q.c | 12 ++++++++++-- + 3 files changed, 12 insertions(+), 3 deletions(-) + +--- a/block/bfq-cgroup.c ++++ b/block/bfq-cgroup.c +@@ -332,7 +332,7 @@ static void bfqg_put(struct bfq_group *b + kfree(bfqg); + } + +-static void bfqg_and_blkg_get(struct bfq_group *bfqg) ++void bfqg_and_blkg_get(struct bfq_group *bfqg) + { + /* see comments in bfq_bic_update_cgroup for why refcounting bfqg */ + bfqg_get(bfqg); +--- a/block/bfq-iosched.h ++++ b/block/bfq-iosched.h +@@ -978,6 +978,7 @@ struct bfq_group *bfq_find_set_group(str + struct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg); + struct bfq_group *bfqq_group(struct bfq_queue *bfqq); + struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node); ++void bfqg_and_blkg_get(struct bfq_group *bfqg); + void bfqg_and_blkg_put(struct bfq_group *bfqg); + + #ifdef CONFIG_BFQ_GROUP_IOSCHED +--- a/block/bfq-wf2q.c ++++ b/block/bfq-wf2q.c +@@ -536,7 +536,9 @@ static void bfq_get_entity(struct bfq_en + bfqq->ref++; + bfq_log_bfqq(bfqq->bfqd, bfqq, "get_entity: %p %d", + bfqq, bfqq->ref); +- } ++ } else ++ bfqg_and_blkg_get(container_of(entity, struct bfq_group, ++ entity)); + } + + /** +@@ -650,8 +652,14 @@ static void bfq_forget_entity(struct bfq + + entity->on_st = false; + st->wsum -= entity->weight; +- if (bfqq && !is_in_service) ++ if (is_in_service) ++ return; ++ ++ if (bfqq) + bfq_put_queue(bfqq); ++ else ++ bfqg_and_blkg_put(container_of(entity, struct bfq_group, ++ entity)); + } + + /** diff --git a/patches.suse/ecryptfs-fix-a-memory-leak-bug-in-ecryptfs_init_mess.patch b/patches.suse/ecryptfs-fix-a-memory-leak-bug-in-ecryptfs_init_mess.patch new file mode 100644 index 0000000..4397e6d --- /dev/null +++ b/patches.suse/ecryptfs-fix-a-memory-leak-bug-in-ecryptfs_init_mess.patch @@ -0,0 +1,38 @@ +From b4a81b87a4cfe2bb26a4a943b748d96a43ef20e8 Mon Sep 17 00:00:00 2001 +From: Wenwen Wang +Date: Tue, 20 Aug 2019 00:33:54 -0500 +Subject: [PATCH] ecryptfs: fix a memory leak bug in ecryptfs_init_messaging() +Git-commit: b4a81b87a4cfe2bb26a4a943b748d96a43ef20e8 +Patch-mainline: v5.6-rc3 +References: bsc#1166872 + +In ecryptfs_init_messaging(), if the allocation for 'ecryptfs_msg_ctx_arr' +fails, the previously allocated 'ecryptfs_daemon_hash' is not deallocated, +leading to a memory leak bug. To fix this issue, free +'ecryptfs_daemon_hash' before returning the error. + +Cc: stable@vger.kernel.org +Fixes: 88b4a07e6610 ("[PATCH] eCryptfs: Public key transport mechanism") +Signed-off-by: Wenwen Wang +Signed-off-by: Tyler Hicks +Acked-by: Jan Kara + +--- + fs/ecryptfs/messaging.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c +index d668e60b85b5..c05ca39aa449 100644 +--- a/fs/ecryptfs/messaging.c ++++ b/fs/ecryptfs/messaging.c +@@ -379,6 +379,7 @@ int __init ecryptfs_init_messaging(void) + * ecryptfs_message_buf_len), + GFP_KERNEL); + if (!ecryptfs_msg_ctx_arr) { ++ kfree(ecryptfs_daemon_hash); + rc = -ENOMEM; + goto out; + } +-- +2.16.4 + diff --git a/patches.suse/ecryptfs-fix-a-memory-leak-bug-in-parse_tag_1_packet.patch b/patches.suse/ecryptfs-fix-a-memory-leak-bug-in-parse_tag_1_packet.patch new file mode 100644 index 0000000..38a0f0c --- /dev/null +++ b/patches.suse/ecryptfs-fix-a-memory-leak-bug-in-parse_tag_1_packet.patch @@ -0,0 +1,39 @@ +From fe2e082f5da5b4a0a92ae32978f81507ef37ec66 Mon Sep 17 00:00:00 2001 +From: Wenwen Wang +Date: Tue, 20 Aug 2019 00:16:40 -0500 +Subject: [PATCH] ecryptfs: fix a memory leak bug in parse_tag_1_packet() +Git-commit: fe2e082f5da5b4a0a92ae32978f81507ef37ec66 +Patch-mainline: v5.6-rc3 +References: bsc#1166871 + +In parse_tag_1_packet(), if tag 1 packet contains a key larger than +ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES, no cleanup is executed, leading to a +memory leak on the allocated 'auth_tok_list_item'. To fix this issue, go to +the label 'out_free' to perform the cleanup work. + +Cc: stable@vger.kernel.org +Fixes: dddfa461fc89 ("[PATCH] eCryptfs: Public key; packet management") +Signed-off-by: Wenwen Wang +Signed-off-by: Tyler Hicks +Acked-by: Jan Kara + +--- + fs/ecryptfs/keystore.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c +index 216fbe6a4837..4dc09638de8f 100644 +--- a/fs/ecryptfs/keystore.c ++++ b/fs/ecryptfs/keystore.c +@@ -1304,7 +1304,7 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat, + printk(KERN_WARNING "Tag 1 packet contains key larger " + "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n"); + rc = -EINVAL; +- goto out; ++ goto out_free; + } + memcpy((*new_auth_tok)->session_key.encrypted_key, + &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2))); +-- +2.16.4 + diff --git a/patches.suse/ecryptfs-replace-BUG_ON-with-error-handling-code.patch b/patches.suse/ecryptfs-replace-BUG_ON-with-error-handling-code.patch new file mode 100644 index 0000000..6ad4c6a --- /dev/null +++ b/patches.suse/ecryptfs-replace-BUG_ON-with-error-handling-code.patch @@ -0,0 +1,43 @@ +From 2c2a7552dd6465e8fde6bc9cccf8d66ed1c1eb72 Mon Sep 17 00:00:00 2001 +From: Aditya Pakki +Date: Fri, 14 Feb 2020 12:21:01 -0600 +Subject: [PATCH] ecryptfs: replace BUG_ON with error handling code +Git-commit: 2c2a7552dd6465e8fde6bc9cccf8d66ed1c1eb72 +Patch-mainline: v5.6-rc3 +References: bsc#1166874 + +In crypt_scatterlist, if the crypt_stat argument is not set up +correctly, the kernel crashes. Instead, by returning an error code +upstream, the error is handled safely. + +The issue is detected via a static analysis tool written by us. + +Fixes: 237fead619984 (ecryptfs: fs/Makefile and fs/Kconfig) +Signed-off-by: Aditya Pakki +Signed-off-by: Tyler Hicks +Acked-by: Jan Kara + +--- + fs/ecryptfs/crypto.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c +index f91db24bbf3b..a064b408d841 100644 +--- a/fs/ecryptfs/crypto.c ++++ b/fs/ecryptfs/crypto.c +@@ -311,8 +311,10 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, + struct extent_crypt_result ecr; + int rc = 0; + +- BUG_ON(!crypt_stat || !crypt_stat->tfm +- || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)); ++ if (!crypt_stat || !crypt_stat->tfm ++ || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)) ++ return -EINVAL; ++ + if (unlikely(ecryptfs_verbosity > 0)) { + ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n", + crypt_stat->key_size); +-- +2.16.4 + diff --git a/patches.suse/ext4-add-cond_resched-to-__ext4_find_entry.patch b/patches.suse/ext4-add-cond_resched-to-__ext4_find_entry.patch new file mode 100644 index 0000000..9ca634c --- /dev/null +++ b/patches.suse/ext4-add-cond_resched-to-__ext4_find_entry.patch @@ -0,0 +1,75 @@ +From 9424ef56e13a1f14c57ea161eed3ecfdc7b2770e Mon Sep 17 00:00:00 2001 +From: Shijie Luo +Date: Sat, 15 Feb 2020 03:02:06 -0500 +Subject: [PATCH] ext4: add cond_resched() to __ext4_find_entry() +Git-commit: 9424ef56e13a1f14c57ea161eed3ecfdc7b2770e +Patch-mainline: v5.6-rc3 +References: bsc#1166862 + +We tested a soft lockup problem in linux 4.19 which could also +be found in linux 5.x. + +When dir inode takes up a large number of blocks, and if the +directory is growing when we are searching, it's possible the +restart branch could be called many times, and the do while loop +could hold cpu a long time. + +Here is the call trace in linux 4.19. + +[ 473.756186] Call trace: +[ 473.756196] dump_backtrace+0x0/0x198 +[ 473.756199] show_stack+0x24/0x30 +[ 473.756205] dump_stack+0xa4/0xcc +[ 473.756210] watchdog_timer_fn+0x300/0x3e8 +[ 473.756215] __hrtimer_run_queues+0x114/0x358 +[ 473.756217] hrtimer_interrupt+0x104/0x2d8 +[ 473.756222] arch_timer_handler_virt+0x38/0x58 +[ 473.756226] handle_percpu_devid_irq+0x90/0x248 +[ 473.756231] generic_handle_irq+0x34/0x50 +[ 473.756234] __handle_domain_irq+0x68/0xc0 +[ 473.756236] gic_handle_irq+0x6c/0x150 +[ 473.756238] el1_irq+0xb8/0x140 +[ 473.756286] ext4_es_lookup_extent+0xdc/0x258 [ext4] +[ 473.756310] ext4_map_blocks+0x64/0x5c0 [ext4] +[ 473.756333] ext4_getblk+0x6c/0x1d0 [ext4] +[ 473.756356] ext4_bread_batch+0x7c/0x1f8 [ext4] +[ 473.756379] ext4_find_entry+0x124/0x3f8 [ext4] +[ 473.756402] ext4_lookup+0x8c/0x258 [ext4] +[ 473.756407] __lookup_hash+0x8c/0xe8 +[ 473.756411] filename_create+0xa0/0x170 +[ 473.756413] do_mkdirat+0x6c/0x140 +[ 473.756415] __arm64_sys_mkdirat+0x28/0x38 +[ 473.756419] el0_svc_common+0x78/0x130 +[ 473.756421] el0_svc_handler+0x38/0x78 +[ 473.756423] el0_svc+0x8/0xc +[ 485.755156] watchdog: BUG: soft lockup - CPU#2 stuck for 22s! [tmp:5149] + +Add cond_resched() to avoid soft lockup and to provide a better +system responding. + +Link: https://lore.kernel.org/r/20200215080206.13293-1-luoshijie1@huawei.com +Signed-off-by: Shijie Luo +Signed-off-by: Theodore Ts'o +Reviewed-by: Jan Kara +Cc: stable@kernel.org +Acked-by: Jan Kara + +--- + fs/ext4/namei.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index ceff4b4b1877..b05ea72f38fd 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -1511,6 +1511,7 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir, + /* + * We deal with the read-ahead logic here. + */ ++ cond_resched(); + if (ra_ptr >= ra_max) { + /* Refill the readahead buffer */ + ra_ptr = 0; +-- +2.16.4 + diff --git a/patches.suse/ext4-don-t-assume-that-mmp_nodename-bdevname-have-NU.patch b/patches.suse/ext4-don-t-assume-that-mmp_nodename-bdevname-have-NU.patch new file mode 100644 index 0000000..b3440e4 --- /dev/null +++ b/patches.suse/ext4-don-t-assume-that-mmp_nodename-bdevname-have-NU.patch @@ -0,0 +1,62 @@ +From 14c9ca0583eee8df285d68a0e6ec71053efd2228 Mon Sep 17 00:00:00 2001 +From: Andreas Dilger +Date: Sun, 26 Jan 2020 15:03:34 -0700 +Subject: [PATCH] ext4: don't assume that mmp_nodename/bdevname have NUL +Git-commit: 14c9ca0583eee8df285d68a0e6ec71053efd2228 +Patch-mainline: v5.6-rc2 +References: bsc#1166860 + +Don't assume that the mmp_nodename and mmp_bdevname strings are NUL +terminated, since they are filled in by snprintf(), which is not +guaranteed to do so. + +Link: https://lore.kernel.org/r/1580076215-1048-1-git-send-email-adilger@dilger.ca +Signed-off-by: Andreas Dilger +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Acked-by: Jan Kara + +--- + fs/ext4/mmp.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c +index 1c44b1a32001..87f7551c5132 100644 +--- a/fs/ext4/mmp.c ++++ b/fs/ext4/mmp.c +@@ -120,10 +120,10 @@ void __dump_mmp_msg(struct super_block *sb, struct mmp_struct *mmp, + { + __ext4_warning(sb, function, line, "%s", msg); + __ext4_warning(sb, function, line, +- "MMP failure info: last update time: %llu, last update " +- "node: %s, last update device: %s", +- (long long unsigned int) le64_to_cpu(mmp->mmp_time), +- mmp->mmp_nodename, mmp->mmp_bdevname); ++ "MMP failure info: last update time: %llu, last update node: %.*s, last update device: %.*s", ++ (unsigned long long)le64_to_cpu(mmp->mmp_time), ++ (int)sizeof(mmp->mmp_nodename), mmp->mmp_nodename, ++ (int)sizeof(mmp->mmp_bdevname), mmp->mmp_bdevname); + } + + /* +@@ -154,6 +154,7 @@ static int kmmpd(void *data) + mmp_check_interval = max(EXT4_MMP_CHECK_MULT * mmp_update_interval, + EXT4_MMP_MIN_CHECK_INTERVAL); + mmp->mmp_check_interval = cpu_to_le16(mmp_check_interval); ++ BUILD_BUG_ON(sizeof(mmp->mmp_bdevname) < BDEVNAME_SIZE); + bdevname(bh->b_bdev, mmp->mmp_bdevname); + + memcpy(mmp->mmp_nodename, init_utsname()->nodename, +@@ -379,7 +380,8 @@ int ext4_multi_mount_protect(struct super_block *sb, + /* + * Start a kernel thread to update the MMP block periodically. + */ +- EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%s", ++ EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%.*s", ++ (int)sizeof(mmp->mmp_bdevname), + bdevname(bh->b_bdev, + mmp->mmp_bdevname)); + if (IS_ERR(EXT4_SB(sb)->s_mmp_tsk)) { +-- +2.16.4 + diff --git a/patches.suse/ext4-fix-a-data-race-in-EXT4_I-inode-i_disksize.patch b/patches.suse/ext4-fix-a-data-race-in-EXT4_I-inode-i_disksize.patch new file mode 100644 index 0000000..15fd929 --- /dev/null +++ b/patches.suse/ext4-fix-a-data-race-in-EXT4_I-inode-i_disksize.patch @@ -0,0 +1,93 @@ +From 35df4299a6487f323b0aca120ea3f485dfee2ae3 Mon Sep 17 00:00:00 2001 +From: Qian Cai +Date: Fri, 7 Feb 2020 09:29:11 -0500 +Subject: [PATCH] ext4: fix a data race in EXT4_I(inode)->i_disksize +Git-commit: 35df4299a6487f323b0aca120ea3f485dfee2ae3 +Patch-mainline: v5.6-rc3 +References: bsc#1166861 + +EXT4_I(inode)->i_disksize could be accessed concurrently as noticed by +KCSAN, + + BUG: KCSAN: data-race in ext4_write_end [ext4] / ext4_writepages [ext4] + + write to 0xffff91c6713b00f8 of 8 bytes by task 49268 on cpu 127: + ext4_write_end+0x4e3/0x750 [ext4] + ext4_update_i_disksize at fs/ext4/ext4.h:3032 + (inlined by) ext4_update_inode_size at fs/ext4/ext4.h:3046 + (inlined by) ext4_write_end at fs/ext4/inode.c:1287 + generic_perform_write+0x208/0x2a0 + ext4_buffered_write_iter+0x11f/0x210 [ext4] + ext4_file_write_iter+0xce/0x9e0 [ext4] + new_sync_write+0x29c/0x3b0 + __vfs_write+0x92/0xa0 + vfs_write+0x103/0x260 + ksys_write+0x9d/0x130 + __x64_sys_write+0x4c/0x60 + do_syscall_64+0x91/0xb47 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + + read to 0xffff91c6713b00f8 of 8 bytes by task 24872 on cpu 37: + ext4_writepages+0x10ac/0x1d00 [ext4] + mpage_map_and_submit_extent at fs/ext4/inode.c:2468 + (inlined by) ext4_writepages at fs/ext4/inode.c:2772 + do_writepages+0x5e/0x130 + __writeback_single_inode+0xeb/0xb20 + writeback_sb_inodes+0x429/0x900 + __writeback_inodes_wb+0xc4/0x150 + wb_writeback+0x4bd/0x870 + wb_workfn+0x6b4/0x960 + process_one_work+0x54c/0xbe0 + worker_thread+0x80/0x650 + kthread+0x1e0/0x200 + ret_from_fork+0x27/0x50 + + Reported by Kernel Concurrency Sanitizer on: + CPU: 37 PID: 24872 Comm: kworker/u261:2 Tainted: G W O L 5.5.0-next-20200204+ #5 + Hardware name: HPE ProLiant DL385 Gen10/ProLiant DL385 Gen10, BIOS A40 07/10/2019 + Workqueue: writeback wb_workfn (flush-7:0) + +Since only the read is operating as lockless (outside of the +"i_data_sem"), load tearing could introduce a logic bug. Fix it by +adding READ_ONCE() for the read and WRITE_ONCE() for the write. + +Signed-off-by: Qian Cai +Link: https://lore.kernel.org/r/1581085751-31793-1-git-send-email-cai@lca.pw +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Acked-by: Jan Kara + +--- + fs/ext4/ext4.h | 2 +- + fs/ext4/inode.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 4441331d06cc..480badcf2783 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -3032,7 +3032,7 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize) + !inode_is_locked(inode)); + down_write(&EXT4_I(inode)->i_data_sem); + if (newsize > EXT4_I(inode)->i_disksize) +- EXT4_I(inode)->i_disksize = newsize; ++ WRITE_ONCE(EXT4_I(inode)->i_disksize, newsize); + up_write(&EXT4_I(inode)->i_data_sem); + } + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index e60aca791d3f..6e1d81ed44ad 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2465,7 +2465,7 @@ static int mpage_map_and_submit_extent(handle_t *handle, + * truncate are avoided by checking i_size under i_data_sem. + */ + disksize = ((loff_t)mpd->first_page) << PAGE_SHIFT; +- if (disksize > EXT4_I(inode)->i_disksize) { ++ if (disksize > READ_ONCE(EXT4_I(inode)->i_disksize)) { + int err2; + loff_t i_size; + +-- +2.16.4 + diff --git a/patches.suse/ext4-fix-potential-race-between-online-resizing-and-.patch b/patches.suse/ext4-fix-potential-race-between-online-resizing-and-.patch new file mode 100644 index 0000000..35f69ce --- /dev/null +++ b/patches.suse/ext4-fix-potential-race-between-online-resizing-and-.patch @@ -0,0 +1,316 @@ +From 1d0c3924a92e69bfa91163bda83c12a994b4d106 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 15 Feb 2020 16:40:37 -0500 +Subject: [PATCH] ext4: fix potential race between online resizing and write + operations +Git-commit: 1d0c3924a92e69bfa91163bda83c12a994b4d106 +Patch-mainline: v5.6-rc3 +References: bsc#1166864 + +During an online resize an array of pointers to buffer heads gets +replaced so it can get enlarged. If there is a racing block +allocation or deallocation which uses the old array, and the old array +has gotten reused this can lead to a GPF or some other random kernel +memory getting modified. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=206443 +Link: https://lore.kernel.org/r/20200221053458.730016-2-tytso@mit.edu +Reported-by: Suraj Jitindar Singh +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Acked-by: Jan Kara + +--- + fs/ext4/balloc.c | 14 +++++++++++--- + fs/ext4/ext4.h | 20 +++++++++++++++++++- + fs/ext4/resize.c | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- + fs/ext4/super.c | 33 +++++++++++++++++++++++---------- + 4 files changed, 97 insertions(+), 25 deletions(-) + +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -270,6 +270,7 @@ struct ext4_group_desc * ext4_get_group_ + ext4_group_t ngroups = ext4_get_groups_count(sb); + struct ext4_group_desc *desc; + struct ext4_sb_info *sbi = EXT4_SB(sb); ++ struct buffer_head *bh_p; + + if (block_group >= ngroups) { + ext4_error(sb, "block_group >= groups_count - block_group = %u," +@@ -280,7 +281,14 @@ struct ext4_group_desc * ext4_get_group_ + + group_desc = block_group >> EXT4_DESC_PER_BLOCK_BITS(sb); + offset = block_group & (EXT4_DESC_PER_BLOCK(sb) - 1); +- if (!sbi->s_group_desc[group_desc]) { ++ bh_p = sbi_array_rcu_deref(sbi, s_group_desc, group_desc); ++ /* ++ * sbi_array_rcu_deref returns with rcu unlocked, this is ok since ++ * the pointer being dereferenced won't be dereferenced again. By ++ * looking at the usage in add_new_gdb() the value isn't modified, ++ * just the pointer, and so it remains valid. ++ */ ++ if (!bh_p) { + ext4_error(sb, "Group descriptor not loaded - " + "block_group = %u, group_desc = %u, desc = %u", + block_group, group_desc, offset); +@@ -288,10 +296,10 @@ struct ext4_group_desc * ext4_get_group_ + } + + desc = (struct ext4_group_desc *)( +- (__u8 *)sbi->s_group_desc[group_desc]->b_data + ++ (__u8 *)bh_p->b_data + + offset * EXT4_DESC_SIZE(sb)); + if (bh) +- *bh = sbi->s_group_desc[group_desc]; ++ *bh = bh_p; + return desc; + } + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1380,7 +1380,7 @@ struct ext4_sb_info { + loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ + struct buffer_head * s_sbh; /* Buffer containing the super block */ + struct ext4_super_block *s_es; /* Pointer to the super block in the buffer */ +- struct buffer_head **s_group_desc; ++ struct buffer_head * __rcu *s_group_desc; + unsigned int s_mount_opt; + unsigned int s_mount_opt2; + unsigned int s_mount_flags; +@@ -1554,6 +1554,23 @@ static inline int ext4_valid_inum(struct + } + + /* ++ * Returns: sbi->field[index] ++ * Used to access an array element from the following sbi fields which require ++ * rcu protection to avoid dereferencing an invalid pointer due to reassignment ++ * - s_group_desc ++ * - s_group_info ++ * - s_flex_group ++ */ ++#define sbi_array_rcu_deref(sbi, field, index) \ ++({ \ ++ typeof(*((sbi)->field)) _v; \ ++ rcu_read_lock(); \ ++ _v = ((typeof(_v)*)rcu_dereference((sbi)->field))[index]; \ ++ rcu_read_unlock(); \ ++ _v; \ ++}) ++ ++/* + * Inode dynamic state flags + */ + enum { +@@ -2636,6 +2653,7 @@ extern int ext4_generic_delete_entry(han + extern bool ext4_empty_dir(struct inode *inode); + + /* resize.c */ ++extern void ext4_kvfree_array_rcu(void *to_free); + extern int ext4_group_add(struct super_block *sb, + struct ext4_new_group_data *input); + extern int ext4_group_extend(struct super_block *sb, +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -17,6 +17,33 @@ + + #include "ext4_jbd2.h" + ++struct ext4_rcu_ptr { ++ struct rcu_head rcu; ++ void *ptr; ++}; ++ ++static void ext4_rcu_ptr_callback(struct rcu_head *head) ++{ ++ struct ext4_rcu_ptr *ptr; ++ ++ ptr = container_of(head, struct ext4_rcu_ptr, rcu); ++ kvfree(ptr->ptr); ++ kfree(ptr); ++} ++ ++void ext4_kvfree_array_rcu(void *to_free) ++{ ++ struct ext4_rcu_ptr *ptr = kzalloc(sizeof(*ptr), GFP_KERNEL); ++ ++ if (ptr) { ++ ptr->ptr = to_free; ++ call_rcu(&ptr->rcu, ext4_rcu_ptr_callback); ++ return; ++ } ++ synchronize_rcu(); ++ kvfree(to_free); ++} ++ + int ext4_resize_begin(struct super_block *sb) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); +@@ -560,8 +587,8 @@ static int setup_new_flex_group_blocks(s + brelse(gdb); + goto out; + } +- memcpy(gdb->b_data, sbi->s_group_desc[j]->b_data, +- gdb->b_size); ++ memcpy(gdb->b_data, sbi_array_rcu_deref(sbi, ++ s_group_desc, j)->b_data, gdb->b_size); + set_buffer_uptodate(gdb); + + err = ext4_handle_dirty_metadata(handle, NULL, gdb); +@@ -879,13 +906,15 @@ static int add_new_gdb(handle_t *handle, + } + brelse(dind); + +- o_group_desc = EXT4_SB(sb)->s_group_desc; ++ rcu_read_lock(); ++ o_group_desc = rcu_dereference(EXT4_SB(sb)->s_group_desc); + memcpy(n_group_desc, o_group_desc, + EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *)); ++ rcu_read_unlock(); + n_group_desc[gdb_num] = gdb_bh; +- EXT4_SB(sb)->s_group_desc = n_group_desc; ++ rcu_assign_pointer(EXT4_SB(sb)->s_group_desc, n_group_desc); + EXT4_SB(sb)->s_gdb_count++; +- kvfree(o_group_desc); ++ ext4_kvfree_array_rcu(o_group_desc); + + le16_add_cpu(&es->s_reserved_gdt_blocks, -1); + err = ext4_handle_dirty_super(handle, sb); +@@ -929,9 +958,11 @@ static int add_new_gdb_meta_bg(struct su + return err; + } + +- o_group_desc = EXT4_SB(sb)->s_group_desc; ++ rcu_read_lock(); ++ o_group_desc = rcu_dereference(EXT4_SB(sb)->s_group_desc); + memcpy(n_group_desc, o_group_desc, + EXT4_SB(sb)->s_gdb_count * sizeof(struct buffer_head *)); ++ rcu_read_unlock(); + n_group_desc[gdb_num] = gdb_bh; + + BUFFER_TRACE(gdb_bh, "get_write_access"); +@@ -942,9 +973,9 @@ static int add_new_gdb_meta_bg(struct su + return err; + } + +- EXT4_SB(sb)->s_group_desc = n_group_desc; ++ rcu_assign_pointer(EXT4_SB(sb)->s_group_desc, n_group_desc); + EXT4_SB(sb)->s_gdb_count++; +- kvfree(o_group_desc); ++ ext4_kvfree_array_rcu(o_group_desc); + return err; + } + +@@ -1210,7 +1241,8 @@ static int ext4_add_new_descs(handle_t * + * use non-sparse filesystems anymore. This is already checked above. + */ + if (gdb_off) { +- gdb_bh = sbi->s_group_desc[gdb_num]; ++ gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc, ++ gdb_num); + BUFFER_TRACE(gdb_bh, "get_write_access"); + err = ext4_journal_get_write_access(handle, gdb_bh); + +@@ -1292,7 +1324,7 @@ static int ext4_setup_new_descs(handle_t + /* + * get_write_access() has been called on gdb_bh by ext4_add_new_desc(). + */ +- gdb_bh = sbi->s_group_desc[gdb_num]; ++ gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc, gdb_num); + /* Update group descriptor block for new group */ + gdp = (struct ext4_group_desc *)(gdb_bh->b_data + + gdb_off * EXT4_DESC_SIZE(sb)); +@@ -1519,7 +1551,8 @@ exit_journal: + for (; gdb_num <= gdb_num_end; gdb_num++) { + struct buffer_head *gdb_bh; + +- gdb_bh = sbi->s_group_desc[gdb_num]; ++ gdb_bh = sbi_array_rcu_deref(sbi, s_group_desc, ++ gdb_num); + if (old_gdb == gdb_bh->b_blocknr) + continue; + update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data, +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -970,6 +970,7 @@ static void ext4_put_super(struct super_ + { + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_super_block *es = sbi->s_es; ++ struct buffer_head **group_desc; + int aborted = 0; + int i, err; + +@@ -1000,9 +1001,12 @@ static void ext4_put_super(struct super_ + if (!sb_rdonly(sb)) + ext4_commit_super(sb, 1); + ++ rcu_read_lock(); ++ group_desc = rcu_dereference(sbi->s_group_desc); + for (i = 0; i < sbi->s_gdb_count; i++) +- brelse(sbi->s_group_desc[i]); +- kvfree(sbi->s_group_desc); ++ brelse(group_desc[i]); ++ kvfree(group_desc); ++ rcu_read_unlock(); + kvfree(sbi->s_flex_groups); + percpu_counter_destroy(&sbi->s_freeclusters_counter); + percpu_counter_destroy(&sbi->s_freeinodes_counter); +@@ -3575,7 +3579,7 @@ static int ext4_fill_super(struct super_ + { + struct dax_device *dax_dev = fs_dax_get_by_bdev(sb->s_bdev); + char *orig_data = kstrdup(data, GFP_KERNEL); +- struct buffer_head *bh; ++ struct buffer_head *bh, **group_desc; + struct ext4_super_block *es = NULL; + struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); + ext4_fsblk_t block; +@@ -4218,9 +4222,10 @@ static int ext4_fill_super(struct super_ + goto failed_mount; + } + } +- sbi->s_group_desc = kvmalloc_array(db_count, +- sizeof(struct buffer_head *), +- GFP_KERNEL); ++ rcu_assign_pointer(sbi->s_group_desc, ++ kvmalloc_array(db_count, ++ sizeof(struct buffer_head *), ++ GFP_KERNEL)); + if (sbi->s_group_desc == NULL) { + ext4_msg(sb, KERN_ERR, "not enough memory"); + ret = -ENOMEM; +@@ -4236,14 +4241,19 @@ static int ext4_fill_super(struct super_ + } + + for (i = 0; i < db_count; i++) { ++ struct buffer_head *bh; ++ + block = descriptor_loc(sb, logical_sb_block, i); +- sbi->s_group_desc[i] = sb_bread_unmovable(sb, block); +- if (!sbi->s_group_desc[i]) { ++ bh = sb_bread_unmovable(sb, block); ++ if (!bh) { + ext4_msg(sb, KERN_ERR, + "can't read group descriptor %d", i); + db_count = i; + goto failed_mount2; + } ++ rcu_read_lock(); ++ rcu_dereference(sbi->s_group_desc)[i] = bh; ++ rcu_read_unlock(); + } + sbi->s_gdb_count = db_count; + if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) { +@@ -4644,9 +4654,12 @@ failed_mount3: + if (sbi->s_mmp_tsk) + kthread_stop(sbi->s_mmp_tsk); + failed_mount2: ++ rcu_read_lock(); ++ group_desc = rcu_dereference(sbi->s_group_desc); + for (i = 0; i < db_count; i++) +- brelse(sbi->s_group_desc[i]); +- kvfree(sbi->s_group_desc); ++ brelse(group_desc[i]); ++ kvfree(group_desc); ++ rcu_read_unlock(); + failed_mount: + if (sbi->s_chksum_driver) + crypto_free_shash(sbi->s_chksum_driver); diff --git a/patches.suse/ext4-fix-potential-race-between-s_flex_groups-online.patch b/patches.suse/ext4-fix-potential-race-between-s_flex_groups-online.patch new file mode 100644 index 0000000..148cf7d --- /dev/null +++ b/patches.suse/ext4-fix-potential-race-between-s_flex_groups-online.patch @@ -0,0 +1,304 @@ +From 7c990728b99ed6fbe9c75fc202fce1172d9916da Mon Sep 17 00:00:00 2001 +From: Suraj Jitindar Singh +Date: Tue, 18 Feb 2020 19:08:51 -0800 +Subject: [PATCH] ext4: fix potential race between s_flex_groups online + resizing and access +Git-commit: 7c990728b99ed6fbe9c75fc202fce1172d9916da +Patch-mainline: v5.6-rc3 +References: bsc#1166867 + +During an online resize an array of s_flex_groups structures gets replaced +so it can get enlarged. If there is a concurrent access to the array and +this memory has been reused then this can lead to an invalid memory access. + +The s_flex_group array has been converted into an array of pointers rather +than an array of structures. This is to ensure that the information +contained in the structures cannot get out of sync during a resize due to +an accessor updating the value in the old structure after it has been +copied but before the array pointer is updated. Since the structures them- +selves are no longer copied but only the pointers to them this case is +mitigated. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=206443 +Link: https://lore.kernel.org/r/20200221053458.730016-4-tytso@mit.edu +Signed-off-by: Suraj Jitindar Singh +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Acked-by: Jan Kara + +--- + fs/ext4/ext4.h | 2 +- + fs/ext4/ialloc.c | 23 +++++++++++------- + fs/ext4/mballoc.c | 9 ++++--- + fs/ext4/resize.c | 7 ++++-- + fs/ext4/super.c | 72 ++++++++++++++++++++++++++++++++++++++----------------- + 5 files changed, 76 insertions(+), 37 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index b1ece5329738..614fefa7dc7a 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1512,7 +1512,7 @@ struct ext4_sb_info { + unsigned int s_extent_max_zeroout_kb; + + unsigned int s_log_groups_per_flex; +- struct flex_groups *s_flex_groups; ++ struct flex_groups * __rcu *s_flex_groups; + ext4_group_t s_flex_groups_allocated; + + /* workqueue for reserved extent conversions (buffered io) */ +diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c +index c66e8f9451a2..f95ee99091e4 100644 +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -328,11 +328,13 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) + + percpu_counter_inc(&sbi->s_freeinodes_counter); + if (sbi->s_log_groups_per_flex) { +- ext4_group_t f = ext4_flex_group(sbi, block_group); ++ struct flex_groups *fg; + +- atomic_inc(&sbi->s_flex_groups[f].free_inodes); ++ fg = sbi_array_rcu_deref(sbi, s_flex_groups, ++ ext4_flex_group(sbi, block_group)); ++ atomic_inc(&fg->free_inodes); + if (is_directory) +- atomic_dec(&sbi->s_flex_groups[f].used_dirs); ++ atomic_dec(&fg->used_dirs); + } + BUFFER_TRACE(bh2, "call ext4_handle_dirty_metadata"); + fatal = ext4_handle_dirty_metadata(handle, NULL, bh2); +@@ -368,12 +370,13 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g, + int flex_size, struct orlov_stats *stats) + { + struct ext4_group_desc *desc; +- struct flex_groups *flex_group = EXT4_SB(sb)->s_flex_groups; + + if (flex_size > 1) { +- stats->free_inodes = atomic_read(&flex_group[g].free_inodes); +- stats->free_clusters = atomic64_read(&flex_group[g].free_clusters); +- stats->used_dirs = atomic_read(&flex_group[g].used_dirs); ++ struct flex_groups *fg = sbi_array_rcu_deref(EXT4_SB(sb), ++ s_flex_groups, g); ++ stats->free_inodes = atomic_read(&fg->free_inodes); ++ stats->free_clusters = atomic64_read(&fg->free_clusters); ++ stats->used_dirs = atomic_read(&fg->used_dirs); + return; + } + +@@ -1054,7 +1057,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, + if (sbi->s_log_groups_per_flex) { + ext4_group_t f = ext4_flex_group(sbi, group); + +- atomic_inc(&sbi->s_flex_groups[f].used_dirs); ++ atomic_inc(&sbi_array_rcu_deref(sbi, s_flex_groups, ++ f)->used_dirs); + } + } + if (ext4_has_group_desc_csum(sb)) { +@@ -1077,7 +1081,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, + + if (sbi->s_log_groups_per_flex) { + flex_group = ext4_flex_group(sbi, group); +- atomic_dec(&sbi->s_flex_groups[flex_group].free_inodes); ++ atomic_dec(&sbi_array_rcu_deref(sbi, s_flex_groups, ++ flex_group)->free_inodes); + } + + inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb); +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index 1b46fb63692a..51a78eb65f3c 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -3038,7 +3038,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, + ext4_group_t flex_group = ext4_flex_group(sbi, + ac->ac_b_ex.fe_group); + atomic64_sub(ac->ac_b_ex.fe_len, +- &sbi->s_flex_groups[flex_group].free_clusters); ++ &sbi_array_rcu_deref(sbi, s_flex_groups, ++ flex_group)->free_clusters); + } + + err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); +@@ -4936,7 +4937,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, + if (sbi->s_log_groups_per_flex) { + ext4_group_t flex_group = ext4_flex_group(sbi, block_group); + atomic64_add(count_clusters, +- &sbi->s_flex_groups[flex_group].free_clusters); ++ &sbi_array_rcu_deref(sbi, s_flex_groups, ++ flex_group)->free_clusters); + } + + /* +@@ -5093,7 +5095,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, + if (sbi->s_log_groups_per_flex) { + ext4_group_t flex_group = ext4_flex_group(sbi, block_group); + atomic64_add(clusters_freed, +- &sbi->s_flex_groups[flex_group].free_clusters); ++ &sbi_array_rcu_deref(sbi, s_flex_groups, ++ flex_group)->free_clusters); + } + + ext4_mb_unload_buddy(&e4b); +diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c +index 536cc9f38091..a50b51270ea9 100644 +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -1430,11 +1430,14 @@ static void ext4_update_super(struct super_block *sb, + percpu_counter_read(&sbi->s_freeclusters_counter)); + if (ext4_has_feature_flex_bg(sb) && sbi->s_log_groups_per_flex) { + ext4_group_t flex_group; ++ struct flex_groups *fg; ++ + flex_group = ext4_flex_group(sbi, group_data[0].group); ++ fg = sbi_array_rcu_deref(sbi, s_flex_groups, flex_group); + atomic64_add(EXT4_NUM_B2C(sbi, free_blocks), +- &sbi->s_flex_groups[flex_group].free_clusters); ++ &fg->free_clusters); + atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count, +- &sbi->s_flex_groups[flex_group].free_inodes); ++ &fg->free_inodes); + } + + /* +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index e00bcc19099f..6b7e628b7903 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1015,6 +1015,7 @@ static void ext4_put_super(struct super_block *sb) + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_super_block *es = sbi->s_es; + struct buffer_head **group_desc; ++ struct flex_groups **flex_groups; + int aborted = 0; + int i, err; + +@@ -1052,8 +1053,13 @@ static void ext4_put_super(struct super_block *sb) + for (i = 0; i < sbi->s_gdb_count; i++) + brelse(group_desc[i]); + kvfree(group_desc); ++ flex_groups = rcu_dereference(sbi->s_flex_groups); ++ if (flex_groups) { ++ for (i = 0; i < sbi->s_flex_groups_allocated; i++) ++ kvfree(flex_groups[i]); ++ kvfree(flex_groups); ++ } + rcu_read_unlock(); +- kvfree(sbi->s_flex_groups); + percpu_counter_destroy(&sbi->s_freeclusters_counter); + percpu_counter_destroy(&sbi->s_freeinodes_counter); + percpu_counter_destroy(&sbi->s_dirs_counter); +@@ -2384,8 +2390,8 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es, + int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); +- struct flex_groups *new_groups; +- int size; ++ struct flex_groups **old_groups, **new_groups; ++ int size, i; + + if (!sbi->s_log_groups_per_flex) + return 0; +@@ -2394,22 +2400,37 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup) + if (size <= sbi->s_flex_groups_allocated) + return 0; + +- size = roundup_pow_of_two(size * sizeof(struct flex_groups)); +- new_groups = kvzalloc(size, GFP_KERNEL); ++ new_groups = kvzalloc(roundup_pow_of_two(size * ++ sizeof(*sbi->s_flex_groups)), GFP_KERNEL); + if (!new_groups) { +- ext4_msg(sb, KERN_ERR, "not enough memory for %d flex groups", +- size / (int) sizeof(struct flex_groups)); ++ ext4_msg(sb, KERN_ERR, ++ "not enough memory for %d flex group pointers", size); + return -ENOMEM; + } +- +- if (sbi->s_flex_groups) { +- memcpy(new_groups, sbi->s_flex_groups, +- (sbi->s_flex_groups_allocated * +- sizeof(struct flex_groups))); +- kvfree(sbi->s_flex_groups); ++ for (i = sbi->s_flex_groups_allocated; i < size; i++) { ++ new_groups[i] = kvzalloc(roundup_pow_of_two( ++ sizeof(struct flex_groups)), ++ GFP_KERNEL); ++ if (!new_groups[i]) { ++ for (i--; i >= sbi->s_flex_groups_allocated; i--) ++ kvfree(new_groups[i]); ++ kvfree(new_groups); ++ ext4_msg(sb, KERN_ERR, ++ "not enough memory for %d flex groups", size); ++ return -ENOMEM; ++ } + } +- sbi->s_flex_groups = new_groups; +- sbi->s_flex_groups_allocated = size / sizeof(struct flex_groups); ++ rcu_read_lock(); ++ old_groups = rcu_dereference(sbi->s_flex_groups); ++ if (old_groups) ++ memcpy(new_groups, old_groups, ++ (sbi->s_flex_groups_allocated * ++ sizeof(struct flex_groups *))); ++ rcu_read_unlock(); ++ rcu_assign_pointer(sbi->s_flex_groups, new_groups); ++ sbi->s_flex_groups_allocated = size; ++ if (old_groups) ++ ext4_kvfree_array_rcu(old_groups); + return 0; + } + +@@ -2417,6 +2438,7 @@ static int ext4_fill_flex_info(struct super_block *sb) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_group_desc *gdp = NULL; ++ struct flex_groups *fg; + ext4_group_t flex_group; + int i, err; + +@@ -2434,12 +2456,11 @@ static int ext4_fill_flex_info(struct super_block *sb) + gdp = ext4_get_group_desc(sb, i, NULL); + + flex_group = ext4_flex_group(sbi, i); +- atomic_add(ext4_free_inodes_count(sb, gdp), +- &sbi->s_flex_groups[flex_group].free_inodes); ++ fg = sbi_array_rcu_deref(sbi, s_flex_groups, flex_group); ++ atomic_add(ext4_free_inodes_count(sb, gdp), &fg->free_inodes); + atomic64_add(ext4_free_group_clusters(sb, gdp), +- &sbi->s_flex_groups[flex_group].free_clusters); +- atomic_add(ext4_used_dirs_count(sb, gdp), +- &sbi->s_flex_groups[flex_group].used_dirs); ++ &fg->free_clusters); ++ atomic_add(ext4_used_dirs_count(sb, gdp), &fg->used_dirs); + } + + return 1; +@@ -3641,6 +3662,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + struct buffer_head *bh, **group_desc; + struct ext4_super_block *es = NULL; + struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); ++ struct flex_groups **flex_groups; + ext4_fsblk_t block; + ext4_fsblk_t sb_block = get_sb_block(&data); + ext4_fsblk_t logical_sb_block; +@@ -4692,8 +4714,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) + ext4_unregister_li_request(sb); + failed_mount6: + ext4_mb_release(sb); +- if (sbi->s_flex_groups) +- kvfree(sbi->s_flex_groups); ++ rcu_read_lock(); ++ flex_groups = rcu_dereference(sbi->s_flex_groups); ++ if (flex_groups) { ++ for (i = 0; i < sbi->s_flex_groups_allocated; i++) ++ kvfree(flex_groups[i]); ++ kvfree(flex_groups); ++ } ++ rcu_read_unlock(); + percpu_counter_destroy(&sbi->s_freeclusters_counter); + percpu_counter_destroy(&sbi->s_freeinodes_counter); + percpu_counter_destroy(&sbi->s_dirs_counter); +-- +2.16.4 + diff --git a/patches.suse/ext4-fix-potential-race-between-s_group_info-online-.patch b/patches.suse/ext4-fix-potential-race-between-s_group_info-online-.patch new file mode 100644 index 0000000..6c31926 --- /dev/null +++ b/patches.suse/ext4-fix-potential-race-between-s_group_info-online-.patch @@ -0,0 +1,187 @@ +From df3da4ea5a0fc5d115c90d5aa6caa4dd433750a7 Mon Sep 17 00:00:00 2001 +From: Suraj Jitindar Singh +Date: Tue, 18 Feb 2020 19:08:50 -0800 +Subject: [PATCH] ext4: fix potential race between s_group_info online resizing + and access +Git-commit: df3da4ea5a0fc5d115c90d5aa6caa4dd433750a7 +Patch-mainline: v5.6-rc3 +References: bsc#1166866 + +During an online resize an array of pointers to s_group_info gets replaced +so it can get enlarged. If there is a concurrent access to the array in +ext4_get_group_info() and this memory has been reused then this can lead to +an invalid memory access. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=206443 +Link: https://lore.kernel.org/r/20200221053458.730016-3-tytso@mit.edu +Signed-off-by: Suraj Jitindar Singh +Signed-off-by: Theodore Ts'o +Reviewed-by: Balbir Singh +Cc: stable@kernel.org +Acked-by: Jan Kara + +--- + fs/ext4/ext4.h | 8 ++++---- + fs/ext4/mballoc.c | 52 +++++++++++++++++++++++++++++++++++----------------- + 2 files changed, 39 insertions(+), 21 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index b51003f75568..b1ece5329738 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1462,7 +1462,7 @@ struct ext4_sb_info { + #endif + + /* for buddy allocator */ +- struct ext4_group_info ***s_group_info; ++ struct ext4_group_info ** __rcu *s_group_info; + struct inode *s_buddy_cache; + spinlock_t s_md_lock; + unsigned short *s_mb_offsets; +@@ -2994,13 +2994,13 @@ static inline + struct ext4_group_info *ext4_get_group_info(struct super_block *sb, + ext4_group_t group) + { +- struct ext4_group_info ***grp_info; ++ struct ext4_group_info **grp_info; + long indexv, indexh; + BUG_ON(group >= EXT4_SB(sb)->s_groups_count); +- grp_info = EXT4_SB(sb)->s_group_info; + indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb)); + indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1); +- return grp_info[indexv][indexh]; ++ grp_info = sbi_array_rcu_deref(EXT4_SB(sb), s_group_info, indexv); ++ return grp_info[indexh]; + } + + /* +diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c +index f64838187559..1b46fb63692a 100644 +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -2356,7 +2356,7 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); + unsigned size; +- struct ext4_group_info ***new_groupinfo; ++ struct ext4_group_info ***old_groupinfo, ***new_groupinfo; + + size = (ngroups + EXT4_DESC_PER_BLOCK(sb) - 1) >> + EXT4_DESC_PER_BLOCK_BITS(sb); +@@ -2369,13 +2369,16 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups) + ext4_msg(sb, KERN_ERR, "can't allocate buddy meta group"); + return -ENOMEM; + } +- if (sbi->s_group_info) { +- memcpy(new_groupinfo, sbi->s_group_info, ++ rcu_read_lock(); ++ old_groupinfo = rcu_dereference(sbi->s_group_info); ++ if (old_groupinfo) ++ memcpy(new_groupinfo, old_groupinfo, + sbi->s_group_info_size * sizeof(*sbi->s_group_info)); +- kvfree(sbi->s_group_info); +- } +- sbi->s_group_info = new_groupinfo; ++ rcu_read_unlock(); ++ rcu_assign_pointer(sbi->s_group_info, new_groupinfo); + sbi->s_group_info_size = size / sizeof(*sbi->s_group_info); ++ if (old_groupinfo) ++ ext4_kvfree_array_rcu(old_groupinfo); + ext4_debug("allocated s_groupinfo array for %d meta_bg's\n", + sbi->s_group_info_size); + return 0; +@@ -2387,6 +2390,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group, + { + int i; + int metalen = 0; ++ int idx = group >> EXT4_DESC_PER_BLOCK_BITS(sb); + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_group_info **meta_group_info; + struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits); +@@ -2405,12 +2409,12 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group, + "for a buddy group"); + goto exit_meta_group_info; + } +- sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] = +- meta_group_info; ++ rcu_read_lock(); ++ rcu_dereference(sbi->s_group_info)[idx] = meta_group_info; ++ rcu_read_unlock(); + } + +- meta_group_info = +- sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)]; ++ meta_group_info = sbi_array_rcu_deref(sbi, s_group_info, idx); + i = group & (EXT4_DESC_PER_BLOCK(sb) - 1); + + meta_group_info[i] = kmem_cache_zalloc(cachep, GFP_NOFS); +@@ -2458,8 +2462,13 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group, + exit_group_info: + /* If a meta_group_info table has been allocated, release it now */ + if (group % EXT4_DESC_PER_BLOCK(sb) == 0) { +- kfree(sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)]); +- sbi->s_group_info[group >> EXT4_DESC_PER_BLOCK_BITS(sb)] = NULL; ++ struct ext4_group_info ***group_info; ++ ++ rcu_read_lock(); ++ group_info = rcu_dereference(sbi->s_group_info); ++ kfree(group_info[idx]); ++ group_info[idx] = NULL; ++ rcu_read_unlock(); + } + exit_meta_group_info: + return -ENOMEM; +@@ -2472,6 +2481,7 @@ static int ext4_mb_init_backend(struct super_block *sb) + struct ext4_sb_info *sbi = EXT4_SB(sb); + int err; + struct ext4_group_desc *desc; ++ struct ext4_group_info ***group_info; + struct kmem_cache *cachep; + + err = ext4_mb_alloc_groupinfo(sb, ngroups); +@@ -2507,11 +2517,16 @@ static int ext4_mb_init_backend(struct super_block *sb) + while (i-- > 0) + kmem_cache_free(cachep, ext4_get_group_info(sb, i)); + i = sbi->s_group_info_size; ++ rcu_read_lock(); ++ group_info = rcu_dereference(sbi->s_group_info); + while (i-- > 0) +- kfree(sbi->s_group_info[i]); ++ kfree(group_info[i]); ++ rcu_read_unlock(); + iput(sbi->s_buddy_cache); + err_freesgi: +- kvfree(sbi->s_group_info); ++ rcu_read_lock(); ++ kvfree(rcu_dereference(sbi->s_group_info)); ++ rcu_read_unlock(); + return -ENOMEM; + } + +@@ -2700,7 +2715,7 @@ int ext4_mb_release(struct super_block *sb) + ext4_group_t ngroups = ext4_get_groups_count(sb); + ext4_group_t i; + int num_meta_group_infos; +- struct ext4_group_info *grinfo; ++ struct ext4_group_info *grinfo, ***group_info; + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits); + +@@ -2719,9 +2734,12 @@ int ext4_mb_release(struct super_block *sb) + num_meta_group_infos = (ngroups + + EXT4_DESC_PER_BLOCK(sb) - 1) >> + EXT4_DESC_PER_BLOCK_BITS(sb); ++ rcu_read_lock(); ++ group_info = rcu_dereference(sbi->s_group_info); + for (i = 0; i < num_meta_group_infos; i++) +- kfree(sbi->s_group_info[i]); +- kvfree(sbi->s_group_info); ++ kfree(group_info[i]); ++ kvfree(group_info); ++ rcu_read_unlock(); + } + kfree(sbi->s_mb_offsets); + kfree(sbi->s_mb_maxs); +-- +2.16.4 + diff --git a/patches.suse/ext4-fix-race-between-writepages-and-enabling-EXT4_E.patch b/patches.suse/ext4-fix-race-between-writepages-and-enabling-EXT4_E.patch new file mode 100644 index 0000000..ea18c6e --- /dev/null +++ b/patches.suse/ext4-fix-race-between-writepages-and-enabling-EXT4_E.patch @@ -0,0 +1,167 @@ +From cb85f4d23f794e24127f3e562cb3b54b0803f456 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 19 Feb 2020 10:30:47 -0800 +Subject: [PATCH] ext4: fix race between writepages and enabling + EXT4_EXTENTS_FL +Git-commit: cb85f4d23f794e24127f3e562cb3b54b0803f456 +Patch-mainline: v5.6-rc3 +References: bsc#1166870 + +If EXT4_EXTENTS_FL is set on an inode while ext4_writepages() is running +on it, the following warning in ext4_add_complete_io() can be hit: + +Warning: CPU: 1 PID: 0 at fs/ext4/page-io.c:234 ext4_put_io_end_defer+0xf0/0x120 + +Here's a minimal reproducer (not 100% reliable) (root isn't required): + + while true; do + sync + done & + while true; do + rm -f file + touch file + chattr -e file + echo X >> file + chattr +e file + done + +The problem is that in ext4_writepages(), ext4_should_dioread_nolock() +(which only returns true on extent-based files) is checked once to set +the number of reserved journal credits, and also again later to select +the flags for ext4_map_blocks() and copy the reserved journal handle to +ext4_io_end::handle. But if EXT4_EXTENTS_FL is being concurrently set, +the first check can see dioread_nolock disabled while the later one can +see it enabled, causing the reserved handle to unexpectedly be NULL. + +Since changing EXT4_EXTENTS_FL is uncommon, and there may be other races +related to doing so as well, fix this by synchronizing changing +EXT4_EXTENTS_FL with ext4_writepages() via the existing +s_writepages_rwsem (previously called s_journal_flag_rwsem). + +This was originally reported by syzbot without a reproducer at +https://syzkaller.appspot.com/bug?extid=2202a584a00fffd19fbf, +but now that dioread_nolock is the default I also started seeing this +when running syzkaller locally. + +Link: https://lore.kernel.org/r/20200219183047.47417-3-ebiggers@kernel.org +Reported-by: syzbot+2202a584a00fffd19fbf@syzkaller.appspotmail.com +Fixes: 6b523df4fb5a ("ext4: use transaction reservation for extent conversion in ext4_end_io") +Signed-off-by: Eric Biggers +Signed-off-by: Theodore Ts'o +Reviewed-by: Jan Kara +Cc: stable@kernel.org +Acked-by: Jan Kara + +--- + fs/ext4/ext4.h | 5 ++++- + fs/ext4/migrate.c | 27 +++++++++++++++++++-------- + 2 files changed, 23 insertions(+), 9 deletions(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1532,7 +1532,10 @@ struct ext4_sb_info { + struct ratelimit_state s_warning_ratelimit_state; + struct ratelimit_state s_msg_ratelimit_state; + +- /* Barrier between changing inodes' journal flags and writepages ops. */ ++ /* ++ * Barrier between writepages ops and changing any inode's JOURNAL_DATA ++ * or EXTENTS flag. ++ */ + struct percpu_rw_semaphore s_writepages_rwsem; + struct dax_device *s_daxdev; + }; +--- a/fs/ext4/migrate.c ++++ b/fs/ext4/migrate.c +@@ -427,6 +427,7 @@ static int free_ext_block(handle_t *hand + + int ext4_ext_migrate(struct inode *inode) + { ++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + handle_t *handle; + int retval = 0, i; + __le32 *i_data; +@@ -451,6 +452,8 @@ int ext4_ext_migrate(struct inode *inode + */ + return retval; + ++ percpu_down_write(&sbi->s_writepages_rwsem); ++ + /* + * Worst case we can touch the allocation bitmaps, a bgd + * block, and a block to link in the orphan list. We do need +@@ -461,7 +464,7 @@ int ext4_ext_migrate(struct inode *inode + + if (IS_ERR(handle)) { + retval = PTR_ERR(handle); +- return retval; ++ goto out_unlock; + } + goal = (((inode->i_ino - 1) / EXT4_INODES_PER_GROUP(inode->i_sb)) * + EXT4_INODES_PER_GROUP(inode->i_sb)) + 1; +@@ -472,7 +475,7 @@ int ext4_ext_migrate(struct inode *inode + if (IS_ERR(tmp_inode)) { + retval = PTR_ERR(tmp_inode); + ext4_journal_stop(handle); +- return retval; ++ goto out_unlock; + } + i_size_write(tmp_inode, i_size_read(inode)); + /* +@@ -514,7 +517,7 @@ int ext4_ext_migrate(struct inode *inode + */ + ext4_orphan_del(NULL, tmp_inode); + retval = PTR_ERR(handle); +- goto out; ++ goto out_tmp_inode; + } + + ei = EXT4_I(inode); +@@ -595,10 +598,11 @@ err_out: + /* Reset the extent details */ + ext4_ext_tree_init(handle, tmp_inode); + ext4_journal_stop(handle); +-out: ++out_tmp_inode: + unlock_new_inode(tmp_inode); + iput(tmp_inode); +- ++out_unlock: ++ percpu_up_write(&sbi->s_writepages_rwsem); + return retval; + } + +@@ -608,7 +612,8 @@ out: + int ext4_ind_migrate(struct inode *inode) + { + struct ext4_extent_header *eh; +- struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; ++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); ++ struct ext4_super_block *es = sbi->s_es; + struct ext4_inode_info *ei = EXT4_I(inode); + struct ext4_extent *ex; + unsigned int i, len; +@@ -632,9 +637,13 @@ int ext4_ind_migrate(struct inode *inode + if (test_opt(inode->i_sb, DELALLOC)) + ext4_alloc_da_blocks(inode); + ++ percpu_down_write(&sbi->s_writepages_rwsem); ++ + handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1); +- if (IS_ERR(handle)) +- return PTR_ERR(handle); ++ if (IS_ERR(handle)) { ++ ret = PTR_ERR(handle); ++ goto out_unlock; ++ } + + down_write(&EXT4_I(inode)->i_data_sem); + ret = ext4_ext_check_inode(inode); +@@ -669,5 +678,7 @@ int ext4_ind_migrate(struct inode *inode + errout: + ext4_journal_stop(handle); + up_write(&EXT4_I(inode)->i_data_sem); ++out_unlock: ++ percpu_up_write(&sbi->s_writepages_rwsem); + return ret; + } diff --git a/patches.suse/ext4-potential-crash-on-allocation-error-in-ext4_all.patch b/patches.suse/ext4-potential-crash-on-allocation-error-in-ext4_all.patch new file mode 100644 index 0000000..70203b2 --- /dev/null +++ b/patches.suse/ext4-potential-crash-on-allocation-error-in-ext4_all.patch @@ -0,0 +1,55 @@ +From 37b0b6b8b99c0e1c1f11abbe7cf49b6d03795b3f Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 28 Feb 2020 12:22:56 +0300 +Subject: [PATCH] ext4: potential crash on allocation error in + ext4_alloc_flex_bg_array() +Git-commit: 37b0b6b8b99c0e1c1f11abbe7cf49b6d03795b3f +Patch-mainline: v5.6-rc4 +References: bsc#1166940 + +If sbi->s_flex_groups_allocated is zero and the first allocation fails +then this code will crash. The problem is that "i--" will set "i" to +-1 but when we compare "i >= sbi->s_flex_groups_allocated" then the -1 +is type promoted to unsigned and becomes UINT_MAX. Since UINT_MAX +is more than zero, the condition is true so we call kvfree(new_groups[-1]). +The loop will carry on freeing invalid memory until it crashes. + +Fixes: 7c990728b99e ("ext4: fix potential race between s_flex_groups online resizing and access") +Reviewed-by: Suraj Jitindar Singh +Signed-off-by: Dan Carpenter +Cc: stable@kernel.org +Link: https://lore.kernel.org/r/20200228092142.7irbc44yaz3by7nb@kili.mountain +Signed-off-by: Theodore Ts'o +Acked-by: Jan Kara + +--- + fs/ext4/super.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index ff1b764b0c0e..0c7c4adb664e 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2391,7 +2391,7 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup) + { + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct flex_groups **old_groups, **new_groups; +- int size, i; ++ int size, i, j; + + if (!sbi->s_log_groups_per_flex) + return 0; +@@ -2412,8 +2412,8 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup) + sizeof(struct flex_groups)), + GFP_KERNEL); + if (!new_groups[i]) { +- for (i--; i >= sbi->s_flex_groups_allocated; i--) +- kvfree(new_groups[i]); ++ for (j = sbi->s_flex_groups_allocated; j < i; j++) ++ kvfree(new_groups[j]); + kvfree(new_groups); + ext4_msg(sb, KERN_ERR, + "not enough memory for %d flex groups", size); +-- +2.16.4 + diff --git a/patches.suse/ext4-rename-s_journal_flag_rwsem-to-s_writepages_rws.patch b/patches.suse/ext4-rename-s_journal_flag_rwsem-to-s_writepages_rws.patch new file mode 100644 index 0000000..78c537a --- /dev/null +++ b/patches.suse/ext4-rename-s_journal_flag_rwsem-to-s_writepages_rws.patch @@ -0,0 +1,129 @@ +From bbd55937de8f2754adc5792b0f8e5ff7d9c0420e Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 19 Feb 2020 10:30:46 -0800 +Subject: [PATCH] ext4: rename s_journal_flag_rwsem to s_writepages_rwsem +Git-commit: bbd55937de8f2754adc5792b0f8e5ff7d9c0420e +Patch-mainline: v5.6-rc3 +References: bsc#1166868 + +In preparation for making s_journal_flag_rwsem synchronize +ext4_writepages() with changes to both the EXTENTS and JOURNAL_DATA +flags (rather than just JOURNAL_DATA as it does currently), rename it to +s_writepages_rwsem. + +Link: https://lore.kernel.org/r/20200219183047.47417-2-ebiggers@kernel.org +Signed-off-by: Eric Biggers +Signed-off-by: Theodore Ts'o +Reviewed-by: Jan Kara +Cc: stable@kernel.org +Acked-by: Jan Kara + +--- + fs/ext4/ext4.h | 2 +- + fs/ext4/inode.c | 14 +++++++------- + fs/ext4/super.c | 6 +++--- + 3 files changed, 11 insertions(+), 11 deletions(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1533,7 +1533,7 @@ struct ext4_sb_info { + struct ratelimit_state s_msg_ratelimit_state; + + /* Barrier between changing inodes' journal flags and writepages ops. */ +- struct percpu_rw_semaphore s_journal_flag_rwsem; ++ struct percpu_rw_semaphore s_writepages_rwsem; + struct dax_device *s_daxdev; + }; + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -2762,7 +2762,7 @@ static int ext4_writepages(struct addres + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) + return -EIO; + +- percpu_down_read(&sbi->s_journal_flag_rwsem); ++ percpu_down_read(&sbi->s_writepages_rwsem); + trace_ext4_writepages(inode, wbc); + + /* +@@ -2983,7 +2983,7 @@ unplug: + out_writepages: + trace_ext4_writepages_result(inode, wbc, ret, + nr_to_write - wbc->nr_to_write); +- percpu_up_read(&sbi->s_journal_flag_rwsem); ++ percpu_up_read(&sbi->s_writepages_rwsem); + return ret; + } + +@@ -2998,13 +2998,13 @@ static int ext4_dax_writepages(struct ad + if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) + return -EIO; + +- percpu_down_read(&sbi->s_journal_flag_rwsem); ++ percpu_down_read(&sbi->s_writepages_rwsem); + trace_ext4_writepages(inode, wbc); + + ret = dax_writeback_mapping_range(mapping, inode->i_sb->s_bdev, wbc); + trace_ext4_writepages_result(inode, wbc, ret, + nr_to_write - wbc->nr_to_write); +- percpu_up_read(&sbi->s_journal_flag_rwsem); ++ percpu_up_read(&sbi->s_writepages_rwsem); + return ret; + } + +@@ -6212,7 +6212,7 @@ int ext4_change_inode_journal_flag(struc + } + } + +- percpu_down_write(&sbi->s_journal_flag_rwsem); ++ percpu_down_write(&sbi->s_writepages_rwsem); + jbd2_journal_lock_updates(journal); + + /* +@@ -6229,7 +6229,7 @@ int ext4_change_inode_journal_flag(struc + err = jbd2_journal_flush(journal); + if (err < 0) { + jbd2_journal_unlock_updates(journal); +- percpu_up_write(&sbi->s_journal_flag_rwsem); ++ percpu_up_write(&sbi->s_writepages_rwsem); + return err; + } + ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA); +@@ -6237,7 +6237,7 @@ int ext4_change_inode_journal_flag(struc + ext4_set_aops(inode); + + jbd2_journal_unlock_updates(journal); +- percpu_up_write(&sbi->s_journal_flag_rwsem); ++ percpu_up_write(&sbi->s_writepages_rwsem); + + if (val) + up_write(&EXT4_I(inode)->i_mmap_sem); +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1018,7 +1018,7 @@ static void ext4_put_super(struct super_ + percpu_counter_destroy(&sbi->s_freeinodes_counter); + percpu_counter_destroy(&sbi->s_dirs_counter); + percpu_counter_destroy(&sbi->s_dirtyclusters_counter); +- percpu_free_rwsem(&sbi->s_journal_flag_rwsem); ++ percpu_free_rwsem(&sbi->s_writepages_rwsem); + #ifdef CONFIG_QUOTA + for (i = 0; i < EXT4_MAXQUOTAS; i++) + kfree(get_qf_name(sb, sbi, i)); +@@ -4553,7 +4553,7 @@ no_journal: + err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0, + GFP_KERNEL); + if (!err) +- err = percpu_init_rwsem(&sbi->s_journal_flag_rwsem); ++ err = percpu_init_rwsem(&sbi->s_writepages_rwsem); + + if (err) { + ext4_msg(sb, KERN_ERR, "insufficient memory"); +@@ -4653,7 +4653,7 @@ failed_mount6: + percpu_counter_destroy(&sbi->s_freeinodes_counter); + percpu_counter_destroy(&sbi->s_dirs_counter); + percpu_counter_destroy(&sbi->s_dirtyclusters_counter); +- percpu_free_rwsem(&sbi->s_journal_flag_rwsem); ++ percpu_free_rwsem(&sbi->s_writepages_rwsem); + failed_mount5: + ext4_ext_release(sb); + ext4_release_system_zone(sb); diff --git a/patches.suse/io_uring-fix-__io_iopoll_check-deadlock-in-io_sq_thr.patch b/patches.suse/io_uring-fix-__io_iopoll_check-deadlock-in-io_sq_thr.patch new file mode 100644 index 0000000..5af6d08 --- /dev/null +++ b/patches.suse/io_uring-fix-__io_iopoll_check-deadlock-in-io_sq_thr.patch @@ -0,0 +1,87 @@ +From c7849be9cc2dd2754c48ddbaca27c2de6d80a95d Mon Sep 17 00:00:00 2001 +From: Xiaoguang Wang +Date: Sat, 22 Feb 2020 14:46:05 +0800 +Subject: [PATCH] io_uring: fix __io_iopoll_check deadlock in io_sq_thread +Git-commit: c7849be9cc2dd2754c48ddbaca27c2de6d80a95d +Patch-mainline: v5.6-rc3 +References: bsc#1166876 + +Since commit a3a0e43fd770 ("io_uring: don't enter poll loop if we have +CQEs pending"), if we already events pending, we won't enter poll loop. +In case SETUP_IOPOLL and SETUP_SQPOLL are both enabled, if app has +been terminated and don't reap pending events which are already in cq +ring, and there are some reqs in poll_list, io_sq_thread will enter +__io_iopoll_check(), and find pending events, then return, this loop +will never have a chance to exit. + +I have seen this issue in fio stress tests, to fix this issue, let +io_sq_thread call io_iopoll_getevents() with argument 'min' being zero, +and remove __io_iopoll_check(). + +Fixes: a3a0e43fd770 ("io_uring: don't enter poll loop if we have CQEs pending") +Signed-off-by: Xiaoguang Wang +Signed-off-by: Jens Axboe +Acked-by: Jan Kara + +--- + fs/io_uring.c | 27 +++++++++------------------ + 1 file changed, 9 insertions(+), 18 deletions(-) + +diff --git a/fs/io_uring.c b/fs/io_uring.c +index b43467b3a8dc..de650df9ac53 100644 +--- a/fs/io_uring.c ++++ b/fs/io_uring.c +@@ -1672,11 +1672,17 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx) + mutex_unlock(&ctx->uring_lock); + } + +-static int __io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events, +- long min) ++static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events, ++ long min) + { + int iters = 0, ret = 0; + ++ /* ++ * We disallow the app entering submit/complete with polling, but we ++ * still need to lock the ring to prevent racing with polled issue ++ * that got punted to a workqueue. ++ */ ++ mutex_lock(&ctx->uring_lock); + do { + int tmin = 0; + +@@ -1712,21 +1718,6 @@ static int __io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events, + ret = 0; + } while (min && !*nr_events && !need_resched()); + +- return ret; +-} +- +-static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events, +- long min) +-{ +- int ret; +- +- /* +- * We disallow the app entering submit/complete with polling, but we +- * still need to lock the ring to prevent racing with polled issue +- * that got punted to a workqueue. +- */ +- mutex_lock(&ctx->uring_lock); +- ret = __io_iopoll_check(ctx, nr_events, min); + mutex_unlock(&ctx->uring_lock); + return ret; + } +@@ -5118,7 +5109,7 @@ static int io_sq_thread(void *data) + */ + mutex_lock(&ctx->uring_lock); + if (!list_empty(&ctx->poll_list)) +- __io_iopoll_check(ctx, &nr_events, 0); ++ io_iopoll_getevents(ctx, &nr_events, 0); + else + inflight = 0; + mutex_unlock(&ctx->uring_lock); +-- +2.16.4 + diff --git a/patches.suse/io_uring-prevent-sq_thread-from-spinning-when-it-sho.patch b/patches.suse/io_uring-prevent-sq_thread-from-spinning-when-it-sho.patch new file mode 100644 index 0000000..d8efb54 --- /dev/null +++ b/patches.suse/io_uring-prevent-sq_thread-from-spinning-when-it-sho.patch @@ -0,0 +1,63 @@ +From 7143b5ac5750f404ff3a594b34fdf3fc2f99f828 Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Fri, 21 Feb 2020 16:42:16 +0100 +Subject: [PATCH] io_uring: prevent sq_thread from spinning when it should stop +Git-commit: 7143b5ac5750f404ff3a594b34fdf3fc2f99f828 +Patch-mainline: v5.6-rc3 +References: bsc#1166875 + +This patch drops 'cur_mm' before calling cond_resched(), to prevent +the sq_thread from spinning even when the user process is finished. + +Before this patch, if the user process ended without closing the +io_uring fd, the sq_thread continues to spin until the +'sq_thread_idle' timeout ends. + +In the worst case where the 'sq_thread_idle' parameter is bigger than +INT_MAX, the sq_thread will spin forever. + +Fixes: 6c271ce2f1d5 ("io_uring: add submission polling") +Signed-off-by: Stefano Garzarella +Signed-off-by: Jens Axboe +Acked-by: Jan Kara + +--- + fs/io_uring.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +--- a/fs/io_uring.c ++++ b/fs/io_uring.c +@@ -2420,16 +2420,6 @@ static int io_sq_thread(void *data) + to_submit = io_sqring_entries(ctx); + if (!to_submit) { + /* +- * We're polling. If we're within the defined idle +- * period, then let us spin without work before going +- * to sleep. +- */ +- if (inflight || !time_after(jiffies, timeout)) { +- cpu_relax(); +- continue; +- } +- +- /* + * Drop cur_mm before scheduling, we can't hold it for + * long periods (or over schedule()). Do this before + * adding ourselves to the waitqueue, as the unuse/drop +@@ -2441,6 +2431,16 @@ static int io_sq_thread(void *data) + cur_mm = NULL; + } + ++ /* ++ * We're polling. If we're within the defined idle ++ * period, then let us spin without work before going ++ * to sleep. ++ */ ++ if (inflight || !time_after(jiffies, timeout)) { ++ cpu_relax(); ++ continue; ++ } ++ + prepare_to_wait(&ctx->sqo_wait, &wait, + TASK_INTERRUPTIBLE); + diff --git a/patches.suse/jbd2-fix-ocfs2-corrupt-when-clearing-block-group-bit.patch b/patches.suse/jbd2-fix-ocfs2-corrupt-when-clearing-block-group-bit.patch new file mode 100644 index 0000000..5ba2d60 --- /dev/null +++ b/patches.suse/jbd2-fix-ocfs2-corrupt-when-clearing-block-group-bit.patch @@ -0,0 +1,184 @@ +From 8eedabfd66b68a4623beec0789eac54b8c9d0fb6 Mon Sep 17 00:00:00 2001 +From: wangyan +Date: Thu, 20 Feb 2020 21:46:14 +0800 +Subject: [PATCH] jbd2: fix ocfs2 corrupt when clearing block group bits +Git-commit: 8eedabfd66b68a4623beec0789eac54b8c9d0fb6 +Patch-mainline: v5.6-rc3 +References: bsc#1166878 + +I found a NULL pointer dereference in ocfs2_block_group_clear_bits(). +The running environment: + kernel version: 4.19 + A cluster with two nodes, 5 luns mounted on two nodes, and do some + file operations like dd/fallocate/truncate/rm on every lun with storage + network disconnection. + +The fallocate operation on dm-23-45 caused an null pointer dereference. + +The information of NULL pointer dereference as follows: + [577992.878282] JBD2: Error -5 detected when updating journal superblock for dm-23-45. + [577992.878290] Aborting journal on device dm-23-45. + ... + [577992.890778] JBD2: Error -5 detected when updating journal superblock for dm-24-46. + [577992.890908] __journal_remove_journal_head: freeing b_committed_data + [577992.890916] (fallocate,88392,52):ocfs2_extend_trans:474 ERROR: status = -30 + [577992.890918] __journal_remove_journal_head: freeing b_committed_data + [577992.890920] (fallocate,88392,52):ocfs2_rotate_tree_right:2500 ERROR: status = -30 + [577992.890922] __journal_remove_journal_head: freeing b_committed_data + [577992.890924] (fallocate,88392,52):ocfs2_do_insert_extent:4382 ERROR: status = -30 + [577992.890928] (fallocate,88392,52):ocfs2_insert_extent:4842 ERROR: status = -30 + [577992.890928] __journal_remove_journal_head: freeing b_committed_data + [577992.890930] (fallocate,88392,52):ocfs2_add_clusters_in_btree:4947 ERROR: status = -30 + [577992.890933] __journal_remove_journal_head: freeing b_committed_data + [577992.890939] __journal_remove_journal_head: freeing b_committed_data + [577992.890949] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020 + [577992.890950] Mem abort info: + [577992.890951] ESR = 0x96000004 + [577992.890952] Exception class = DABT (current EL), IL = 32 bits + [577992.890952] SET = 0, FnV = 0 + [577992.890953] EA = 0, S1PTW = 0 + [577992.890954] Data abort info: + [577992.890955] ISV = 0, ISS = 0x00000004 + [577992.890956] CM = 0, WnR = 0 + [577992.890958] user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000f8da07a9 + [577992.890960] [0000000000000020] pgd=0000000000000000 + [577992.890964] Internal error: Oops: 96000004 [#1] SMP + [577992.890965] Process fallocate (pid: 88392, stack limit = 0x00000000013db2fd) + [577992.890968] CPU: 52 PID: 88392 Comm: fallocate Kdump: loaded Tainted: G W OE 4.19.36 #1 + [577992.890969] Hardware name: Huawei TaiShan 2280 V2/BC82AMDD, BIOS 0.98 08/25/2019 + [577992.890971] pstate: 60400009 (nZCv daif +PAN -UAO) + [577992.891054] pc : _ocfs2_free_suballoc_bits+0x63c/0x968 [ocfs2] + [577992.891082] lr : _ocfs2_free_suballoc_bits+0x618/0x968 [ocfs2] + [577992.891084] sp : ffff0000c8e2b810 + [577992.891085] x29: ffff0000c8e2b820 x28: 0000000000000000 + [577992.891087] x27: 00000000000006f3 x26: ffffa07957b02e70 + [577992.891089] x25: ffff807c59d50000 x24: 00000000000006f2 + [577992.891091] x23: 0000000000000001 x22: ffff807bd39abc30 + [577992.891093] x21: ffff0000811d9000 x20: ffffa07535d6a000 + [577992.891097] x19: ffff000001681638 x18: ffffffffffffffff + [577992.891098] x17: 0000000000000000 x16: ffff000080a03df0 + [577992.891100] x15: ffff0000811d9708 x14: 203d207375746174 + [577992.891101] x13: 73203a524f525245 x12: 20373439343a6565 + [577992.891103] x11: 0000000000000038 x10: 0101010101010101 + [577992.891106] x9 : ffffa07c68a85d70 x8 : 7f7f7f7f7f7f7f7f + [577992.891109] x7 : 0000000000000000 x6 : 0000000000000080 + [577992.891110] x5 : 0000000000000000 x4 : 0000000000000002 + [577992.891112] x3 : ffff000001713390 x2 : 2ff90f88b1c22f00 + [577992.891114] x1 : ffff807bd39abc30 x0 : 0000000000000000 + [577992.891116] Call trace: + [577992.891139] _ocfs2_free_suballoc_bits+0x63c/0x968 [ocfs2] + [577992.891162] _ocfs2_free_clusters+0x100/0x290 [ocfs2] + [577992.891185] ocfs2_free_clusters+0x50/0x68 [ocfs2] + [577992.891206] ocfs2_add_clusters_in_btree+0x198/0x5e0 [ocfs2] + [577992.891227] ocfs2_add_inode_data+0x94/0xc8 [ocfs2] + [577992.891248] ocfs2_extend_allocation+0x1bc/0x7a8 [ocfs2] + [577992.891269] ocfs2_allocate_extents+0x14c/0x338 [ocfs2] + [577992.891290] __ocfs2_change_file_space+0x3f8/0x610 [ocfs2] + [577992.891309] ocfs2_fallocate+0xe4/0x128 [ocfs2] + [577992.891316] vfs_fallocate+0x11c/0x250 + [577992.891317] ksys_fallocate+0x54/0x88 + [577992.891319] __arm64_sys_fallocate+0x28/0x38 + [577992.891323] el0_svc_common+0x78/0x130 + [577992.891325] el0_svc_handler+0x38/0x78 + [577992.891327] el0_svc+0x8/0xc + +My analysis process as follows: +ocfs2_fallocate + __ocfs2_change_file_space + ocfs2_allocate_extents + ocfs2_extend_allocation + ocfs2_add_inode_data + ocfs2_add_clusters_in_btree + ocfs2_insert_extent + ocfs2_do_insert_extent + ocfs2_rotate_tree_right + ocfs2_extend_rotate_transaction + ocfs2_extend_trans + jbd2_journal_restart + jbd2__journal_restart + /* handle->h_transaction is NULL, + * is_handle_aborted(handle) is true + */ + handle->h_transaction = NULL; + start_this_handle + return -EROFS; + ocfs2_free_clusters + _ocfs2_free_clusters + _ocfs2_free_suballoc_bits + ocfs2_block_group_clear_bits + ocfs2_journal_access_gd + __ocfs2_journal_access + jbd2_journal_get_undo_access + /* I think jbd2_write_access_granted() will + * return true, because do_get_write_access() + * will return -EROFS. + */ + if (jbd2_write_access_granted(...)) return 0; + do_get_write_access + /* handle->h_transaction is NULL, it will + * return -EROFS here, so do_get_write_access() + * was not called. + */ + if (is_handle_aborted(handle)) return -EROFS; + /* bh2jh(group_bh) is NULL, caused NULL + pointer dereference */ + undo_bg = (struct ocfs2_group_desc *) + bh2jh(group_bh)->b_committed_data; + +If handle->h_transaction == NULL, then jbd2_write_access_granted() +does not really guarantee that journal_head will stay around, +not even speaking of its b_committed_data. The bh2jh(group_bh) +can be removed after ocfs2_journal_access_gd() and before call +"bh2jh(group_bh)->b_committed_data". So, we should move +is_handle_aborted() check from do_get_write_access() into +jbd2_journal_get_undo_access() and jbd2_journal_get_write_access() +before the call to jbd2_write_access_granted(). + +Link: https://lore.kernel.org/r/f72a623f-b3f1-381a-d91d-d22a1c83a336@huawei.com +Signed-off-by: Yan Wang +Signed-off-by: Theodore Ts'o +Reviewed-by: Jun Piao +Reviewed-by: Jan Kara +Cc: stable@kernel.org +Acked-by: Jan Kara + +--- + fs/jbd2/transaction.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index 2dd848a743ed..d181948c0390 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -936,8 +936,6 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, + char *frozen_buffer = NULL; + unsigned long start_lock, time_lock; + +- if (is_handle_aborted(handle)) +- return -EROFS; + journal = transaction->t_journal; + + jbd_debug(5, "journal_head %p, force_copy %d\n", jh, force_copy); +@@ -1189,6 +1187,9 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh) + struct journal_head *jh; + int rc; + ++ if (is_handle_aborted(handle)) ++ return -EROFS; ++ + if (jbd2_write_access_granted(handle, bh, false)) + return 0; + +@@ -1326,6 +1327,9 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh) + struct journal_head *jh; + char *committed_data = NULL; + ++ if (is_handle_aborted(handle)) ++ return -EROFS; ++ + if (jbd2_write_access_granted(handle, bh, true)) + return 0; + +-- +2.16.4 + diff --git a/series.conf b/series.conf index f7a78d6..dade072 100644 --- a/series.conf +++ b/series.conf @@ -9543,6 +9543,7 @@ patches.suse/0024-bcache-fix-incorrect-data-type-usage-in-btree_flush_.patch patches.suse/0025-bcache-check-return-value-of-prio_read.patch patches.suse/block-bfq-do-not-plug-I-O-for-bfq_queues-with-no-pro.patch + patches.suse/block-bfq-get-a-ref-to-a-group-when-adding-it-to-a-s.patch patches.suse/eventfd-track-eventfd_signal-recursion-depth.patch patches.suse/aio-prevent-potential-eventfd-recursion-on-poll.patch patches.suse/tracing-fix-very-unlikely-race-of-registering-two-stat-tracers.patch @@ -9780,6 +9781,7 @@ patches.suse/Input-synaptics-switch-T470s-to-RMI4-by-default.patch patches.suse/Input-synaptics-enable-SMBus-on-ThinkPad-L470.patch patches.suse/Input-synaptics-remove-the-LEN0049-dmi-id-from-topbu.patch + patches.suse/ext4-don-t-assume-that-mmp_nodename-bdevname-have-NU.patch patches.suse/ext4-fix-support-for-inode-sizes-1024-bytes.patch patches.suse/ext4-fix-checksum-errors-with-indexed-dirs.patch patches.suse/ext4-add-cond_resched-to-ext4_protect_reserved_inode.patch @@ -9803,6 +9805,9 @@ patches.suse/drivers-ipmi-Modify-max-length-of-IPMB-packet.patch patches.suse/ipmi-ssif-Handle-a-possible-NULL-pointer-reference.patch patches.suse/drivers-ipmi-fix-off-by-one-bounds-check-that-leads-.patch + patches.suse/ecryptfs-fix-a-memory-leak-bug-in-parse_tag_1_packet.patch + patches.suse/ecryptfs-fix-a-memory-leak-bug-in-ecryptfs_init_mess.patch + patches.suse/ecryptfs-replace-BUG_ON-with-error-handling-code.patch patches.suse/tpm-Initialize-crypto_id-of-allocated_banks-to-HASH_.patch patches.suse/dma-contiguous-cma-give-precedence-to-cmdline.patch patches.suse/dma-direct-relax-addressability-checks-in-dma_direct_supported.patch @@ -9897,9 +9902,19 @@ patches.suse/watchdog-da9062-do-not-ping-the-hw-during-stop.patch patches.suse/powerpc-tm-Fix-clearing-MSR-TS-in-current-when-recla.patch patches.suse/0001-xen-Enable-interrupts-when-calling-_cond_resched.patch + patches.suse/io_uring-prevent-sq_thread-from-spinning-when-it-sho.patch + patches.suse/io_uring-fix-__io_iopoll_check-deadlock-in-io_sq_thr.patch patches.suse/x86-cpu-amd-enable-the-fixed-instructions-retired-counter-irperf.patch patches.suse/x86-mce-amd-publish-the-bank-pointer-only-after-setup-has-succeeded.patch patches.suse/x86-mce-amd-fix-kobject-lifetime.patch + patches.suse/ext4-fix-a-data-race-in-EXT4_I-inode-i_disksize.patch + patches.suse/ext4-add-cond_resched-to-__ext4_find_entry.patch + patches.suse/ext4-fix-potential-race-between-online-resizing-and-.patch + patches.suse/ext4-fix-potential-race-between-s_group_info-online-.patch + patches.suse/ext4-fix-potential-race-between-s_flex_groups-online.patch + patches.suse/ext4-rename-s_journal_flag_rwsem-to-s_writepages_rws.patch + patches.suse/ext4-fix-race-between-writepages-and-enabling-EXT4_E.patch + patches.suse/jbd2-fix-ocfs2-corrupt-when-clearing-block-group-bit.patch patches.suse/ext4-Fix-mount-failure-with-quota-configured-as-modu.patch patches.suse/floppy-check-FDC-index-for-errors-before-assigning-i.patch patches.suse/kvm-nvmx-don-t-emulate-instructions-in-guest-mode @@ -9934,6 +9949,7 @@ patches.suse/pci-brcmstb-fix-build-on-32bit-arm-platforms-with-older-compilers.patch patches.suse/i2c-altera-Fix-potential-integer-overflow.patch patches.suse/kvm-vmx-check-descriptor-table-exits-on-instruction-emulation + patches.suse/ext4-potential-crash-on-allocation-error-in-ext4_all.patch patches.suse/cifs-don-t-leak-EAGAIN-for-stat-during-reconnect.patch patches.suse/cifs-fix-potential-mismatch-of-UNC-paths.patch patches.suse/cifs-add-missing-mount-option-to-proc-mounts.patch @@ -9978,6 +9994,7 @@ patches.suse/media-v4l2-mem2mem.c-fix-broken-links.patch patches.suse/media-mc-entity.c-use-to-check-pad-flags-not.patch patches.suse/media-hantro-Fix-broken-media-controller-links.patch + patches.suse/blktrace-fix-dereference-after-null-check.patch patches.suse/RDMA-core-Fix-use-of-logical-OR-in-get_new_pps.patch patches.suse/RDMA-rw-Fix-error-flow-during-RDMA-context-initializ.patch patches.suse/RDMA-core-Fix-pkey-and-port-assignment-in-get_new_pp.patch