From 4f7e02c52dc78cc23a33452157255f8755edc9c8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 12 May 2020 15:27:48 +0200 Subject: [PATCH] 4.19-stable patches added patches: netfilter-nat-never-update-the-udp-checksum-when-it-s-0.patch netfilter-nf_osf-avoid-passing-pointer-to-local-var.patch objtool-fix-stack-offset-tracking-for-indirect-cfas.patch scripts-decodecode-fix-trapping-instruction-formatting.patch x86-entry-64-fix-unwind-hints-in-kernel-exit-path.patch x86-entry-64-fix-unwind-hints-in-register-clearing-code.patch x86-entry-64-fix-unwind-hints-in-rewind_stack_do_exit.patch x86-unwind-orc-don-t-skip-the-first-frame-for-inactive-tasks.patch x86-unwind-orc-fix-error-path-for-bad-orc-entry-type.patch x86-unwind-orc-fix-premature-unwind-stoppage-due-to-iret-frames.patch x86-unwind-orc-prevent-unwinding-before-orc-initialization.patch --- ...-update-the-udp-checksum-when-it-s-0.patch | 68 ++++++ ...f-avoid-passing-pointer-to-local-var.patch | 75 ++++++ ...ck-offset-tracking-for-indirect-cfas.patch | 50 ++++ ...-fix-trapping-instruction-formatting.patch | 46 ++++ queue-4.19/series | 11 + ...fix-unwind-hints-in-kernel-exit-path.patch | 69 ++++++ ...wind-hints-in-register-clearing-code.patch | 110 +++++++++ ...unwind-hints-in-rewind_stack_do_exit.patch | 41 ++++ ...p-the-first-frame-for-inactive-tasks.patch | 48 ++++ ...ix-error-path-for-bad-orc-entry-type.patch | 41 ++++ ...e-unwind-stoppage-due-to-iret-frames.patch | 215 ++++++++++++++++++ ...-unwinding-before-orc-initialization.patch | 55 +++++ 12 files changed, 829 insertions(+) create mode 100644 queue-4.19/netfilter-nat-never-update-the-udp-checksum-when-it-s-0.patch create mode 100644 queue-4.19/netfilter-nf_osf-avoid-passing-pointer-to-local-var.patch create mode 100644 queue-4.19/objtool-fix-stack-offset-tracking-for-indirect-cfas.patch create mode 100644 queue-4.19/scripts-decodecode-fix-trapping-instruction-formatting.patch create mode 100644 queue-4.19/x86-entry-64-fix-unwind-hints-in-kernel-exit-path.patch create mode 100644 queue-4.19/x86-entry-64-fix-unwind-hints-in-register-clearing-code.patch create mode 100644 queue-4.19/x86-entry-64-fix-unwind-hints-in-rewind_stack_do_exit.patch create mode 100644 queue-4.19/x86-unwind-orc-don-t-skip-the-first-frame-for-inactive-tasks.patch create mode 100644 queue-4.19/x86-unwind-orc-fix-error-path-for-bad-orc-entry-type.patch create mode 100644 queue-4.19/x86-unwind-orc-fix-premature-unwind-stoppage-due-to-iret-frames.patch create mode 100644 queue-4.19/x86-unwind-orc-prevent-unwinding-before-orc-initialization.patch diff --git a/queue-4.19/netfilter-nat-never-update-the-udp-checksum-when-it-s-0.patch b/queue-4.19/netfilter-nat-never-update-the-udp-checksum-when-it-s-0.patch new file mode 100644 index 00000000000..85bb352c3b5 --- /dev/null +++ b/queue-4.19/netfilter-nat-never-update-the-udp-checksum-when-it-s-0.patch @@ -0,0 +1,68 @@ +From ea64d8d6c675c0bb712689b13810301de9d8f77a Mon Sep 17 00:00:00 2001 +From: Guillaume Nault +Date: Tue, 21 Apr 2020 02:42:19 +0200 +Subject: netfilter: nat: never update the UDP checksum when it's 0 + +From: Guillaume Nault + +commit ea64d8d6c675c0bb712689b13810301de9d8f77a upstream. + +If the UDP header of a local VXLAN endpoint is NAT-ed, and the VXLAN +device has disabled UDP checksums and enabled Tx checksum offloading, +then the skb passed to udp_manip_pkt() has hdr->check == 0 (outer +checksum disabled) and skb->ip_summed == CHECKSUM_PARTIAL (inner packet +checksum offloaded). + +Because of the ->ip_summed value, udp_manip_pkt() tries to update the +outer checksum with the new address and port, leading to an invalid +checksum sent on the wire, as the original null checksum obviously +didn't take the old address and port into account. + +So, we can't take ->ip_summed into account in udp_manip_pkt(), as it +might not refer to the checksum we're acting on. Instead, we can base +the decision to update the UDP checksum entirely on the value of +hdr->check, because it's null if and only if checksum is disabled: + + * A fully computed checksum can't be 0, since a 0 checksum is + represented by the CSUM_MANGLED_0 value instead. + + * A partial checksum can't be 0, since the pseudo-header always adds + at least one non-zero value (the UDP protocol type 0x11) and adding + more values to the sum can't make it wrap to 0 as the carry is then + added to the wrapped number. + + * A disabled checksum uses the special value 0. + +The problem seems to be there from day one, although it was probably +not visible before UDP tunnels were implemented. + +Fixes: 5b1158e909ec ("[NETFILTER]: Add NAT support for nf_conntrack") +Signed-off-by: Guillaume Nault +Reviewed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + net/netfilter/nf_nat_proto_udp.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/net/netfilter/nf_nat_proto_udp.c ++++ b/net/netfilter/nf_nat_proto_udp.c +@@ -66,15 +66,14 @@ static bool udp_manip_pkt(struct sk_buff + enum nf_nat_manip_type maniptype) + { + struct udphdr *hdr; +- bool do_csum; + + if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) + return false; + + hdr = (struct udphdr *)(skb->data + hdroff); +- do_csum = hdr->check || skb->ip_summed == CHECKSUM_PARTIAL; ++ __udp_manip_pkt(skb, l3proto, iphdroff, hdr, tuple, maniptype, ++ !!hdr->check); + +- __udp_manip_pkt(skb, l3proto, iphdroff, hdr, tuple, maniptype, do_csum); + return true; + } + diff --git a/queue-4.19/netfilter-nf_osf-avoid-passing-pointer-to-local-var.patch b/queue-4.19/netfilter-nf_osf-avoid-passing-pointer-to-local-var.patch new file mode 100644 index 00000000000..3d33ce3682b --- /dev/null +++ b/queue-4.19/netfilter-nf_osf-avoid-passing-pointer-to-local-var.patch @@ -0,0 +1,75 @@ +From c165d57b552aaca607fa5daf3fb524a6efe3c5a3 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Wed, 29 Apr 2020 21:00:41 +0200 +Subject: netfilter: nf_osf: avoid passing pointer to local var + +From: Arnd Bergmann + +commit c165d57b552aaca607fa5daf3fb524a6efe3c5a3 upstream. + +gcc-10 points out that a code path exists where a pointer to a stack +variable may be passed back to the caller: + +net/netfilter/nfnetlink_osf.c: In function 'nf_osf_hdr_ctx_init': +cc1: warning: function may return address of local variable [-Wreturn-local-addr] +net/netfilter/nfnetlink_osf.c:171:16: note: declared here + 171 | struct tcphdr _tcph; + | ^~~~~ + +I am not sure whether this can happen in practice, but moving the +variable declaration into the callers avoids the problem. + +Fixes: 31a9c29210e2 ("netfilter: nf_osf: add struct nf_osf_hdr_ctx") +Signed-off-by: Arnd Bergmann +Reviewed-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman + +--- + net/netfilter/nfnetlink_osf.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/net/netfilter/nfnetlink_osf.c ++++ b/net/netfilter/nfnetlink_osf.c +@@ -170,12 +170,12 @@ static bool nf_osf_match_one(const struc + static const struct tcphdr *nf_osf_hdr_ctx_init(struct nf_osf_hdr_ctx *ctx, + const struct sk_buff *skb, + const struct iphdr *ip, +- unsigned char *opts) ++ unsigned char *opts, ++ struct tcphdr *_tcph) + { + const struct tcphdr *tcp; +- struct tcphdr _tcph; + +- tcp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(struct tcphdr), &_tcph); ++ tcp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(struct tcphdr), _tcph); + if (!tcp) + return NULL; + +@@ -210,10 +210,11 @@ nf_osf_match(const struct sk_buff *skb, + int fmatch = FMATCH_WRONG; + struct nf_osf_hdr_ctx ctx; + const struct tcphdr *tcp; ++ struct tcphdr _tcph; + + memset(&ctx, 0, sizeof(ctx)); + +- tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts); ++ tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts, &_tcph); + if (!tcp) + return false; + +@@ -270,10 +271,11 @@ const char *nf_osf_find(const struct sk_ + struct nf_osf_hdr_ctx ctx; + const struct tcphdr *tcp; + const char *genre = NULL; ++ struct tcphdr _tcph; + + memset(&ctx, 0, sizeof(ctx)); + +- tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts); ++ tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts, &_tcph); + if (!tcp) + return NULL; + diff --git a/queue-4.19/objtool-fix-stack-offset-tracking-for-indirect-cfas.patch b/queue-4.19/objtool-fix-stack-offset-tracking-for-indirect-cfas.patch new file mode 100644 index 00000000000..41fe47d338a --- /dev/null +++ b/queue-4.19/objtool-fix-stack-offset-tracking-for-indirect-cfas.patch @@ -0,0 +1,50 @@ +From d8dd25a461e4eec7190cb9d66616aceacc5110ad Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Sat, 25 Apr 2020 05:03:00 -0500 +Subject: objtool: Fix stack offset tracking for indirect CFAs + +From: Josh Poimboeuf + +commit d8dd25a461e4eec7190cb9d66616aceacc5110ad upstream. + +When the current frame address (CFA) is stored on the stack (i.e., +cfa->base == CFI_SP_INDIRECT), objtool neglects to adjust the stack +offset when there are subsequent pushes or pops. This results in bad +ORC data at the end of the ENTER_IRQ_STACK macro, when it puts the +previous stack pointer on the stack and does a subsequent push. + +This fixes the following unwinder warning: + + WARNING: can't dereference registers at 00000000f0a6bdba for ip interrupt_entry+0x9f/0xa0 + +Fixes: 627fce14809b ("objtool: Add ORC unwind table generation") +Reported-by: Vince Weaver +Reported-by: Dave Jones +Reported-by: Steven Rostedt +Reported-by: Vegard Nossum +Reported-by: Joe Mario +Reviewed-by: Miroslav Benes +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: Jann Horn +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Link: https://lore.kernel.org/r/853d5d691b29e250333332f09b8e27410b2d9924.1587808742.git.jpoimboe@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + tools/objtool/check.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1315,7 +1315,7 @@ static int update_insn_state_regs(struct + struct cfi_reg *cfa = &state->cfa; + struct stack_op *op = &insn->stack_op; + +- if (cfa->base != CFI_SP) ++ if (cfa->base != CFI_SP && cfa->base != CFI_SP_INDIRECT) + return 0; + + /* push */ diff --git a/queue-4.19/scripts-decodecode-fix-trapping-instruction-formatting.patch b/queue-4.19/scripts-decodecode-fix-trapping-instruction-formatting.patch new file mode 100644 index 00000000000..92b090e14c7 --- /dev/null +++ b/queue-4.19/scripts-decodecode-fix-trapping-instruction-formatting.patch @@ -0,0 +1,46 @@ +From e08df079b23e2e982df15aa340bfbaf50f297504 Mon Sep 17 00:00:00 2001 +From: Ivan Delalande +Date: Thu, 7 May 2020 18:35:53 -0700 +Subject: scripts/decodecode: fix trapping instruction formatting + +From: Ivan Delalande + +commit e08df079b23e2e982df15aa340bfbaf50f297504 upstream. + +If the trapping instruction contains a ':', for a memory access through +segment registers for example, the sed substitution will insert the '*' +marker in the middle of the instruction instead of the line address: + + 2b: 65 48 0f c7 0f cmpxchg16b %gs:*(%rdi) <-- trapping instruction + +I started to think I had forgotten some quirk of the assembly syntax +before noticing that it was actually coming from the script. Fix it to +add the address marker at the right place for these instructions: + + 28: 49 8b 06 mov (%r14),%rax + 2b:* 65 48 0f c7 0f cmpxchg16b %gs:(%rdi) <-- trapping instruction + 30: 0f 94 c0 sete %al + +Fixes: 18ff44b189e2 ("scripts/decodecode: make faulting insn ptr more robust") +Signed-off-by: Ivan Delalande +Signed-off-by: Andrew Morton +Reviewed-by: Borislav Petkov +Link: http://lkml.kernel.org/r/20200419223653.GA31248@visor +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + scripts/decodecode | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/scripts/decodecode ++++ b/scripts/decodecode +@@ -119,7 +119,7 @@ faultlinenum=$(( $(wc -l $T.oo | cut -d + faultline=`cat $T.dis | head -1 | cut -d":" -f2-` + faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'` + +-cat $T.oo | sed -e "${faultlinenum}s/^\(.*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/" ++cat $T.oo | sed -e "${faultlinenum}s/^\([^:]*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/" + echo + cat $T.aa + cleanup diff --git a/queue-4.19/series b/queue-4.19/series index bef7adb9a41..4b94b37a9d7 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -34,3 +34,14 @@ batman-adv-fix-batadv_nc_random_weight_tq.patch batman-adv-fix-refcnt-leak-in-batadv_show_throughput_override.patch batman-adv-fix-refcnt-leak-in-batadv_store_throughput_override.patch batman-adv-fix-refcnt-leak-in-batadv_v_ogm_process.patch +x86-entry-64-fix-unwind-hints-in-register-clearing-code.patch +x86-entry-64-fix-unwind-hints-in-kernel-exit-path.patch +x86-entry-64-fix-unwind-hints-in-rewind_stack_do_exit.patch +x86-unwind-orc-don-t-skip-the-first-frame-for-inactive-tasks.patch +x86-unwind-orc-prevent-unwinding-before-orc-initialization.patch +x86-unwind-orc-fix-error-path-for-bad-orc-entry-type.patch +x86-unwind-orc-fix-premature-unwind-stoppage-due-to-iret-frames.patch +netfilter-nat-never-update-the-udp-checksum-when-it-s-0.patch +netfilter-nf_osf-avoid-passing-pointer-to-local-var.patch +objtool-fix-stack-offset-tracking-for-indirect-cfas.patch +scripts-decodecode-fix-trapping-instruction-formatting.patch diff --git a/queue-4.19/x86-entry-64-fix-unwind-hints-in-kernel-exit-path.patch b/queue-4.19/x86-entry-64-fix-unwind-hints-in-kernel-exit-path.patch new file mode 100644 index 00000000000..562d8e4af01 --- /dev/null +++ b/queue-4.19/x86-entry-64-fix-unwind-hints-in-kernel-exit-path.patch @@ -0,0 +1,69 @@ +From 1fb143634a38095b641a3a21220774799772dc4c Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Sat, 25 Apr 2020 05:03:02 -0500 +Subject: x86/entry/64: Fix unwind hints in kernel exit path + +From: Josh Poimboeuf + +commit 1fb143634a38095b641a3a21220774799772dc4c upstream. + +In swapgs_restore_regs_and_return_to_usermode, after the stack is +switched to the trampoline stack, the existing UNWIND_HINT_REGS hint is +no longer valid, which can result in the following ORC unwinder warning: + + WARNING: can't dereference registers at 000000003aeb0cdd for ip swapgs_restore_regs_and_return_to_usermode+0x93/0xa0 + +For full correctness, we could try to add complicated unwind hints so +the unwinder could continue to find the registers, but when when it's +this close to kernel exit, unwind hints aren't really needed anymore and +it's fine to just use an empty hint which tells the unwinder to stop. + +For consistency, also move the UNWIND_HINT_EMPTY in +entry_SYSCALL_64_after_hwframe to a similar location. + +Fixes: 3e3b9293d392 ("x86/entry/64: Return to userspace from the trampoline stack") +Reported-by: Vince Weaver +Reported-by: Dave Jones +Reported-by: Dr. David Alan Gilbert +Reported-by: Joe Mario +Reported-by: Jann Horn +Reported-by: Linus Torvalds +Reviewed-by: Miroslav Benes +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Link: https://lore.kernel.org/r/60ea8f562987ed2d9ace2977502fe481c0d7c9a0.1587808742.git.jpoimboe@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/entry/entry_64.S | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/x86/entry/entry_64.S ++++ b/arch/x86/entry/entry_64.S +@@ -312,7 +312,6 @@ GLOBAL(entry_SYSCALL_64_after_hwframe) + */ + syscall_return_via_sysret: + /* rcx and r11 are already restored (see code above) */ +- UNWIND_HINT_EMPTY + POP_REGS pop_rdi=0 skip_r11rcx=1 + + /* +@@ -321,6 +320,7 @@ syscall_return_via_sysret: + */ + movq %rsp, %rdi + movq PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp ++ UNWIND_HINT_EMPTY + + pushq RSP-RDI(%rdi) /* RSP */ + pushq (%rdi) /* RDI */ +@@ -700,6 +700,7 @@ GLOBAL(swapgs_restore_regs_and_return_to + */ + movq %rsp, %rdi + movq PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp ++ UNWIND_HINT_EMPTY + + /* Copy the IRET frame to the trampoline stack. */ + pushq 6*8(%rdi) /* SS */ diff --git a/queue-4.19/x86-entry-64-fix-unwind-hints-in-register-clearing-code.patch b/queue-4.19/x86-entry-64-fix-unwind-hints-in-register-clearing-code.patch new file mode 100644 index 00000000000..5d65eb030f0 --- /dev/null +++ b/queue-4.19/x86-entry-64-fix-unwind-hints-in-register-clearing-code.patch @@ -0,0 +1,110 @@ +From 06a9750edcffa808494d56da939085c35904e618 Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Sat, 25 Apr 2020 05:03:01 -0500 +Subject: x86/entry/64: Fix unwind hints in register clearing code + +From: Josh Poimboeuf + +commit 06a9750edcffa808494d56da939085c35904e618 upstream. + +The PUSH_AND_CLEAR_REGS macro zeroes each register immediately after +pushing it. If an NMI or exception hits after a register is cleared, +but before the UNWIND_HINT_REGS annotation, the ORC unwinder will +wrongly think the previous value of the register was zero. This can +confuse the unwinding process and cause it to exit early. + +Because ORC is simpler than DWARF, there are a limited number of unwind +annotation states, so it's not possible to add an individual unwind hint +after each push/clear combination. Instead, the register clearing +instructions need to be consolidated and moved to after the +UNWIND_HINT_REGS annotation. + +Fixes: 3f01daecd545 ("x86/entry/64: Introduce the PUSH_AND_CLEAN_REGS macro") +Reviewed-by: Miroslav Benes +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: Dave Jones +Cc: Jann Horn +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Vince Weaver +Link: https://lore.kernel.org/r/68fd3d0bc92ae2d62ff7879d15d3684217d51f08.1587808742.git.jpoimboe@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/entry/calling.h | 40 +++++++++++++++++++++------------------- + 1 file changed, 21 insertions(+), 19 deletions(-) + +--- a/arch/x86/entry/calling.h ++++ b/arch/x86/entry/calling.h +@@ -98,13 +98,6 @@ For 32-bit we have the following convent + #define SIZEOF_PTREGS 21*8 + + .macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0 +- /* +- * Push registers and sanitize registers of values that a +- * speculation attack might otherwise want to exploit. The +- * lower registers are likely clobbered well before they +- * could be put to use in a speculative execution gadget. +- * Interleave XOR with PUSH for better uop scheduling: +- */ + .if \save_ret + pushq %rsi /* pt_regs->si */ + movq 8(%rsp), %rsi /* temporarily store the return address in %rsi */ +@@ -114,34 +107,43 @@ For 32-bit we have the following convent + pushq %rsi /* pt_regs->si */ + .endif + pushq \rdx /* pt_regs->dx */ +- xorl %edx, %edx /* nospec dx */ + pushq %rcx /* pt_regs->cx */ +- xorl %ecx, %ecx /* nospec cx */ + pushq \rax /* pt_regs->ax */ + pushq %r8 /* pt_regs->r8 */ +- xorl %r8d, %r8d /* nospec r8 */ + pushq %r9 /* pt_regs->r9 */ +- xorl %r9d, %r9d /* nospec r9 */ + pushq %r10 /* pt_regs->r10 */ +- xorl %r10d, %r10d /* nospec r10 */ + pushq %r11 /* pt_regs->r11 */ +- xorl %r11d, %r11d /* nospec r11*/ + pushq %rbx /* pt_regs->rbx */ +- xorl %ebx, %ebx /* nospec rbx*/ + pushq %rbp /* pt_regs->rbp */ +- xorl %ebp, %ebp /* nospec rbp*/ + pushq %r12 /* pt_regs->r12 */ +- xorl %r12d, %r12d /* nospec r12*/ + pushq %r13 /* pt_regs->r13 */ +- xorl %r13d, %r13d /* nospec r13*/ + pushq %r14 /* pt_regs->r14 */ +- xorl %r14d, %r14d /* nospec r14*/ + pushq %r15 /* pt_regs->r15 */ +- xorl %r15d, %r15d /* nospec r15*/ + UNWIND_HINT_REGS ++ + .if \save_ret + pushq %rsi /* return address on top of stack */ + .endif ++ ++ /* ++ * Sanitize registers of values that a speculation attack might ++ * otherwise want to exploit. The lower registers are likely clobbered ++ * well before they could be put to use in a speculative execution ++ * gadget. ++ */ ++ xorl %edx, %edx /* nospec dx */ ++ xorl %ecx, %ecx /* nospec cx */ ++ xorl %r8d, %r8d /* nospec r8 */ ++ xorl %r9d, %r9d /* nospec r9 */ ++ xorl %r10d, %r10d /* nospec r10 */ ++ xorl %r11d, %r11d /* nospec r11 */ ++ xorl %ebx, %ebx /* nospec rbx */ ++ xorl %ebp, %ebp /* nospec rbp */ ++ xorl %r12d, %r12d /* nospec r12 */ ++ xorl %r13d, %r13d /* nospec r13 */ ++ xorl %r14d, %r14d /* nospec r14 */ ++ xorl %r15d, %r15d /* nospec r15 */ ++ + .endm + + .macro POP_REGS pop_rdi=1 skip_r11rcx=0 diff --git a/queue-4.19/x86-entry-64-fix-unwind-hints-in-rewind_stack_do_exit.patch b/queue-4.19/x86-entry-64-fix-unwind-hints-in-rewind_stack_do_exit.patch new file mode 100644 index 00000000000..1d0c4e4797d --- /dev/null +++ b/queue-4.19/x86-entry-64-fix-unwind-hints-in-rewind_stack_do_exit.patch @@ -0,0 +1,41 @@ +From f977df7b7ca45a4ac4b66d30a8931d0434c394b1 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Sat, 25 Apr 2020 05:03:04 -0500 +Subject: x86/entry/64: Fix unwind hints in rewind_stack_do_exit() + +From: Jann Horn + +commit f977df7b7ca45a4ac4b66d30a8931d0434c394b1 upstream. + +The LEAQ instruction in rewind_stack_do_exit() moves the stack pointer +directly below the pt_regs at the top of the task stack before calling +do_exit(). Tell the unwinder to expect pt_regs. + +Fixes: 8c1f75587a18 ("x86/entry/64: Add unwind hint annotations") +Reviewed-by: Miroslav Benes +Signed-off-by: Jann Horn +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: Dave Jones +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Vince Weaver +Link: https://lore.kernel.org/r/68c33e17ae5963854916a46f522624f8e1d264f2.1587808742.git.jpoimboe@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/entry/entry_64.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/entry/entry_64.S ++++ b/arch/x86/entry/entry_64.S +@@ -1745,7 +1745,7 @@ ENTRY(rewind_stack_do_exit) + + movq PER_CPU_VAR(cpu_current_top_of_stack), %rax + leaq -PTREGS_SIZE(%rax), %rsp +- UNWIND_HINT_FUNC sp_offset=PTREGS_SIZE ++ UNWIND_HINT_REGS + + call do_exit + END(rewind_stack_do_exit) diff --git a/queue-4.19/x86-unwind-orc-don-t-skip-the-first-frame-for-inactive-tasks.patch b/queue-4.19/x86-unwind-orc-don-t-skip-the-first-frame-for-inactive-tasks.patch new file mode 100644 index 00000000000..c775c0e4c7c --- /dev/null +++ b/queue-4.19/x86-unwind-orc-don-t-skip-the-first-frame-for-inactive-tasks.patch @@ -0,0 +1,48 @@ +From f1d9a2abff66aa8156fbc1493abed468db63ea48 Mon Sep 17 00:00:00 2001 +From: Miroslav Benes +Date: Sat, 25 Apr 2020 05:03:07 -0500 +Subject: x86/unwind/orc: Don't skip the first frame for inactive tasks + +From: Miroslav Benes + +commit f1d9a2abff66aa8156fbc1493abed468db63ea48 upstream. + +When unwinding an inactive task, the ORC unwinder skips the first frame +by default. If both the 'regs' and 'first_frame' parameters of +unwind_start() are NULL, 'state->sp' and 'first_frame' are later +initialized to the same value for an inactive task. Given there is a +"less than or equal to" comparison used at the end of __unwind_start() +for skipping stack frames, the first frame is skipped. + +Drop the equal part of the comparison and make the behavior equivalent +to the frame pointer unwinder. + +Fixes: ee9f8fce9964 ("x86/unwind: Add the ORC unwinder") +Reviewed-by: Miroslav Benes +Signed-off-by: Miroslav Benes +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: Dave Jones +Cc: Jann Horn +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Vince Weaver +Link: https://lore.kernel.org/r/7f08db872ab59e807016910acdbe82f744de7065.1587808742.git.jpoimboe@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/unwind_orc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/kernel/unwind_orc.c ++++ b/arch/x86/kernel/unwind_orc.c +@@ -629,7 +629,7 @@ void __unwind_start(struct unwind_state + /* Otherwise, skip ahead to the user-specified starting frame: */ + while (!unwind_done(state) && + (!on_stack(&state->stack_info, first_frame, sizeof(long)) || +- state->sp <= (unsigned long)first_frame)) ++ state->sp < (unsigned long)first_frame)) + unwind_next_frame(state); + + return; diff --git a/queue-4.19/x86-unwind-orc-fix-error-path-for-bad-orc-entry-type.patch b/queue-4.19/x86-unwind-orc-fix-error-path-for-bad-orc-entry-type.patch new file mode 100644 index 00000000000..15075c1f43e --- /dev/null +++ b/queue-4.19/x86-unwind-orc-fix-error-path-for-bad-orc-entry-type.patch @@ -0,0 +1,41 @@ +From a0f81bf26888048100bf017fadf438a5bdffa8d8 Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Sat, 25 Apr 2020 05:06:13 -0500 +Subject: x86/unwind/orc: Fix error path for bad ORC entry type + +From: Josh Poimboeuf + +commit a0f81bf26888048100bf017fadf438a5bdffa8d8 upstream. + +If the ORC entry type is unknown, nothing else can be done other than +reporting an error. Exit the function instead of breaking out of the +switch statement. + +Fixes: ee9f8fce9964 ("x86/unwind: Add the ORC unwinder") +Reviewed-by: Miroslav Benes +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: Dave Jones +Cc: Jann Horn +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Vince Weaver +Link: https://lore.kernel.org/r/a7fa668ca6eabbe81ab18b2424f15adbbfdc810a.1587808742.git.jpoimboe@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/unwind_orc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/kernel/unwind_orc.c ++++ b/arch/x86/kernel/unwind_orc.c +@@ -509,7 +509,7 @@ bool unwind_next_frame(struct unwind_sta + default: + orc_warn("unknown .orc_unwind entry type %d for ip %pB\n", + orc->type, (void *)orig_ip); +- break; ++ goto err; + } + + /* Find BP: */ diff --git a/queue-4.19/x86-unwind-orc-fix-premature-unwind-stoppage-due-to-iret-frames.patch b/queue-4.19/x86-unwind-orc-fix-premature-unwind-stoppage-due-to-iret-frames.patch new file mode 100644 index 00000000000..e09414d0812 --- /dev/null +++ b/queue-4.19/x86-unwind-orc-fix-premature-unwind-stoppage-due-to-iret-frames.patch @@ -0,0 +1,215 @@ +From 81b67439d147677d844d492fcbd03712ea438f42 Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Sat, 25 Apr 2020 05:06:14 -0500 +Subject: x86/unwind/orc: Fix premature unwind stoppage due to IRET frames + +From: Josh Poimboeuf + +commit 81b67439d147677d844d492fcbd03712ea438f42 upstream. + +The following execution path is possible: + + fsnotify() + [ realign the stack and store previous SP in R10 ] + + [ only IRET regs saved ] + common_interrupt() + interrupt_entry() + + [ full pt_regs saved ] + ... + [ unwind stack ] + +When the unwinder goes through the NMI and the IRQ on the stack, and +then sees fsnotify(), it doesn't have access to the value of R10, +because it only has the five IRET registers. So the unwind stops +prematurely. + +However, because the interrupt_entry() code is careful not to clobber +R10 before saving the full regs, the unwinder should be able to read R10 +from the previously saved full pt_regs associated with the NMI. + +Handle this case properly. When encountering an IRET regs frame +immediately after a full pt_regs frame, use the pt_regs as a backup +which can be used to get the C register values. + +Also, note that a call frame resets the 'prev_regs' value, because a +function is free to clobber the registers. For this fix to work, the +IRET and full regs frames must be adjacent, with no FUNC frames in +between. So replace the FUNC hint in interrupt_entry() with an +IRET_REGS hint. + +Fixes: ee9f8fce9964 ("x86/unwind: Add the ORC unwinder") +Reviewed-by: Miroslav Benes +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: Dave Jones +Cc: Jann Horn +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Vince Weaver +Link: https://lore.kernel.org/r/97a408167cc09f1cfa0de31a7b70dd88868d743f.1587808742.git.jpoimboe@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/entry/entry_64.S | 4 +-- + arch/x86/include/asm/unwind.h | 2 - + arch/x86/kernel/unwind_orc.c | 51 ++++++++++++++++++++++++++++++++---------- + 3 files changed, 43 insertions(+), 14 deletions(-) + +--- a/arch/x86/entry/entry_64.S ++++ b/arch/x86/entry/entry_64.S +@@ -575,7 +575,7 @@ END(spurious_entries_start) + * +----------------------------------------------------+ + */ + ENTRY(interrupt_entry) +- UNWIND_HINT_FUNC ++ UNWIND_HINT_IRET_REGS offset=16 + ASM_CLAC + cld + +@@ -607,9 +607,9 @@ ENTRY(interrupt_entry) + pushq 5*8(%rdi) /* regs->eflags */ + pushq 4*8(%rdi) /* regs->cs */ + pushq 3*8(%rdi) /* regs->ip */ ++ UNWIND_HINT_IRET_REGS + pushq 2*8(%rdi) /* regs->orig_ax */ + pushq 8(%rdi) /* return address */ +- UNWIND_HINT_FUNC + + movq (%rdi), %rdi + jmp 2f +--- a/arch/x86/include/asm/unwind.h ++++ b/arch/x86/include/asm/unwind.h +@@ -19,7 +19,7 @@ struct unwind_state { + #if defined(CONFIG_UNWINDER_ORC) + bool signal, full_regs; + unsigned long sp, bp, ip; +- struct pt_regs *regs; ++ struct pt_regs *regs, *prev_regs; + #elif defined(CONFIG_UNWINDER_FRAME_POINTER) + bool got_irq; + unsigned long *bp, *orig_sp, ip; +--- a/arch/x86/kernel/unwind_orc.c ++++ b/arch/x86/kernel/unwind_orc.c +@@ -364,9 +364,38 @@ static bool deref_stack_iret_regs(struct + return true; + } + ++/* ++ * If state->regs is non-NULL, and points to a full pt_regs, just get the reg ++ * value from state->regs. ++ * ++ * Otherwise, if state->regs just points to IRET regs, and the previous frame ++ * had full regs, it's safe to get the value from the previous regs. This can ++ * happen when early/late IRQ entry code gets interrupted by an NMI. ++ */ ++static bool get_reg(struct unwind_state *state, unsigned int reg_off, ++ unsigned long *val) ++{ ++ unsigned int reg = reg_off/8; ++ ++ if (!state->regs) ++ return false; ++ ++ if (state->full_regs) { ++ *val = ((unsigned long *)state->regs)[reg]; ++ return true; ++ } ++ ++ if (state->prev_regs) { ++ *val = ((unsigned long *)state->prev_regs)[reg]; ++ return true; ++ } ++ ++ return false; ++} ++ + bool unwind_next_frame(struct unwind_state *state) + { +- unsigned long ip_p, sp, orig_ip = state->ip, prev_sp = state->sp; ++ unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp; + enum stack_type prev_type = state->stack_info.type; + struct orc_entry *orc; + bool indirect = false; +@@ -420,39 +449,35 @@ bool unwind_next_frame(struct unwind_sta + break; + + case ORC_REG_R10: +- if (!state->regs || !state->full_regs) { ++ if (!get_reg(state, offsetof(struct pt_regs, r10), &sp)) { + orc_warn("missing regs for base reg R10 at ip %pB\n", + (void *)state->ip); + goto err; + } +- sp = state->regs->r10; + break; + + case ORC_REG_R13: +- if (!state->regs || !state->full_regs) { ++ if (!get_reg(state, offsetof(struct pt_regs, r13), &sp)) { + orc_warn("missing regs for base reg R13 at ip %pB\n", + (void *)state->ip); + goto err; + } +- sp = state->regs->r13; + break; + + case ORC_REG_DI: +- if (!state->regs || !state->full_regs) { ++ if (!get_reg(state, offsetof(struct pt_regs, di), &sp)) { + orc_warn("missing regs for base reg DI at ip %pB\n", + (void *)state->ip); + goto err; + } +- sp = state->regs->di; + break; + + case ORC_REG_DX: +- if (!state->regs || !state->full_regs) { ++ if (!get_reg(state, offsetof(struct pt_regs, dx), &sp)) { + orc_warn("missing regs for base reg DX at ip %pB\n", + (void *)state->ip); + goto err; + } +- sp = state->regs->dx; + break; + + default: +@@ -479,6 +504,7 @@ bool unwind_next_frame(struct unwind_sta + + state->sp = sp; + state->regs = NULL; ++ state->prev_regs = NULL; + state->signal = false; + break; + +@@ -490,6 +516,7 @@ bool unwind_next_frame(struct unwind_sta + } + + state->regs = (struct pt_regs *)sp; ++ state->prev_regs = NULL; + state->full_regs = true; + state->signal = true; + break; +@@ -501,6 +528,8 @@ bool unwind_next_frame(struct unwind_sta + goto err; + } + ++ if (state->full_regs) ++ state->prev_regs = state->regs; + state->regs = (void *)sp - IRET_FRAME_OFFSET; + state->full_regs = false; + state->signal = true; +@@ -515,8 +544,8 @@ bool unwind_next_frame(struct unwind_sta + /* Find BP: */ + switch (orc->bp_reg) { + case ORC_REG_UNDEFINED: +- if (state->regs && state->full_regs) +- state->bp = state->regs->bp; ++ if (get_reg(state, offsetof(struct pt_regs, bp), &tmp)) ++ state->bp = tmp; + break; + + case ORC_REG_PREV_SP: diff --git a/queue-4.19/x86-unwind-orc-prevent-unwinding-before-orc-initialization.patch b/queue-4.19/x86-unwind-orc-prevent-unwinding-before-orc-initialization.patch new file mode 100644 index 00000000000..51d4f8d7d5c --- /dev/null +++ b/queue-4.19/x86-unwind-orc-prevent-unwinding-before-orc-initialization.patch @@ -0,0 +1,55 @@ +From 98d0c8ebf77e0ba7c54a9ae05ea588f0e9e3f46e Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Sat, 25 Apr 2020 05:03:08 -0500 +Subject: x86/unwind/orc: Prevent unwinding before ORC initialization + +From: Josh Poimboeuf + +commit 98d0c8ebf77e0ba7c54a9ae05ea588f0e9e3f46e upstream. + +If the unwinder is called before the ORC data has been initialized, +orc_find() returns NULL, and it tries to fall back to using frame +pointers. This can cause some unexpected warnings during boot. + +Move the 'orc_init' check from orc_find() to __unwind_init(), so that it +doesn't even try to unwind from an uninitialized state. + +Fixes: ee9f8fce9964 ("x86/unwind: Add the ORC unwinder") +Reviewed-by: Miroslav Benes +Signed-off-by: Josh Poimboeuf +Signed-off-by: Ingo Molnar +Cc: Andy Lutomirski +Cc: Dave Jones +Cc: Jann Horn +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Cc: Vince Weaver +Link: https://lore.kernel.org/r/069d1499ad606d85532eb32ce39b2441679667d5.1587808742.git.jpoimboe@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/unwind_orc.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/x86/kernel/unwind_orc.c ++++ b/arch/x86/kernel/unwind_orc.c +@@ -131,9 +131,6 @@ static struct orc_entry *orc_find(unsign + { + static struct orc_entry *orc; + +- if (!orc_init) +- return NULL; +- + if (ip == 0) + return &null_orc_entry; + +@@ -563,6 +560,9 @@ EXPORT_SYMBOL_GPL(unwind_next_frame); + void __unwind_start(struct unwind_state *state, struct task_struct *task, + struct pt_regs *regs, unsigned long *first_frame) + { ++ if (!orc_init) ++ goto done; ++ + memset(state, 0, sizeof(*state)); + state->task = task; + -- 2.47.3