diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel')
18 files changed, 1391 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-27815/0001-jfs-Fix-array-index-bounds-check-in-dbAdjTree.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-27815/0001-jfs-Fix-array-index-bounds-check-in-dbAdjTree.patch new file mode 100644 index 000000000..013f21a39 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-27815/0001-jfs-Fix-array-index-bounds-check-in-dbAdjTree.patch @@ -0,0 +1,35 @@ +From c2032bf94ba4fb15db0c277614338d377fe430d2 Mon Sep 17 00:00:00 2001 +From: Dave Kleikamp <dave.kleikamp@oracle.com> +Date: Fri, 13 Nov 2020 14:58:46 -0600 +Subject: [PATCH] jfs: Fix array index bounds check in dbAdjTree + +commit c61b3e4839007668360ed8b87d7da96d2e59fc6c upstream. + +Bounds checking tools can flag a bug in dbAdjTree() for an array index +out of bounds in dmt_stree. Since dmt_stree can refer to the stree in +both structures dmaptree and dmapctl, use the larger array to eliminate +the false positive. + +Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com> +Reported-by: butt3rflyh4ck <butterflyhuangxx@gmail.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + fs/jfs/jfs_dmap.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h +index 29891fad3f09..aa03a904d5ab 100644 +--- a/fs/jfs/jfs_dmap.h ++++ b/fs/jfs/jfs_dmap.h +@@ -183,7 +183,7 @@ typedef union dmtree { + #define dmt_leafidx t1.leafidx + #define dmt_height t1.height + #define dmt_budmin t1.budmin +-#define dmt_stree t1.stree ++#define dmt_stree t2.stree + + /* + * on-disk aggregate disk allocation map descriptor. +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-28588/0001-lib-syscall-fix-syscall-registers-retrieval-on-32-bi.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-28588/0001-lib-syscall-fix-syscall-registers-retrieval-on-32-bi.patch new file mode 100644 index 000000000..dc2ae62fc --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-28588/0001-lib-syscall-fix-syscall-registers-retrieval-on-32-bi.patch @@ -0,0 +1,62 @@ +From 4f134b89a24b965991e7c345b9a4591821f7c2a6 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau <w@1wt.eu> +Date: Mon, 30 Nov 2020 08:36:48 +0100 +Subject: [PATCH] lib/syscall: fix syscall registers retrieval on 32-bit + platforms + +Lilith >_> and Claudio Bozzato of Cisco Talos security team reported +that collect_syscall() improperly casts the syscall registers to 64-bit +values leaking the uninitialized last 24 bytes on 32-bit platforms, that +are visible in /proc/self/syscall. + +The cause is that info->data.args are u64 while syscall_get_arguments() +uses longs, as hinted by the bogus pointer cast in the function. + +Let's just proceed like the other call places, by retrieving the +registers into an array of longs before assigning them to the caller's +array. This was successfully tested on x86_64, i386 and ppc32. + +Reference: CVE-2020-28588, TALOS-2020-1211 +Fixes: 631b7abacd02 ("ptrace: Remove maxargs from task_current_syscall()") +Cc: Greg KH <greg@kroah.com> +Reviewed-by: Kees Cook <keescook@chromium.org> +Tested-by: Michael Ellerman <mpe@ellerman.id.au> (ppc32) +Signed-off-by: Willy Tarreau <w@1wt.eu> +Reviewed-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +--- + lib/syscall.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/lib/syscall.c b/lib/syscall.c +index 8533d2fea2d7..ba13e924c430 100644 +--- a/lib/syscall.c ++++ b/lib/syscall.c +@@ -7,6 +7,7 @@ + + static int collect_syscall(struct task_struct *target, struct syscall_info *info) + { ++ unsigned long args[6] = { }; + struct pt_regs *regs; + + if (!try_get_task_stack(target)) { +@@ -27,8 +28,14 @@ static int collect_syscall(struct task_struct *target, struct syscall_info *info + + info->data.nr = syscall_get_nr(target, regs); + if (info->data.nr != -1L) +- syscall_get_arguments(target, regs, +- (unsigned long *)&info->data.args[0]); ++ syscall_get_arguments(target, regs, args); ++ ++ info->data.args[0] = args[0]; ++ info->data.args[1] = args[1]; ++ info->data.args[2] = args[2]; ++ info->data.args[3] = args[3]; ++ info->data.args[4] = args[4]; ++ info->data.args[5] = args[5]; + + put_task_stack(target); + return 0; +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-35508/0001-fork-fix-copy_process-CLONE_PARENT-race-with-the-exi.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-35508/0001-fork-fix-copy_process-CLONE_PARENT-race-with-the-exi.patch new file mode 100644 index 000000000..61004dbdc --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-35508/0001-fork-fix-copy_process-CLONE_PARENT-race-with-the-exi.patch @@ -0,0 +1,55 @@ +From 7589cef5e0bd71dc3830aeccbda9c0b718641a63 Mon Sep 17 00:00:00 2001 +From: Eddy Wu <itseddy0402@gmail.com> +Date: Sat, 7 Nov 2020 14:47:22 +0800 +Subject: [PATCH] fork: fix copy_process(CLONE_PARENT) race with the exiting + ->real_parent + +current->group_leader->exit_signal may change during copy_process() if +current->real_parent exits. + +Move the assignment inside tasklist_lock to avoid the race. + +Signed-off-by: Eddy Wu <eddy_wu@trendmicro.com> +Acked-by: Oleg Nesterov <oleg@redhat.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +--- + kernel/fork.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/kernel/fork.c b/kernel/fork.c +index 9180f4416dba..fe799c9e787b 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -2080,14 +2080,9 @@ static __latent_entropy struct task_struct *copy_process( + /* ok, now we should be set up.. */ + p->pid = pid_nr(pid); + if (clone_flags & CLONE_THREAD) { +- p->exit_signal = -1; + p->group_leader = current->group_leader; + p->tgid = current->tgid; + } else { +- if (clone_flags & CLONE_PARENT) +- p->exit_signal = current->group_leader->exit_signal; +- else +- p->exit_signal = args->exit_signal; + p->group_leader = p; + p->tgid = p->pid; + } +@@ -2132,9 +2127,14 @@ static __latent_entropy struct task_struct *copy_process( + if (clone_flags & (CLONE_PARENT|CLONE_THREAD)) { + p->real_parent = current->real_parent; + p->parent_exec_id = current->parent_exec_id; ++ if (clone_flags & CLONE_THREAD) ++ p->exit_signal = -1; ++ else ++ p->exit_signal = current->group_leader->exit_signal; + } else { + p->real_parent = current; + p->parent_exec_id = current->self_exec_id; ++ p->exit_signal = args->exit_signal; + } + + klp_copy_process(p); +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-20177/0001-netfilter-add-and-use-nf_hook_slow_list.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-20177/0001-netfilter-add-and-use-nf_hook_slow_list.patch new file mode 100644 index 000000000..8563d5cae --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-20177/0001-netfilter-add-and-use-nf_hook_slow_list.patch @@ -0,0 +1,119 @@ +From ca58fbe06c54795f00db79e447f94c2028d30124 Mon Sep 17 00:00:00 2001 +From: Florian Westphal <fw@strlen.de> +Date: Fri, 11 Oct 2019 00:30:37 +0200 +Subject: [PATCH] netfilter: add and use nf_hook_slow_list() + +At this time, NF_HOOK_LIST() macro will iterate the list and then calls +nf_hook() for each individual skb. + +This makes it so the entire list is passed into the netfilter core. +The advantage is that we only need to fetch the rule blob once per list +instead of per-skb. + +NF_HOOK_LIST now only works for ipv4 and ipv6, as those are the only +callers. + +v2: use skb_list_del_init() instead of list_del (Edward Cree) + +Signed-off-by: Florian Westphal <fw@strlen.de> +Acked-by: Edward Cree <ecree@solarflare.com> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +--- + include/linux/netfilter.h | 41 +++++++++++++++++++++++++++++---------- + net/netfilter/core.c | 20 +++++++++++++++++++ + 2 files changed, 51 insertions(+), 10 deletions(-) + +diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h +index 77ebb61faf48..eb312e7ca36e 100644 +--- a/include/linux/netfilter.h ++++ b/include/linux/netfilter.h +@@ -199,6 +199,8 @@ extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; + int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state, + const struct nf_hook_entries *e, unsigned int i); + ++void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state, ++ const struct nf_hook_entries *e); + /** + * nf_hook - call a netfilter hook + * +@@ -311,17 +313,36 @@ NF_HOOK_LIST(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, + struct list_head *head, struct net_device *in, struct net_device *out, + int (*okfn)(struct net *, struct sock *, struct sk_buff *)) + { +- struct sk_buff *skb, *next; +- struct list_head sublist; +- +- INIT_LIST_HEAD(&sublist); +- list_for_each_entry_safe(skb, next, head, list) { +- list_del(&skb->list); +- if (nf_hook(pf, hook, net, sk, skb, in, out, okfn) == 1) +- list_add_tail(&skb->list, &sublist); ++ struct nf_hook_entries *hook_head = NULL; ++ ++#ifdef CONFIG_JUMP_LABEL ++ if (__builtin_constant_p(pf) && ++ __builtin_constant_p(hook) && ++ !static_key_false(&nf_hooks_needed[pf][hook])) ++ return; ++#endif ++ ++ rcu_read_lock(); ++ switch (pf) { ++ case NFPROTO_IPV4: ++ hook_head = rcu_dereference(net->nf.hooks_ipv4[hook]); ++ break; ++ case NFPROTO_IPV6: ++ hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]); ++ break; ++ default: ++ WARN_ON_ONCE(1); ++ break; + } +- /* Put passed packets back on main list */ +- list_splice(&sublist, head); ++ ++ if (hook_head) { ++ struct nf_hook_state state; ++ ++ nf_hook_state_init(&state, hook, pf, in, out, sk, net, okfn); ++ ++ nf_hook_slow_list(head, &state, hook_head); ++ } ++ rcu_read_unlock(); + } + + /* Call setsockopt() */ +diff --git a/net/netfilter/core.c b/net/netfilter/core.c +index 5d5bdf450091..78f046ec506f 100644 +--- a/net/netfilter/core.c ++++ b/net/netfilter/core.c +@@ -536,6 +536,26 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state, + } + EXPORT_SYMBOL(nf_hook_slow); + ++void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state, ++ const struct nf_hook_entries *e) ++{ ++ struct sk_buff *skb, *next; ++ struct list_head sublist; ++ int ret; ++ ++ INIT_LIST_HEAD(&sublist); ++ ++ list_for_each_entry_safe(skb, next, head, list) { ++ skb_list_del_init(skb); ++ ret = nf_hook_slow(skb, state, e, 0); ++ if (ret == 1) ++ list_add_tail(&skb->list, &sublist); ++ } ++ /* Put passed packets back on main list */ ++ list_splice(&sublist, head); ++} ++EXPORT_SYMBOL(nf_hook_slow_list); ++ + /* This needs to be compiled in any case to avoid dependencies between the + * nfnetlink_queue code and nf_conntrack. + */ +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-29650/0001-netfilter-x_tables-Use-correct-memory-barriers.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-29650/0001-netfilter-x_tables-Use-correct-memory-barriers.patch new file mode 100644 index 000000000..b0232e56d --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-29650/0001-netfilter-x_tables-Use-correct-memory-barriers.patch @@ -0,0 +1,58 @@ +From add3b2ec508d24c739ad1842dc1590fd0ca026f9 Mon Sep 17 00:00:00 2001 +From: Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz> +Date: Mon, 8 Mar 2021 14:24:13 +1300 +Subject: [PATCH] netfilter: x_tables: Use correct memory barriers. + +When a new table value was assigned, it was followed by a write memory +barrier. This ensured that all writes before this point would complete +before any writes after this point. However, to determine whether the +rules are unused, the sequence counter is read. To ensure that all +writes have been done before these reads, a full memory barrier is +needed, not just a write memory barrier. The same argument applies when +incrementing the counter, before the rules are read. + +Changing to using smp_mb() instead of smp_wmb() fixes the kernel panic +reported in cc00bcaa5899 (which is still present), while still +maintaining the same speed of replacing tables. + +The smb_mb() barriers potentially slow the packet path, however testing +has shown no measurable change in performance on a 4-core MIPS64 +platform. + +Fixes: 7f5c6d4f665b ("netfilter: get rid of atomic ops in fast path") +Signed-off-by: Mark Tomlinson <mark.tomlinson@alliedtelesis.co.nz> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +--- + include/linux/netfilter/x_tables.h | 2 +- + net/netfilter/x_tables.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h +index 1b261c51b3a3..04e7f5630509 100644 +--- a/include/linux/netfilter/x_tables.h ++++ b/include/linux/netfilter/x_tables.h +@@ -376,7 +376,7 @@ static inline unsigned int xt_write_recseq_begin(void) + * since addend is most likely 1 + */ + __this_cpu_add(xt_recseq.sequence, addend); +- smp_wmb(); ++ smp_mb(); + + return addend; + } +diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c +index 44f971f31992..e1a5a32605a4 100644 +--- a/net/netfilter/x_tables.c ++++ b/net/netfilter/x_tables.c +@@ -1387,7 +1387,7 @@ xt_replace_table(struct xt_table *table, + table->private = newinfo; + + /* make sure all cpus see new ->private value */ +- smp_wmb(); ++ smp_mb(); + + /* + * Even though table entries have now been swapped, other CPU's +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-30002/0001-media-v4l-ioctl-Fix-memory-leak-in-video_usercopy.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-30002/0001-media-v4l-ioctl-Fix-memory-leak-in-video_usercopy.patch new file mode 100644 index 000000000..2b3916723 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-30002/0001-media-v4l-ioctl-Fix-memory-leak-in-video_usercopy.patch @@ -0,0 +1,78 @@ +From 12c97777a902f6a04f3c268038ed831d405ebf1a Mon Sep 17 00:00:00 2001 +From: Sakari Ailus <sakari.ailus@linux.intel.com> +Date: Sat, 19 Dec 2020 23:29:58 +0100 +Subject: [PATCH] media: v4l: ioctl: Fix memory leak in video_usercopy + +When an IOCTL with argument size larger than 128 that also used array +arguments were handled, two memory allocations were made but alas, only +the latter one of them was released. This happened because there was only +a single local variable to hold such a temporary allocation. + +Fix this by adding separate variables to hold the pointers to the +temporary allocations. + +Reported-by: Arnd Bergmann <arnd@kernel.org> +Reported-by: syzbot+1115e79c8df6472c612b@syzkaller.appspotmail.com +Fixes: d14e6d76ebf7 ("[media] v4l: Add multi-planar ioctl handling code") +Cc: stable@vger.kernel.org +Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Acked-by: Arnd Bergmann <arnd@arndb.de> +Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> +Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> +--- + drivers/media/v4l2-core/v4l2-ioctl.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c +index 58868d7129eb..d72a274ade8d 100644 +--- a/drivers/media/v4l2-core/v4l2-ioctl.c ++++ b/drivers/media/v4l2-core/v4l2-ioctl.c +@@ -3016,7 +3016,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, + v4l2_kioctl func) + { + char sbuf[128]; +- void *mbuf = NULL; ++ void *mbuf = NULL, *array_buf = NULL; + void *parg = (void *)arg; + long err = -EINVAL; + bool has_array_args; +@@ -3081,14 +3081,14 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, + * array) fits into sbuf (so that mbuf will still remain + * unused up to here). + */ +- mbuf = kvmalloc(array_size, GFP_KERNEL); ++ array_buf = kvmalloc(array_size, GFP_KERNEL); + err = -ENOMEM; +- if (NULL == mbuf) ++ if (array_buf == NULL) + goto out_array_args; + err = -EFAULT; +- if (copy_from_user(mbuf, user_ptr, array_size)) ++ if (copy_from_user(array_buf, user_ptr, array_size)) + goto out_array_args; +- *kernel_ptr = mbuf; ++ *kernel_ptr = array_buf; + } + + /* Handles IOCTL */ +@@ -3107,7 +3107,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, + + if (has_array_args) { + *kernel_ptr = (void __force *)user_ptr; +- if (copy_to_user(user_ptr, mbuf, array_size)) ++ if (copy_to_user(user_ptr, array_buf, array_size)) + err = -EFAULT; + goto out_array_args; + } +@@ -3129,6 +3129,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, + } + + out: ++ kvfree(array_buf); + kvfree(mbuf); + return err; + } +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-31916/0001-dm-ioctl-fix-out-of-bounds-array-access-when-no-devi.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-31916/0001-dm-ioctl-fix-out-of-bounds-array-access-when-no-devi.patch new file mode 100644 index 000000000..95def3832 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-31916/0001-dm-ioctl-fix-out-of-bounds-array-access-when-no-devi.patch @@ -0,0 +1,40 @@ +From 921aae17bb0f02181fa05cf5580ebc855fdbd74d Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka <mpatocka@redhat.com> +Date: Fri, 26 Mar 2021 14:32:32 -0400 +Subject: [PATCH] dm ioctl: fix out of bounds array access when no devices + +commit 4edbe1d7bcffcd6269f3b5eb63f710393ff2ec7a upstream. + +If there are not any dm devices, we need to zero the "dev" argument in +the first structure dm_name_list. However, this can cause out of +bounds write, because the "needed" variable is zero and len may be +less than eight. + +Fix this bug by reporting DM_BUFFER_FULL_FLAG if the result buffer is +too small to hold the "nl->dev" value. + +Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Cc: stable@vger.kernel.org +Signed-off-by: Mike Snitzer <snitzer@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/md/dm-ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c +index 5e306bba4375..1ca65b434f1f 100644 +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -529,7 +529,7 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_ + * Grab our output buffer. + */ + nl = orig_nl = get_result_buffer(param, param_size, &len); +- if (len < needed) { ++ if (len < needed || len < sizeof(nl->dev)) { + param->flags |= DM_BUFFER_FULL_FLAG; + goto out; + } +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0001-futex-Fix-incorrect-should_fail_futex-handling.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0001-futex-Fix-incorrect-should_fail_futex-handling.patch new file mode 100644 index 000000000..15420d4a4 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0001-futex-Fix-incorrect-should_fail_futex-handling.patch @@ -0,0 +1,47 @@ +From 2db7590371520735366639647352b44c0eeda11f Mon Sep 17 00:00:00 2001 +From: Mateusz Nosek <mateusznosek0@gmail.com> +Date: Sun, 27 Sep 2020 02:08:58 +0200 +Subject: [PATCH] futex: Fix incorrect should_fail_futex() handling + +[ Upstream commit 921c7ebd1337d1a46783d7e15a850e12aed2eaa0 ] + +If should_futex_fail() returns true in futex_wake_pi(), then the 'ret' +variable is set to -EFAULT and then immediately overwritten. So the failure +injection is non-functional. + +Fix it by actually leaving the function and returning -EFAULT. + +The Fixes tag is kinda blury because the initial commit which introduced +failure injection was already sloppy, but the below mentioned commit broke +it completely. + +[ tglx: Massaged changelog ] + +Fixes: 6b4f4bc9cb22 ("locking/futex: Allow low-level atomic operations to return -EAGAIN") +Signed-off-by: Mateusz Nosek <mateusznosek0@gmail.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Link: https://lore.kernel.org/r/20200927000858.24219-1-mateusznosek0@gmail.com +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + kernel/futex.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index 5660c02b01b0..17fba7a986e0 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -1594,8 +1594,10 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_ + */ + newval = FUTEX_WAITERS | task_pid_vnr(new_owner); + +- if (unlikely(should_fail_futex(true))) ++ if (unlikely(should_fail_futex(true))) { + ret = -EFAULT; ++ goto out_unlock; ++ } + + ret = cmpxchg_futex_value_locked(&curval, uaddr, uval, newval); + if (!ret && (curval != uval)) { +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0002-futex-Handle-transient-ownerless-rtmutex-state-corre.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0002-futex-Handle-transient-ownerless-rtmutex-state-corre.patch new file mode 100644 index 000000000..c8c3b08eb --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0002-futex-Handle-transient-ownerless-rtmutex-state-corre.patch @@ -0,0 +1,82 @@ +From 2716e78a6486814537df95a82efec4e9e4e081d9 Mon Sep 17 00:00:00 2001 +From: Mike Galbraith <efault@gmx.de> +Date: Wed, 4 Nov 2020 16:12:44 +0100 +Subject: [PATCH] futex: Handle transient "ownerless" rtmutex state correctly + +commit 9f5d1c336a10c0d24e83e40b4c1b9539f7dba627 upstream. + +Gratian managed to trigger the BUG_ON(!newowner) in fixup_pi_state_owner(). +This is one possible chain of events leading to this: + +Task Prio Operation +T1 120 lock(F) +T2 120 lock(F) -> blocks (top waiter) +T3 50 (RT) lock(F) -> boosts T1 and blocks (new top waiter) +XX timeout/ -> wakes T2 + signal +T1 50 unlock(F) -> wakes T3 (rtmutex->owner == NULL, waiter bit is set) +T2 120 cleanup -> try_to_take_mutex() fails because T3 is the top waiter + and the lower priority T2 cannot steal the lock. + -> fixup_pi_state_owner() sees newowner == NULL -> BUG_ON() + +The comment states that this is invalid and rt_mutex_real_owner() must +return a non NULL owner when the trylock failed, but in case of a queued +and woken up waiter rt_mutex_real_owner() == NULL is a valid transient +state. The higher priority waiter has simply not yet managed to take over +the rtmutex. + +The BUG_ON() is therefore wrong and this is just another retry condition in +fixup_pi_state_owner(). + +Drop the locks, so that T3 can make progress, and then try the fixup again. + +Gratian provided a great analysis, traces and a reproducer. The analysis is +to the point, but it confused the hell out of that tglx dude who had to +page in all the futex horrors again. Condensed version is above. + +[ tglx: Wrote comment and changelog ] + +Fixes: c1e2f0eaf015 ("futex: Avoid violating the 10th rule of futex") +Reported-by: Gratian Crisan <gratian.crisan@ni.com> +Signed-off-by: Mike Galbraith <efault@gmx.de> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/87a6w6x7bb.fsf@ni.com +Link: https://lore.kernel.org/r/87sg9pkvf7.fsf@nanos.tec.linutronix.de +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/futex.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index 17fba7a986e0..9c4f9b868a49 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -2511,10 +2511,22 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + } + + /* +- * Since we just failed the trylock; there must be an owner. ++ * The trylock just failed, so either there is an owner or ++ * there is a higher priority waiter than this one. + */ + newowner = rt_mutex_owner(&pi_state->pi_mutex); +- BUG_ON(!newowner); ++ /* ++ * If the higher priority waiter has not yet taken over the ++ * rtmutex then newowner is NULL. We can't return here with ++ * that state because it's inconsistent vs. the user space ++ * state. So drop the locks and try again. It's a valid ++ * situation and not any different from the other retry ++ * conditions. ++ */ ++ if (unlikely(!newowner)) { ++ err = -EAGAIN; ++ goto handle_err; ++ } + } else { + WARN_ON_ONCE(argowner != current); + if (oldowner == current) { +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0003-futex-Don-t-enable-IRQs-unconditionally-in-put_pi_st.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0003-futex-Don-t-enable-IRQs-unconditionally-in-put_pi_st.patch new file mode 100644 index 000000000..d58a046fc --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0003-futex-Don-t-enable-IRQs-unconditionally-in-put_pi_st.patch @@ -0,0 +1,51 @@ +From 2192d905df0d540f6f3240046bcb06c53bcf5016 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter <dan.carpenter@oracle.com> +Date: Fri, 6 Nov 2020 11:52:05 +0300 +Subject: [PATCH] futex: Don't enable IRQs unconditionally in put_pi_state() + +commit 1e106aa3509b86738769775969822ffc1ec21bf4 upstream. + +The exit_pi_state_list() function calls put_pi_state() with IRQs disabled +and is not expecting that IRQs will be enabled inside the function. + +Use the _irqsave() variant so that IRQs are restored to the original state +instead of being enabled unconditionally. + +Fixes: 153fbd1226fb ("futex: Fix more put_pi_state() vs. exit_pi_state_list() races") +Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20201106085205.GA1159983@mwanda +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/futex.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index 9c4f9b868a49..b6dec5f79370 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -880,8 +880,9 @@ static void put_pi_state(struct futex_pi_state *pi_state) + */ + if (pi_state->owner) { + struct task_struct *owner; ++ unsigned long flags; + +- raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); ++ raw_spin_lock_irqsave(&pi_state->pi_mutex.wait_lock, flags); + owner = pi_state->owner; + if (owner) { + raw_spin_lock(&owner->pi_lock); +@@ -889,7 +890,7 @@ static void put_pi_state(struct futex_pi_state *pi_state) + raw_spin_unlock(&owner->pi_lock); + } + rt_mutex_proxy_unlock(&pi_state->pi_mutex, owner); +- raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); ++ raw_spin_unlock_irqrestore(&pi_state->pi_mutex.wait_lock, flags); + } + + if (current->pi_state_cache) { +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0004-futex-Ensure-the-correct-return-value-from-futex_loc.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0004-futex-Ensure-the-correct-return-value-from-futex_loc.patch new file mode 100644 index 000000000..24f1986a8 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0004-futex-Ensure-the-correct-return-value-from-futex_loc.patch @@ -0,0 +1,138 @@ +From 0dae88a92596db9405fd4a341c1915cf7d8fbad4 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Wed, 20 Jan 2021 16:00:24 +0100 +Subject: [PATCH] futex: Ensure the correct return value from futex_lock_pi() + +commit 12bb3f7f1b03d5913b3f9d4236a488aa7774dfe9 upstream + +In case that futex_lock_pi() was aborted by a signal or a timeout and the +task returned without acquiring the rtmutex, but is the designated owner of +the futex due to a concurrent futex_unlock_pi() fixup_owner() is invoked to +establish consistent state. In that case it invokes fixup_pi_state_owner() +which in turn tries to acquire the rtmutex again. If that succeeds then it +does not propagate this success to fixup_owner() and futex_lock_pi() +returns -EINTR or -ETIMEOUT despite having the futex locked. + +Return success from fixup_pi_state_owner() in all cases where the current +task owns the rtmutex and therefore the futex and propagate it correctly +through fixup_owner(). Fixup the other callsite which does not expect a +positive return value. + +Fixes: c1e2f0eaf015 ("futex: Avoid violating the 10th rule of futex") +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/futex.c | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index b6dec5f79370..d2cc406c6658 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -2506,8 +2506,8 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + } + + if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) { +- /* We got the lock after all, nothing to fix. */ +- ret = 0; ++ /* We got the lock. pi_state is correct. Tell caller. */ ++ ret = 1; + goto out_unlock; + } + +@@ -2535,7 +2535,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + * We raced against a concurrent self; things are + * already fixed up. Nothing to do. + */ +- ret = 0; ++ ret = 1; + goto out_unlock; + } + newowner = argowner; +@@ -2581,7 +2581,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + raw_spin_unlock(&newowner->pi_lock); + raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); + +- return 0; ++ return argowner == current; + + /* + * In order to reschedule or handle a page fault, we need to drop the +@@ -2623,7 +2623,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + * Check if someone else fixed it for us: + */ + if (pi_state->owner != oldowner) { +- ret = 0; ++ ret = argowner == current; + goto out_unlock; + } + +@@ -2656,8 +2656,6 @@ static long futex_wait_restart(struct restart_block *restart); + */ + static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked) + { +- int ret = 0; +- + if (locked) { + /* + * Got the lock. We might not be the anticipated owner if we +@@ -2668,8 +2666,8 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked) + * stable state, anything else needs more attention. + */ + if (q->pi_state->owner != current) +- ret = fixup_pi_state_owner(uaddr, q, current); +- goto out; ++ return fixup_pi_state_owner(uaddr, q, current); ++ return 1; + } + + /* +@@ -2680,10 +2678,8 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked) + * Another speculative read; pi_state->owner == current is unstable + * but needs our attention. + */ +- if (q->pi_state->owner == current) { +- ret = fixup_pi_state_owner(uaddr, q, NULL); +- goto out; +- } ++ if (q->pi_state->owner == current) ++ return fixup_pi_state_owner(uaddr, q, NULL); + + /* + * Paranoia check. If we did not take the lock, then we should not be +@@ -2696,8 +2692,7 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked) + q->pi_state->owner); + } + +-out: +- return ret ? ret : locked; ++ return 0; + } + + /** +@@ -3406,7 +3401,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, + if (q.pi_state && (q.pi_state->owner != current)) { + spin_lock(q.lock_ptr); + ret = fixup_pi_state_owner(uaddr2, &q, current); +- if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) { ++ if (ret < 0 && rt_mutex_owner(&q.pi_state->pi_mutex) == current) { + pi_state = q.pi_state; + get_pi_state(pi_state); + } +@@ -3416,6 +3411,11 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, + */ + put_pi_state(q.pi_state); + spin_unlock(q.lock_ptr); ++ /* ++ * Adjust the return value. It's either -EFAULT or ++ * success (1) but the caller expects 0 for success. ++ */ ++ ret = ret < 0 ? ret : 0; + } + } else { + struct rt_mutex *pi_mutex; +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0005-futex-Replace-pointless-printk-in-fixup_owner.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0005-futex-Replace-pointless-printk-in-fixup_owner.patch new file mode 100644 index 000000000..d8711e8b9 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0005-futex-Replace-pointless-printk-in-fixup_owner.patch @@ -0,0 +1,44 @@ +From 65aad57cac8db8dd0d1dcdd86bc8603039d937b7 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Tue, 19 Jan 2021 16:06:10 +0100 +Subject: [PATCH] futex: Replace pointless printk in fixup_owner() + +commit 04b79c55201f02ffd675e1231d731365e335c307 upstream + +If that unexpected case of inconsistent arguments ever happens then the +futex state is left completely inconsistent and the printk is not really +helpful. Replace it with a warning and make the state consistent. + +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/futex.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index d2cc406c6658..8bfb16258ae7 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -2683,14 +2683,10 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked) + + /* + * Paranoia check. If we did not take the lock, then we should not be +- * the owner of the rt_mutex. ++ * the owner of the rt_mutex. Warn and establish consistent state. + */ +- if (rt_mutex_owner(&q->pi_state->pi_mutex) == current) { +- printk(KERN_ERR "fixup_owner: ret = %d pi-mutex: %p " +- "pi-state %p\n", ret, +- q->pi_state->pi_mutex.owner, +- q->pi_state->owner); +- } ++ if (WARN_ON_ONCE(rt_mutex_owner(&q->pi_state->pi_mutex) == current)) ++ return fixup_pi_state_owner(uaddr, q, current); + + return 0; + } +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0006-futex-Provide-and-use-pi_state_update_owner.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0006-futex-Provide-and-use-pi_state_update_owner.patch new file mode 100644 index 000000000..ae0f63a18 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0006-futex-Provide-and-use-pi_state_update_owner.patch @@ -0,0 +1,117 @@ +From 015b6a4c2564a9385401a6105e80a20c333e1d44 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Tue, 19 Jan 2021 15:21:35 +0100 +Subject: [PATCH] futex: Provide and use pi_state_update_owner() + +commit c5cade200ab9a2a3be9e7f32a752c8d86b502ec7 upstream + +Updating pi_state::owner is done at several places with the same +code. Provide a function for it and use that at the obvious places. + +This is also a preparation for a bug fix to avoid yet another copy of the +same code or alternatively introducing a completely unpenetratable mess of +gotos. + +Originally-by: Peter Zijlstra <peterz@infradead.org> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/futex.c | 66 +++++++++++++++++++++++++------------------------- + 1 file changed, 33 insertions(+), 33 deletions(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index 8bfb16258ae7..69f62d0f5851 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -857,6 +857,29 @@ static struct futex_pi_state *alloc_pi_state(void) + return pi_state; + } + ++static void pi_state_update_owner(struct futex_pi_state *pi_state, ++ struct task_struct *new_owner) ++{ ++ struct task_struct *old_owner = pi_state->owner; ++ ++ lockdep_assert_held(&pi_state->pi_mutex.wait_lock); ++ ++ if (old_owner) { ++ raw_spin_lock(&old_owner->pi_lock); ++ WARN_ON(list_empty(&pi_state->list)); ++ list_del_init(&pi_state->list); ++ raw_spin_unlock(&old_owner->pi_lock); ++ } ++ ++ if (new_owner) { ++ raw_spin_lock(&new_owner->pi_lock); ++ WARN_ON(!list_empty(&pi_state->list)); ++ list_add(&pi_state->list, &new_owner->pi_state_list); ++ pi_state->owner = new_owner; ++ raw_spin_unlock(&new_owner->pi_lock); ++ } ++} ++ + static void get_pi_state(struct futex_pi_state *pi_state) + { + WARN_ON_ONCE(!refcount_inc_not_zero(&pi_state->refcount)); +@@ -1614,26 +1637,15 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_ + ret = -EINVAL; + } + +- if (ret) +- goto out_unlock; +- +- /* +- * This is a point of no return; once we modify the uval there is no +- * going back and subsequent operations must not fail. +- */ +- +- raw_spin_lock(&pi_state->owner->pi_lock); +- WARN_ON(list_empty(&pi_state->list)); +- list_del_init(&pi_state->list); +- raw_spin_unlock(&pi_state->owner->pi_lock); +- +- raw_spin_lock(&new_owner->pi_lock); +- WARN_ON(!list_empty(&pi_state->list)); +- list_add(&pi_state->list, &new_owner->pi_state_list); +- pi_state->owner = new_owner; +- raw_spin_unlock(&new_owner->pi_lock); +- +- postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q); ++ if (!ret) { ++ /* ++ * This is a point of no return; once we modified the uval ++ * there is no going back and subsequent operations must ++ * not fail. ++ */ ++ pi_state_update_owner(pi_state, new_owner); ++ postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q); ++ } + + out_unlock: + raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); +@@ -2566,19 +2578,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + * We fixed up user space. Now we need to fix the pi_state + * itself. + */ +- if (pi_state->owner != NULL) { +- raw_spin_lock(&pi_state->owner->pi_lock); +- WARN_ON(list_empty(&pi_state->list)); +- list_del_init(&pi_state->list); +- raw_spin_unlock(&pi_state->owner->pi_lock); +- } +- +- pi_state->owner = newowner; +- +- raw_spin_lock(&newowner->pi_lock); +- WARN_ON(!list_empty(&pi_state->list)); +- list_add(&pi_state->list, &newowner->pi_state_list); +- raw_spin_unlock(&newowner->pi_lock); ++ pi_state_update_owner(pi_state, newowner); + raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); + + return argowner == current; +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0007-rtmutex-Remove-unused-argument-from-rt_mutex_proxy_u.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0007-rtmutex-Remove-unused-argument-from-rt_mutex_proxy_u.patch new file mode 100644 index 000000000..9196c9ed2 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0007-rtmutex-Remove-unused-argument-from-rt_mutex_proxy_u.patch @@ -0,0 +1,64 @@ +From ceb83cf9ed6764977c86a03fe187578def3b4e18 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Wed, 20 Jan 2021 11:32:07 +0100 +Subject: [PATCH] rtmutex: Remove unused argument from rt_mutex_proxy_unlock() + +commit 2156ac1934166d6deb6cd0f6ffc4c1076ec63697 upstream + +Nothing uses the argument. Remove it as preparation to use +pi_state_update_owner(). + +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/futex.c | 2 +- + kernel/locking/rtmutex.c | 3 +-- + kernel/locking/rtmutex_common.h | 3 +-- + 3 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index 69f62d0f5851..8175bdce7267 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -912,7 +912,7 @@ static void put_pi_state(struct futex_pi_state *pi_state) + list_del_init(&pi_state->list); + raw_spin_unlock(&owner->pi_lock); + } +- rt_mutex_proxy_unlock(&pi_state->pi_mutex, owner); ++ rt_mutex_proxy_unlock(&pi_state->pi_mutex); + raw_spin_unlock_irqrestore(&pi_state->pi_mutex.wait_lock, flags); + } + +diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c +index 2874bf556162..734698aec5f9 100644 +--- a/kernel/locking/rtmutex.c ++++ b/kernel/locking/rtmutex.c +@@ -1718,8 +1718,7 @@ void rt_mutex_init_proxy_locked(struct rt_mutex *lock, + * possible because it belongs to the pi_state which is about to be freed + * and it is not longer visible to other tasks. + */ +-void rt_mutex_proxy_unlock(struct rt_mutex *lock, +- struct task_struct *proxy_owner) ++void rt_mutex_proxy_unlock(struct rt_mutex *lock) + { + debug_rt_mutex_proxy_unlock(lock); + rt_mutex_set_owner(lock, NULL); +diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h +index d1d62f942be2..ca6fb489007b 100644 +--- a/kernel/locking/rtmutex_common.h ++++ b/kernel/locking/rtmutex_common.h +@@ -133,8 +133,7 @@ enum rtmutex_chainwalk { + extern struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock); + extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock, + struct task_struct *proxy_owner); +-extern void rt_mutex_proxy_unlock(struct rt_mutex *lock, +- struct task_struct *proxy_owner); ++extern void rt_mutex_proxy_unlock(struct rt_mutex *lock); + extern void rt_mutex_init_waiter(struct rt_mutex_waiter *waiter); + extern int __rt_mutex_start_proxy_lock(struct rt_mutex *lock, + struct rt_mutex_waiter *waiter, +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0008-futex-Use-pi_state_update_owner-in-put_pi_state.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0008-futex-Use-pi_state_update_owner-in-put_pi_state.patch new file mode 100644 index 000000000..cfff74b57 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0008-futex-Use-pi_state_update_owner-in-put_pi_state.patch @@ -0,0 +1,42 @@ +From a3155c362ca0a4677d0c886798bbeb5f0a9efe86 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Wed, 20 Jan 2021 11:35:19 +0100 +Subject: [PATCH] futex: Use pi_state_update_owner() in put_pi_state() + +commit 6ccc84f917d33312eb2846bd7b567639f585ad6d upstream + +No point in open coding it. This way it gains the extra sanity checks. + +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/futex.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index 8175bdce7267..758deac71345 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -902,16 +902,10 @@ static void put_pi_state(struct futex_pi_state *pi_state) + * and has cleaned up the pi_state already + */ + if (pi_state->owner) { +- struct task_struct *owner; + unsigned long flags; + + raw_spin_lock_irqsave(&pi_state->pi_mutex.wait_lock, flags); +- owner = pi_state->owner; +- if (owner) { +- raw_spin_lock(&owner->pi_lock); +- list_del_init(&pi_state->list); +- raw_spin_unlock(&owner->pi_lock); +- } ++ pi_state_update_owner(pi_state, NULL); + rt_mutex_proxy_unlock(&pi_state->pi_mutex); + raw_spin_unlock_irqrestore(&pi_state->pi_mutex.wait_lock, flags); + } +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0009-futex-Simplify-fixup_pi_state_owner.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0009-futex-Simplify-fixup_pi_state_owner.patch new file mode 100644 index 000000000..d6b60749d --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0009-futex-Simplify-fixup_pi_state_owner.patch @@ -0,0 +1,138 @@ +From 55ea172ce3ebe276e734352eb1b236b3065496c3 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Tue, 19 Jan 2021 16:26:38 +0100 +Subject: [PATCH] futex: Simplify fixup_pi_state_owner() + +commit f2dac39d93987f7de1e20b3988c8685523247ae2 upstream + +Too many gotos already and an upcoming fix would make it even more +unreadable. + +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/futex.c | 53 +++++++++++++++++++++++++------------------------- + 1 file changed, 26 insertions(+), 27 deletions(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index 758deac71345..48c37ff4388d 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -2462,18 +2462,13 @@ static void unqueue_me_pi(struct futex_q *q) + spin_unlock(q->lock_ptr); + } + +-static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, +- struct task_struct *argowner) ++static int __fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, ++ struct task_struct *argowner) + { ++ u32 uval, uninitialized_var(curval), newval, newtid; + struct futex_pi_state *pi_state = q->pi_state; +- u32 uval, uninitialized_var(curval), newval; + struct task_struct *oldowner, *newowner; +- u32 newtid; +- int ret, err = 0; +- +- lockdep_assert_held(q->lock_ptr); +- +- raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); ++ int err = 0; + + oldowner = pi_state->owner; + +@@ -2507,14 +2502,12 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + * We raced against a concurrent self; things are + * already fixed up. Nothing to do. + */ +- ret = 0; +- goto out_unlock; ++ return 0; + } + + if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) { + /* We got the lock. pi_state is correct. Tell caller. */ +- ret = 1; +- goto out_unlock; ++ return 1; + } + + /* +@@ -2541,8 +2534,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + * We raced against a concurrent self; things are + * already fixed up. Nothing to do. + */ +- ret = 1; +- goto out_unlock; ++ return 1; + } + newowner = argowner; + } +@@ -2573,7 +2565,6 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + * itself. + */ + pi_state_update_owner(pi_state, newowner); +- raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); + + return argowner == current; + +@@ -2596,17 +2587,16 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + + switch (err) { + case -EFAULT: +- ret = fault_in_user_writeable(uaddr); ++ err = fault_in_user_writeable(uaddr); + break; + + case -EAGAIN: + cond_resched(); +- ret = 0; ++ err = 0; + break; + + default: + WARN_ON_ONCE(1); +- ret = err; + break; + } + +@@ -2616,17 +2606,26 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + /* + * Check if someone else fixed it for us: + */ +- if (pi_state->owner != oldowner) { +- ret = argowner == current; +- goto out_unlock; +- } ++ if (pi_state->owner != oldowner) ++ return argowner == current; + +- if (ret) +- goto out_unlock; ++ /* Retry if err was -EAGAIN or the fault in succeeded */ ++ if (!err) ++ goto retry; + +- goto retry; ++ return err; ++} + +-out_unlock: ++static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, ++ struct task_struct *argowner) ++{ ++ struct futex_pi_state *pi_state = q->pi_state; ++ int ret; ++ ++ lockdep_assert_held(q->lock_ptr); ++ ++ raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); ++ ret = __fixup_pi_state_owner(uaddr, q, argowner); + raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); + return ret; + } +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0010-futex-Handle-faults-correctly-for-PI-futexes.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0010-futex-Handle-faults-correctly-for-PI-futexes.patch new file mode 100644 index 000000000..321ba84d8 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-3347/0010-futex-Handle-faults-correctly-for-PI-futexes.patch @@ -0,0 +1,164 @@ +From ecd62d2e9ab405d9575c3aa8eb44e44e523a0d19 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner <tglx@linutronix.de> +Date: Mon, 18 Jan 2021 19:01:21 +0100 +Subject: [PATCH] futex: Handle faults correctly for PI futexes + +commit 34b1a1ce1458f50ef27c54e28eb9b1947012907a upstream + +fixup_pi_state_owner() tries to ensure that the state of the rtmutex, +pi_state and the user space value related to the PI futex are consistent +before returning to user space. In case that the user space value update +faults and the fault cannot be resolved by faulting the page in via +fault_in_user_writeable() the function returns with -EFAULT and leaves +the rtmutex and pi_state owner state inconsistent. + +A subsequent futex_unlock_pi() operates on the inconsistent pi_state and +releases the rtmutex despite not owning it which can corrupt the RB tree of +the rtmutex and cause a subsequent kernel stack use after free. + +It was suggested to loop forever in fixup_pi_state_owner() if the fault +cannot be resolved, but that results in runaway tasks which is especially +undesired when the problem happens due to a programming error and not due +to malice. + +As the user space value cannot be fixed up, the proper solution is to make +the rtmutex and the pi_state consistent so both have the same owner. This +leaves the user space value out of sync. Any subsequent operation on the +futex will fail because the 10th rule of PI futexes (pi_state owner and +user space value are consistent) has been violated. + +As a consequence this removes the inept attempts of 'fixing' the situation +in case that the current task owns the rtmutex when returning with an +unresolvable fault by unlocking the rtmutex which left pi_state::owner and +rtmutex::owner out of sync in a different and only slightly less dangerous +way. + +Fixes: 1b7558e457ed ("futexes: fix fault handling in futex_lock_pi") +Reported-by: gzobqq@gmail.com +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/futex.c | 56 ++++++++++++++++++-------------------------------- + 1 file changed, 20 insertions(+), 36 deletions(-) + +diff --git a/kernel/futex.c b/kernel/futex.c +index 48c37ff4388d..042c2707e913 100644 +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -1052,7 +1052,8 @@ static inline void exit_pi_state_list(struct task_struct *curr) { } + * FUTEX_OWNER_DIED bit. See [4] + * + * [10] There is no transient state which leaves owner and user space +- * TID out of sync. ++ * TID out of sync. Except one error case where the kernel is denied ++ * write access to the user address, see fixup_pi_state_owner(). + * + * + * Serialization and lifetime rules: +@@ -2613,6 +2614,24 @@ static int __fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + if (!err) + goto retry; + ++ /* ++ * fault_in_user_writeable() failed so user state is immutable. At ++ * best we can make the kernel state consistent but user state will ++ * be most likely hosed and any subsequent unlock operation will be ++ * rejected due to PI futex rule [10]. ++ * ++ * Ensure that the rtmutex owner is also the pi_state owner despite ++ * the user space value claiming something different. There is no ++ * point in unlocking the rtmutex if current is the owner as it ++ * would need to wait until the next waiter has taken the rtmutex ++ * to guarantee consistent state. Keep it simple. Userspace asked ++ * for this wreckaged state. ++ * ++ * The rtmutex has an owner - either current or some other ++ * task. See the EAGAIN loop above. ++ */ ++ pi_state_update_owner(pi_state, rt_mutex_owner(&pi_state->pi_mutex)); ++ + return err; + } + +@@ -2893,7 +2912,6 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, + ktime_t *time, int trylock) + { + struct hrtimer_sleeper timeout, *to; +- struct futex_pi_state *pi_state = NULL; + struct task_struct *exiting = NULL; + struct rt_mutex_waiter rt_waiter; + struct futex_hash_bucket *hb; +@@ -3030,23 +3048,9 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, + if (res) + ret = (res < 0) ? res : 0; + +- /* +- * If fixup_owner() faulted and was unable to handle the fault, unlock +- * it and return the fault to userspace. +- */ +- if (ret && (rt_mutex_owner(&q.pi_state->pi_mutex) == current)) { +- pi_state = q.pi_state; +- get_pi_state(pi_state); +- } +- + /* Unqueue and drop the lock */ + unqueue_me_pi(&q); + +- if (pi_state) { +- rt_mutex_futex_unlock(&pi_state->pi_mutex); +- put_pi_state(pi_state); +- } +- + goto out_put_key; + + out_unlock_put_key: +@@ -3312,7 +3316,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, + u32 __user *uaddr2) + { + struct hrtimer_sleeper timeout, *to; +- struct futex_pi_state *pi_state = NULL; + struct rt_mutex_waiter rt_waiter; + struct futex_hash_bucket *hb; + union futex_key key2 = FUTEX_KEY_INIT; +@@ -3390,10 +3393,6 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, + if (q.pi_state && (q.pi_state->owner != current)) { + spin_lock(q.lock_ptr); + ret = fixup_pi_state_owner(uaddr2, &q, current); +- if (ret < 0 && rt_mutex_owner(&q.pi_state->pi_mutex) == current) { +- pi_state = q.pi_state; +- get_pi_state(pi_state); +- } + /* + * Drop the reference to the pi state which + * the requeue_pi() code acquired for us. +@@ -3435,25 +3434,10 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, + if (res) + ret = (res < 0) ? res : 0; + +- /* +- * If fixup_pi_state_owner() faulted and was unable to handle +- * the fault, unlock the rt_mutex and return the fault to +- * userspace. +- */ +- if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) { +- pi_state = q.pi_state; +- get_pi_state(pi_state); +- } +- + /* Unqueue and drop the lock. */ + unqueue_me_pi(&q); + } + +- if (pi_state) { +- rt_mutex_futex_unlock(&pi_state->pi_mutex); +- put_pi_state(pi_state); +- } +- + if (ret == -EINTR) { + /* + * We've already been requeued, but cannot restart by calling +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend index 0186ee5f4..467578d85 100644 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend @@ -207,5 +207,62 @@ SRC_URI += " \ file://0001-tracing-Fix-race-in-trace_open-and-buffer-resize-cal.patch \ " +# CVE-2021-3347 vulnerability fix +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2021-3347:" +SRC_URI += " \ + file://0001-futex-Fix-incorrect-should_fail_futex-handling.patch \ + file://0002-futex-Handle-transient-ownerless-rtmutex-state-corre.patch \ + file://0003-futex-Don-t-enable-IRQs-unconditionally-in-put_pi_st.patch \ + file://0004-futex-Ensure-the-correct-return-value-from-futex_loc.patch \ + file://0005-futex-Replace-pointless-printk-in-fixup_owner.patch \ + file://0006-futex-Provide-and-use-pi_state_update_owner.patch \ + file://0007-rtmutex-Remove-unused-argument-from-rt_mutex_proxy_u.patch \ + file://0008-futex-Use-pi_state_update_owner-in-put_pi_state.patch \ + file://0009-futex-Simplify-fixup_pi_state_owner.patch \ + file://0010-futex-Handle-faults-correctly-for-PI-futexes.patch \ + " + +# CVE-2020-35508 vulnerability fix +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2020-35508:" +SRC_URI += " \ + file://0001-fork-fix-copy_process-CLONE_PARENT-race-with-the-exi.patch \ + " + +# CVE-2021-29650 vulnerability fix +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2021-29650:" +SRC_URI += " \ + file://0001-netfilter-x_tables-Use-correct-memory-barriers.patch \ + " + +# CVE-2021-30002 vulnerability fix +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2021-30002:" +SRC_URI += " \ + file://0001-media-v4l-ioctl-Fix-memory-leak-in-video_usercopy.patch \ + " + +# CVE-2020-28588 vulnerability fix +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2020-28588:" +SRC_URI += " \ + file://0001-lib-syscall-fix-syscall-registers-retrieval-on-32-bi.patch \ + " + +# CVE-2020-27815 vulnerability fix +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2020-27815:" +SRC_URI += " \ + file://0001-jfs-Fix-array-index-bounds-check-in-dbAdjTree.patch \ + " + +# CVE-2021-20177 vulnerability fix +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2021-20177:" +SRC_URI += " \ + file://0001-netfilter-add-and-use-nf_hook_slow_list.patch \ + " + +# CVE-2021-31916 vulnerability fix +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}/CVE-2021-31916:" +SRC_URI += " \ + file://0001-dm-ioctl-fix-out-of-bounds-array-access-when-no-devi.patch \ + " + SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'file://0005-128MB-flashmap-for-PFR.patch', '', d)}" SRC_URI += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks', 'file://debug.cfg', '', d)}" |