From: Greg Kroah-Hartman Date: Mon, 15 Mar 2021 09:01:39 +0000 (+0100) Subject: 4.19-stable patches X-Git-Tag: v4.4.262~32 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d3a9bfc27787066421c39760d71b38c43bae7f97;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: binfmt_misc-fix-possible-deadlock-in-bm_register_write.patch powerpc-64s-fix-instruction-encoding-for-lis-in-ppc_function_entry.patch x86-unwind-orc-disable-kasan-checking-in-the-orc-unwinder-part-2.patch --- diff --git a/queue-4.19/binfmt_misc-fix-possible-deadlock-in-bm_register_write.patch b/queue-4.19/binfmt_misc-fix-possible-deadlock-in-bm_register_write.patch new file mode 100644 index 00000000000..dddcd0b412d --- /dev/null +++ b/queue-4.19/binfmt_misc-fix-possible-deadlock-in-bm_register_write.patch @@ -0,0 +1,118 @@ +From e7850f4d844e0acfac7e570af611d89deade3146 Mon Sep 17 00:00:00 2001 +From: Lior Ribak +Date: Fri, 12 Mar 2021 21:07:41 -0800 +Subject: binfmt_misc: fix possible deadlock in bm_register_write + +From: Lior Ribak + +commit e7850f4d844e0acfac7e570af611d89deade3146 upstream. + +There is a deadlock in bm_register_write: + +First, in the begining of the function, a lock is taken on the binfmt_misc +root inode with inode_lock(d_inode(root)). + +Then, if the user used the MISC_FMT_OPEN_FILE flag, the function will call +open_exec on the user-provided interpreter. + +open_exec will call a path lookup, and if the path lookup process includes +the root of binfmt_misc, it will try to take a shared lock on its inode +again, but it is already locked, and the code will get stuck in a deadlock + +To reproduce the bug: +$ echo ":iiiii:E::ii::/proc/sys/fs/binfmt_misc/bla:F" > /proc/sys/fs/binfmt_misc/register + +backtrace of where the lock occurs (#5): +0 schedule () at ./arch/x86/include/asm/current.h:15 +1 0xffffffff81b51237 in rwsem_down_read_slowpath (sem=0xffff888003b202e0, count=, state=state@entry=2) at kernel/locking/rwsem.c:992 +2 0xffffffff81b5150a in __down_read_common (state=2, sem=) at kernel/locking/rwsem.c:1213 +3 __down_read (sem=) at kernel/locking/rwsem.c:1222 +4 down_read (sem=) at kernel/locking/rwsem.c:1355 +5 0xffffffff811ee22a in inode_lock_shared (inode=) at ./include/linux/fs.h:783 +6 open_last_lookups (op=0xffffc9000022fe34, file=0xffff888004098600, nd=0xffffc9000022fd10) at fs/namei.c:3177 +7 path_openat (nd=nd@entry=0xffffc9000022fd10, op=op@entry=0xffffc9000022fe34, flags=flags@entry=65) at fs/namei.c:3366 +8 0xffffffff811efe1c in do_filp_open (dfd=, pathname=pathname@entry=0xffff8880031b9000, op=op@entry=0xffffc9000022fe34) at fs/namei.c:3396 +9 0xffffffff811e493f in do_open_execat (fd=fd@entry=-100, name=name@entry=0xffff8880031b9000, flags=, flags@entry=0) at fs/exec.c:913 +10 0xffffffff811e4a92 in open_exec (name=) at fs/exec.c:948 +11 0xffffffff8124aa84 in bm_register_write (file=, buffer=, count=19, ppos=) at fs/binfmt_misc.c:682 +12 0xffffffff811decd2 in vfs_write (file=file@entry=0xffff888004098500, buf=buf@entry=0xa758d0 ":iiiii:E::ii::i:CF +", count=count@entry=19, pos=pos@entry=0xffffc9000022ff10) at fs/read_write.c:603 +13 0xffffffff811defda in ksys_write (fd=, buf=0xa758d0 ":iiiii:E::ii::i:CF +", count=19) at fs/read_write.c:658 +14 0xffffffff81b49813 in do_syscall_64 (nr=, regs=0xffffc9000022ff58) at arch/x86/entry/common.c:46 +15 0xffffffff81c0007c in entry_SYSCALL_64 () at arch/x86/entry/entry_64.S:120 + +To solve the issue, the open_exec call is moved to before the write +lock is taken by bm_register_write + +Link: https://lkml.kernel.org/r/20210228224414.95962-1-liorribak@gmail.com +Fixes: 948b701a607f1 ("binfmt_misc: add persistent opened binary handler for containers") +Signed-off-by: Lior Ribak +Acked-by: Helge Deller +Cc: Al Viro +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + fs/binfmt_misc.c | 29 ++++++++++++++--------------- + 1 file changed, 14 insertions(+), 15 deletions(-) + +--- a/fs/binfmt_misc.c ++++ b/fs/binfmt_misc.c +@@ -694,12 +694,24 @@ static ssize_t bm_register_write(struct + struct super_block *sb = file_inode(file)->i_sb; + struct dentry *root = sb->s_root, *dentry; + int err = 0; ++ struct file *f = NULL; + + e = create_entry(buffer, count); + + if (IS_ERR(e)) + return PTR_ERR(e); + ++ if (e->flags & MISC_FMT_OPEN_FILE) { ++ f = open_exec(e->interpreter); ++ if (IS_ERR(f)) { ++ pr_notice("register: failed to install interpreter file %s\n", ++ e->interpreter); ++ kfree(e); ++ return PTR_ERR(f); ++ } ++ e->interp_file = f; ++ } ++ + inode_lock(d_inode(root)); + dentry = lookup_one_len(e->name, root, strlen(e->name)); + err = PTR_ERR(dentry); +@@ -723,21 +735,6 @@ static ssize_t bm_register_write(struct + goto out2; + } + +- if (e->flags & MISC_FMT_OPEN_FILE) { +- struct file *f; +- +- f = open_exec(e->interpreter); +- if (IS_ERR(f)) { +- err = PTR_ERR(f); +- pr_notice("register: failed to install interpreter file %s\n", e->interpreter); +- simple_release_fs(&bm_mnt, &entry_count); +- iput(inode); +- inode = NULL; +- goto out2; +- } +- e->interp_file = f; +- } +- + e->dentry = dget(dentry); + inode->i_private = e; + inode->i_fop = &bm_entry_operations; +@@ -754,6 +751,8 @@ out: + inode_unlock(d_inode(root)); + + if (err) { ++ if (f) ++ filp_close(f, NULL); + kfree(e); + return err; + } diff --git a/queue-4.19/powerpc-64s-fix-instruction-encoding-for-lis-in-ppc_function_entry.patch b/queue-4.19/powerpc-64s-fix-instruction-encoding-for-lis-in-ppc_function_entry.patch new file mode 100644 index 00000000000..fd10e9bd2e6 --- /dev/null +++ b/queue-4.19/powerpc-64s-fix-instruction-encoding-for-lis-in-ppc_function_entry.patch @@ -0,0 +1,36 @@ +From cea15316ceee2d4a51dfdecd79e08a438135416c Mon Sep 17 00:00:00 2001 +From: "Naveen N. Rao" +Date: Thu, 4 Mar 2021 07:34:11 +0530 +Subject: powerpc/64s: Fix instruction encoding for lis in ppc_function_entry() + +From: Naveen N. Rao + +commit cea15316ceee2d4a51dfdecd79e08a438135416c upstream. + +'lis r2,N' is 'addis r2,0,N' and the instruction encoding in the macro +LIS_R2 is incorrect (it currently maps to 'addis r0,r2,N'). Fix the +same. + +Fixes: c71b7eff426f ("powerpc: Add ABIv2 support to ppc_function_entry") +Cc: stable@vger.kernel.org # v3.16+ +Reported-by: Jiri Olsa +Signed-off-by: Naveen N. Rao +Acked-by: Segher Boessenkool +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20210304020411.16796-1-naveen.n.rao@linux.vnet.ibm.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/powerpc/include/asm/code-patching.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/include/asm/code-patching.h ++++ b/arch/powerpc/include/asm/code-patching.h +@@ -52,7 +52,7 @@ void __patch_exception(int exc, unsigned + #endif + + #define OP_RT_RA_MASK 0xffff0000UL +-#define LIS_R2 0x3c020000UL ++#define LIS_R2 0x3c400000UL + #define ADDIS_R2_R12 0x3c4c0000UL + #define ADDI_R2_R2 0x38420000UL + diff --git a/queue-4.19/series b/queue-4.19/series index 501040e5dbd..5d1888dae40 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -137,3 +137,6 @@ hrtimer-update-softirq_expires_next-correctly-after-.patch stop_machine-mark-helpers-__always_inline.patch include-linux-sched-mm.h-use-rcu_dereference-in-in_v.patch prctl-fix-pr_set_mm_auxv-kernel-stack-leak.patch +powerpc-64s-fix-instruction-encoding-for-lis-in-ppc_function_entry.patch +binfmt_misc-fix-possible-deadlock-in-bm_register_write.patch +x86-unwind-orc-disable-kasan-checking-in-the-orc-unwinder-part-2.patch diff --git a/queue-4.19/x86-unwind-orc-disable-kasan-checking-in-the-orc-unwinder-part-2.patch b/queue-4.19/x86-unwind-orc-disable-kasan-checking-in-the-orc-unwinder-part-2.patch new file mode 100644 index 00000000000..c41f40697ef --- /dev/null +++ b/queue-4.19/x86-unwind-orc-disable-kasan-checking-in-the-orc-unwinder-part-2.patch @@ -0,0 +1,87 @@ +From e504e74cc3a2c092b05577ce3e8e013fae7d94e6 Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Fri, 5 Feb 2021 08:24:02 -0600 +Subject: x86/unwind/orc: Disable KASAN checking in the ORC unwinder, part 2 + +From: Josh Poimboeuf + +commit e504e74cc3a2c092b05577ce3e8e013fae7d94e6 upstream. + +KASAN reserves "redzone" areas between stack frames in order to detect +stack overruns. A read or write to such an area triggers a KASAN +"stack-out-of-bounds" BUG. + +Normally, the ORC unwinder stays in-bounds and doesn't access the +redzone. But sometimes it can't find ORC metadata for a given +instruction. This can happen for code which is missing ORC metadata, or +for generated code. In such cases, the unwinder attempts to fall back +to frame pointers, as a best-effort type thing. + +This fallback often works, but when it doesn't, the unwinder can get +confused and go off into the weeds into the KASAN redzone, triggering +the aforementioned KASAN BUG. + +But in this case, the unwinder's confusion is actually harmless and +working as designed. It already has checks in place to prevent +off-stack accesses, but those checks get short-circuited by the KASAN +BUG. And a BUG is a lot more disruptive than a harmless unwinder +warning. + +Disable the KASAN checks by using READ_ONCE_NOCHECK() for all stack +accesses. This finishes the job started by commit 881125bfe65b +("x86/unwind: Disable KASAN checking in the ORC unwinder"), which only +partially fixed the issue. + +Fixes: ee9f8fce9964 ("x86/unwind: Add the ORC unwinder") +Reported-by: Ivan Babrou +Signed-off-by: Josh Poimboeuf +Signed-off-by: Peter Zijlstra (Intel) +Signed-off-by: Borislav Petkov +Reviewed-by: Steven Rostedt (VMware) +Tested-by: Ivan Babrou +Cc: stable@kernel.org +Link: https://lkml.kernel.org/r/9583327904ebbbeda399eca9c56d6c7085ac20fe.1612534649.git.jpoimboe@redhat.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/unwind_orc.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/arch/x86/kernel/unwind_orc.c ++++ b/arch/x86/kernel/unwind_orc.c +@@ -346,8 +346,8 @@ static bool deref_stack_regs(struct unwi + if (!stack_access_ok(state, addr, sizeof(struct pt_regs))) + return false; + +- *ip = regs->ip; +- *sp = regs->sp; ++ *ip = READ_ONCE_NOCHECK(regs->ip); ++ *sp = READ_ONCE_NOCHECK(regs->sp); + return true; + } + +@@ -359,8 +359,8 @@ static bool deref_stack_iret_regs(struct + if (!stack_access_ok(state, addr, IRET_FRAME_SIZE)) + return false; + +- *ip = regs->ip; +- *sp = regs->sp; ++ *ip = READ_ONCE_NOCHECK(regs->ip); ++ *sp = READ_ONCE_NOCHECK(regs->sp); + return true; + } + +@@ -381,12 +381,12 @@ static bool get_reg(struct unwind_state + return false; + + if (state->full_regs) { +- *val = ((unsigned long *)state->regs)[reg]; ++ *val = READ_ONCE_NOCHECK(((unsigned long *)state->regs)[reg]); + return true; + } + + if (state->prev_regs) { +- *val = ((unsigned long *)state->prev_regs)[reg]; ++ *val = READ_ONCE_NOCHECK(((unsigned long *)state->prev_regs)[reg]); + return true; + } +