From 401046e00052b3c8adffd5edcd95ddd30f112e3d Mon Sep 17 00:00:00 2001 From: Kernel Build Daemon Date: Sep 06 2022 05:55:51 +0000 Subject: Merge branch 'SLE12-SP5' into SLE12-SP5-AZURE --- diff --git a/blacklist.conf b/blacklist.conf index 048cc02..963c0ae 100644 --- a/blacklist.conf +++ b/blacklist.conf @@ -2238,3 +2238,6 @@ f53bad0881a35c45d89bd8c552dc0498b96403c5 # relevant only on m68k 089bca2caed0d0dea7da235ce1fe245808f5ec02 # lockdep warning 369f61bee0f584aee09f0736431eb9b330c98571 # lockdep warning b6d49cab44b567b3e0a5544b3d61e516a7355fad # Kconfig from imply to depends +dbac14a5a05ff8e1ce7c0da0e1f520ce39ec62ea # removal of export would break kabi +c5deb27895e017a0267de0a20d140ad5fcc55a54 # no fix needed, as problem is prohibited by other means +2fdbb8dd01556e1501132b5ad3826e8f71e24a8b # risk is too high without a real request diff --git a/patches.suse/KVM-x86-Mark-TSS-busy-during-LTR-emulation-_after_-a.patch b/patches.suse/KVM-x86-Mark-TSS-busy-during-LTR-emulation-_after_-a.patch new file mode 100644 index 0000000..1e716f0 --- /dev/null +++ b/patches.suse/KVM-x86-Mark-TSS-busy-during-LTR-emulation-_after_-a.patch @@ -0,0 +1,70 @@ +Patch-mainline: v6.0-rc1 +Git-commit: ec6e4d863258d4bfb36d48d5e3ef68140234d688 +References: git-fixes +From: Sean Christopherson +Date: Mon, 11 Jul 2022 23:27:48 +0000 +Subject: [PATCH] KVM: x86: Mark TSS busy during LTR emulation _after_ all + fault checks + +Wait to mark the TSS as busy during LTR emulation until after all fault +checks for the LTR have passed. Specifically, don't mark the TSS busy if +the new TSS base is non-canonical. + +Opportunistically drop the one-off !seg_desc.PRESENT check for TR as the +only reason for the early check was to avoid marking a !PRESENT TSS as +busy, i.e. the common !PRESENT is now done before setting the busy bit. + +Fixes: e37a75a13cda ("KVM: x86: Emulator ignores LDTR/TR extended base on LLDT/LTR") +Reported-by: syzbot+760a73552f47a8cd0fd9@syzkaller.appspotmail.com +Cc: stable@vger.kernel.org +Cc: Tetsuo Handa +Cc: Hou Wenlong +Signed-off-by: Sean Christopherson +Reviewed-by: Maxim Levitsky +Link: https://lore.kernel.org/r/20220711232750.1092012-2-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Juergen Gross +--- + arch/x86/kvm/emulate.c | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 39ea9138224c..09e4b67b881f 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -1699,16 +1699,6 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, + case VCPU_SREG_TR: + if (seg_desc.s || (seg_desc.type != 1 && seg_desc.type != 9)) + goto exception; +- if (!seg_desc.p) { +- err_vec = NP_VECTOR; +- goto exception; +- } +- old_desc = seg_desc; +- seg_desc.type |= 2; /* busy */ +- ret = ctxt->ops->cmpxchg_emulated(ctxt, desc_addr, &old_desc, &seg_desc, +- sizeof(seg_desc), &ctxt->exception); +- if (ret != X86EMUL_CONTINUE) +- return ret; + break; + case VCPU_SREG_LDTR: + if (seg_desc.s || seg_desc.type != 2) +@@ -1749,6 +1739,15 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, + ((u64)base3 << 32), ctxt)) + return emulate_gp(ctxt, 0); + } ++ ++ if (seg == VCPU_SREG_TR) { ++ old_desc = seg_desc; ++ seg_desc.type |= 2; /* busy */ ++ ret = ctxt->ops->cmpxchg_emulated(ctxt, desc_addr, &old_desc, &seg_desc, ++ sizeof(seg_desc), &ctxt->exception); ++ if (ret != X86EMUL_CONTINUE) ++ return ret; ++ } + load: + ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg); + if (desc) +-- +2.35.3 + diff --git a/patches.suse/KVM-x86-Set-error-code-to-segment-selector-on-LLDT-L.patch b/patches.suse/KVM-x86-Set-error-code-to-segment-selector-on-LLDT-L.patch new file mode 100644 index 0000000..ef736c8 --- /dev/null +++ b/patches.suse/KVM-x86-Set-error-code-to-segment-selector-on-LLDT-L.patch @@ -0,0 +1,45 @@ +Patch-mainline: v6.0-rc1 +Git-commit: 2626206963ace9e8bf92b6eea5ff78dd674c555c +References: git-fixes +From: Sean Christopherson +Date: Mon, 11 Jul 2022 23:27:49 +0000 +Subject: [PATCH] KVM: x86: Set error code to segment selector on LLDT/LTR + non-canonical #GP + +When injecting a #GP on LLDT/LTR due to a non-canonical LDT/TSS base, set +the error code to the selector. Intel SDM's says nothing about the #GP, +but AMD's APM explicitly states that both LLDT and LTR set the error code +to the selector, not zero. + +Note, a non-canonical memory operand on LLDT/LTR does generate a #GP(0), +but the KVM code in question is specific to the base from the descriptor. + +Fixes: e37a75a13cda ("KVM: x86: Emulator ignores LDTR/TR extended base on LLDT/LTR") +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson +Reviewed-by: Maxim Levitsky +Link: https://lore.kernel.org/r/20220711232750.1092012-3-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Juergen Gross +--- + arch/x86/kvm/emulate.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c +index 09e4b67b881f..bd9e9c5627d0 100644 +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -1736,8 +1736,8 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, + if (ret != X86EMUL_CONTINUE) + return ret; + if (emul_is_noncanonical_address(get_desc_base(&seg_desc) | +- ((u64)base3 << 32), ctxt)) +- return emulate_gp(ctxt, 0); ++ ((u64)base3 << 32), ctxt)) ++ return emulate_gp(ctxt, err_code); + } + + if (seg == VCPU_SREG_TR) { +-- +2.35.3 + diff --git a/patches.suse/SUNRPC-Fix-the-svc_deferred_event-trace-class.patch b/patches.suse/SUNRPC-Fix-the-svc_deferred_event-trace-class.patch new file mode 100644 index 0000000..e65ab52 --- /dev/null +++ b/patches.suse/SUNRPC-Fix-the-svc_deferred_event-trace-class.patch @@ -0,0 +1,66 @@ +From: Chuck Lever +Date: Wed, 6 Apr 2022 13:51:32 -0400 +Subject: SUNRPC: Fix the svc_deferred_event trace class +Git-commit: 4d5004451ab2218eab94a30e1841462c9316ba19 +Patch-mainline: v5.18-rc3 +References: git-fixes + +Fix a NULL deref crash that occurs when an svc_rqst is deferred +while the sunrpc tracing subsystem is enabled. svc_revisit() sets +dr->xprt to NULL, so it can't be relied upon in the tracepoint to +provide the remote's address. + +Unfortunately we can't revert the "svc_deferred_class" hunk in +commit ece200ddd54b ("sunrpc: Save remote presentation address in +svc_xprt for trace events") because there is now a specific check +of event format specifiers for unsafe dereferences. The warning +that check emits is: + + event svc_defer_recv has unsafe dereference of argument 1 + +A "%pISpc" format specifier with a "struct sockaddr *" is indeed +flagged by this check. + +Instead, take the brute-force approach used by the svcrdma_qp_error +tracepoint. Convert the dr::addr field into a presentation address +in the TP_fast_assign() arm of the trace event, and store that as +a string. This fix can be backported to -stable kernels. + +In the meantime, commit c6ced22997ad ("tracing: Update print fmt +check to handle new __get_sockaddr() macro") is now in v5.18, so +this wonky fix can be replaced with __sockaddr() and friends +properly during the v5.19 merge window. + +Fixes: ece200ddd54b ("sunrpc: Save remote presentation address in svc_xprt for trace events") +Signed-off-by: Chuck Lever +Acked-by: Petr Pavlu +--- + include/trace/events/sunrpc.h | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h +index ab8ae1f6ba84..4eb706fa5825 100644 +--- a/include/trace/events/sunrpc.h ++++ b/include/trace/events/sunrpc.h +@@ -2017,16 +2017,17 @@ DECLARE_EVENT_CLASS(svc_deferred_event, + + TP_STRUCT__entry( + __field(u32, xid) +- __string(addr, dr->xprt->xpt_remotebuf) ++ __array(__u8, addr, INET6_ADDRSTRLEN + 10) + ), + + TP_fast_assign( + __entry->xid = be32_to_cpu(*(__be32 *)(dr->args + + (dr->xprt_hlen>>2))); +- __assign_str(addr, dr->xprt->xpt_remotebuf); ++ snprintf(__entry->addr, sizeof(__entry->addr) - 1, ++ "%pISpc", (struct sockaddr *)&dr->addr); + ), + +- TP_printk("addr=%s xid=0x%08x", __get_str(addr), __entry->xid) ++ TP_printk("addr=%s xid=0x%08x", __entry->addr, __entry->xid) + ); + + DEFINE_EVENT(svc_deferred_event, svc_drop_deferred, + diff --git a/patches.suse/ceph-don-t-truncate-file-in-atomic_open.patch b/patches.suse/ceph-don-t-truncate-file-in-atomic_open.patch new file mode 100644 index 0000000..8af47bb --- /dev/null +++ b/patches.suse/ceph-don-t-truncate-file-in-atomic_open.patch @@ -0,0 +1,50 @@ +From: Hu Weiwen +Date: Fri, 1 Jul 2022 10:52:27 +0800 +Subject: ceph: don't truncate file in atomic_open +Git-commit: 7cb9994754f8a36ae9e5ec4597c5c4c2d6c03832 +Patch-mainline: v6.0-rc1 +References: bsc#1202830 + +Clear O_TRUNC from the flags sent in the MDS create request. + +`atomic_open' is called before permission check. We should not do any +modification to the file here. The caller will do the truncation +afterward. + +Fixes: 124e68e74099 ("ceph: file operations") +Signed-off-by: Hu Weiwen +Reviewed-by: Xiubo Li +Signed-off-by: Ilya Dryomov +Acked-by: Luis Henriques + +--- + fs/ceph/file.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/fs/ceph/file.c ++++ b/fs/ceph/file.c +@@ -447,6 +447,12 @@ int ceph_atomic_open(struct inode *dir, + if (dentry->d_name.len > NAME_MAX) + return -ENAMETOOLONG; + ++ /* ++ * Do not truncate the file, since atomic_open is called before the ++ * permission check. The caller will do the truncation afterward. ++ */ ++ flags &= ~O_TRUNC; ++ + if (flags & O_CREAT) { + if (ceph_quota_is_max_files_exceeded(dir)) + return -EDQUOT; +@@ -482,9 +488,7 @@ int ceph_atomic_open(struct inode *dir, + + req->r_parent = dir; + set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags); +- err = ceph_mdsc_do_request(mdsc, +- (flags & (O_CREAT|O_TRUNC)) ? dir : NULL, +- req); ++ err = ceph_mdsc_do_request(mdsc, (flags & O_CREAT) ? dir : NULL, req); + err = ceph_handle_snapdir(req, dentry, err); + if (err) + goto out_req; + diff --git a/patches.suse/fuse-limit-nsec.patch b/patches.suse/fuse-limit-nsec.patch new file mode 100644 index 0000000..d39da45 --- /dev/null +++ b/patches.suse/fuse-limit-nsec.patch @@ -0,0 +1,34 @@ +From: Miklos Szeredi +Date: Thu, 21 Jul 2022 16:06:18 +0200 +Subject: fuse: limit nsec +Git-commit: 47912eaa061a6a81e4aa790591a1874c650733c0 +Patch-mainline: v6.0-rc1 +References: bsc#1203126 + +Limit nanoseconds to 0..999999999. + +Fixes: d8a5ba45457e ("[PATCH] FUSE - core") +Cc: +Signed-off-by: Miklos Szeredi +Acked-by: Luis Henriques + +--- + fs/fuse/inode.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/fuse/inode.c ++++ b/fs/fuse/inode.c +@@ -174,6 +174,12 @@ void fuse_change_attributes_common(struc + inode->i_uid = make_kuid(&init_user_ns, attr->uid); + inode->i_gid = make_kgid(&init_user_ns, attr->gid); + inode->i_blocks = attr->blocks; ++ ++ /* Sanitize nsecs */ ++ attr->atimensec = min_t(u32, attr->atimensec, NSEC_PER_SEC - 1); ++ attr->mtimensec = min_t(u32, attr->mtimensec, NSEC_PER_SEC - 1); ++ attr->ctimensec = min_t(u32, attr->ctimensec, NSEC_PER_SEC - 1); ++ + inode->i_atime.tv_sec = attr->atime; + inode->i_atime.tv_nsec = attr->atimensec; + /* mtime from server may be stale due to local buffered write */ + diff --git a/patches.suse/objtool-Add-backtrace-support.patch b/patches.suse/objtool-Add-backtrace-support.patch new file mode 100644 index 0000000..7b0c9f4 --- /dev/null +++ b/patches.suse/objtool-Add-backtrace-support.patch @@ -0,0 +1,166 @@ +From: Peter Zijlstra +Date: Fri, 1 Mar 2019 11:15:49 +0100 +Subject: objtool: Add --backtrace support +Git-commit: 7697eee3ddd768a1fd78c1e687afaa6c5aa5072d +Patch-mainline: v5.2-rc1 +References: bsc#1202396 + +For when you want to know the path that reached your fail state: + + $ ./objtool check --no-fp --backtrace arch/x86/lib/usercopy_64.o + arch/x86/lib/usercopy_64.o: warning: objtool: .altinstr_replacement+0x3: UACCESS disable without MEMOPs: __clear_user() + arch/x86/lib/usercopy_64.o: warning: objtool: __clear_user()+0x3a: (alt) + arch/x86/lib/usercopy_64.o: warning: objtool: __clear_user()+0x2e: (branch) + arch/x86/lib/usercopy_64.o: warning: objtool: __clear_user()+0x18: (branch) + arch/x86/lib/usercopy_64.o: warning: objtool: .altinstr_replacement+0xffffffffffffffff: (branch) + arch/x86/lib/usercopy_64.o: warning: objtool: __clear_user()+0x5: (alt) + arch/x86/lib/usercopy_64.o: warning: objtool: __clear_user()+0x0: <=== (func) + + 0000000000000000 <__clear_user>: + 0: e8 00 00 00 00 callq 5 <__clear_user+0x5> + 1: R_X86_64_PLT32 __fentry__-0x4 + 5: 90 nop + 6: 90 nop + 7: 90 nop + 8: 48 89 f0 mov %rsi,%rax + b: 48 c1 ee 03 shr $0x3,%rsi + f: 83 e0 07 and $0x7,%eax + 12: 48 89 f1 mov %rsi,%rcx + 15: 48 85 c9 test %rcx,%rcx + 18: 74 0f je 29 <__clear_user+0x29> + 1a: 48 c7 07 00 00 00 00 movq $0x0,(%rdi) + 21: 48 83 c7 08 add $0x8,%rdi + 25: ff c9 dec %ecx + 27: 75 f1 jne 1a <__clear_user+0x1a> + 29: 48 89 c1 mov %rax,%rcx + 2c: 85 c9 test %ecx,%ecx + 2e: 74 0a je 3a <__clear_user+0x3a> + 30: c6 07 00 movb $0x0,(%rdi) + 33: 48 ff c7 inc %rdi + 36: ff c9 dec %ecx + 38: 75 f6 jne 30 <__clear_user+0x30> + 3a: 90 nop + 3b: 90 nop + 3c: 90 nop + 3d: 48 89 c8 mov %rcx,%rax + 40: c3 retq + +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Josh Poimboeuf +Cc: Borislav Petkov +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Signed-off-by: Ingo Molnar +Acked-by: Miroslav Benes +--- + tools/objtool/builtin-check.c | 3 ++- + tools/objtool/builtin.h | 2 +- + tools/objtool/check.c | 18 ++++++++++++++---- + tools/objtool/warn.h | 8 ++++++++ + 4 files changed, 25 insertions(+), 6 deletions(-) + +diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c +index 694abc628e9b..99f10c585cbe 100644 +--- a/tools/objtool/builtin-check.c ++++ b/tools/objtool/builtin-check.c +@@ -29,7 +29,7 @@ + #include "builtin.h" + #include "check.h" + +-bool no_fp, no_unreachable, retpoline, module; ++bool no_fp, no_unreachable, retpoline, module, backtrace; + + static const char * const check_usage[] = { + "objtool check [] file.o", +@@ -41,6 +41,7 @@ const struct option check_options[] = { + OPT_BOOLEAN('u', "no-unreachable", &no_unreachable, "Skip 'unreachable instruction' warnings"), + OPT_BOOLEAN('r', "retpoline", &retpoline, "Validate retpoline assumptions"), + OPT_BOOLEAN('m', "module", &module, "Indicates the object will be part of a kernel module"), ++ OPT_BOOLEAN('b', "backtrace", &backtrace, "unwind on error"), + OPT_END(), + }; + +diff --git a/tools/objtool/builtin.h b/tools/objtool/builtin.h +index 28ff40e19a14..65fd3cc3c98b 100644 +--- a/tools/objtool/builtin.h ++++ b/tools/objtool/builtin.h +@@ -20,7 +20,7 @@ + #include + + extern const struct option check_options[]; +-extern bool no_fp, no_unreachable, retpoline, module; ++extern bool no_fp, no_unreachable, retpoline, module, backtrace; + + extern int cmd_check(int argc, const char **argv); + extern int cmd_orc(int argc, const char **argv); +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 8d8191f25381..ccc66af5907f 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1885,8 +1885,11 @@ static int validate_branch(struct objtool_file *file, struct instruction *first, + if (!insn->ignore_alts) { + list_for_each_entry(alt, &insn->alts, list) { + ret = validate_branch(file, alt->insn, state); +- if (ret) +- return 1; ++ if (ret) { ++ if (backtrace) ++ BT_FUNC("(alt)", insn); ++ return ret; ++ } + } + } + +@@ -1933,8 +1936,11 @@ static int validate_branch(struct objtool_file *file, struct instruction *first, + insn->jump_dest->func->pfunc == func)) { + ret = validate_branch(file, insn->jump_dest, + state); +- if (ret) +- return 1; ++ if (ret) { ++ if (backtrace) ++ BT_FUNC("(branch)", insn); ++ return ret; ++ } + + } else if (func && has_modified_stack_frame(&state)) { + WARN_FUNC("sibling call from callable instruction with modified stack frame", +@@ -2005,6 +2011,8 @@ static int validate_unwind_hints(struct objtool_file *file) + for_each_insn(file, insn) { + if (insn->hint && !insn->visited) { + ret = validate_branch(file, insn, state); ++ if (ret && backtrace) ++ BT_FUNC("<=== (hint)", insn); + warnings += ret; + } + } +@@ -2133,6 +2141,8 @@ static int validate_functions(struct objtool_file *file) + continue; + + ret = validate_branch(file, insn, state); ++ if (ret && backtrace) ++ BT_FUNC("<=== (func)", insn); + warnings += ret; + } + } +diff --git a/tools/objtool/warn.h b/tools/objtool/warn.h +index afd9f7a05f6d..f4fbb972b611 100644 +--- a/tools/objtool/warn.h ++++ b/tools/objtool/warn.h +@@ -64,6 +64,14 @@ static inline char *offstr(struct section *sec, unsigned long offset) + free(_str); \ + }) + ++#define BT_FUNC(format, insn, ...) \ ++({ \ ++ struct instruction *_insn = (insn); \ ++ char *_str = offstr(_insn->sec, _insn->offset); \ ++ WARN(" %s: " format, _str, ##__VA_ARGS__); \ ++ free(_str); \ ++}) ++ + #define WARN_ELF(format, ...) \ + WARN(format ": %s", ##__VA_ARGS__, elf_errmsg(-1)) + + diff --git a/patches.suse/objtool-Add-support-for-intra-function-calls.patch b/patches.suse/objtool-Add-support-for-intra-function-calls.patch new file mode 100644 index 0000000..73db894 --- /dev/null +++ b/patches.suse/objtool-Add-support-for-intra-function-calls.patch @@ -0,0 +1,199 @@ +From: Alexandre Chartre +Date: Tue, 14 Apr 2020 12:36:12 +0200 +Subject: objtool: Add support for intra-function calls +Git-commit: 8aa8eb2a8f5b3305a95f39957dd2b715fa668e21 +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +Change objtool to support intra-function calls. On x86, an intra-function +call is represented in objtool as a push onto the stack (of the return +address), and a jump to the destination address. That way the stack +information is correctly updated and the call flow is still accurate. + +Signed-off-by: Alexandre Chartre +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Miroslav Benes +Acked-by: Josh Poimboeuf +Link: https://lkml.kernel.org/r/20200414103618.12657-4-alexandre.chartre@oracle.com + +Acked-by: Miroslav Benes +--- + include/linux/frame.h | 11 +++ + tools/objtool/Documentation/stack-validation.txt | 8 ++ + tools/objtool/arch/x86/decode.c | 8 ++ + tools/objtool/check.c | 79 +++++++++++++++++++++-- + 4 files changed, 102 insertions(+), 4 deletions(-) + +--- a/include/linux/frame.h ++++ b/include/linux/frame.h +@@ -14,9 +14,20 @@ + static void __used __section(.discard.func_stack_frame_non_standard) \ + *__func_stack_frame_non_standard_##func = func + ++/* ++ * This macro indicates that the following intra-function call is valid. ++ * Any non-annotated intra-function call will cause objtool to issue a warning. ++ */ ++#define ANNOTATE_INTRA_FUNCTION_CALL \ ++ 999: \ ++ .pushsection .discard.intra_function_calls; \ ++ .long 999b; \ ++ .popsection; ++ + #else /* !CONFIG_STACK_VALIDATION */ + + #define STACK_FRAME_NON_STANDARD(func) ++#define ANNOTATE_INTRA_FUNCTION_CALL + + #endif /* CONFIG_STACK_VALIDATION */ + +--- a/tools/objtool/Documentation/stack-validation.txt ++++ b/tools/objtool/Documentation/stack-validation.txt +@@ -290,6 +290,14 @@ they mean, and suggestions for how to fi + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70646 + + ++11. file.o: warning: unannotated intra-function call ++ ++ This warning means that a direct call is done to a destination which ++ is not at the beginning of a function. If this is a legit call, you ++ can remove this warning by putting the ANNOTATE_INTRA_FUNCTION_CALL ++ directive right before the call. ++ ++ + If the error doesn't seem to make sense, it could be a bug in objtool. + Feel free to ask the objtool maintainer for help. + +--- a/tools/objtool/arch/x86/decode.c ++++ b/tools/objtool/arch/x86/decode.c +@@ -470,6 +470,14 @@ int arch_decode_instruction(struct elf * + + case 0xe8: + *type = INSN_CALL; ++ /* ++ * For the impact on the stack, a CALL behaves like ++ * a PUSH of an immediate value (the return address). ++ */ ++ ADD_OP(op) { ++ op->src.type = OP_SRC_CONST; ++ op->dest.type = OP_DEST_PUSH; ++ } + break; + + case 0xff: +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -590,6 +590,16 @@ static int add_jump_destinations(struct + return 0; + } + ++static void remove_insn_ops(struct instruction *insn) ++{ ++ struct stack_op *op, *tmp; ++ ++ list_for_each_entry_safe(op, tmp, &insn->stack_ops, list) { ++ list_del(&op->list); ++ free(op); ++ } ++} ++ + /* + * Find the destination instructions for all calls. + */ +@@ -611,10 +621,7 @@ static int add_call_destinations(struct + dest_off); + + if (!insn->call_dest && !insn->ignore) { +- WARN_FUNC("unsupported intra-function call", +- insn->sec, insn->offset); +- if (retpoline) +- WARN("If this is a retpoline, please patch it in with alternatives and annotate it with ANNOTATE_NOSPEC_ALTERNATIVE."); ++ WARN_FUNC("unannotated intra-function call", insn->sec, insn->offset); + return -1; + } + +@@ -631,6 +638,15 @@ static int add_call_destinations(struct + } + } else + insn->call_dest = rela->sym; ++ ++ /* ++ * Whatever stack impact regular CALLs have, should be undone ++ * by the RETURN of the called function. ++ * ++ * Annotated intra-function calls retain the stack_ops but ++ * are converted to JUMP, see read_intra_function_calls(). ++ */ ++ remove_insn_ops(insn); + } + + return 0; +@@ -1243,6 +1259,57 @@ static int read_retpoline_hints(struct o + return 0; + } + ++static int read_intra_function_calls(struct objtool_file *file) ++{ ++ struct instruction *insn; ++ struct section *sec; ++ struct rela *rela; ++ ++ sec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls"); ++ if (!sec) ++ return 0; ++ ++ list_for_each_entry(rela, &sec->rela_list, list) { ++ unsigned long dest_off; ++ ++ if (rela->sym->type != STT_SECTION) { ++ WARN("unexpected relocation symbol type in %s", ++ sec->name); ++ return -1; ++ } ++ ++ insn = find_insn(file, rela->sym->sec, rela->addend); ++ if (!insn) { ++ WARN("bad .discard.intra_function_call entry"); ++ return -1; ++ } ++ ++ if (insn->type != INSN_CALL) { ++ WARN_FUNC("intra_function_call not a direct call", ++ insn->sec, insn->offset); ++ return -1; ++ } ++ ++ /* ++ * Treat intra-function CALLs as JMPs, but with a stack_op. ++ * See add_call_destinations(), which strips stack_ops from ++ * normal CALLs. ++ */ ++ insn->type = INSN_JUMP_UNCONDITIONAL; ++ ++ dest_off = insn->offset + insn->len + insn->immediate; ++ insn->jump_dest = find_insn(file, insn->sec, dest_off); ++ if (!insn->jump_dest) { ++ WARN_FUNC("can't find call dest at %s+0x%lx", ++ insn->sec, insn->offset, ++ insn->sec->name, dest_off); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ + static int decode_sections(struct objtool_file *file) + { + int ret; +@@ -1269,6 +1336,10 @@ static int decode_sections(struct objtoo + if (ret) + return ret; + ++ ret = read_intra_function_calls(file); ++ if (ret) ++ return ret; ++ + ret = add_call_destinations(file); + if (ret) + return ret; diff --git a/patches.suse/objtool-Allow-no-op-CFI-ops-in-alternatives.patch b/patches.suse/objtool-Allow-no-op-CFI-ops-in-alternatives.patch new file mode 100644 index 0000000..860e263 --- /dev/null +++ b/patches.suse/objtool-Allow-no-op-CFI-ops-in-alternatives.patch @@ -0,0 +1,59 @@ +From: Peter Zijlstra +Date: Fri, 8 May 2020 12:34:33 +0200 +Subject: objtool: Allow no-op CFI ops in alternatives +Git-commit: ab3852ab5cb8fd2e2c5bfa176e5f953353836907 +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +Randy reported a false-positive: + + arch/x86/hyperv/hv_apic.o: warning: objtool: hv_apic_write()+0x25: alternative modifies stack + +What happens is that: + + alternative_io("movl %0, %P1", "xchgl %0, %P1", X86_BUG_11AP, + 13d: 89 9d 00 d0 7f ff mov %ebx,-0x803000(%rbp) + +decodes to an instruction with CFI-ops because it modifies RBP. +However, due to this being a !frame-pointer build, that should not in +fact change the CFI state. + +So instead of dis-allowing any CFI-op, verify the op would've actually +changed the CFI state. + +Fixes: 7117f16bf460 ("objtool: Fix ORC vs alternatives") +Reported-by: Randy Dunlap +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Josh Poimboeuf +Acked-by: Randy Dunlap +Tested-by: Randy Dunlap +Acked-by: Miroslav Benes +--- + tools/objtool/check.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1842,16 +1842,17 @@ static int handle_insn_ops(struct instru + struct stack_op *op; + + list_for_each_entry(op, &insn->stack_ops, list) { ++ struct cfi_state old_cfi = state->cfi; + int res; + +- if (insn->alt_group) { +- WARN_FUNC("alternative modifies stack", insn->sec, insn->offset); +- return -1; +- } +- + res = update_cfi_state(insn, &state->cfi, op); + if (res) + return res; ++ ++ if (insn->alt_group && memcmp(&state->cfi, &old_cfi, sizeof(struct cfi_state))) { ++ WARN_FUNC("alternative modifies stack", insn->sec, insn->offset); ++ return -1; ++ } + } + + return 0; diff --git a/patches.suse/objtool-Convert-insn-type-to-enum.patch b/patches.suse/objtool-Convert-insn-type-to-enum.patch new file mode 100644 index 0000000..0a31ef1 --- /dev/null +++ b/patches.suse/objtool-Convert-insn-type-to-enum.patch @@ -0,0 +1,105 @@ +From: Josh Poimboeuf +Date: Wed, 17 Jul 2019 20:36:56 -0500 +Subject: objtool: Convert insn type to enum +Git-commit: 9fe7b7642fe2c5158904d06fe31b740ca0695a01 +Patch-mainline: v5.3-rc1 +References: bsc#1202396 + +This makes it easier to add new instruction types. Also it's hopefully +more robust since the compiler should warn about out-of-range enums. + +Signed-off-by: Josh Poimboeuf +Signed-off-by: Thomas Gleixner +Tested-by: Nick Desaulniers +Acked-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/0740e96af0d40e54cfd6a07bf09db0fbd10793cd.1563413318.git.jpoimboe@redhat.com + +Acked-by: Miroslav Benes +--- + tools/objtool/arch.h | 27 ++++++++++++++------------- + tools/objtool/arch/x86/decode.c | 2 +- + tools/objtool/check.c | 7 ------- + tools/objtool/check.h | 2 +- + 4 files changed, 16 insertions(+), 22 deletions(-) + +--- a/tools/objtool/arch.h ++++ b/tools/objtool/arch.h +@@ -23,18 +23,19 @@ + #include "elf.h" + #include "cfi.h" + +-#define INSN_JUMP_CONDITIONAL 1 +-#define INSN_JUMP_UNCONDITIONAL 2 +-#define INSN_JUMP_DYNAMIC 3 +-#define INSN_CALL 4 +-#define INSN_CALL_DYNAMIC 5 +-#define INSN_RETURN 6 +-#define INSN_CONTEXT_SWITCH 7 +-#define INSN_STACK 8 +-#define INSN_BUG 9 +-#define INSN_NOP 10 +-#define INSN_OTHER 11 +-#define INSN_LAST INSN_OTHER ++enum insn_type { ++ INSN_JUMP_CONDITIONAL, ++ INSN_JUMP_UNCONDITIONAL, ++ INSN_JUMP_DYNAMIC, ++ INSN_CALL, ++ INSN_CALL_DYNAMIC, ++ INSN_RETURN, ++ INSN_CONTEXT_SWITCH, ++ INSN_STACK, ++ INSN_BUG, ++ INSN_NOP, ++ INSN_OTHER, ++}; + + enum op_dest_type { + OP_DEST_REG, +@@ -74,7 +75,7 @@ void arch_initial_func_cfi_state(struct + + int arch_decode_instruction(struct elf *elf, struct section *sec, + unsigned long offset, unsigned int maxlen, +- unsigned int *len, unsigned char *type, ++ unsigned int *len, enum insn_type *type, + unsigned long *immediate, struct stack_op *op); + + bool arch_callee_saved_reg(unsigned char reg); +--- a/tools/objtool/arch/x86/decode.c ++++ b/tools/objtool/arch/x86/decode.c +@@ -80,7 +80,7 @@ bool arch_callee_saved_reg(unsigned char + + int arch_decode_instruction(struct elf *elf, struct section *sec, + unsigned long offset, unsigned int maxlen, +- unsigned int *len, unsigned char *type, ++ unsigned int *len, enum insn_type *type, + unsigned long *immediate, struct stack_op *op) + { + struct insn insn; +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -295,13 +295,6 @@ static int decode_instructions(struct ob + if (ret) + goto err; + +- if (!insn->type || insn->type > INSN_LAST) { +- WARN_FUNC("invalid instruction type %d", +- insn->sec, insn->offset, insn->type); +- ret = -1; +- goto err; +- } +- + hash_add(file->insn_hash, &insn->hash, insn->offset); + list_add_tail(&insn->list, &file->insn_list); + } +--- a/tools/objtool/check.h ++++ b/tools/objtool/check.h +@@ -42,7 +42,7 @@ struct instruction { + struct section *sec; + unsigned long offset; + unsigned int len; +- unsigned char type; ++ enum insn_type type; + unsigned long immediate; + bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts; + bool retpoline_safe; diff --git a/patches.suse/objtool-Don-t-use-ignore-flag-for-fake-jumps.patch b/patches.suse/objtool-Don-t-use-ignore-flag-for-fake-jumps.patch new file mode 100644 index 0000000..3647904 --- /dev/null +++ b/patches.suse/objtool-Don-t-use-ignore-flag-for-fake-jumps.patch @@ -0,0 +1,68 @@ +From: Josh Poimboeuf +Date: Mon, 13 May 2019 12:01:31 -0500 +Subject: objtool: Don't use ignore flag for fake jumps +Git-commit: e6da9567959e164f82bc81967e0d5b10dee870b4 +Patch-mainline: v5.2-rc1 +References: bsc#1202396 + +The ignore flag is set on fake jumps in order to keep +add_jump_destinations() from setting their jump_dest, since it already +got set when the fake jump was created. + +But using the ignore flag is a bit of a hack. It's normally used to +skip validation of an instruction, which doesn't really make sense for +fake jumps. + +Also, after the next patch, using the ignore flag for fake jumps can +trigger a false "why am I validating an ignored function?" warning. + +Instead just add an explicit check in add_jump_destinations() to skip +fake jumps. + +Signed-off-by: Josh Poimboeuf +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Link: http://lkml.kernel.org/r/71abc072ff48b2feccc197723a9c52859476c068.1557766718.git.jpoimboe@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Miroslav Benes +--- + tools/objtool/check.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index ac743a1d53ab..90226791df6b 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -28,6 +28,8 @@ + #include + #include + ++#define FAKE_JUMP_OFFSET -1 ++ + struct alternative { + struct list_head list; + struct instruction *insn; +@@ -568,7 +570,7 @@ static int add_jump_destinations(struct objtool_file *file) + insn->type != INSN_JUMP_UNCONDITIONAL) + continue; + +- if (insn->ignore) ++ if (insn->ignore || insn->offset == FAKE_JUMP_OFFSET) + continue; + + rela = find_rela_by_dest_range(insn->sec, insn->offset, +@@ -745,10 +747,10 @@ static int handle_group_alt(struct objtool_file *file, + clear_insn_state(&fake_jump->state); + + fake_jump->sec = special_alt->new_sec; +- fake_jump->offset = -1; ++ fake_jump->offset = FAKE_JUMP_OFFSET; + fake_jump->type = INSN_JUMP_UNCONDITIONAL; + fake_jump->jump_dest = list_next_entry(last_orig_insn, list); +- fake_jump->ignore = true; ++ fake_jump->func = orig_insn->func; + } + + if (!special_alt->new_len) { + diff --git a/patches.suse/objtool-Fix-CFI-insn_state-propagation.patch b/patches.suse/objtool-Fix-CFI-insn_state-propagation.patch new file mode 100644 index 0000000..e73694a --- /dev/null +++ b/patches.suse/objtool-Fix-CFI-insn_state-propagation.patch @@ -0,0 +1,738 @@ +From: Peter Zijlstra +Date: Wed, 25 Mar 2020 14:04:45 +0100 +Subject: objtool: Fix !CFI insn_state propagation +Git-commit: e7c0219b328c96746767f21b9532eed6a48f61c5 +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +Objtool keeps per instruction CFI state in struct insn_state and will +save/restore this where required. However, insn_state has grown some +!CFI state, and this must not be saved/restored (that would +loose/destroy state). + +Fix this by moving the CFI specific parts of insn_state into struct +cfi_state. + +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Miroslav Benes +Reviewed-by: Alexandre Chartre +Acked-by: Josh Poimboeuf +Link: https://lkml.kernel.org/r/20200416115119.045821071@infradead.org +Signed-off-by: Ingo Molnar +Acked-by: Miroslav Benes +--- + tools/objtool/cfi.h | 12 ++ + tools/objtool/check.c | 264 ++++++++++++++++++++++++------------------------ + tools/objtool/check.h | 11 -- + tools/objtool/orc_gen.c | 6 - + 4 files changed, 154 insertions(+), 139 deletions(-) + +--- a/tools/objtool/cfi.h ++++ b/tools/objtool/cfi.h +@@ -48,8 +48,20 @@ struct cfi_reg { + }; + + struct cfi_init_state { ++ struct cfi_reg regs[CFI_NUM_REGS]; + struct cfi_reg cfa; ++}; ++ ++struct cfi_state { + struct cfi_reg regs[CFI_NUM_REGS]; ++ struct cfi_reg vals[CFI_NUM_REGS]; ++ struct cfi_reg cfa; ++ int stack_size; ++ int drap_reg, drap_offset; ++ unsigned char type; ++ bool bp_scratch; ++ bool drap; ++ bool end; + }; + + #endif /* _OBJTOOL_CFI_H */ +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -238,18 +238,23 @@ static int dead_end_function(struct objt + return __dead_end_function(file, func, 0); + } + +-static void clear_insn_state(struct insn_state *state) ++static void init_cfi_state(struct cfi_state *cfi) + { + int i; + +- memset(state, 0, sizeof(*state)); +- state->cfa.base = CFI_UNDEFINED; + for (i = 0; i < CFI_NUM_REGS; i++) { +- state->regs[i].base = CFI_UNDEFINED; +- state->vals[i].base = CFI_UNDEFINED; ++ cfi->regs[i].base = CFI_UNDEFINED; ++ cfi->vals[i].base = CFI_UNDEFINED; + } +- state->drap_reg = CFI_UNDEFINED; +- state->drap_offset = -1; ++ cfi->cfa.base = CFI_UNDEFINED; ++ cfi->drap_reg = CFI_UNDEFINED; ++ cfi->drap_offset = -1; ++} ++ ++static void clear_insn_state(struct insn_state *state) ++{ ++ memset(state, 0, sizeof(*state)); ++ init_cfi_state(&state->cfi); + } + + /* +@@ -283,7 +288,7 @@ static int decode_instructions(struct ob + memset(insn, 0, sizeof(*insn)); + INIT_LIST_HEAD(&insn->alts); + INIT_LIST_HEAD(&insn->stack_ops); +- clear_insn_state(&insn->state); ++ init_cfi_state(&insn->cfi); + + insn->sec = sec; + insn->offset = offset; +@@ -675,7 +680,7 @@ static int handle_group_alt(struct objto + memset(fake_jump, 0, sizeof(*fake_jump)); + INIT_LIST_HEAD(&fake_jump->alts); + INIT_LIST_HEAD(&fake_jump->stack_ops); +- clear_insn_state(&fake_jump->state); ++ init_cfi_state(&fake_jump->cfi); + + fake_jump->sec = special_alt->new_sec; + fake_jump->offset = FAKE_JUMP_OFFSET; +@@ -1147,7 +1152,7 @@ static int read_unwind_hints(struct objt + return -1; + } + +- cfa = &insn->state.cfa; ++ cfa = &insn->cfi.cfa; + + if (hint->type == UNWIND_HINT_TYPE_SAVE) { + insn->save = true; +@@ -1193,7 +1198,7 @@ static int read_unwind_hints(struct objt + } + + cfa->offset = hint->sp_offset; +- insn->state.type = hint->type; ++ insn->cfi.type = hint->type; + } + + return 0; +@@ -1291,17 +1296,18 @@ static bool is_fentry_call(struct instru + + static bool has_modified_stack_frame(struct insn_state *state) + { ++ struct cfi_state *cfi = &state->cfi; + int i; + +- if (state->cfa.base != initial_func_cfi.cfa.base || +- state->cfa.offset != initial_func_cfi.cfa.offset || +- state->stack_size != initial_func_cfi.cfa.offset || +- state->drap) ++ if (cfi->cfa.base != initial_func_cfi.cfa.base || ++ cfi->cfa.offset != initial_func_cfi.cfa.offset || ++ cfi->stack_size != initial_func_cfi.cfa.offset || ++ cfi->drap) + return true; + + for (i = 0; i < CFI_NUM_REGS; i++) +- if (state->regs[i].base != initial_func_cfi.regs[i].base || +- state->regs[i].offset != initial_func_cfi.regs[i].offset) ++ if (cfi->regs[i].base != initial_func_cfi.regs[i].base || ++ cfi->regs[i].offset != initial_func_cfi.regs[i].offset) + return true; + + return false; +@@ -1309,21 +1315,23 @@ static bool has_modified_stack_frame(str + + static bool has_valid_stack_frame(struct insn_state *state) + { +- if (state->cfa.base == CFI_BP && state->regs[CFI_BP].base == CFI_CFA && +- state->regs[CFI_BP].offset == -16) ++ struct cfi_state *cfi = &state->cfi; ++ ++ if (cfi->cfa.base == CFI_BP && cfi->regs[CFI_BP].base == CFI_CFA && ++ cfi->regs[CFI_BP].offset == -16) + return true; + +- if (state->drap && state->regs[CFI_BP].base == CFI_BP) ++ if (cfi->drap && cfi->regs[CFI_BP].base == CFI_BP) + return true; + + return false; + } + +-static int update_insn_state_regs(struct instruction *insn, +- struct insn_state *state, ++static int update_cfi_state_regs(struct instruction *insn, ++ struct cfi_state *cfi, + struct stack_op *op) + { +- struct cfi_reg *cfa = &state->cfa; ++ struct cfi_reg *cfa = &cfi->cfa; + + if (cfa->base != CFI_SP && cfa->base != CFI_SP_INDIRECT) + return 0; +@@ -1344,20 +1352,19 @@ static int update_insn_state_regs(struct + return 0; + } + +-static void save_reg(struct insn_state *state, unsigned char reg, int base, +- int offset) ++static void save_reg(struct cfi_state *cfi, unsigned char reg, int base, int offset) + { + if (arch_callee_saved_reg(reg) && +- state->regs[reg].base == CFI_UNDEFINED) { +- state->regs[reg].base = base; +- state->regs[reg].offset = offset; ++ cfi->regs[reg].base == CFI_UNDEFINED) { ++ cfi->regs[reg].base = base; ++ cfi->regs[reg].offset = offset; + } + } + +-static void restore_reg(struct insn_state *state, unsigned char reg) ++static void restore_reg(struct cfi_state *cfi, unsigned char reg) + { +- state->regs[reg].base = CFI_UNDEFINED; +- state->regs[reg].offset = 0; ++ cfi->regs[reg].base = CFI_UNDEFINED; ++ cfi->regs[reg].offset = 0; + } + + /* +@@ -1413,11 +1420,11 @@ static void restore_reg(struct insn_stat + * 41 5d pop %r13 + * c3 retq + */ +-static int update_insn_state(struct instruction *insn, struct insn_state *state, ++static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi, + struct stack_op *op) + { +- struct cfi_reg *cfa = &state->cfa; +- struct cfi_reg *regs = state->regs; ++ struct cfi_reg *cfa = &cfi->cfa; ++ struct cfi_reg *regs = cfi->regs; + + /* stack operations don't make sense with an undefined CFA */ + if (cfa->base == CFI_UNDEFINED) { +@@ -1428,8 +1435,8 @@ static int update_insn_state(struct inst + return 0; + } + +- if (state->type == ORC_TYPE_REGS || state->type == ORC_TYPE_REGS_IRET) +- return update_insn_state_regs(insn, state, op); ++ if (cfi->type == ORC_TYPE_REGS || cfi->type == ORC_TYPE_REGS_IRET) ++ return update_cfi_state_regs(insn, cfi, op); + + switch (op->dest.type) { + +@@ -1444,16 +1451,16 @@ static int update_insn_state(struct inst + + /* mov %rsp, %rbp */ + cfa->base = op->dest.reg; +- state->bp_scratch = false; ++ cfi->bp_scratch = false; + } + + else if (op->src.reg == CFI_SP && +- op->dest.reg == CFI_BP && state->drap) { ++ op->dest.reg == CFI_BP && cfi->drap) { + + /* drap: mov %rsp, %rbp */ + regs[CFI_BP].base = CFI_BP; +- regs[CFI_BP].offset = -state->stack_size; +- state->bp_scratch = false; ++ regs[CFI_BP].offset = -cfi->stack_size; ++ cfi->bp_scratch = false; + } + + else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) { +@@ -1468,15 +1475,15 @@ static int update_insn_state(struct inst + * ... + * mov %rax, %rsp + */ +- state->vals[op->dest.reg].base = CFI_CFA; +- state->vals[op->dest.reg].offset = -state->stack_size; ++ cfi->vals[op->dest.reg].base = CFI_CFA; ++ cfi->vals[op->dest.reg].offset = -cfi->stack_size; + } + + else if (op->dest.reg == cfa->base) { + + /* mov %reg, %rsp */ + if (cfa->base == CFI_SP && +- state->vals[op->src.reg].base == CFI_CFA) { ++ cfi->vals[op->src.reg].base == CFI_CFA) { + + /* + * This is needed for the rare case +@@ -1486,8 +1493,8 @@ static int update_insn_state(struct inst + * ... + * mov %rcx, %rsp + */ +- cfa->offset = -state->vals[op->src.reg].offset; +- state->stack_size = cfa->offset; ++ cfa->offset = -cfi->vals[op->src.reg].offset; ++ cfi->stack_size = cfa->offset; + + } else { + cfa->base = CFI_UNDEFINED; +@@ -1501,7 +1508,7 @@ static int update_insn_state(struct inst + if (op->dest.reg == CFI_SP && op->src.reg == CFI_SP) { + + /* add imm, %rsp */ +- state->stack_size -= op->src.offset; ++ cfi->stack_size -= op->src.offset; + if (cfa->base == CFI_SP) + cfa->offset -= op->src.offset; + break; +@@ -1510,14 +1517,14 @@ static int update_insn_state(struct inst + if (op->dest.reg == CFI_SP && op->src.reg == CFI_BP) { + + /* lea disp(%rbp), %rsp */ +- state->stack_size = -(op->src.offset + regs[CFI_BP].offset); ++ cfi->stack_size = -(op->src.offset + regs[CFI_BP].offset); + break; + } + + if (op->src.reg == CFI_SP && cfa->base == CFI_SP) { + + /* drap: lea disp(%rsp), %drap */ +- state->drap_reg = op->dest.reg; ++ cfi->drap_reg = op->dest.reg; + + /* + * lea disp(%rsp), %reg +@@ -1529,25 +1536,25 @@ static int update_insn_state(struct inst + * ... + * mov %rcx, %rsp + */ +- state->vals[op->dest.reg].base = CFI_CFA; +- state->vals[op->dest.reg].offset = \ +- -state->stack_size + op->src.offset; ++ cfi->vals[op->dest.reg].base = CFI_CFA; ++ cfi->vals[op->dest.reg].offset = \ ++ -cfi->stack_size + op->src.offset; + + break; + } + +- if (state->drap && op->dest.reg == CFI_SP && +- op->src.reg == state->drap_reg) { ++ if (cfi->drap && op->dest.reg == CFI_SP && ++ op->src.reg == cfi->drap_reg) { + + /* drap: lea disp(%drap), %rsp */ + cfa->base = CFI_SP; +- cfa->offset = state->stack_size = -op->src.offset; +- state->drap_reg = CFI_UNDEFINED; +- state->drap = false; ++ cfa->offset = cfi->stack_size = -op->src.offset; ++ cfi->drap_reg = CFI_UNDEFINED; ++ cfi->drap = false; + break; + } + +- if (op->dest.reg == state->cfa.base) { ++ if (op->dest.reg == cfi->cfa.base) { + WARN_FUNC("unsupported stack register modification", + insn->sec, insn->offset); + return -1; +@@ -1557,18 +1564,18 @@ static int update_insn_state(struct inst + + case OP_SRC_AND: + if (op->dest.reg != CFI_SP || +- (state->drap_reg != CFI_UNDEFINED && cfa->base != CFI_SP) || +- (state->drap_reg == CFI_UNDEFINED && cfa->base != CFI_BP)) { ++ (cfi->drap_reg != CFI_UNDEFINED && cfa->base != CFI_SP) || ++ (cfi->drap_reg == CFI_UNDEFINED && cfa->base != CFI_BP)) { + WARN_FUNC("unsupported stack pointer realignment", + insn->sec, insn->offset); + return -1; + } + +- if (state->drap_reg != CFI_UNDEFINED) { ++ if (cfi->drap_reg != CFI_UNDEFINED) { + /* drap: and imm, %rsp */ +- cfa->base = state->drap_reg; +- cfa->offset = state->stack_size = 0; +- state->drap = true; ++ cfa->base = cfi->drap_reg; ++ cfa->offset = cfi->stack_size = 0; ++ cfi->drap = true; + } + + /* +@@ -1579,57 +1586,57 @@ static int update_insn_state(struct inst + break; + + case OP_SRC_POP: +- if (!state->drap && op->dest.type == OP_DEST_REG && ++ if (!cfi->drap && op->dest.type == OP_DEST_REG && + op->dest.reg == cfa->base) { + + /* pop %rbp */ + cfa->base = CFI_SP; + } + +- if (state->drap && cfa->base == CFI_BP_INDIRECT && ++ if (cfi->drap && cfa->base == CFI_BP_INDIRECT && + op->dest.type == OP_DEST_REG && +- op->dest.reg == state->drap_reg && +- state->drap_offset == -state->stack_size) { ++ op->dest.reg == cfi->drap_reg && ++ cfi->drap_offset == -cfi->stack_size) { + + /* drap: pop %drap */ +- cfa->base = state->drap_reg; ++ cfa->base = cfi->drap_reg; + cfa->offset = 0; +- state->drap_offset = -1; ++ cfi->drap_offset = -1; + +- } else if (regs[op->dest.reg].offset == -state->stack_size) { ++ } else if (regs[op->dest.reg].offset == -cfi->stack_size) { + + /* pop %reg */ +- restore_reg(state, op->dest.reg); ++ restore_reg(cfi, op->dest.reg); + } + +- state->stack_size -= 8; ++ cfi->stack_size -= 8; + if (cfa->base == CFI_SP) + cfa->offset -= 8; + + break; + + case OP_SRC_REG_INDIRECT: +- if (state->drap && op->src.reg == CFI_BP && +- op->src.offset == state->drap_offset) { ++ if (cfi->drap && op->src.reg == CFI_BP && ++ op->src.offset == cfi->drap_offset) { + + /* drap: mov disp(%rbp), %drap */ +- cfa->base = state->drap_reg; ++ cfa->base = cfi->drap_reg; + cfa->offset = 0; +- state->drap_offset = -1; ++ cfi->drap_offset = -1; + } + +- if (state->drap && op->src.reg == CFI_BP && ++ if (cfi->drap && op->src.reg == CFI_BP && + op->src.offset == regs[op->dest.reg].offset) { + + /* drap: mov disp(%rbp), %reg */ +- restore_reg(state, op->dest.reg); ++ restore_reg(cfi, op->dest.reg); + + } else if (op->src.reg == cfa->base && + op->src.offset == regs[op->dest.reg].offset + cfa->offset) { + + /* mov disp(%rbp), %reg */ + /* mov disp(%rsp), %reg */ +- restore_reg(state, op->dest.reg); ++ restore_reg(cfi, op->dest.reg); + } + + break; +@@ -1643,78 +1650,78 @@ static int update_insn_state(struct inst + break; + + case OP_DEST_PUSH: +- state->stack_size += 8; ++ cfi->stack_size += 8; + if (cfa->base == CFI_SP) + cfa->offset += 8; + + if (op->src.type != OP_SRC_REG) + break; + +- if (state->drap) { +- if (op->src.reg == cfa->base && op->src.reg == state->drap_reg) { ++ if (cfi->drap) { ++ if (op->src.reg == cfa->base && op->src.reg == cfi->drap_reg) { + + /* drap: push %drap */ + cfa->base = CFI_BP_INDIRECT; +- cfa->offset = -state->stack_size; ++ cfa->offset = -cfi->stack_size; + + /* save drap so we know when to restore it */ +- state->drap_offset = -state->stack_size; ++ cfi->drap_offset = -cfi->stack_size; + +- } else if (op->src.reg == CFI_BP && cfa->base == state->drap_reg) { ++ } else if (op->src.reg == CFI_BP && cfa->base == cfi->drap_reg) { + + /* drap: push %rbp */ +- state->stack_size = 0; ++ cfi->stack_size = 0; + + } else if (regs[op->src.reg].base == CFI_UNDEFINED) { + + /* drap: push %reg */ +- save_reg(state, op->src.reg, CFI_BP, -state->stack_size); ++ save_reg(cfi, op->src.reg, CFI_BP, -cfi->stack_size); + } + + } else { + + /* push %reg */ +- save_reg(state, op->src.reg, CFI_CFA, -state->stack_size); ++ save_reg(cfi, op->src.reg, CFI_CFA, -cfi->stack_size); + } + + /* detect when asm code uses rbp as a scratch register */ + if (!no_fp && insn->func && op->src.reg == CFI_BP && + cfa->base != CFI_BP) +- state->bp_scratch = true; ++ cfi->bp_scratch = true; + break; + + case OP_DEST_REG_INDIRECT: + +- if (state->drap) { +- if (op->src.reg == cfa->base && op->src.reg == state->drap_reg) { ++ if (cfi->drap) { ++ if (op->src.reg == cfa->base && op->src.reg == cfi->drap_reg) { + + /* drap: mov %drap, disp(%rbp) */ + cfa->base = CFI_BP_INDIRECT; + cfa->offset = op->dest.offset; + + /* save drap offset so we know when to restore it */ +- state->drap_offset = op->dest.offset; ++ cfi->drap_offset = op->dest.offset; + } + + else if (regs[op->src.reg].base == CFI_UNDEFINED) { + + /* drap: mov reg, disp(%rbp) */ +- save_reg(state, op->src.reg, CFI_BP, op->dest.offset); ++ save_reg(cfi, op->src.reg, CFI_BP, op->dest.offset); + } + + } else if (op->dest.reg == cfa->base) { + + /* mov reg, disp(%rbp) */ + /* mov reg, disp(%rsp) */ +- save_reg(state, op->src.reg, CFI_CFA, +- op->dest.offset - state->cfa.offset); ++ save_reg(cfi, op->src.reg, CFI_CFA, ++ op->dest.offset - cfi->cfa.offset); + } + + break; + + case OP_DEST_LEAVE: +- if ((!state->drap && cfa->base != CFI_BP) || +- (state->drap && cfa->base != state->drap_reg)) { ++ if ((!cfi->drap && cfa->base != CFI_BP) || ++ (cfi->drap && cfa->base != cfi->drap_reg)) { + WARN_FUNC("leave instruction with modified stack frame", + insn->sec, insn->offset); + return -1; +@@ -1722,10 +1729,10 @@ static int update_insn_state(struct inst + + /* leave (mov %rbp, %rsp; pop %rbp) */ + +- state->stack_size = -state->regs[CFI_BP].offset - 8; +- restore_reg(state, CFI_BP); ++ cfi->stack_size = -cfi->regs[CFI_BP].offset - 8; ++ restore_reg(cfi, CFI_BP); + +- if (!state->drap) { ++ if (!cfi->drap) { + cfa->base = CFI_SP; + cfa->offset -= 8; + } +@@ -1740,7 +1747,7 @@ static int update_insn_state(struct inst + } + + /* pop mem */ +- state->stack_size -= 8; ++ cfi->stack_size -= 8; + if (cfa->base == CFI_SP) + cfa->offset -= 8; + +@@ -1762,7 +1769,7 @@ static int handle_insn_ops(struct instru + list_for_each_entry(op, &insn->stack_ops, list) { + int res; + +- res = update_insn_state(insn, state, op); ++ res = update_cfi_state(insn, &state->cfi, op); + if (res) + return res; + } +@@ -1770,41 +1777,44 @@ static int handle_insn_ops(struct instru + return 0; + } + +-static bool insn_state_match(struct instruction *insn, struct insn_state *state) ++static bool insn_cfi_match(struct instruction *insn, struct cfi_state *cfi2) + { +- struct insn_state *state1 = &insn->state, *state2 = state; ++ struct cfi_state *cfi1 = &insn->cfi; + int i; + +- if (memcmp(&state1->cfa, &state2->cfa, sizeof(state1->cfa))) { ++ if (memcmp(&cfi1->cfa, &cfi2->cfa, sizeof(cfi1->cfa))) { ++ + WARN_FUNC("stack state mismatch: cfa1=%d%+d cfa2=%d%+d", + insn->sec, insn->offset, +- state1->cfa.base, state1->cfa.offset, +- state2->cfa.base, state2->cfa.offset); ++ cfi1->cfa.base, cfi1->cfa.offset, ++ cfi2->cfa.base, cfi2->cfa.offset); + +- } else if (memcmp(&state1->regs, &state2->regs, sizeof(state1->regs))) { ++ } else if (memcmp(&cfi1->regs, &cfi2->regs, sizeof(cfi1->regs))) { + for (i = 0; i < CFI_NUM_REGS; i++) { +- if (!memcmp(&state1->regs[i], &state2->regs[i], ++ if (!memcmp(&cfi1->regs[i], &cfi2->regs[i], + sizeof(struct cfi_reg))) + continue; + + WARN_FUNC("stack state mismatch: reg1[%d]=%d%+d reg2[%d]=%d%+d", + insn->sec, insn->offset, +- i, state1->regs[i].base, state1->regs[i].offset, +- i, state2->regs[i].base, state2->regs[i].offset); ++ i, cfi1->regs[i].base, cfi1->regs[i].offset, ++ i, cfi2->regs[i].base, cfi2->regs[i].offset); + break; + } + +- } else if (state1->type != state2->type) { ++ } else if (cfi1->type != cfi2->type) { ++ + WARN_FUNC("stack state mismatch: type1=%d type2=%d", +- insn->sec, insn->offset, state1->type, state2->type); ++ insn->sec, insn->offset, cfi1->type, cfi2->type); ++ ++ } else if (cfi1->drap != cfi2->drap || ++ (cfi1->drap && cfi1->drap_reg != cfi2->drap_reg) || ++ (cfi1->drap && cfi1->drap_offset != cfi2->drap_offset)) { + +- } else if (state1->drap != state2->drap || +- (state1->drap && state1->drap_reg != state2->drap_reg) || +- (state1->drap && state1->drap_offset != state2->drap_offset)) { + WARN_FUNC("stack state mismatch: drap1=%d(%d,%d) drap2=%d(%d,%d)", + insn->sec, insn->offset, +- state1->drap, state1->drap_reg, state1->drap_offset, +- state2->drap, state2->drap_reg, state2->drap_offset); ++ cfi1->drap, cfi1->drap_reg, cfi1->drap_offset, ++ cfi2->drap, cfi2->drap_reg, cfi2->drap_offset); + + } else + return true; +@@ -1862,7 +1872,7 @@ static int validate_branch(struct objtoo + } + + if (insn->visited) { +- if (!insn->hint && !insn_state_match(insn, &state)) ++ if (!insn->hint && !insn_cfi_match(insn, &state.cfi)) + return 1; + + return 0; +@@ -1903,13 +1913,13 @@ static int validate_branch(struct objtoo + return 1; + } + +- insn->state = save_insn->state; ++ insn->cfi = save_insn->cfi; + } + +- state = insn->state; ++ state.cfi = insn->cfi; + + } else +- insn->state = state; ++ insn->cfi = state.cfi; + + insn->visited = true; + +@@ -1941,7 +1951,7 @@ static int validate_branch(struct objtoo + return 1; + } + +- if (state.bp_scratch) { ++ if (state.cfi.bp_scratch) { + WARN_FUNC("BP used as a scratch register", + sec, insn->offset); + return 1; +@@ -2027,7 +2037,7 @@ static int validate_branch(struct objtoo + return 0; + + if (!next_insn) { +- if (state.cfa.base == CFI_UNDEFINED) ++ if (state.cfi.cfa.base == CFI_UNDEFINED) + return 0; + WARN("%s: unexpected end of section", sec->name); + return 1; +@@ -2176,10 +2186,10 @@ static int validate_functions(struct obj + continue; + + clear_insn_state(&state); +- state.cfa = initial_func_cfi.cfa; +- memcpy(&state.regs, &initial_func_cfi.regs, ++ state.cfi.cfa = initial_func_cfi.cfa; ++ memcpy(&state.cfi.regs, &initial_func_cfi.regs, + CFI_NUM_REGS * sizeof(struct cfi_reg)); +- state.stack_size = initial_func_cfi.cfa.offset; ++ state.cfi.stack_size = initial_func_cfi.cfa.offset; + + ret = validate_branch(file, func, insn, state); + if (ret && backtrace) +--- a/tools/objtool/check.h ++++ b/tools/objtool/check.h +@@ -26,14 +26,7 @@ + #include + + struct insn_state { +- struct cfi_reg cfa; +- struct cfi_reg regs[CFI_NUM_REGS]; +- int stack_size; +- unsigned char type; +- bool bp_scratch; +- bool drap; +- int drap_reg, drap_offset; +- struct cfi_reg vals[CFI_NUM_REGS]; ++ struct cfi_state cfi; + }; + + struct instruction { +@@ -52,7 +45,7 @@ struct instruction { + struct list_head alts; + struct symbol *func; + struct list_head stack_ops; +- struct insn_state state; ++ struct cfi_state cfi; + struct orc_entry orc; + }; + +--- a/tools/objtool/orc_gen.c ++++ b/tools/objtool/orc_gen.c +@@ -28,8 +28,8 @@ int create_orc(struct objtool_file *file + + for_each_insn(file, insn) { + struct orc_entry *orc = &insn->orc; +- struct cfi_reg *cfa = &insn->state.cfa; +- struct cfi_reg *bp = &insn->state.regs[CFI_BP]; ++ struct cfi_reg *cfa = &insn->cfi.cfa; ++ struct cfi_reg *bp = &insn->cfi.regs[CFI_BP]; + + if (cfa->base == CFI_UNDEFINED) { + orc->sp_reg = ORC_REG_UNDEFINED; +@@ -85,7 +85,7 @@ int create_orc(struct objtool_file *file + + orc->sp_offset = cfa->offset; + orc->bp_offset = bp->offset; +- orc->type = insn->state.type; ++ orc->type = insn->cfi.type; + } + + return 0; diff --git a/patches.suse/objtool-Fix-ORC-vs-alternatives.patch b/patches.suse/objtool-Fix-ORC-vs-alternatives.patch new file mode 100644 index 0000000..39dbe6e --- /dev/null +++ b/patches.suse/objtool-Fix-ORC-vs-alternatives.patch @@ -0,0 +1,141 @@ +From: Peter Zijlstra +Date: Tue, 28 Apr 2020 19:37:01 +0200 +Subject: objtool: Fix ORC vs alternatives +Git-commit: 7117f16bf460ef8cd132e6e80c989677397b4868 +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +Jann reported that (for instance) entry_64.o:general_protection has +very odd ORC data: + + 0000000000000f40 : + #######sp:sp+8 bp:(und) type:iret end:0 + f40: 90 nop + #######sp:(und) bp:(und) type:call end:0 + f41: 90 nop + f42: 90 nop + #######sp:sp+8 bp:(und) type:iret end:0 + f43: e8 a8 01 00 00 callq 10f0 + #######sp:sp+0 bp:(und) type:regs end:0 + f48: f6 84 24 88 00 00 00 testb $0x3,0x88(%rsp) + f4f: 03 + f50: 74 00 je f52 + f52: 48 89 e7 mov %rsp,%rdi + f55: 48 8b 74 24 78 mov 0x78(%rsp),%rsi + f5a: 48 c7 44 24 78 ff ff movq $0xffffffffffffffff,0x78(%rsp) + f61: ff ff + f63: e8 00 00 00 00 callq f68 + f68: e9 73 02 00 00 jmpq 11e0 + #######sp:(und) bp:(und) type:call end:0 + f6d: 0f 1f 00 nopl (%rax) + +Note the entry at 0xf41. Josh found this was the result of commit: + + 764eef4b109a ("objtool: Rewrite alt->skip_orig") + +Due to the early return in validate_branch() we no longer set +insn->cfi of the original instruction stream (the NOPs at 0xf41 and +0xf42) and we'll end up with the above weirdness. + +In other discussions we realized alternatives should be ORC invariant; +that is, due to there being only a single ORC table, it must be valid +for all alternatives. The easiest way to ensure this is to not allow +any stack modifications in alternatives. + +When we enforce this latter observation, we get the property that the +whole alternative must have the same CFI, which we can employ to fix +the former report. + +Fixes: 764eef4b109a ("objtool: Rewrite alt->skip_orig") +Reported-by: Jann Horn +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Miroslav Benes +Acked-by: Josh Poimboeuf +Link: https://lkml.kernel.org/r/20200428191659.499074346@infradead.org + +Acked-by: Miroslav Benes +--- + tools/objtool/Documentation/stack-validation.txt | 7 ++++ + tools/objtool/check.c | 34 ++++++++++++++++++++++- + 2 files changed, 40 insertions(+), 1 deletion(-) + +--- a/tools/objtool/Documentation/stack-validation.txt ++++ b/tools/objtool/Documentation/stack-validation.txt +@@ -293,6 +293,13 @@ they mean, and suggestions for how to fi + If the error doesn't seem to make sense, it could be a bug in objtool. + Feel free to ask the objtool maintainer for help. + ++10. file.o: warning: func()+0x5c: alternative modifies stack ++ ++ This means that an alternative includes instructions that modify the ++ stack. The problem is that there is only one ORC unwind table, this means ++ that the ORC unwind entries must be valid for each of the alternatives. ++ The easiest way to enforce this is to ensure alternatives do not contain ++ any ORC entries, which in turn implies the above constraint. + + Adding exceptions + ----------------- +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1773,6 +1773,11 @@ static int handle_insn_ops(struct instru + list_for_each_entry(op, &insn->stack_ops, list) { + int res; + ++ if (insn->alt_group) { ++ WARN_FUNC("alternative modifies stack", insn->sec, insn->offset); ++ return -1; ++ } ++ + res = update_cfi_state(insn, &state->cfi, op); + if (res) + return res; +@@ -1838,6 +1843,30 @@ static int validate_sibling_call(struct + } + + /* ++ * Alternatives should not contain any ORC entries, this in turn means they ++ * should not contain any CFI ops, which implies all instructions should have ++ * the same same CFI state. ++ * ++ * It is possible to constuct alternatives that have unreachable holes that go ++ * unreported (because they're NOPs), such holes would result in CFI_UNDEFINED ++ * states which then results in ORC entries, which we just said we didn't want. ++ * ++ * Avoid them by copying the CFI entry of the first instruction into the whole ++ * alternative. ++ */ ++static void fill_alternative_cfi(struct objtool_file *file, struct instruction *insn) ++{ ++ struct instruction *first_insn = insn; ++ int alt_group = insn->alt_group; ++ ++ sec_for_each_insn_continue(file, insn) { ++ if (insn->alt_group != alt_group) ++ break; ++ insn->cfi = first_insn->cfi; ++ } ++} ++ ++/* + * Follow the branch starting at the given instruction, and recursively follow + * any other branches (jumps). Meanwhile, track the frame pointer state at + * each instruction and validate all the rules described in +@@ -1921,7 +1950,7 @@ static int validate_branch(struct objtoo + + insn->visited = true; + +- if (!insn->ignore_alts) { ++ if (!insn->ignore_alts && !list_empty(&insn->alts)) { + bool skip_orig = false; + + list_for_each_entry(alt, &insn->alts, list) { +@@ -1936,6 +1965,9 @@ static int validate_branch(struct objtoo + } + } + ++ if (insn->alt_group) ++ fill_alternative_cfi(file, insn); ++ + if (skip_orig) + return 0; + } diff --git a/patches.suse/objtool-Fix-sibling-call-detection.patch b/patches.suse/objtool-Fix-sibling-call-detection.patch new file mode 100644 index 0000000..cdce79a --- /dev/null +++ b/patches.suse/objtool-Fix-sibling-call-detection.patch @@ -0,0 +1,180 @@ +From: Peter Zijlstra +Date: Wed, 6 Mar 2019 12:58:15 +0100 +Subject: objtool: Fix sibling call detection +Git-commit: 54262aa2830151f89699fa8a6c5aa05f0992e672 +Patch-mainline: v5.2-rc1 +References: bsc#1202396 + +It turned out that we failed to detect some sibling calls; +specifically those without relocation records; like: + + $ ./objdump-func.sh defconfig-build/mm/kasan/generic.o __asan_loadN + 0000 0000000000000840 <__asan_loadN>: + 0000 840: 48 8b 0c 24 mov (%rsp),%rcx + 0004 844: 31 d2 xor %edx,%edx + 0006 846: e9 45 fe ff ff jmpq 690 + +So extend the cross-function jump to also consider those that are not +between known (or newly detected) parent/child functions, as +sibling-cals when they jump to the start of the function. + +The second part of that condition is to deal with random jumps to the +middle of other function, as can be found in +arch/x86/lib/copy_user_64.S for example. + +This then (with later patches applied) makes the above recognise the +sibling call: + + mm/kasan/generic.o: warning: objtool: __asan_loadN()+0x6: call to check_memory_region() with UACCESS enabled + +Also make sure to set insn->call_dest for sibling calls so we can know +who we're calling. This is useful information when printing validation +warnings later. + +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Josh Poimboeuf +Cc: Borislav Petkov +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Signed-off-by: Ingo Molnar +Acked-by: Miroslav Benes +--- + tools/objtool/check.c | 86 ++++++++++++++++++++++++++++++++------------------- + 1 file changed, 55 insertions(+), 31 deletions(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 5264a305d658..8118361295dd 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -515,7 +515,8 @@ static int add_jump_destinations(struct objtool_file *file) + continue; + } else { + /* sibling call */ +- insn->jump_dest = 0; ++ insn->call_dest = rela->sym; ++ insn->jump_dest = NULL; + continue; + } + +@@ -537,25 +538,38 @@ static int add_jump_destinations(struct objtool_file *file) + } + + /* +- * For GCC 8+, create parent/child links for any cold +- * subfunctions. This is _mostly_ redundant with a similar +- * initialization in read_symbols(). +- * +- * If a function has aliases, we want the *first* such function +- * in the symbol table to be the subfunction's parent. In that +- * case we overwrite the initialization done in read_symbols(). +- * +- * However this code can't completely replace the +- * read_symbols() code because this doesn't detect the case +- * where the parent function's only reference to a subfunction +- * is through a switch table. ++ * Cross-function jump. + */ + if (insn->func && insn->jump_dest->func && +- insn->func != insn->jump_dest->func && +- !strstr(insn->func->name, ".cold.") && +- strstr(insn->jump_dest->func->name, ".cold.")) { +- insn->func->cfunc = insn->jump_dest->func; +- insn->jump_dest->func->pfunc = insn->func; ++ insn->func != insn->jump_dest->func) { ++ ++ /* ++ * For GCC 8+, create parent/child links for any cold ++ * subfunctions. This is _mostly_ redundant with a ++ * similar initialization in read_symbols(). ++ * ++ * If a function has aliases, we want the *first* such ++ * function in the symbol table to be the subfunction's ++ * parent. In that case we overwrite the ++ * initialization done in read_symbols(). ++ * ++ * However this code can't completely replace the ++ * read_symbols() code because this doesn't detect the ++ * case where the parent function's only reference to a ++ * subfunction is through a switch table. ++ */ ++ if (!strstr(insn->func->name, ".cold.") && ++ strstr(insn->jump_dest->func->name, ".cold.")) { ++ insn->func->cfunc = insn->jump_dest->func; ++ insn->jump_dest->func->pfunc = insn->func; ++ ++ } else if (insn->jump_dest->func->pfunc != insn->func->pfunc && ++ insn->jump_dest->offset == insn->jump_dest->func->offset) { ++ ++ /* sibling class */ ++ insn->call_dest = insn->jump_dest->func; ++ insn->jump_dest = NULL; ++ } + } + } + +@@ -1785,6 +1799,17 @@ static bool insn_state_match(struct instruction *insn, struct insn_state *state) + return false; + } + ++static int validate_sibling_call(struct instruction *insn, struct insn_state *state) ++{ ++ if (has_modified_stack_frame(state)) { ++ WARN_FUNC("sibling call from callable instruction with modified stack frame", ++ insn->sec, insn->offset); ++ return 1; ++ } ++ ++ return 0; ++} ++ + /* + * Follow the branch starting at the given instruction, and recursively follow + * any other branches (jumps). Meanwhile, track the frame pointer state at +@@ -1935,9 +1960,14 @@ static int validate_branch(struct objtool_file *file, struct instruction *first, + + case INSN_JUMP_CONDITIONAL: + case INSN_JUMP_UNCONDITIONAL: +- if (insn->jump_dest && +- (!func || !insn->jump_dest->func || +- insn->jump_dest->func->pfunc == func)) { ++ if (func && !insn->jump_dest) { ++ ret = validate_sibling_call(insn, &state); ++ if (ret) ++ return ret; ++ ++ } else if (insn->jump_dest && ++ (!func || !insn->jump_dest->func || ++ insn->jump_dest->func->pfunc == func)) { + ret = validate_branch(file, insn->jump_dest, + state); + if (ret) { +@@ -1945,11 +1975,6 @@ static int validate_branch(struct objtool_file *file, struct instruction *first, + BT_FUNC("(branch)", insn); + return ret; + } +- +- } else if (func && has_modified_stack_frame(&state)) { +- WARN_FUNC("sibling call from callable instruction with modified stack frame", +- sec, insn->offset); +- return 1; + } + + if (insn->type == INSN_JUMP_UNCONDITIONAL) +@@ -1958,11 +1983,10 @@ static int validate_branch(struct objtool_file *file, struct instruction *first, + break; + + case INSN_JUMP_DYNAMIC: +- if (func && list_empty(&insn->alts) && +- has_modified_stack_frame(&state)) { +- WARN_FUNC("sibling call from callable instruction with modified stack frame", +- sec, insn->offset); +- return 1; ++ if (func && list_empty(&insn->alts)) { ++ ret = validate_sibling_call(insn, &state); ++ if (ret) ++ return ret; + } + + return 0; + diff --git a/patches.suse/objtool-Make-handle_insn_ops-unconditional.patch b/patches.suse/objtool-Make-handle_insn_ops-unconditional.patch new file mode 100644 index 0000000..f408e2e --- /dev/null +++ b/patches.suse/objtool-Make-handle_insn_ops-unconditional.patch @@ -0,0 +1,46 @@ +From: Peter Zijlstra +Date: Fri, 24 Apr 2020 16:16:41 +0200 +Subject: objtool: Make handle_insn_ops() unconditional +Git-commit: 60041bcd8f5ab560dabf44dc384f58bbeb5a6a30 +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +Now that every instruction has a list of stack_ops; we can trivially +distinquish those instructions that do not have stack_ops, their list +is empty. + +This means we can now call handle_insn_ops() unconditionally. + +Suggested-by: Julien Thierry +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Miroslav Benes +Acked-by: Josh Poimboeuf +Link: https://lkml.kernel.org/r/20200428191659.795115188@infradead.org + +Acked-by: Miroslav Benes +--- + tools/objtool/check.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1972,6 +1972,9 @@ static int validate_branch(struct objtoo + return 0; + } + ++ if (handle_insn_ops(insn, &state)) ++ return 1; ++ + switch (insn->type) { + + case INSN_RETURN: +@@ -2054,9 +2057,6 @@ static int validate_branch(struct objtoo + return 0; + + case INSN_STACK: +- if (handle_insn_ops(insn, &state)) +- return 1; +- + break; + + default: diff --git a/patches.suse/objtool-Remove-INSN_STACK.patch b/patches.suse/objtool-Remove-INSN_STACK.patch new file mode 100644 index 0000000..ee7454f --- /dev/null +++ b/patches.suse/objtool-Remove-INSN_STACK.patch @@ -0,0 +1,231 @@ +From: Peter Zijlstra +Date: Fri, 24 Apr 2020 16:18:58 +0200 +Subject: objtool: Remove INSN_STACK +Git-commit: b09fb65e863733e192d4825a285b4b4998969ce0 +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +With the unconditional use of handle_insn_ops(), INSN_STACK has lost +its purpose. Remove it. + +Suggested-by: Julien Thierry +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Miroslav Benes +Acked-by: Josh Poimboeuf +Link: https://lkml.kernel.org/r/20200428191659.854203028@infradead.org + +Acked-by: Miroslav Benes +--- + tools/objtool/arch.h | 1 - + tools/objtool/arch/x86/decode.c | 23 ----------------------- + tools/objtool/check.c | 3 --- + 3 files changed, 27 deletions(-) + +--- a/tools/objtool/arch.h ++++ b/tools/objtool/arch.h +@@ -32,7 +32,6 @@ enum insn_type { + INSN_CALL_DYNAMIC, + INSN_RETURN, + INSN_CONTEXT_SWITCH, +- INSN_STACK, + INSN_BUG, + INSN_NOP, + INSN_OTHER, +--- a/tools/objtool/arch/x86/decode.c ++++ b/tools/objtool/arch/x86/decode.c +@@ -142,7 +142,6 @@ int arch_decode_instruction(struct elf * + if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) { + + /* add/sub reg, %rsp */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_ADD; + op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; +@@ -155,7 +154,6 @@ int arch_decode_instruction(struct elf * + case 0x50 ... 0x57: + + /* push reg */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_REG; + op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; +@@ -167,7 +165,6 @@ int arch_decode_instruction(struct elf * + case 0x58 ... 0x5f: + + /* pop reg */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_POP; + op->dest.type = OP_DEST_REG; +@@ -179,7 +176,6 @@ int arch_decode_instruction(struct elf * + case 0x68: + case 0x6a: + /* push immediate */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_CONST; + op->dest.type = OP_DEST_PUSH; +@@ -197,7 +193,6 @@ int arch_decode_instruction(struct elf * + + if (modrm == 0xe4) { + /* and imm, %rsp */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_AND; + op->src.reg = CFI_SP; +@@ -216,7 +211,6 @@ int arch_decode_instruction(struct elf * + break; + + /* add/sub imm, %rsp */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_ADD; + op->src.reg = CFI_SP; +@@ -230,7 +224,6 @@ int arch_decode_instruction(struct elf * + if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) { + + /* mov %rsp, reg */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_REG; + op->src.reg = CFI_SP; +@@ -243,7 +236,6 @@ int arch_decode_instruction(struct elf * + if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) { + + /* mov reg, %rsp */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_REG; + op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; +@@ -259,7 +251,6 @@ int arch_decode_instruction(struct elf * + (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) { + + /* mov reg, disp(%rbp) */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_REG; + op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; +@@ -271,7 +262,6 @@ int arch_decode_instruction(struct elf * + } else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) { + + /* mov reg, disp(%rsp) */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_REG; + op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; +@@ -287,7 +277,6 @@ int arch_decode_instruction(struct elf * + if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) { + + /* mov disp(%rbp), reg */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_REG_INDIRECT; + op->src.reg = CFI_BP; +@@ -300,7 +289,6 @@ int arch_decode_instruction(struct elf * + modrm_mod != 3 && modrm_rm == 4) { + + /* mov disp(%rsp), reg */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_REG_INDIRECT; + op->src.reg = CFI_SP; +@@ -315,7 +303,6 @@ int arch_decode_instruction(struct elf * + case 0x8d: + if (sib == 0x24 && rex_w && !rex_b && !rex_x) { + +- *type = INSN_STACK; + ADD_OP(op) { + if (!insn.displacement.value) { + /* lea (%rsp), reg */ +@@ -333,7 +320,6 @@ int arch_decode_instruction(struct elf * + } else if (rex == 0x48 && modrm == 0x65) { + + /* lea disp(%rbp), %rsp */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_ADD; + op->src.reg = CFI_BP; +@@ -351,7 +337,6 @@ int arch_decode_instruction(struct elf * + * Restoring rsp back to its original value after a + * stack realignment. + */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_ADD; + op->src.reg = CFI_R10; +@@ -369,7 +354,6 @@ int arch_decode_instruction(struct elf * + * Restoring rsp back to its original value after a + * stack realignment. + */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_ADD; + op->src.reg = CFI_R13; +@@ -383,7 +367,6 @@ int arch_decode_instruction(struct elf * + + case 0x8f: + /* pop to mem */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_POP; + op->dest.type = OP_DEST_MEM; +@@ -396,7 +379,6 @@ int arch_decode_instruction(struct elf * + + case 0x9c: + /* pushf */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_CONST; + op->dest.type = OP_DEST_PUSH; +@@ -405,7 +387,6 @@ int arch_decode_instruction(struct elf * + + case 0x9d: + /* popf */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_POP; + op->dest.type = OP_DEST_MEM; +@@ -437,7 +418,6 @@ int arch_decode_instruction(struct elf * + } else if (op2 == 0xa0 || op2 == 0xa8) { + + /* push fs/gs */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_CONST; + op->dest.type = OP_DEST_PUSH; +@@ -446,7 +426,6 @@ int arch_decode_instruction(struct elf * + } else if (op2 == 0xa1 || op2 == 0xa9) { + + /* pop fs/gs */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_POP; + op->dest.type = OP_DEST_MEM; +@@ -463,7 +442,6 @@ int arch_decode_instruction(struct elf * + * mov bp, sp + * pop bp + */ +- *type = INSN_STACK; + ADD_OP(op) + op->dest.type = OP_DEST_LEAVE; + +@@ -511,7 +489,6 @@ int arch_decode_instruction(struct elf * + else if (modrm_reg == 6) { + + /* push from mem */ +- *type = INSN_STACK; + ADD_OP(op) { + op->src.type = OP_SRC_CONST; + op->dest.type = OP_DEST_PUSH; +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -2056,9 +2056,6 @@ static int validate_branch(struct objtoo + } + return 0; + +- case INSN_STACK: +- break; +- + default: + break; + } diff --git a/patches.suse/objtool-Remove-check-preventing-branches-within-alternative.patch b/patches.suse/objtool-Remove-check-preventing-branches-within-alternative.patch new file mode 100644 index 0000000..69ef4f3 --- /dev/null +++ b/patches.suse/objtool-Remove-check-preventing-branches-within-alternative.patch @@ -0,0 +1,42 @@ +From: Julien Thierry +Date: Fri, 27 Mar 2020 15:28:42 +0000 +Subject: objtool: Remove check preventing branches within alternative +Git-commit: 9e98d62aa7ea1375052895650f3e6d362336c5c9 +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +While jumping from outside an alternative region to the middle of an +alternative region is very likely wrong, jumping from an alternative +region into the same region is valid. It is a common pattern on arm64. + +The first pattern is unlikely to happen in practice and checking only +for this adds a lot of complexity. + +Just remove the current check. + +Suggested-by: Josh Poimboeuf +Signed-off-by: Julien Thierry +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Miroslav Benes +Link: https://lkml.kernel.org/r/20200327152847.15294-6-jthierry@redhat.com + +Acked-by: Miroslav Benes +--- + tools/objtool/check.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1850,12 +1850,6 @@ static int validate_branch(struct objtoo + insn = first; + sec = insn->sec; + +- if (insn->alt_group && list_empty(&insn->alts)) { +- WARN_FUNC("don't know how to handle branch to middle of alternative instruction group", +- sec, insn->offset); +- return 1; +- } +- + while (1) { + next_insn = next_insn_same_sec(file, insn); + diff --git a/patches.suse/objtool-Rename-elf_open-to-prevent-conflict-with-libelf-from-elftoolchain.patch b/patches.suse/objtool-Rename-elf_open-to-prevent-conflict-with-libelf-from-elftoolchain.patch new file mode 100644 index 0000000..ad8492b --- /dev/null +++ b/patches.suse/objtool-Rename-elf_open-to-prevent-conflict-with-libelf-from-elftoolchain.patch @@ -0,0 +1,67 @@ +From: Michael Forney +Date: Wed, 10 Jul 2019 16:20:11 -0500 +Subject: objtool: Rename elf_open() to prevent conflict with libelf from + elftoolchain +Git-commit: 8e144797f1a67c52e386161863da4614a23ad913 +Patch-mainline: v5.3-rc1 +References: bsc#1202396 + +The elftoolchain version of libelf has a function named elf_open(). + +The function name isn't quite accurate anyway, since it also reads all +the ELF data. Rename it to elf_read(), which is more accurate. + +[ jpoimboe: rename to elf_read(); write commit description ] + +Signed-off-by: Michael Forney +Signed-off-by: Josh Poimboeuf +Signed-off-by: Thomas Gleixner +Link: https://lkml.kernel.org/r/7ce2d1b35665edf19fd0eb6fbc0b17b81a48e62f.1562793604.git.jpoimboe@redhat.com + +Acked-by: Miroslav Benes +--- + tools/objtool/check.c | 2 +- + tools/objtool/elf.c | 2 +- + tools/objtool/elf.h | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 172f99195726..de8f40730b37 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -2407,7 +2407,7 @@ int check(const char *_objname, bool orc) + + objname = _objname; + +- file.elf = elf_open(objname, orc ? O_RDWR : O_RDONLY); ++ file.elf = elf_read(objname, orc ? O_RDWR : O_RDONLY); + if (!file.elf) + return 1; + +diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c +index 76e4f7ceab82..e18698262837 100644 +--- a/tools/objtool/elf.c ++++ b/tools/objtool/elf.c +@@ -401,7 +401,7 @@ static int read_relas(struct elf *elf) + return 0; + } + +-struct elf *elf_open(const char *name, int flags) ++struct elf *elf_read(const char *name, int flags) + { + struct elf *elf; + Elf_Cmd cmd; +diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h +index e44ca5d51871..2fe0b0aa741d 100644 +--- a/tools/objtool/elf.h ++++ b/tools/objtool/elf.h +@@ -74,7 +74,7 @@ struct elf { + }; + + +-struct elf *elf_open(const char *name, int flags); ++struct elf *elf_read(const char *name, int flags); + struct section *find_section_by_name(struct elf *elf, const char *name); + struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); + struct symbol *find_symbol_by_name(struct elf *elf, const char *name); + diff --git a/patches.suse/objtool-Rename-struct-cfi_state.patch b/patches.suse/objtool-Rename-struct-cfi_state.patch new file mode 100644 index 0000000..f16444b --- /dev/null +++ b/patches.suse/objtool-Rename-struct-cfi_state.patch @@ -0,0 +1,68 @@ +From: Peter Zijlstra +Date: Wed, 25 Mar 2020 15:34:50 +0100 +Subject: objtool: Rename struct cfi_state +Git-commit: a3608f5954d07a40fb93764dc6d06195fa52eb14 +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +There's going to be a new struct cfi_state, rename this one to make +place. + +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Miroslav Benes +Reviewed-by: Alexandre Chartre +Acked-by: Josh Poimboeuf +Link: https://lkml.kernel.org/r/20200416115118.986441913@infradead.org +Signed-off-by: Ingo Molnar +Acked-by: Miroslav Benes +--- + tools/objtool/arch.h | 2 +- + tools/objtool/arch/x86/decode.c | 2 +- + tools/objtool/cfi.h | 2 +- + tools/objtool/check.c | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +--- a/tools/objtool/arch.h ++++ b/tools/objtool/arch.h +@@ -73,7 +73,7 @@ struct stack_op { + struct list_head list; + }; + +-void arch_initial_func_cfi_state(struct cfi_state *state); ++void arch_initial_func_cfi_state(struct cfi_init_state *state); + + int arch_decode_instruction(struct elf *elf, struct section *sec, + unsigned long offset, unsigned int maxlen, +--- a/tools/objtool/arch/x86/decode.c ++++ b/tools/objtool/arch/x86/decode.c +@@ -488,7 +488,7 @@ int arch_decode_instruction(struct elf * + return 0; + } + +-void arch_initial_func_cfi_state(struct cfi_state *state) ++void arch_initial_func_cfi_state(struct cfi_init_state *state) + { + int i; + +--- a/tools/objtool/cfi.h ++++ b/tools/objtool/cfi.h +@@ -47,7 +47,7 @@ struct cfi_reg { + int offset; + }; + +-struct cfi_state { ++struct cfi_init_state { + struct cfi_reg cfa; + struct cfi_reg regs[CFI_NUM_REGS]; + }; +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -37,7 +37,7 @@ struct alternative { + }; + + const char *objname; +-struct cfi_state initial_func_cfi; ++struct cfi_init_state initial_func_cfi; + + struct instruction *find_insn(struct objtool_file *file, + struct section *sec, unsigned long offset) diff --git a/patches.suse/objtool-Rework-allocating-stack_ops-on-decode.patch b/patches.suse/objtool-Rework-allocating-stack_ops-on-decode.patch new file mode 100644 index 0000000..e680451 --- /dev/null +++ b/patches.suse/objtool-Rework-allocating-stack_ops-on-decode.patch @@ -0,0 +1,442 @@ +From: Peter Zijlstra +Date: Thu, 23 Apr 2020 13:22:10 +0200 +Subject: objtool: Rework allocating stack_ops on decode +Git-commit: 7d989fcadd6e225a61d6490dd15bdbdfc8a53d5c +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +Wrap each stack_op in a macro that allocates and adds it to the list. +This simplifies trying to figure out what to do with the pre-allocated +stack_op at the end. + +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Alexandre Chartre +Reviewed-by: Miroslav Benes +Acked-by: Josh Poimboeuf +Link: https://lkml.kernel.org/r/20200428191659.736151601@infradead.org + +Acked-by: Miroslav Benes +--- + tools/objtool/arch/x86/decode.c | 237 +++++++++++++++++++++++----------------- + 1 file changed, 139 insertions(+), 98 deletions(-) + +--- a/tools/objtool/arch/x86/decode.c ++++ b/tools/objtool/arch/x86/decode.c +@@ -78,6 +78,11 @@ bool arch_callee_saved_reg(unsigned char + } + } + ++#define ADD_OP(op) \ ++ if (!(op = calloc(1, sizeof(*op)))) \ ++ return -1; \ ++ else for (list_add_tail(&op->list, ops_list); op; op = NULL) ++ + int arch_decode_instruction(struct elf *elf, struct section *sec, + unsigned long offset, unsigned int maxlen, + unsigned int *len, enum insn_type *type, +@@ -89,7 +94,7 @@ int arch_decode_instruction(struct elf * + unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, + rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0, + modrm_reg = 0, sib = 0; +- struct stack_op *op; ++ struct stack_op *op = NULL; + + x86_64 = is_x86_64(elf); + if (x86_64 == -1) +@@ -130,10 +135,6 @@ int arch_decode_instruction(struct elf * + if (insn.sib.nbytes) + sib = insn.sib.bytes[0]; + +- op = calloc(1, sizeof(*op)); +- if (!op) +- return -1; +- + switch (op1) { + + case 0x1: +@@ -142,10 +143,12 @@ int arch_decode_instruction(struct elf * + + /* add/sub reg, %rsp */ + *type = INSN_STACK; +- op->src.type = OP_SRC_ADD; +- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = CFI_SP; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_ADD; ++ op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = CFI_SP; ++ } + } + break; + +@@ -153,9 +156,11 @@ int arch_decode_instruction(struct elf * + + /* push reg */ + *type = INSN_STACK; +- op->src.type = OP_SRC_REG; +- op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; +- op->dest.type = OP_DEST_PUSH; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_REG; ++ op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; ++ op->dest.type = OP_DEST_PUSH; ++ } + + break; + +@@ -163,9 +168,11 @@ int arch_decode_instruction(struct elf * + + /* pop reg */ + *type = INSN_STACK; +- op->src.type = OP_SRC_POP; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_POP; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; ++ } + + break; + +@@ -173,8 +180,10 @@ int arch_decode_instruction(struct elf * + case 0x6a: + /* push immediate */ + *type = INSN_STACK; +- op->src.type = OP_SRC_CONST; +- op->dest.type = OP_DEST_PUSH; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_CONST; ++ op->dest.type = OP_DEST_PUSH; ++ } + break; + + case 0x70 ... 0x7f: +@@ -189,11 +198,13 @@ int arch_decode_instruction(struct elf * + if (modrm == 0xe4) { + /* and imm, %rsp */ + *type = INSN_STACK; +- op->src.type = OP_SRC_AND; +- op->src.reg = CFI_SP; +- op->src.offset = insn.immediate.value; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = CFI_SP; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_AND; ++ op->src.reg = CFI_SP; ++ op->src.offset = insn.immediate.value; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = CFI_SP; ++ } + break; + } + +@@ -206,11 +217,13 @@ int arch_decode_instruction(struct elf * + + /* add/sub imm, %rsp */ + *type = INSN_STACK; +- op->src.type = OP_SRC_ADD; +- op->src.reg = CFI_SP; +- op->src.offset = insn.immediate.value * sign; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = CFI_SP; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_ADD; ++ op->src.reg = CFI_SP; ++ op->src.offset = insn.immediate.value * sign; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = CFI_SP; ++ } + break; + + case 0x89: +@@ -218,10 +231,12 @@ int arch_decode_instruction(struct elf * + + /* mov %rsp, reg */ + *type = INSN_STACK; +- op->src.type = OP_SRC_REG; +- op->src.reg = CFI_SP; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b]; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_REG; ++ op->src.reg = CFI_SP; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b]; ++ } + break; + } + +@@ -229,10 +244,12 @@ int arch_decode_instruction(struct elf * + + /* mov reg, %rsp */ + *type = INSN_STACK; +- op->src.type = OP_SRC_REG; +- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = CFI_SP; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_REG; ++ op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = CFI_SP; ++ } + break; + } + +@@ -243,21 +260,25 @@ int arch_decode_instruction(struct elf * + + /* mov reg, disp(%rbp) */ + *type = INSN_STACK; +- op->src.type = OP_SRC_REG; +- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; +- op->dest.type = OP_DEST_REG_INDIRECT; +- op->dest.reg = CFI_BP; +- op->dest.offset = insn.displacement.value; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_REG; ++ op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; ++ op->dest.type = OP_DEST_REG_INDIRECT; ++ op->dest.reg = CFI_BP; ++ op->dest.offset = insn.displacement.value; ++ } + + } else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) { + + /* mov reg, disp(%rsp) */ + *type = INSN_STACK; +- op->src.type = OP_SRC_REG; +- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; +- op->dest.type = OP_DEST_REG_INDIRECT; +- op->dest.reg = CFI_SP; +- op->dest.offset = insn.displacement.value; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_REG; ++ op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; ++ op->dest.type = OP_DEST_REG_INDIRECT; ++ op->dest.reg = CFI_SP; ++ op->dest.offset = insn.displacement.value; ++ } + } + + break; +@@ -267,22 +288,26 @@ int arch_decode_instruction(struct elf * + + /* mov disp(%rbp), reg */ + *type = INSN_STACK; +- op->src.type = OP_SRC_REG_INDIRECT; +- op->src.reg = CFI_BP; +- op->src.offset = insn.displacement.value; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_REG_INDIRECT; ++ op->src.reg = CFI_BP; ++ op->src.offset = insn.displacement.value; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; ++ } + + } else if (rex_w && !rex_b && sib == 0x24 && + modrm_mod != 3 && modrm_rm == 4) { + + /* mov disp(%rsp), reg */ + *type = INSN_STACK; +- op->src.type = OP_SRC_REG_INDIRECT; +- op->src.reg = CFI_SP; +- op->src.offset = insn.displacement.value; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_REG_INDIRECT; ++ op->src.reg = CFI_SP; ++ op->src.offset = insn.displacement.value; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; ++ } + } + + break; +@@ -291,27 +316,31 @@ int arch_decode_instruction(struct elf * + if (sib == 0x24 && rex_w && !rex_b && !rex_x) { + + *type = INSN_STACK; +- if (!insn.displacement.value) { +- /* lea (%rsp), reg */ +- op->src.type = OP_SRC_REG; +- } else { +- /* lea disp(%rsp), reg */ +- op->src.type = OP_SRC_ADD; +- op->src.offset = insn.displacement.value; ++ ADD_OP(op) { ++ if (!insn.displacement.value) { ++ /* lea (%rsp), reg */ ++ op->src.type = OP_SRC_REG; ++ } else { ++ /* lea disp(%rsp), reg */ ++ op->src.type = OP_SRC_ADD; ++ op->src.offset = insn.displacement.value; ++ } ++ op->src.reg = CFI_SP; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; + } +- op->src.reg = CFI_SP; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; + + } else if (rex == 0x48 && modrm == 0x65) { + + /* lea disp(%rbp), %rsp */ + *type = INSN_STACK; +- op->src.type = OP_SRC_ADD; +- op->src.reg = CFI_BP; +- op->src.offset = insn.displacement.value; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = CFI_SP; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_ADD; ++ op->src.reg = CFI_BP; ++ op->src.offset = insn.displacement.value; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = CFI_SP; ++ } + + } else if (rex == 0x49 && modrm == 0x62 && + insn.displacement.value == -8) { +@@ -323,11 +352,13 @@ int arch_decode_instruction(struct elf * + * stack realignment. + */ + *type = INSN_STACK; +- op->src.type = OP_SRC_ADD; +- op->src.reg = CFI_R10; +- op->src.offset = -8; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = CFI_SP; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_ADD; ++ op->src.reg = CFI_R10; ++ op->src.offset = -8; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = CFI_SP; ++ } + + } else if (rex == 0x49 && modrm == 0x65 && + insn.displacement.value == -16) { +@@ -339,11 +370,13 @@ int arch_decode_instruction(struct elf * + * stack realignment. + */ + *type = INSN_STACK; +- op->src.type = OP_SRC_ADD; +- op->src.reg = CFI_R13; +- op->src.offset = -16; +- op->dest.type = OP_DEST_REG; +- op->dest.reg = CFI_SP; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_ADD; ++ op->src.reg = CFI_R13; ++ op->src.offset = -16; ++ op->dest.type = OP_DEST_REG; ++ op->dest.reg = CFI_SP; ++ } + } + + break; +@@ -351,8 +384,10 @@ int arch_decode_instruction(struct elf * + case 0x8f: + /* pop to mem */ + *type = INSN_STACK; +- op->src.type = OP_SRC_POP; +- op->dest.type = OP_DEST_MEM; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_POP; ++ op->dest.type = OP_DEST_MEM; ++ } + break; + + case 0x90: +@@ -362,15 +397,19 @@ int arch_decode_instruction(struct elf * + case 0x9c: + /* pushf */ + *type = INSN_STACK; +- op->src.type = OP_SRC_CONST; +- op->dest.type = OP_DEST_PUSH; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_CONST; ++ op->dest.type = OP_DEST_PUSH; ++ } + break; + + case 0x9d: + /* popf */ + *type = INSN_STACK; +- op->src.type = OP_SRC_POP; +- op->dest.type = OP_DEST_MEM; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_POP; ++ op->dest.type = OP_DEST_MEM; ++ } + break; + + case 0x0f: +@@ -399,15 +438,19 @@ int arch_decode_instruction(struct elf * + + /* push fs/gs */ + *type = INSN_STACK; +- op->src.type = OP_SRC_CONST; +- op->dest.type = OP_DEST_PUSH; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_CONST; ++ op->dest.type = OP_DEST_PUSH; ++ } + + } else if (op2 == 0xa1 || op2 == 0xa9) { + + /* pop fs/gs */ + *type = INSN_STACK; +- op->src.type = OP_SRC_POP; +- op->dest.type = OP_DEST_MEM; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_POP; ++ op->dest.type = OP_DEST_MEM; ++ } + } + + break; +@@ -421,7 +464,8 @@ int arch_decode_instruction(struct elf * + * pop bp + */ + *type = INSN_STACK; +- op->dest.type = OP_DEST_LEAVE; ++ ADD_OP(op) ++ op->dest.type = OP_DEST_LEAVE; + + break; + +@@ -468,8 +512,10 @@ int arch_decode_instruction(struct elf * + + /* push from mem */ + *type = INSN_STACK; +- op->src.type = OP_SRC_CONST; +- op->dest.type = OP_DEST_PUSH; ++ ADD_OP(op) { ++ op->src.type = OP_SRC_CONST; ++ op->dest.type = OP_DEST_PUSH; ++ } + } + + break; +@@ -480,11 +526,6 @@ int arch_decode_instruction(struct elf * + + *immediate = insn.immediate.nbytes ? insn.immediate.value : 0; + +- if (*type == INSN_STACK) +- list_add_tail(&op->list, ops_list); +- else +- free(op); +- + return 0; + } + diff --git a/patches.suse/objtool-Rewrite-alt-skip_orig.patch b/patches.suse/objtool-Rewrite-alt-skip_orig.patch new file mode 100644 index 0000000..a991943 --- /dev/null +++ b/patches.suse/objtool-Rewrite-alt-skip_orig.patch @@ -0,0 +1,89 @@ +From: Peter Zijlstra +Date: Fri, 1 Mar 2019 11:19:03 +0100 +Subject: objtool: Rewrite alt->skip_orig +Git-commit: 764eef4b109ae11e6c987de9c14fc7c482041be0 +Patch-mainline: v5.2-rc1 +References: bsc#1202396 + +Really skip the original instruction flow, instead of letting it +continue with NOPs. + +Since the alternative code flow already continues after the original +instructions, only the alt-original is skipped. + +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Josh Poimboeuf +Cc: Borislav Petkov +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Signed-off-by: Ingo Molnar +Acked-by: Miroslav Benes +--- + tools/objtool/check.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index ccc66af5907f..5264a305d658 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -31,6 +31,7 @@ + struct alternative { + struct list_head list; + struct instruction *insn; ++ bool skip_orig; + }; + + const char *objname; +@@ -623,9 +624,6 @@ static int add_call_destinations(struct objtool_file *file) + * conditionally jumps to the _end_ of the entry. We have to modify these + * jumps' destinations to point back to .text rather than the end of the + * entry in .altinstr_replacement. +- * +- * 4. It has been requested that we don't validate the !POPCNT feature path +- * which is a "very very small percentage of machines". + */ + static int handle_group_alt(struct objtool_file *file, + struct special_alt *special_alt, +@@ -641,9 +639,6 @@ static int handle_group_alt(struct objtool_file *file, + if (insn->offset >= special_alt->orig_off + special_alt->orig_len) + break; + +- if (special_alt->skip_orig) +- insn->type = INSN_NOP; +- + insn->alt_group = true; + last_orig_insn = insn; + } +@@ -808,6 +803,7 @@ static int add_special_section_alts(struct objtool_file *file) + } + + alt->insn = new_insn; ++ alt->skip_orig = special_alt->skip_orig; + list_add_tail(&alt->list, &orig_insn->alts); + + list_del(&special_alt->list); +@@ -1883,7 +1879,12 @@ static int validate_branch(struct objtool_file *file, struct instruction *first, + insn->visited = true; + + if (!insn->ignore_alts) { ++ bool skip_orig = false; ++ + list_for_each_entry(alt, &insn->alts, list) { ++ if (alt->skip_orig) ++ skip_orig = true; ++ + ret = validate_branch(file, alt->insn, state); + if (ret) { + if (backtrace) +@@ -1891,6 +1892,9 @@ static int validate_branch(struct objtool_file *file, struct instruction *first, + return ret; + } + } ++ ++ if (skip_orig) ++ return 0; + } + + switch (insn->type) { + diff --git a/patches.suse/objtool-Set-insn-func-for-alternatives.patch b/patches.suse/objtool-Set-insn-func-for-alternatives.patch new file mode 100644 index 0000000..9765e9e --- /dev/null +++ b/patches.suse/objtool-Set-insn-func-for-alternatives.patch @@ -0,0 +1,38 @@ +From: Peter Zijlstra +Date: Mon, 25 Feb 2019 10:31:24 +0100 +Subject: objtool: Set insn->func for alternatives +Git-commit: a4d09dde9093a04a9b48fb9e5ef3177bdfaff199 +Patch-mainline: v5.2-rc1 +References: bsc#1202396 + +In preparation of function attributes, we need each instruction to +have a valid link back to its function. + +Therefore make sure we set the function association for alternative +instruction sequences; they are, after all, still part of the function. + +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Josh Poimboeuf +Cc: Borislav Petkov +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Signed-off-by: Ingo Molnar +Acked-by: Miroslav Benes +--- + tools/objtool/check.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 110ea3d84772..950d0f62d22b 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -695,6 +695,7 @@ static int handle_group_alt(struct objtool_file *file, + last_new_insn = insn; + + insn->ignore = orig_insn->ignore_alts; ++ insn->func = orig_insn->func; + + if (insn->type != INSN_JUMP_CONDITIONAL && + insn->type != INSN_JUMP_UNCONDITIONAL) + diff --git a/patches.suse/objtool-Support-conditional-retpolines.patch b/patches.suse/objtool-Support-conditional-retpolines.patch new file mode 100644 index 0000000..dc616e2 --- /dev/null +++ b/patches.suse/objtool-Support-conditional-retpolines.patch @@ -0,0 +1,79 @@ +From: Josh Poimboeuf +Date: Wed, 17 Jul 2019 20:36:57 -0500 +Subject: objtool: Support conditional retpolines +Git-commit: b68b9907069a8d3a65bc16a35360bf8f8603c8fa +Patch-mainline: v5.3-rc1 +References: bsc#1202396 + +A Clang-built kernel is showing the following warning: + + arch/x86/kernel/platform-quirks.o: warning: objtool: x86_early_init_platform_quirks()+0x84: unreachable instruction + +That corresponds to this code: + + 7e: 0f 85 00 00 00 00 jne 84 + 80: R_X86_64_PC32 __x86_indirect_thunk_r11-0x4 + 84: c3 retq + +This is a conditional retpoline sibling call, which is now possible +thanks to retpolines. Objtool hasn't seen that before. It's +incorrectly interpreting the conditional jump as an unconditional +dynamic jump. + +Reported-by: Nick Desaulniers +Signed-off-by: Josh Poimboeuf +Signed-off-by: Thomas Gleixner +Tested-by: Nick Desaulniers +Acked-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/30d4c758b267ef487fb97e6ecb2f148ad007b554.1563413318.git.jpoimboe@redhat.com + +Acked-by: Miroslav Benes +--- + tools/objtool/arch.h | 1 + + tools/objtool/check.c | 12 ++++++++++-- + 2 files changed, 11 insertions(+), 2 deletions(-) + +--- a/tools/objtool/arch.h ++++ b/tools/objtool/arch.h +@@ -27,6 +27,7 @@ enum insn_type { + INSN_JUMP_CONDITIONAL, + INSN_JUMP_UNCONDITIONAL, + INSN_JUMP_DYNAMIC, ++ INSN_JUMP_DYNAMIC_CONDITIONAL, + INSN_CALL, + INSN_CALL_DYNAMIC, + INSN_RETURN, +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -514,7 +514,11 @@ static int add_jump_destinations(struct + * Retpoline jumps are really dynamic jumps in + * disguise, so convert them accordingly. + */ +- insn->type = INSN_JUMP_DYNAMIC; ++ if (insn->type == INSN_JUMP_UNCONDITIONAL) ++ insn->type = INSN_JUMP_DYNAMIC; ++ else ++ insn->type = INSN_JUMP_DYNAMIC_CONDITIONAL; ++ + insn->retpoline_safe = true; + continue; + } else { +@@ -1945,13 +1949,17 @@ static int validate_branch(struct objtoo + break; + + case INSN_JUMP_DYNAMIC: ++ case INSN_JUMP_DYNAMIC_CONDITIONAL: + if (func && list_empty(&insn->alts)) { + ret = validate_sibling_call(insn, &state); + if (ret) + return ret; + } + +- return 0; ++ if (insn->type == INSN_JUMP_DYNAMIC) ++ return 0; ++ ++ break; + + case INSN_CONTEXT_SWITCH: + if (func && (!next_insn || !next_insn->hint)) { diff --git a/patches.suse/objtool-Support-multiple-stack_op-per-instruction.patch b/patches.suse/objtool-Support-multiple-stack_op-per-instruction.patch new file mode 100644 index 0000000..b875ff1 --- /dev/null +++ b/patches.suse/objtool-Support-multiple-stack_op-per-instruction.patch @@ -0,0 +1,198 @@ +From: Julien Thierry +Date: Fri, 27 Mar 2020 15:28:47 +0000 +Subject: objtool: Support multiple stack_op per instruction +Git-commit: 65ea47dcf4f936987a5fbf839c97acea00f4f196 +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +Instruction sets can include more or less complex operations which might +not fit the currently defined set of stack_ops. + +Combining more than one stack_op provides more flexibility to describe +the behaviour of an instruction. This also reduces the need to define +new stack_ops specific to a single instruction set. + +Allow instruction decoders to generate multiple stack_op per +instruction. + +Signed-off-by: Julien Thierry +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Miroslav Benes +Reviewed-by: Alexandre Chartre +Acked-by: Josh Poimboeuf +Link: https://lkml.kernel.org/r/20200327152847.15294-11-jthierry@redhat.com +Signed-off-by: Ingo Molnar +Acked-by: Miroslav Benes +--- + tools/objtool/arch.h | 4 +++- + tools/objtool/arch/x86/decode.c | 13 ++++++++++++- + tools/objtool/check.c | 32 +++++++++++++++++++++++++------- + tools/objtool/check.h | 2 +- + 4 files changed, 41 insertions(+), 10 deletions(-) + +--- a/tools/objtool/arch.h ++++ b/tools/objtool/arch.h +@@ -70,6 +70,7 @@ struct op_src { + struct stack_op { + struct op_dest dest; + struct op_src src; ++ struct list_head list; + }; + + void arch_initial_func_cfi_state(struct cfi_state *state); +@@ -77,7 +78,8 @@ void arch_initial_func_cfi_state(struct + int arch_decode_instruction(struct elf *elf, struct section *sec, + unsigned long offset, unsigned int maxlen, + unsigned int *len, enum insn_type *type, +- unsigned long *immediate, struct stack_op *op); ++ unsigned long *immediate, ++ struct list_head *ops_list); + + bool arch_callee_saved_reg(unsigned char reg); + +--- a/tools/objtool/arch/x86/decode.c ++++ b/tools/objtool/arch/x86/decode.c +@@ -81,13 +81,15 @@ bool arch_callee_saved_reg(unsigned char + int arch_decode_instruction(struct elf *elf, struct section *sec, + unsigned long offset, unsigned int maxlen, + unsigned int *len, enum insn_type *type, +- unsigned long *immediate, struct stack_op *op) ++ unsigned long *immediate, ++ struct list_head *ops_list) + { + struct insn insn; + int x86_64, sign; + unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, + rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0, + modrm_reg = 0, sib = 0; ++ struct stack_op *op; + + x86_64 = is_x86_64(elf); + if (x86_64 == -1) +@@ -128,6 +130,10 @@ int arch_decode_instruction(struct elf * + if (insn.sib.nbytes) + sib = insn.sib.bytes[0]; + ++ op = calloc(1, sizeof(*op)); ++ if (!op) ++ return -1; ++ + switch (op1) { + + case 0x1: +@@ -474,6 +480,11 @@ int arch_decode_instruction(struct elf * + + *immediate = insn.immediate.nbytes ? insn.immediate.value : 0; + ++ if (*type == INSN_STACK) ++ list_add_tail(&op->list, ops_list); ++ else ++ free(op); ++ + return 0; + } + +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -282,6 +282,7 @@ static int decode_instructions(struct ob + } + memset(insn, 0, sizeof(*insn)); + INIT_LIST_HEAD(&insn->alts); ++ INIT_LIST_HEAD(&insn->stack_ops); + clear_insn_state(&insn->state); + + insn->sec = sec; +@@ -291,7 +292,7 @@ static int decode_instructions(struct ob + sec->len - offset, + &insn->len, &insn->type, + &insn->immediate, +- &insn->stack_op); ++ &insn->stack_ops); + if (ret) + goto err; + +@@ -673,6 +674,7 @@ static int handle_group_alt(struct objto + } + memset(fake_jump, 0, sizeof(*fake_jump)); + INIT_LIST_HEAD(&fake_jump->alts); ++ INIT_LIST_HEAD(&fake_jump->stack_ops); + clear_insn_state(&fake_jump->state); + + fake_jump->sec = special_alt->new_sec; +@@ -1317,10 +1319,11 @@ static bool has_valid_stack_frame(struct + return false; + } + +-static int update_insn_state_regs(struct instruction *insn, struct insn_state *state) ++static int update_insn_state_regs(struct instruction *insn, ++ struct insn_state *state, ++ struct stack_op *op) + { + struct cfi_reg *cfa = &state->cfa; +- struct stack_op *op = &insn->stack_op; + + if (cfa->base != CFI_SP && cfa->base != CFI_SP_INDIRECT) + return 0; +@@ -1410,9 +1413,9 @@ static void restore_reg(struct insn_stat + * 41 5d pop %r13 + * c3 retq + */ +-static int update_insn_state(struct instruction *insn, struct insn_state *state) ++static int update_insn_state(struct instruction *insn, struct insn_state *state, ++ struct stack_op *op) + { +- struct stack_op *op = &insn->stack_op; + struct cfi_reg *cfa = &state->cfa; + struct cfi_reg *regs = state->regs; + +@@ -1426,7 +1429,7 @@ static int update_insn_state(struct inst + } + + if (state->type == ORC_TYPE_REGS || state->type == ORC_TYPE_REGS_IRET) +- return update_insn_state_regs(insn, state); ++ return update_insn_state_regs(insn, state, op); + + switch (op->dest.type) { + +@@ -1752,6 +1755,21 @@ static int update_insn_state(struct inst + return 0; + } + ++static int handle_insn_ops(struct instruction *insn, struct insn_state *state) ++{ ++ struct stack_op *op; ++ ++ list_for_each_entry(op, &insn->stack_ops, list) { ++ int res; ++ ++ res = update_insn_state(insn, state, op); ++ if (res) ++ return res; ++ } ++ ++ return 0; ++} ++ + static bool insn_state_match(struct instruction *insn, struct insn_state *state) + { + struct insn_state *state1 = &insn->state, *state2 = state; +@@ -1996,7 +2014,7 @@ static int validate_branch(struct objtoo + return 0; + + case INSN_STACK: +- if (update_insn_state(insn, &state)) ++ if (handle_insn_ops(insn, &state)) + return 1; + + break; +--- a/tools/objtool/check.h ++++ b/tools/objtool/check.h +@@ -51,7 +51,7 @@ struct instruction { + struct instruction *first_jump_src; + struct list_head alts; + struct symbol *func; +- struct stack_op stack_op; ++ struct list_head stack_ops; + struct insn_state state; + struct orc_entry orc; + }; diff --git a/patches.suse/objtool-Track-original-function-across-branches.patch b/patches.suse/objtool-Track-original-function-across-branches.patch new file mode 100644 index 0000000..8338c7d --- /dev/null +++ b/patches.suse/objtool-Track-original-function-across-branches.patch @@ -0,0 +1,117 @@ +From: Josh Poimboeuf +Date: Wed, 17 Jul 2019 20:36:47 -0500 +Subject: objtool: Track original function across branches +Git-commit: c705cecc8431951b4f34178e6b1db51b4a504c43 +Patch-mainline: v5.3-rc1 +References: bsc#1202396 + +If 'insn->func' is NULL, objtool skips some important checks, including +sibling call validation. So if some .fixup code does an invalid sibling +call, objtool ignores it. + +Treat all code branches (including alts) as part of the original +function by keeping track of the original func value from +validate_functions(). + +This improves the usefulness of some clang function fallthrough +warnings, and exposes some additional kernel bugs in the process. + +Signed-off-by: Josh Poimboeuf +Signed-off-by: Thomas Gleixner +Tested-by: Nick Desaulniers +Acked-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/505df630f33c9717e1ccde6e4b64c5303135c25f.1563413318.git.jpoimboe@redhat.com + +Acked-by: Miroslav Benes +--- + tools/objtool/check.c | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -1788,13 +1788,12 @@ static int validate_sibling_call(struct + * each instruction and validate all the rules described in + * tools/objtool/Documentation/stack-validation.txt. + */ +-static int validate_branch(struct objtool_file *file, struct instruction *first, +- struct insn_state state) ++static int validate_branch(struct objtool_file *file, struct symbol *func, ++ struct instruction *first, struct insn_state state) + { + struct alternative *alt; + struct instruction *insn, *next_insn; + struct section *sec; +- struct symbol *func = NULL; + int ret; + + insn = first; +@@ -1815,9 +1814,6 @@ static int validate_branch(struct objtoo + return 1; + } + +- if (insn->func) +- func = insn->func->pfunc; +- + if (func && insn->ignore) { + WARN_FUNC("BUG: why am I validating an ignored function?", + sec, insn->offset); +@@ -1837,7 +1833,7 @@ static int validate_branch(struct objtoo + + i = insn; + save_insn = NULL; +- func_for_each_insn_continue_reverse(file, insn->func, i) { ++ func_for_each_insn_continue_reverse(file, func, i) { + if (i->save) { + save_insn = i; + break; +@@ -1883,7 +1879,7 @@ static int validate_branch(struct objtoo + if (alt->skip_orig) + skip_orig = true; + +- ret = validate_branch(file, alt->insn, state); ++ ret = validate_branch(file, func, alt->insn, state); + if (ret) { + if (backtrace) + BT_FUNC("(alt)", insn); +@@ -1906,7 +1902,7 @@ static int validate_branch(struct objtoo + + if (state.bp_scratch) { + WARN("%s uses BP as a scratch register", +- insn->func->name); ++ func->name); + return 1; + } + +@@ -1941,8 +1937,8 @@ static int validate_branch(struct objtoo + } else if (insn->jump_dest && + (!func || !insn->jump_dest->func || + insn->jump_dest->func->pfunc == func)) { +- ret = validate_branch(file, insn->jump_dest, +- state); ++ ret = validate_branch(file, func, ++ insn->jump_dest, state); + if (ret) { + if (backtrace) + BT_FUNC("(branch)", insn); +@@ -2011,7 +2007,7 @@ static int validate_unwind_hints(struct + + for_each_insn(file, insn) { + if (insn->hint && !insn->visited) { +- ret = validate_branch(file, insn, state); ++ ret = validate_branch(file, insn->func, insn, state); + if (ret && backtrace) + BT_FUNC("<=== (hint)", insn); + warnings += ret; +@@ -2138,10 +2134,10 @@ static int validate_functions(struct obj + continue; + + insn = find_insn(file, sec, func->offset); +- if (!insn || insn->ignore) ++ if (!insn || insn->ignore || insn->visited) + continue; + +- ret = validate_branch(file, insn, state); ++ ret = validate_branch(file, func, insn, state); + if (ret && backtrace) + BT_FUNC("<=== (func)", insn); + warnings += ret; diff --git a/patches.suse/objtool-Uniquely-identify-alternative-instruction-groups.patch b/patches.suse/objtool-Uniquely-identify-alternative-instruction-groups.patch new file mode 100644 index 0000000..ca0418e --- /dev/null +++ b/patches.suse/objtool-Uniquely-identify-alternative-instruction-groups.patch @@ -0,0 +1,71 @@ +From: Alexandre Chartre +Date: Tue, 14 Apr 2020 12:36:11 +0200 +Subject: objtool: Uniquely identify alternative instruction groups +Git-commit: 13fab06d9a3ad3afdfd51c7f8f87f2ae28444648 +Patch-mainline: v5.8-rc1 +References: bsc#1202396 + +Assign a unique identifier to every alternative instruction group in +order to be able to tell which instructions belong to what +alternative. + +[peterz: extracted from a larger patch] +Signed-off-by: Alexandre Chartre +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Miroslav Benes +Acked-by: Miroslav Benes +--- + tools/objtool/check.c | 6 +++++- + tools/objtool/check.h | 3 ++- + 2 files changed, 7 insertions(+), 2 deletions(-) + +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -658,7 +658,9 @@ static int handle_group_alt(struct objto + struct instruction *orig_insn, + struct instruction **new_insn) + { ++ static unsigned int alt_group_next_index = 1; + struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump = NULL; ++ unsigned int alt_group = alt_group_next_index++; + unsigned long dest_off; + + last_orig_insn = NULL; +@@ -667,7 +669,7 @@ static int handle_group_alt(struct objto + if (insn->offset >= special_alt->orig_off + special_alt->orig_len) + break; + +- insn->alt_group = true; ++ insn->alt_group = alt_group; + last_orig_insn = insn; + } + +@@ -701,6 +703,7 @@ static int handle_group_alt(struct objto + } + + last_new_insn = NULL; ++ alt_group = alt_group_next_index++; + insn = *new_insn; + sec_for_each_insn_from(file, insn) { + if (insn->offset >= special_alt->new_off + special_alt->new_len) +@@ -710,6 +713,7 @@ static int handle_group_alt(struct objto + + insn->ignore = orig_insn->ignore_alts; + insn->func = orig_insn->func; ++ insn->alt_group = alt_group; + + /* + * Since alternative replacement code is copy/pasted by the +--- a/tools/objtool/check.h ++++ b/tools/objtool/check.h +@@ -37,8 +37,9 @@ struct instruction { + unsigned int len; + enum insn_type type; + unsigned long immediate; +- bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts; ++ bool visited, dead_end, ignore, hint, save, restore, ignore_alts; + bool retpoline_safe; ++ int alt_group; + struct symbol *call_dest; + struct instruction *jump_dest; + struct instruction *first_jump_src; diff --git a/patches.suse/objtool-Use-Elf_Scn-typedef-instead-of-assuming-struct-name.patch b/patches.suse/objtool-Use-Elf_Scn-typedef-instead-of-assuming-struct-name.patch new file mode 100644 index 0000000..1fdf84a --- /dev/null +++ b/patches.suse/objtool-Use-Elf_Scn-typedef-instead-of-assuming-struct-name.patch @@ -0,0 +1,34 @@ +From: Michael Forney +Date: Wed, 10 Jul 2019 16:17:35 -0500 +Subject: objtool: Use Elf_Scn typedef instead of assuming struct name +Git-commit: 3c3ea5031761fdd144b461d23a077c3a0cf427fa +Patch-mainline: v5.3-rc1 +References: bsc#1202396 + +The libelf implementation might use a different struct name, and the +Elf_Scn typedef is already used throughout the rest of objtool. + +Signed-off-by: Michael Forney +Signed-off-by: Josh Poimboeuf +Signed-off-by: Thomas Gleixner +Link: https://lkml.kernel.org/r/d270e1be2835fc2a10acf67535ff2ebd2145bf43.1562793448.git.jpoimboe@redhat.com + +Acked-by: Miroslav Benes +--- + tools/objtool/elf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c +index e99e1be19ad9..76e4f7ceab82 100644 +--- a/tools/objtool/elf.c ++++ b/tools/objtool/elf.c +@@ -463,7 +463,7 @@ struct section *elf_create_section(struct elf *elf, const char *name, + { + struct section *sec, *shstrtab; + size_t size = entsize * nr; +- struct Elf_Scn *s; ++ Elf_Scn *s; + Elf_Data *data; + + sec = malloc(sizeof(*sec)); + diff --git a/patches.suse/objtool-add-is_static_jump-helper.patch b/patches.suse/objtool-add-is_static_jump-helper.patch index aab4832..2d40385 100644 --- a/patches.suse/objtool-add-is_static_jump-helper.patch +++ b/patches.suse/objtool-add-is_static_jump-helper.patch @@ -20,7 +20,7 @@ Acked-by: Miroslav Benes --- a/tools/objtool/check.c +++ b/tools/objtool/check.c -@@ -104,6 +104,12 @@ static struct instruction *next_insn_sam +@@ -107,6 +107,12 @@ static struct instruction *next_insn_sam for (insn = next_insn_same_sec(file, insn); insn; \ insn = next_insn_same_sec(file, insn)) @@ -33,7 +33,7 @@ Acked-by: Miroslav Benes /* * Check if the function has been manually whitelisted with the * STACK_FRAME_NON_STANDARD macro, or if it should be automatically whitelisted -@@ -495,8 +501,7 @@ static int add_jump_destinations(struct +@@ -498,8 +504,7 @@ static int add_jump_destinations(struct unsigned long dest_off; for_each_insn(file, insn) { @@ -42,10 +42,10 @@ Acked-by: Miroslav Benes + if (!is_static_jump(insn)) continue; - if (insn->ignore) -@@ -695,8 +700,7 @@ static int handle_group_alt(struct objto - + if (insn->ignore || insn->offset == FAKE_JUMP_OFFSET) +@@ -707,8 +712,7 @@ static int handle_group_alt(struct objto insn->ignore = orig_insn->ignore_alts; + insn->func = orig_insn->func; - if (insn->type != INSN_JUMP_CONDITIONAL && - insn->type != INSN_JUMP_UNCONDITIONAL) diff --git a/patches.suse/objtool-add-relocation-check-for-alternative-sections.patch b/patches.suse/objtool-add-relocation-check-for-alternative-sections.patch index 9c6841f..fc87904 100644 --- a/patches.suse/objtool-add-relocation-check-for-alternative-sections.patch +++ b/patches.suse/objtool-add-relocation-check-for-alternative-sections.patch @@ -32,9 +32,9 @@ Acked-by: Miroslav Benes --- a/tools/objtool/check.c +++ b/tools/objtool/check.c -@@ -700,6 +700,27 @@ static int handle_group_alt(struct objto - +@@ -701,6 +701,27 @@ static int handle_group_alt(struct objto insn->ignore = orig_insn->ignore_alts; + insn->func = orig_insn->func; + /* + * Since alternative replacement code is copy/pasted by the diff --git a/patches.suse/objtool-clean-instruction-state-before-each-function-validation.patch b/patches.suse/objtool-clean-instruction-state-before-each-function-validation.patch index ed71c45..f5ee01b 100644 --- a/patches.suse/objtool-clean-instruction-state-before-each-function-validation.patch +++ b/patches.suse/objtool-clean-instruction-state-before-each-function-validation.patch @@ -24,7 +24,7 @@ Acked-by: Miroslav Benes --- a/tools/objtool/check.c +++ b/tools/objtool/check.c -@@ -2108,13 +2108,6 @@ static int validate_functions(struct obj +@@ -2143,13 +2143,6 @@ static int validate_functions(struct obj struct insn_state state; int ret, warnings = 0; @@ -38,8 +38,8 @@ Acked-by: Miroslav Benes for_each_sec(file, sec) { list_for_each_entry(func, &sec->symbol_list, list) { if (func->type != STT_FUNC || func->pfunc != func) -@@ -2124,6 +2117,12 @@ static int validate_functions(struct obj - if (!insn || insn->ignore) +@@ -2159,6 +2152,12 @@ static int validate_functions(struct obj + if (!insn || insn->ignore || insn->visited) continue; + clear_insn_state(&state); @@ -48,6 +48,6 @@ Acked-by: Miroslav Benes + CFI_NUM_REGS * sizeof(struct cfi_reg)); + state.stack_size = initial_func_cfi.cfa.offset; + - ret = validate_branch(file, insn, state); - warnings += ret; - } + ret = validate_branch(file, func, insn, state); + if (ret && backtrace) + BT_FUNC("<=== (func)", insn); diff --git a/patches.suse/objtool-make-bp-scratch-register-warning-more-robust.patch b/patches.suse/objtool-make-bp-scratch-register-warning-more-robust.patch index bf918b1..de2d249 100644 --- a/patches.suse/objtool-make-bp-scratch-register-warning-more-robust.patch +++ b/patches.suse/objtool-make-bp-scratch-register-warning-more-robust.patch @@ -23,14 +23,14 @@ Acked-by: Miroslav Benes --- a/tools/objtool/check.c +++ b/tools/objtool/check.c -@@ -1892,8 +1892,8 @@ static int validate_branch(struct objtoo +@@ -1923,8 +1923,8 @@ static int validate_branch(struct objtoo } if (state.bp_scratch) { - WARN("%s uses BP as a scratch register", -- insn->func->name); +- func->name); + WARN_FUNC("BP used as a scratch register", -+ insn->sec, insn->offset); ++ sec, insn->offset); return 1; } diff --git a/patches.suse/powerpc-Use-sizeof-foo-rather-than-sizeof-struct-foo.patch b/patches.suse/powerpc-Use-sizeof-foo-rather-than-sizeof-struct-foo.patch new file mode 100644 index 0000000..1f8c140 --- /dev/null +++ b/patches.suse/powerpc-Use-sizeof-foo-rather-than-sizeof-struct-foo.patch @@ -0,0 +1,357 @@ +From a0828cf57acce9bf941539e1f633e9a91f9df57d Mon Sep 17 00:00:00 2001 +From: Markus Elfring +Date: Thu, 19 Jan 2017 17:15:30 +0100 +Subject: [PATCH] powerpc: Use sizeof(*foo) rather than sizeof(struct foo) + +References: FATE#322448, bsc#1054914, git-fixes +Patch-mainline: v4.17-rc1 +Git-commit: a0828cf57acce9bf941539e1f633e9a91f9df57d + +It's slightly less error prone to use sizeof(*foo) rather than +specifying the type. + +Signed-off-by: Markus Elfring +[mpe: Consolidate into one patch, rewrite change log] +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/kernel/nvram_64.c | 9 +++------ + arch/powerpc/oprofile/cell/spu_task_sync.c | 2 +- + arch/powerpc/oprofile/cell/vma_map.c | 4 ++-- + arch/powerpc/platforms/4xx/msi.c | 2 +- + arch/powerpc/platforms/4xx/ocm.c | 2 +- + arch/powerpc/platforms/cell/axon_msi.c | 2 +- + arch/powerpc/platforms/cell/spider-pci.c | 2 +- + arch/powerpc/platforms/cell/spufs/lscsa_alloc.c | 2 +- + arch/powerpc/platforms/powermac/low_i2c.c | 2 +- + arch/powerpc/platforms/powermac/pfunc_core.c | 4 ++-- + arch/powerpc/platforms/powernv/opal-flash.c | 4 ++-- + arch/powerpc/platforms/powernv/opal-hmi.c | 2 +- + arch/powerpc/platforms/powernv/opal-imc.c | 10 +++++----- + arch/powerpc/platforms/powernv/opal-memory-errors.c | 2 +- + arch/powerpc/platforms/powernv/opal-psr.c | 2 +- + arch/powerpc/platforms/powernv/opal-sensor-groups.c | 4 ++-- + arch/powerpc/platforms/powernv/opal-xscom.c | 2 +- + arch/powerpc/platforms/powernv/pci-ioda.c | 2 +- + arch/powerpc/platforms/ps3/mm.c | 6 ++---- + drivers/macintosh/rack-meter.c | 2 +- + 20 files changed, 31 insertions(+), 36 deletions(-) + +diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c +index 496d6393bd41..ba681dac7b46 100644 +--- a/arch/powerpc/kernel/nvram_64.c ++++ b/arch/powerpc/kernel/nvram_64.c +@@ -207,8 +207,7 @@ int nvram_write_os_partition(struct nvram_os_partition *part, + + tmp_index = part->index; + +- rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), +- &tmp_index); ++ rc = ppc_md.nvram_write((char *)&info, sizeof(info), &tmp_index); + if (rc <= 0) { + pr_err("%s: Failed nvram_write (%d)\n", __func__, rc); + return rc; +@@ -244,9 +243,7 @@ int nvram_read_partition(struct nvram_os_partition *part, char *buff, + tmp_index = part->index; + + if (part->os_partition) { +- rc = ppc_md.nvram_read((char *)&info, +- sizeof(struct err_log_info), +- &tmp_index); ++ rc = ppc_md.nvram_read((char *)&info, sizeof(info), &tmp_index); + if (rc <= 0) { + pr_err("%s: Failed nvram_read (%d)\n", __func__, rc); + return rc; +@@ -1173,7 +1170,7 @@ int __init nvram_scan_partitions(void) + "detected: 0-length partition\n"); + goto out; + } +- tmp_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); ++ tmp_part = kmalloc(sizeof(*tmp_part), GFP_KERNEL); + err = -ENOMEM; + if (!tmp_part) { + printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n"); +diff --git a/arch/powerpc/oprofile/cell/spu_task_sync.c b/arch/powerpc/oprofile/cell/spu_task_sync.c +index 44d67b167e0b..2668cc414e4e 100644 +--- a/arch/powerpc/oprofile/cell/spu_task_sync.c ++++ b/arch/powerpc/oprofile/cell/spu_task_sync.c +@@ -208,7 +208,7 @@ prepare_cached_spu_info(struct spu *spu, unsigned long objectId) + /* Create cached_info and set spu_info[spu->number] to point to it. + * spu->number is a system-wide value, not a per-node value. + */ +- info = kzalloc(sizeof(struct cached_info), GFP_KERNEL); ++ info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) { + printk(KERN_ERR "SPU_PROF: " + "%s, line %d: create vma_map failed\n", +diff --git a/arch/powerpc/oprofile/cell/vma_map.c b/arch/powerpc/oprofile/cell/vma_map.c +index c579b16845da..f40e37316dd6 100644 +--- a/arch/powerpc/oprofile/cell/vma_map.c ++++ b/arch/powerpc/oprofile/cell/vma_map.c +@@ -69,8 +69,8 @@ vma_map_add(struct vma_to_fileoffset_map *map, unsigned int vma, + unsigned int size, unsigned int offset, unsigned int guard_ptr, + unsigned int guard_val) + { +- struct vma_to_fileoffset_map *new = +- kzalloc(sizeof(struct vma_to_fileoffset_map), GFP_KERNEL); ++ struct vma_to_fileoffset_map *new = kzalloc(sizeof(*new), GFP_KERNEL); ++ + if (!new) { + printk(KERN_ERR "SPU_PROF: %s, line %d: malloc failed\n", + __func__, __LINE__); +diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c +index 6ea3f248b155..326d34e2aa02 100644 +--- a/arch/powerpc/platforms/cell/axon_msi.c ++++ b/arch/powerpc/platforms/cell/axon_msi.c +@@ -342,7 +342,7 @@ static int axon_msi_probe(struct platform_device *device) + + pr_devel("axon_msi: setting up dn %pOF\n", dn); + +- msic = kzalloc(sizeof(struct axon_msic), GFP_KERNEL); ++ msic = kzalloc(sizeof(*msic), GFP_KERNEL); + if (!msic) { + printk(KERN_ERR "axon_msi: couldn't allocate msic for %pOF\n", + dn); +diff --git a/arch/powerpc/platforms/cell/spider-pci.c b/arch/powerpc/platforms/cell/spider-pci.c +index d1e61e273e64..1200d0dea512 100644 +--- a/arch/powerpc/platforms/cell/spider-pci.c ++++ b/arch/powerpc/platforms/cell/spider-pci.c +@@ -133,7 +133,7 @@ int __init spiderpci_iowa_init(struct iowa_bus *bus, void *data) + pr_debug("SPIDERPCI-IOWA:Bus initialize for spider(%pOF)\n", + np); + +- priv = kzalloc(sizeof(struct spiderpci_iowa_private), GFP_KERNEL); ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + pr_err("SPIDERPCI-IOWA:" + "Can't allocate struct spiderpci_iowa_private"); +diff --git a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c +index b847e9403566..d9de848dae47 100644 +--- a/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c ++++ b/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c +@@ -36,7 +36,7 @@ int spu_alloc_lscsa(struct spu_state *csa) + struct spu_lscsa *lscsa; + unsigned char *p; + +- lscsa = vzalloc(sizeof(struct spu_lscsa)); ++ lscsa = vzalloc(sizeof(*lscsa)); + if (!lscsa) + return -ENOMEM; + csa->lscsa = lscsa; +diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c +index 3408f315ef48..fa89f30e7f27 100644 +--- a/arch/powerpc/platforms/powermac/low_i2c.c ++++ b/arch/powerpc/platforms/powermac/low_i2c.c +@@ -492,7 +492,7 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) + const u32 *psteps, *prate, *addrp; + u32 steps; + +- host = kzalloc(sizeof(struct pmac_i2c_host_kw), GFP_KERNEL); ++ host = kzalloc(sizeof(*host), GFP_KERNEL); + if (host == NULL) { + printk(KERN_ERR "low_i2c: Can't allocate host for %pOF\n", + np); +diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c +index df3c93bef228..e0462fedcdb8 100644 +--- a/arch/powerpc/platforms/powermac/pfunc_core.c ++++ b/arch/powerpc/platforms/powermac/pfunc_core.c +@@ -643,7 +643,7 @@ static int pmf_add_function_prop(struct pmf_device *dev, void *driverdata, + + while (length >= 12) { + /* Allocate a structure */ +- func = kzalloc(sizeof(struct pmf_function), GFP_KERNEL); ++ func = kzalloc(sizeof(*func), GFP_KERNEL); + if (func == NULL) + goto bail; + kref_init(&func->ref); +@@ -719,7 +719,7 @@ int pmf_register_driver(struct device_node *np, + return -EBUSY; + } + +- dev = kzalloc(sizeof(struct pmf_device), GFP_KERNEL); ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + DBG("pmf: no memory !\n"); + return -ENOMEM; +diff --git a/arch/powerpc/platforms/powernv/opal-flash.c b/arch/powerpc/platforms/powernv/opal-flash.c +index 2fa3ac80cb4e..1cb0b895a236 100644 +--- a/arch/powerpc/platforms/powernv/opal-flash.c ++++ b/arch/powerpc/platforms/powernv/opal-flash.c +@@ -418,12 +418,12 @@ static int alloc_image_buf(char *buffer, size_t count) + void *addr; + int size; + +- if (count < sizeof(struct image_header_t)) { ++ if (count < sizeof(image_header)) { + pr_warn("FLASH: Invalid candidate image\n"); + return -EINVAL; + } + +- memcpy(&image_header, (void *)buffer, sizeof(struct image_header_t)); ++ memcpy(&image_header, (void *)buffer, sizeof(image_header)); + image_data.size = be32_to_cpu(image_header.size); + pr_debug("FLASH: Candidate image size = %u\n", image_data.size); + +diff --git a/arch/powerpc/platforms/powernv/opal-hmi.c b/arch/powerpc/platforms/powernv/opal-hmi.c +index c9e1a4ff295c..4efc95b4c7d4 100644 +--- a/arch/powerpc/platforms/powernv/opal-hmi.c ++++ b/arch/powerpc/platforms/powernv/opal-hmi.c +@@ -314,7 +314,7 @@ static int opal_handle_hmi_event(struct notifier_block *nb, + pr_err("HMI: out of memory, Opal message event not handled\n"); + return -ENOMEM; + } +- memcpy(&msg_node->hmi_evt, hmi_evt, sizeof(struct OpalHMIEvent)); ++ memcpy(&msg_node->hmi_evt, hmi_evt, sizeof(*hmi_evt)); + + spin_lock_irqsave(&opal_hmi_evt_lock, flags); + list_add(&msg_node->list, &opal_hmi_evt_list); +diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c +index f6f55ab4980e..2a14fda5ea26 100644 +--- a/arch/powerpc/platforms/powernv/opal-imc.c ++++ b/arch/powerpc/platforms/powernv/opal-imc.c +@@ -110,11 +110,11 @@ static int imc_get_mem_addr_nest(struct device_node *node, + if (nr_chips <= 0) + return -ENODEV; + +- base_addr_arr = kcalloc(nr_chips, sizeof(u64), GFP_KERNEL); ++ base_addr_arr = kcalloc(nr_chips, sizeof(*base_addr_arr), GFP_KERNEL); + if (!base_addr_arr) + return -ENOMEM; + +- chipid_arr = kcalloc(nr_chips, sizeof(u32), GFP_KERNEL); ++ chipid_arr = kcalloc(nr_chips, sizeof(*chipid_arr), GFP_KERNEL); + if (!chipid_arr) + return -ENOMEM; + +@@ -125,8 +125,8 @@ static int imc_get_mem_addr_nest(struct device_node *node, + nr_chips)) + goto error; + +- pmu_ptr->mem_info = kcalloc(nr_chips, sizeof(struct imc_mem_info), +- GFP_KERNEL); ++ pmu_ptr->mem_info = kcalloc(nr_chips, sizeof(*pmu_ptr->mem_info), ++ GFP_KERNEL); + if (!pmu_ptr->mem_info) + goto error; + +@@ -161,7 +161,7 @@ static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain) + u32 offset; + + /* memory for pmu */ +- pmu_ptr = kzalloc(sizeof(struct imc_pmu), GFP_KERNEL); ++ pmu_ptr = kzalloc(sizeof(*pmu_ptr), GFP_KERNEL); + if (!pmu_ptr) + return -ENOMEM; + +diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c +index 8ddc1accf199..dcb42bcb5efa 100644 +--- a/arch/powerpc/platforms/powernv/opal-memory-errors.c ++++ b/arch/powerpc/platforms/powernv/opal-memory-errors.c +@@ -112,7 +112,7 @@ static int opal_memory_err_event(struct notifier_block *nb, + "handled\n"); + return -ENOMEM; + } +- memcpy(&msg_node->msg, msg, sizeof(struct opal_msg)); ++ memcpy(&msg_node->msg, msg, sizeof(msg_node->msg)); + + spin_lock_irqsave(&opal_mem_err_lock, flags); + list_add(&msg_node->list, &opal_memory_err_list); +diff --git a/arch/powerpc/platforms/powernv/opal-psr.c b/arch/powerpc/platforms/powernv/opal-psr.c +index 7313b7fc9071..74986b35cf77 100644 +--- a/arch/powerpc/platforms/powernv/opal-psr.c ++++ b/arch/powerpc/platforms/powernv/opal-psr.c +@@ -136,7 +136,7 @@ void __init opal_psr_init(void) + return; + } + +- psr_attrs = kcalloc(of_get_child_count(psr), sizeof(struct psr_attr), ++ psr_attrs = kcalloc(of_get_child_count(psr), sizeof(*psr_attrs), + GFP_KERNEL); + if (!psr_attrs) + return; +diff --git a/arch/powerpc/platforms/powernv/opal-sensor-groups.c b/arch/powerpc/platforms/powernv/opal-sensor-groups.c +index 7e5a235ebf76..541c9ea04a32 100644 +--- a/arch/powerpc/platforms/powernv/opal-sensor-groups.c ++++ b/arch/powerpc/platforms/powernv/opal-sensor-groups.c +@@ -166,13 +166,13 @@ void __init opal_sensor_groups_init(void) + if (!nr_attrs) + continue; + +- sgs[i].sgattrs = kcalloc(nr_attrs, sizeof(struct sg_attr), ++ sgs[i].sgattrs = kcalloc(nr_attrs, sizeof(*sgs[i].sgattrs), + GFP_KERNEL); + if (!sgs[i].sgattrs) + goto out_sgs_sgattrs; + + sgs[i].sg.attrs = kcalloc(nr_attrs + 1, +- sizeof(struct attribute *), ++ sizeof(*sgs[i].sg.attrs), + GFP_KERNEL); + + if (!sgs[i].sg.attrs) { +diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c +index 81c0a943dea9..22d5e1110dbb 100644 +--- a/arch/powerpc/platforms/powernv/opal-xscom.c ++++ b/arch/powerpc/platforms/powernv/opal-xscom.c +@@ -46,7 +46,7 @@ static scom_map_t opal_scom_map(struct device_node *dev, u64 reg, u64 count) + __func__, dev); + return SCOM_MAP_INVALID; + } +- m = kmalloc(sizeof(struct opal_scom_map), GFP_KERNEL); ++ m = kmalloc(sizeof(*m), GFP_KERNEL); + if (!m) + return NULL; + m->chip = be32_to_cpup(gcid); +diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c +index a6c92c78c9b2..6c307f0650bb 100644 +--- a/arch/powerpc/platforms/powernv/pci-ioda.c ++++ b/arch/powerpc/platforms/powernv/pci-ioda.c +@@ -3843,7 +3843,7 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np, + phb_id = be64_to_cpup(prop64); + pr_debug(" PHB-ID : 0x%016llx\n", phb_id); + +- phb = memblock_virt_alloc(sizeof(struct pnv_phb), 0); ++ phb = memblock_virt_alloc(sizeof(*phb), 0); + + /* Allocate PCI controller */ + phb->hose = hose = pcibios_alloc_controller(np); +diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c +index 7f870ec29daf..8c7009d001d9 100644 +--- a/arch/powerpc/platforms/ps3/mm.c ++++ b/arch/powerpc/platforms/ps3/mm.c +@@ -524,8 +524,7 @@ static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, + int result; + struct dma_chunk *c; + +- c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC); +- ++ c = kzalloc(sizeof(*c), GFP_ATOMIC); + if (!c) { + result = -ENOMEM; + goto fail_alloc; +@@ -570,8 +569,7 @@ static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, + + DBG(KERN_ERR "%s: phy=%#lx, lpar%#lx, len=%#lx\n", __func__, + phys_addr, ps3_mm_phys_to_lpar(phys_addr), len); +- c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC); +- ++ c = kzalloc(sizeof(*c), GFP_ATOMIC); + if (!c) { + result = -ENOMEM; + goto fail_alloc; +diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c +index 910b5b6f96b1..190c9efeace5 100644 +--- a/drivers/macintosh/rack-meter.c ++++ b/drivers/macintosh/rack-meter.c +@@ -397,7 +397,7 @@ static int rackmeter_probe(struct macio_dev* mdev, + } + + /* Create and initialize our instance data */ +- rm = kzalloc(sizeof(struct rackmeter), GFP_KERNEL); ++ rm = kzalloc(sizeof(*rm), GFP_KERNEL); + if (rm == NULL) { + printk(KERN_ERR "rackmeter: failed to allocate memory !\n"); + rc = -ENOMEM; +-- +2.35.3 + diff --git a/patches.suse/powerpc-perf-Add-privileged-access-check-for-thread_.patch b/patches.suse/powerpc-perf-Add-privileged-access-check-for-thread_.patch new file mode 100644 index 0000000..39d272b --- /dev/null +++ b/patches.suse/powerpc-perf-Add-privileged-access-check-for-thread_.patch @@ -0,0 +1,38 @@ +From 216c3087a346db8d7c8a064d2b8f0f49e4694934 Mon Sep 17 00:00:00 2001 +From: Madhavan Srinivasan +Date: Tue, 16 Apr 2019 15:18:29 +0530 +Subject: [PATCH] powerpc/perf: Add privileged access check for thread_imc + +References: FATE#322448, bsc#1054914, git-fixes +Patch-mainline: v5.2-rc1 +Git-commit: 216c3087a346db8d7c8a064d2b8f0f49e4694934 + +Add code to restrict user access to thread_imc pmu since +some event report privilege level information. + +Fixes: f74c89bd80fb3 ("powerpc/perf: Add thread IMC PMU support") +Signed-off-by: Madhavan Srinivasan +Signed-off-by: Anju T Sudhakar +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/perf/imc-pmu.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c +index 23092a359ce0..975837d85a80 100644 +--- a/arch/powerpc/perf/imc-pmu.c ++++ b/arch/powerpc/perf/imc-pmu.c +@@ -864,6 +864,9 @@ static int thread_imc_event_init(struct perf_event *event) + if (event->attr.type != event->pmu->type) + return -ENOENT; + ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EACCES; ++ + /* Sampling not supported */ + if (event->hw.sample_period) + return -EINVAL; +-- +2.35.3 + diff --git a/patches.suse/powerpc-perf-Fix-loop-exit-condition-in-nest_imc_eve.patch b/patches.suse/powerpc-perf-Fix-loop-exit-condition-in-nest_imc_eve.patch new file mode 100644 index 0000000..37cfedd --- /dev/null +++ b/patches.suse/powerpc-perf-Fix-loop-exit-condition-in-nest_imc_eve.patch @@ -0,0 +1,62 @@ +From 860b7d2286236170a36f94946d03ca9888d32571 Mon Sep 17 00:00:00 2001 +From: Anju T Sudhakar +Date: Tue, 18 Dec 2018 11:50:41 +0530 +Subject: [PATCH] powerpc/perf: Fix loop exit condition in nest_imc_event_init + +References: FATE#322448, bsc#1054914, git-fixes +Patch-mainline: v5.2-rc1 +Git-commit: 860b7d2286236170a36f94946d03ca9888d32571 + +The data structure (i.e struct imc_mem_info) to hold the memory address +information for nest imc units is allocated based on the number of nodes +in the system. + +nest_imc_event_init() traverse this struct array to calculate the memory +base address for the event-cpu. If we fail to find a match for the event +cpu's chip-id in imc_mem_info struct array, then the do-while loop will +iterate until we crash. + +Fix this by changing the loop exit condition based on the number of +non zero vbase elements in the array, since the allocation is done for +nr_chips + 1. + +Reported-by: Dan Carpenter +Fixes: 885dcd709ba91 ("powerpc/perf: Add nest IMC PMU support") +Signed-off-by: Anju T Sudhakar +Reviewed-by: Madhavan Srinivasan +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/perf/imc-pmu.c | 2 +- + arch/powerpc/platforms/powernv/opal-imc.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c +index 6159e9edddfd..2d12f0037e3a 100644 +--- a/arch/powerpc/perf/imc-pmu.c ++++ b/arch/powerpc/perf/imc-pmu.c +@@ -499,7 +499,7 @@ static int nest_imc_event_init(struct perf_event *event) + break; + } + pcni++; +- } while (pcni); ++ } while (pcni->vbase != 0); + + if (!flag) + return -ENODEV; +diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c +index 58a07948c76e..3d27f02695e4 100644 +--- a/arch/powerpc/platforms/powernv/opal-imc.c ++++ b/arch/powerpc/platforms/powernv/opal-imc.c +@@ -127,7 +127,7 @@ static int imc_get_mem_addr_nest(struct device_node *node, + nr_chips)) + goto error; + +- pmu_ptr->mem_info = kcalloc(nr_chips, sizeof(*pmu_ptr->mem_info), ++ pmu_ptr->mem_info = kcalloc(nr_chips + 1, sizeof(*pmu_ptr->mem_info), + GFP_KERNEL); + if (!pmu_ptr->mem_info) + goto error; +-- +2.35.3 + diff --git a/patches.suse/powerpc-perf-Return-accordingly-on-invalid-chip-id-i.patch b/patches.suse/powerpc-perf-Return-accordingly-on-invalid-chip-id-i.patch new file mode 100644 index 0000000..f5a8f9d --- /dev/null +++ b/patches.suse/powerpc-perf-Return-accordingly-on-invalid-chip-id-i.patch @@ -0,0 +1,43 @@ +From a913e5e8b43be1d3897a141ce61c1ec071cad89c Mon Sep 17 00:00:00 2001 +From: Anju T Sudhakar +Date: Tue, 27 Nov 2018 13:54:52 +0530 +Subject: [PATCH] powerpc/perf: Return accordingly on invalid chip-id in + +References: FATE#322448, bsc#1054914, git-fixes +Patch-mainline: v5.2-rc1 +Git-commit: a913e5e8b43be1d3897a141ce61c1ec071cad89c + +Nest hardware counter memory resides in a per-chip reserve-memory. +During nest_imc_event_init(), chip-id of the event-cpu is considered to +calculate the base memory addresss for that cpu. Return, proper error +condition if the chip_id calculated is invalid. + +Reported-by: Dan Carpenter +Fixes: 885dcd709ba91 ("powerpc/perf: Add nest IMC PMU support") +Reviewed-by: Madhavan Srinivasan +Signed-off-by: Anju T Sudhakar +Signed-off-by: Michael Ellerman +Acked-by: Michal Suchanek +--- + arch/powerpc/perf/imc-pmu.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c +index b1c37cc3fa98..6159e9edddfd 100644 +--- a/arch/powerpc/perf/imc-pmu.c ++++ b/arch/powerpc/perf/imc-pmu.c +@@ -487,6 +487,11 @@ static int nest_imc_event_init(struct perf_event *event) + * Get the base memory addresss for this cpu. + */ + chip_id = cpu_to_chip_id(event->cpu); ++ ++ /* Return, if chip_id is not valid */ ++ if (chip_id < 0) ++ return -ENODEV; ++ + pcni = pmu->mem_info; + do { + if (pcni->id == chip_id) { +-- +2.35.3 + diff --git a/patches.suse/powerpc-powernv-Return-for-invalid-IMC-domain.patch b/patches.suse/powerpc-powernv-Return-for-invalid-IMC-domain.patch index d55a1ba..10b1e32 100644 --- a/patches.suse/powerpc-powernv-Return-for-invalid-IMC-domain.patch +++ b/patches.suse/powerpc-powernv-Return-for-invalid-IMC-domain.patch @@ -1,4 +1,4 @@ -From e66ec5e9303ae62fb3402088cca8d64e167bed69 Mon Sep 17 00:00:00 2001 +From b59bd3527fe3c1939340df558d7f9d568fc9f882 Mon Sep 17 00:00:00 2001 From: Anju T Sudhakar Date: Mon, 20 May 2019 14:27:53 +0530 Subject: [PATCH] powerpc/powernv: Return for invalid IMC domain @@ -33,10 +33,10 @@ Acked-by: Michal Suchanek 1 file changed, 4 insertions(+) diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c -index 38eccc66c7f4..600d863f7dd2 100644 +index 3e497b91d210..52e9e159bb70 100644 --- a/arch/powerpc/platforms/powernv/opal-imc.c +++ b/arch/powerpc/platforms/powernv/opal-imc.c -@@ -87,6 +87,10 @@ static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain) +@@ -161,6 +161,10 @@ static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain) struct imc_pmu *pmu_ptr; u32 offset; @@ -45,8 +45,8 @@ index 38eccc66c7f4..600d863f7dd2 100644 + return -EINVAL; + /* memory for pmu */ - pmu_ptr = kzalloc(sizeof(struct imc_pmu), GFP_KERNEL); + pmu_ptr = kzalloc(sizeof(*pmu_ptr), GFP_KERNEL); if (!pmu_ptr) -- -2.22.0 +2.35.3 diff --git a/patches.suse/spmi-trace-fix-stack-out-of-bound-access-in-SPMI-tracing-functions.patch b/patches.suse/spmi-trace-fix-stack-out-of-bound-access-in-SPMI-tracing-functions.patch new file mode 100644 index 0000000..8a7085b --- /dev/null +++ b/patches.suse/spmi-trace-fix-stack-out-of-bound-access-in-SPMI-tracing-functions.patch @@ -0,0 +1,111 @@ +From: David Collins +Date: Mon, 27 Jun 2022 16:55:12 -0700 +Subject: spmi: trace: fix stack-out-of-bound access in SPMI tracing functions +Git-commit: 2af28b241eea816e6f7668d1954f15894b45d7e3 +Patch-mainline: v6.0-rc1 +References: git-fixes + +trace_spmi_write_begin() and trace_spmi_read_end() both call +memcpy() with a length of "len + 1". This leads to one extra +byte being read beyond the end of the specified buffer. Fix +this out-of-bound memory access by using a length of "len" +instead. + +Here is a KASAN log showing the issue: + +BUG: KASAN: stack-out-of-bounds in trace_event_raw_event_spmi_read_end+0x1d0/0x234 +Read of size 2 at addr ffffffc0265b7540 by task thermal@2.0-ser/1314 +... +Call trace: + dump_backtrace+0x0/0x3e8 + show_stack+0x2c/0x3c + dump_stack_lvl+0xdc/0x11c + print_address_description+0x74/0x384 + kasan_report+0x188/0x268 + kasan_check_range+0x270/0x2b0 + memcpy+0x90/0xe8 + trace_event_raw_event_spmi_read_end+0x1d0/0x234 + spmi_read_cmd+0x294/0x3ac + spmi_ext_register_readl+0x84/0x9c + regmap_spmi_ext_read+0x144/0x1b0 [regmap_spmi] + _regmap_raw_read+0x40c/0x754 + regmap_raw_read+0x3a0/0x514 + regmap_bulk_read+0x418/0x494 + adc5_gen3_poll_wait_hs+0xe8/0x1e0 [qcom_spmi_adc5_gen3] + ... + __arm64_sys_read+0x4c/0x60 + invoke_syscall+0x80/0x218 + el0_svc_common+0xec/0x1c8 + ... + +addr ffffffc0265b7540 is located in stack of task thermal@2.0-ser/1314 at offset 32 in frame: + adc5_gen3_poll_wait_hs+0x0/0x1e0 [qcom_spmi_adc5_gen3] + +this frame has 1 object: + [32, 33) 'status' + +Memory state around the buggy address: + ffffffc0265b7400: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 + ffffffc0265b7480: 04 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 +>ffffffc0265b7500: 00 00 00 00 f1 f1 f1 f1 01 f3 f3 f3 00 00 00 00 + ^ + ffffffc0265b7580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffffffc0265b7600: f1 f1 f1 f1 01 f2 07 f2 f2 f2 01 f3 00 00 00 00 +================================================================== + +Fixes: a9fce374815d ("spmi: add command tracepoints for SPMI") +Cc: stable@vger.kernel.org +Reviewed-by: Stephen Boyd +Acked-by: Steven Rostedt (Google) +Signed-off-by: David Collins +Link: https://lore.kernel.org/r/20220627235512.2272783-1-quic_collinsd@quicinc.com +Signed-off-by: Greg Kroah-Hartman +Acked-by: Petr Pavlu +--- + include/trace/events/spmi.h | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/include/trace/events/spmi.h b/include/trace/events/spmi.h +index 8b60efe18ba6..a6819fd85cdf 100644 +--- a/include/trace/events/spmi.h ++++ b/include/trace/events/spmi.h +@@ -21,15 +21,15 @@ TRACE_EVENT(spmi_write_begin, + __field ( u8, sid ) + __field ( u16, addr ) + __field ( u8, len ) +- __dynamic_array ( u8, buf, len + 1 ) ++ __dynamic_array ( u8, buf, len ) + ), + + TP_fast_assign( + __entry->opcode = opcode; + __entry->sid = sid; + __entry->addr = addr; +- __entry->len = len + 1; +- memcpy(__get_dynamic_array(buf), buf, len + 1); ++ __entry->len = len; ++ memcpy(__get_dynamic_array(buf), buf, len); + ), + + TP_printk("opc=%d sid=%02d addr=0x%04x len=%d buf=0x[%*phD]", +@@ -92,7 +92,7 @@ TRACE_EVENT(spmi_read_end, + __field ( u16, addr ) + __field ( int, ret ) + __field ( u8, len ) +- __dynamic_array ( u8, buf, len + 1 ) ++ __dynamic_array ( u8, buf, len ) + ), + + TP_fast_assign( +@@ -100,8 +100,8 @@ TRACE_EVENT(spmi_read_end, + __entry->sid = sid; + __entry->addr = addr; + __entry->ret = ret; +- __entry->len = len + 1; +- memcpy(__get_dynamic_array(buf), buf, len + 1); ++ __entry->len = len; ++ memcpy(__get_dynamic_array(buf), buf, len); + ), + + TP_printk("opc=%d sid=%02d addr=0x%04x ret=%d len=%02d buf=0x[%*phD]", + diff --git a/patches.suse/squashfs-fix-inode-lookup-sanity-checks.patch b/patches.suse/squashfs-fix-inode-lookup-sanity-checks.patch new file mode 100644 index 0000000..982ceea --- /dev/null +++ b/patches.suse/squashfs-fix-inode-lookup-sanity-checks.patch @@ -0,0 +1,68 @@ +From c1b2028315c6b15e8d6725e0d5884b15887d3daa Mon Sep 17 00:00:00 2001 +From: Sean Nyekjaer +Date: Wed, 24 Mar 2021 21:37:32 -0700 +Subject: [PATCH] squashfs: fix inode lookup sanity checks +Git-commit: c1b2028315c6b15e8d6725e0d5884b15887d3daa +Patch-mainline: v5.12-rc5 +References: bsc#1203013 + +When mouting a squashfs image created without inode compression it fails +With: "unable to read inode lookup table" + +It turns out that the BLOCK_OFFSET is missing when checking the +SQUASHFS_METADATA_SIZE agaist the actual size. + +Link: https://lkml.kernel.org/r/20210226092903.1473545-1-sean@geanix.com +Fixes: eabac19e40c0 ("squashfs: add more sanity checks in inode lookup") +Signed-off-by: Sean Nyekjaer +Acked-by: Phillip Lougher +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Acked-by: Anthony Iliopoulos + +--- + fs/squashfs/export.c | 8 ++++++-- + fs/squashfs/squashfs_fs.h | 1 + + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/fs/squashfs/export.c b/fs/squashfs/export.c +index eb02072d28dd..723763746238 100644 +--- a/fs/squashfs/export.c ++++ b/fs/squashfs/export.c +@@ -152,14 +152,18 @@ __le64 *squashfs_read_inode_lookup_table(struct super_block *sb, + start = le64_to_cpu(table[n]); + end = le64_to_cpu(table[n + 1]); + +- if (start >= end || (end - start) > SQUASHFS_METADATA_SIZE) { ++ if (start >= end ++ || (end - start) > ++ (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { + kfree(table); + return ERR_PTR(-EINVAL); + } + } + + start = le64_to_cpu(table[indexes - 1]); +- if (start >= lookup_table_start || (lookup_table_start - start) > SQUASHFS_METADATA_SIZE) { ++ if (start >= lookup_table_start || ++ (lookup_table_start - start) > ++ (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { + kfree(table); + return ERR_PTR(-EINVAL); + } +diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h +index 8d64edb80ebf..b3fdc8212c5f 100644 +--- a/fs/squashfs/squashfs_fs.h ++++ b/fs/squashfs/squashfs_fs.h +@@ -17,6 +17,7 @@ + + /* size of metadata (inode and directory) blocks */ + #define SQUASHFS_METADATA_SIZE 8192 ++#define SQUASHFS_BLOCK_OFFSET 2 + + /* default size of block device I/O */ + #ifdef CONFIG_SQUASHFS_4K_DEVBLK_SIZE +-- +2.35.3 + diff --git a/patches.suse/squashfs-fix-xattr-id-and-id-lookup-sanity-checks.patch b/patches.suse/squashfs-fix-xattr-id-and-id-lookup-sanity-checks.patch new file mode 100644 index 0000000..baf8e93 --- /dev/null +++ b/patches.suse/squashfs-fix-xattr-id-and-id-lookup-sanity-checks.patch @@ -0,0 +1,74 @@ +From 8b44ca2b634527151af07447a8090a5f3a043321 Mon Sep 17 00:00:00 2001 +From: Phillip Lougher +Date: Wed, 24 Mar 2021 21:37:35 -0700 +Subject: [PATCH] squashfs: fix xattr id and id lookup sanity checks +Git-commit: 8b44ca2b634527151af07447a8090a5f3a043321 +Patch-mainline: v5.12-rc5 +References: bsc#1203013 + +The checks for maximum metadata block size is missing +SQUASHFS_BLOCK_OFFSET (the two byte length count). + +Link: https://lkml.kernel.org/r/2069685113.2081245.1614583677427@webmail.123-reg.co.uk +Fixes: f37aa4c7366e23f ("squashfs: add more sanity checks in id lookup") +Signed-off-by: Phillip Lougher +Cc: Sean Nyekjaer +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Acked-by: Anthony Iliopoulos + +--- + fs/squashfs/id.c | 6 ++++-- + fs/squashfs/xattr_id.c | 6 ++++-- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c +index 11581bf31af4..ea5387679723 100644 +--- a/fs/squashfs/id.c ++++ b/fs/squashfs/id.c +@@ -97,14 +97,16 @@ __le64 *squashfs_read_id_index_table(struct super_block *sb, + start = le64_to_cpu(table[n]); + end = le64_to_cpu(table[n + 1]); + +- if (start >= end || (end - start) > SQUASHFS_METADATA_SIZE) { ++ if (start >= end || (end - start) > ++ (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { + kfree(table); + return ERR_PTR(-EINVAL); + } + } + + start = le64_to_cpu(table[indexes - 1]); +- if (start >= id_table_start || (id_table_start - start) > SQUASHFS_METADATA_SIZE) { ++ if (start >= id_table_start || (id_table_start - start) > ++ (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { + kfree(table); + return ERR_PTR(-EINVAL); + } +diff --git a/fs/squashfs/xattr_id.c b/fs/squashfs/xattr_id.c +index ead66670b41a..087cab8c78f4 100644 +--- a/fs/squashfs/xattr_id.c ++++ b/fs/squashfs/xattr_id.c +@@ -109,14 +109,16 @@ __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 table_start, + start = le64_to_cpu(table[n]); + end = le64_to_cpu(table[n + 1]); + +- if (start >= end || (end - start) > SQUASHFS_METADATA_SIZE) { ++ if (start >= end || (end - start) > ++ (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { + kfree(table); + return ERR_PTR(-EINVAL); + } + } + + start = le64_to_cpu(table[indexes - 1]); +- if (start >= table_start || (table_start - start) > SQUASHFS_METADATA_SIZE) { ++ if (start >= table_start || (table_start - start) > ++ (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { + kfree(table); + return ERR_PTR(-EINVAL); + } +-- +2.35.3 + diff --git a/patches.suse/tracepoint-Add-tracepoint_probe_register_may_exist-for-BPF-tracing.patch b/patches.suse/tracepoint-Add-tracepoint_probe_register_may_exist-for-BPF-tracing.patch new file mode 100644 index 0000000..5173a80 --- /dev/null +++ b/patches.suse/tracepoint-Add-tracepoint_probe_register_may_exist-for-BPF-tracing.patch @@ -0,0 +1,147 @@ +From: "Steven Rostedt (VMware)" +Date: Tue, 29 Jun 2021 09:40:10 -0400 +Subject: tracepoint: Add tracepoint_probe_register_may_exist() for BPF tracing +Git-commit: 9913d5745bd720c4266805c8d29952a3702e4eca +Patch-mainline: v5.14-rc1 +References: git-fixes + +All internal use cases for tracepoint_probe_register() is set to not ever +be called with the same function and data. If it is, it is considered a +bug, as that means the accounting of handling tracepoints is corrupted. +If the function and data for a tracepoint is already registered when +tracepoint_probe_register() is called, it will call WARN_ON_ONCE() and +return with EEXISTS. + +The BPF system call can end up calling tracepoint_probe_register() with +the same data, which now means that this can trigger the warning because +of a user space process. As WARN_ON_ONCE() should not be called because +user space called a system call with bad data, there needs to be a way to +register a tracepoint without triggering a warning. + +Enter tracepoint_probe_register_may_exist(), which can be called, but will +not cause a WARN_ON() if the probe already exists. It will still error out +with EEXIST, which will then be sent to the user space that performed the +BPF system call. + +This keeps the previous testing for issues with other users of the +tracepoint code, while letting BPF call it with duplicated data and not +warn about it. + +Link: https://lore.kernel.org/lkml/20210626135845.4080-1-penguin-kernel@I-love.SAKURA.ne.jp/ +Link: https://syzkaller.appspot.com/bug?id=41f4318cf01762389f4d1c1c459da4f542fe5153 + +Cc: stable@vger.kernel.org +Fixes: c4f6699dfcb85 ("bpf: introduce BPF_RAW_TRACEPOINT") +Reported-by: syzbot +Reported-by: Tetsuo Handa +Tested-by: syzbot+721aa903751db87aa244@syzkaller.appspotmail.com +Signed-off-by: Steven Rostedt (VMware) +Acked-by: Petr Pavlu +--- + include/linux/tracepoint.h | 10 ++++++++++ + kernel/trace/bpf_trace.c | 3 ++- + kernel/tracepoint.c | 33 ++++++++++++++++++++++++++++++--- + 3 files changed, 42 insertions(+), 4 deletions(-) + +diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h +index 13f65420f188..ab58696d0ddd 100644 +--- a/include/linux/tracepoint.h ++++ b/include/linux/tracepoint.h +@@ -41,7 +41,17 @@ extern int + tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, void *data, + int prio); + extern int ++tracepoint_probe_register_prio_may_exist(struct tracepoint *tp, void *probe, void *data, ++ int prio); ++extern int + tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data); ++static inline int ++tracepoint_probe_register_may_exist(struct tracepoint *tp, void *probe, ++ void *data) ++{ ++ return tracepoint_probe_register_prio_may_exist(tp, probe, data, ++ TRACEPOINT_DEFAULT_PRIO); ++} + extern void + for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv), + void *priv); +diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c +index 7a52bc172841..f0568b3d6bd1 100644 +--- a/kernel/trace/bpf_trace.c ++++ b/kernel/trace/bpf_trace.c +@@ -1840,7 +1840,8 @@ static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog * + if (prog->aux->max_ctx_offset > btp->num_args * sizeof(u64)) + return -EINVAL; + +- return tracepoint_probe_register(tp, (void *)btp->bpf_func, prog); ++ return tracepoint_probe_register_may_exist(tp, (void *)btp->bpf_func, ++ prog); + } + + int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog) +diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c +index 9f478d29b926..976bf8ce8039 100644 +--- a/kernel/tracepoint.c ++++ b/kernel/tracepoint.c +@@ -273,7 +273,8 @@ static void tracepoint_update_call(struct tracepoint *tp, struct tracepoint_func + * Add the probe function to a tracepoint. + */ + static int tracepoint_add_func(struct tracepoint *tp, +- struct tracepoint_func *func, int prio) ++ struct tracepoint_func *func, int prio, ++ bool warn) + { + struct tracepoint_func *old, *tp_funcs; + int ret; +@@ -288,7 +289,7 @@ static int tracepoint_add_func(struct tracepoint *tp, + lockdep_is_held(&tracepoints_mutex)); + old = func_add(&tp_funcs, func, prio); + if (IS_ERR(old)) { +- WARN_ON_ONCE(PTR_ERR(old) != -ENOMEM); ++ WARN_ON_ONCE(warn && PTR_ERR(old) != -ENOMEM); + return PTR_ERR(old); + } + +@@ -343,6 +344,32 @@ static int tracepoint_remove_func(struct tracepoint *tp, + return 0; + } + ++/** ++ * tracepoint_probe_register_prio_may_exist - Connect a probe to a tracepoint with priority ++ * @tp: tracepoint ++ * @probe: probe handler ++ * @data: tracepoint data ++ * @prio: priority of this function over other registered functions ++ * ++ * Same as tracepoint_probe_register_prio() except that it will not warn ++ * if the tracepoint is already registered. ++ */ ++int tracepoint_probe_register_prio_may_exist(struct tracepoint *tp, void *probe, ++ void *data, int prio) ++{ ++ struct tracepoint_func tp_func; ++ int ret; ++ ++ mutex_lock(&tracepoints_mutex); ++ tp_func.func = probe; ++ tp_func.data = data; ++ tp_func.prio = prio; ++ ret = tracepoint_add_func(tp, &tp_func, prio, false); ++ mutex_unlock(&tracepoints_mutex); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(tracepoint_probe_register_prio_may_exist); ++ + /** + * tracepoint_probe_register - Connect a probe to a tracepoint + * @tp: tracepoint +@@ -366,7 +393,7 @@ int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, + tp_func.func = probe; + tp_func.data = data; + tp_func.prio = prio; +- ret = tracepoint_add_func(tp, &tp_func, prio); ++ ret = tracepoint_add_func(tp, &tp_func, prio, true); + mutex_unlock(&tracepoints_mutex); + return ret; + } + diff --git a/patches.suse/tracing-Fix-race-in-perf_trace_buf-initialization.patch b/patches.suse/tracing-Fix-race-in-perf_trace_buf-initialization.patch new file mode 100644 index 0000000..cd03268 --- /dev/null +++ b/patches.suse/tracing-Fix-race-in-perf_trace_buf-initialization.patch @@ -0,0 +1,115 @@ +From: Prateek Sood +Date: Tue, 15 Oct 2019 11:47:25 +0530 +Subject: tracing: Fix race in perf_trace_buf initialization +Git-commit: 6b1340cc00edeadd52ebd8a45171f38c8de2a387 +Patch-mainline: v5.4-rc5 +References: git-fixes + +A race condition exists while initialiazing perf_trace_buf from +perf_trace_init() and perf_kprobe_init(). + + CPU0 CPU1 +perf_trace_init() + mutex_lock(&event_mutex) + perf_trace_event_init() + perf_trace_event_reg() + total_ref_count == 0 + buf = alloc_percpu() + perf_trace_buf[i] = buf + tp_event->class->reg() //fails perf_kprobe_init() + goto fail perf_trace_event_init() + perf_trace_event_reg() + fail: + total_ref_count == 0 + + total_ref_count == 0 + buf = alloc_percpu() + perf_trace_buf[i] = buf + tp_event->class->reg() + total_ref_count++ + + free_percpu(perf_trace_buf[i]) + perf_trace_buf[i] = NULL + +Any subsequent call to perf_trace_event_reg() will observe total_ref_count > 0, +causing the perf_trace_buf to be always NULL. This can result in perf_trace_buf +getting accessed from perf_trace_buf_alloc() without being initialized. Acquiring +event_mutex in perf_kprobe_init() before calling perf_trace_event_init() should +fix this race. + +The race caused the following bug: + + Unable to handle kernel paging request at virtual address 0000003106f2003c + Mem abort info: + ESR = 0x96000045 + Exception class = DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + Data abort info: + ISV = 0, ISS = 0x00000045 + CM = 0, WnR = 1 + user pgtable: 4k pages, 39-bit VAs, pgdp = ffffffc034b9b000 + [0000003106f2003c] pgd=0000000000000000, pud=0000000000000000 + Internal error: Oops: 96000045 [#1] PREEMPT SMP + Process syz-executor (pid: 18393, stack limit = 0xffffffc093190000) + pstate: 80400005 (Nzcv daif +PAN -UAO) + pc : __memset+0x20/0x1ac + lr : memset+0x3c/0x50 + sp : ffffffc09319fc50 + + __memset+0x20/0x1ac + perf_trace_buf_alloc+0x140/0x1a0 + perf_trace_sys_enter+0x158/0x310 + syscall_trace_enter+0x348/0x7c0 + el0_svc_common+0x11c/0x368 + el0_svc_handler+0x12c/0x198 + el0_svc+0x8/0xc + +Ramdumps showed the following: + total_ref_count = 3 + perf_trace_buf = ( + 0x0 -> NULL, + 0x0 -> NULL, + 0x0 -> NULL, + 0x0 -> NULL) + +Link: http://lkml.kernel.org/r/1571120245-4186-1-git-send-email-prsood@codeaurora.org + +Cc: stable@vger.kernel.org +Fixes: e12f03d7031a9 ("perf/core: Implement the 'perf_kprobe' PMU") +Acked-by: Song Liu +Signed-off-by: Prateek Sood +Signed-off-by: Steven Rostedt (VMware) +Acked-by: Petr Pavlu +--- + kernel/trace/trace_event_perf.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c +index 0892e38ed6fb..a9dfa04ffa44 100644 +--- a/kernel/trace/trace_event_perf.c ++++ b/kernel/trace/trace_event_perf.c +@@ -272,9 +272,11 @@ int perf_kprobe_init(struct perf_event *p_event, bool is_retprobe) + goto out; + } + ++ mutex_lock(&event_mutex); + ret = perf_trace_event_init(tp_event, p_event); + if (ret) + destroy_local_trace_kprobe(tp_event); ++ mutex_unlock(&event_mutex); + out: + kfree(func); + return ret; +@@ -282,8 +284,10 @@ int perf_kprobe_init(struct perf_event *p_event, bool is_retprobe) + + void perf_kprobe_destroy(struct perf_event *p_event) + { ++ mutex_lock(&event_mutex); + perf_trace_event_close(p_event); + perf_trace_event_unreg(p_event); ++ mutex_unlock(&event_mutex); + + destroy_local_trace_kprobe(p_event->tp_event); + } + diff --git a/patches.suse/tracing-perf-Use-strndup_user-instead-of-buggy-open-coded-version.patch b/patches.suse/tracing-perf-Use-strndup_user-instead-of-buggy-open-coded-version.patch new file mode 100644 index 0000000..530b055 --- /dev/null +++ b/patches.suse/tracing-perf-Use-strndup_user-instead-of-buggy-open-coded-version.patch @@ -0,0 +1,54 @@ +From: Jann Horn +Date: Wed, 20 Feb 2019 17:54:43 +0100 +Subject: tracing/perf: Use strndup_user() instead of buggy open-coded version +Git-commit: 83540fbc8812a580b6ad8f93f4c29e62e417687e +Patch-mainline: v5.1-rc1 +References: git-fixes + +The first version of this method was missing the check for +`ret == PATH_MAX`; then such a check was added, but it didn't call kfree() +on error, so there was still a small memory leak in the error case. +Fix it by using strndup_user() instead of open-coding it. + +Link: http://lkml.kernel.org/r/20190220165443.152385-1-jannh@google.com + +Cc: Ingo Molnar +Cc: stable@vger.kernel.org +Fixes: 0eadcc7a7bc0 ("perf/core: Fix perf_uprobe_init()") +Reviewed-by: Masami Hiramatsu +Acked-by: Song Liu +Signed-off-by: Jann Horn +Signed-off-by: Steven Rostedt (VMware) +Acked-by: Petr Pavlu +--- + kernel/trace/trace_event_perf.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c +index 76217bbef815..4629a6104474 100644 +--- a/kernel/trace/trace_event_perf.c ++++ b/kernel/trace/trace_event_perf.c +@@ -299,15 +299,13 @@ int perf_uprobe_init(struct perf_event *p_event, + + if (!p_event->attr.uprobe_path) + return -EINVAL; +- path = kzalloc(PATH_MAX, GFP_KERNEL); +- if (!path) +- return -ENOMEM; +- ret = strncpy_from_user( +- path, u64_to_user_ptr(p_event->attr.uprobe_path), PATH_MAX); +- if (ret == PATH_MAX) +- return -E2BIG; +- if (ret < 0) +- goto out; ++ ++ path = strndup_user(u64_to_user_ptr(p_event->attr.uprobe_path), ++ PATH_MAX); ++ if (IS_ERR(path)) { ++ ret = PTR_ERR(path); ++ return (ret == -EINVAL) ? -E2BIG : ret; ++ } + if (path[0] == '\0') { + ret = -EINVAL; + goto out; + diff --git a/patches.suse/tracing-uprobes-Check-the-return-value-of-kstrdup-for-tu-filename.patch b/patches.suse/tracing-uprobes-Check-the-return-value-of-kstrdup-for-tu-filename.patch new file mode 100644 index 0000000..6c73f08 --- /dev/null +++ b/patches.suse/tracing-uprobes-Check-the-return-value-of-kstrdup-for-tu-filename.patch @@ -0,0 +1,39 @@ +From: Xiaoke Wang +Date: Tue, 14 Dec 2021 09:28:02 +0800 +Subject: tracing/uprobes: Check the return value of kstrdup() for tu->filename +Git-commit: 8c7224245557707c613f130431cafbaaa4889615 +Patch-mainline: v5.17-rc1 +References: git-fixes + +kstrdup() returns NULL when some internal memory errors happen, it is +better to check the return value of it so to catch the memory error in +time. + +Link: https://lkml.kernel.org/r/tencent_3C2E330722056D7891D2C83F29C802734B06@qq.com + +Acked-by: Masami Hiramatsu +Fixes: 33ea4b24277b ("perf/core: Implement the 'perf_uprobe' PMU") +Signed-off-by: Xiaoke Wang +Signed-off-by: Steven Rostedt +Acked-by: Petr Pavlu +--- + kernel/trace/trace_uprobe.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c +index 3bd09d612137..08b0e8417302 100644 +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -1609,6 +1609,11 @@ create_local_trace_uprobe(char *name, unsigned long offs, + tu->offset = offs; + tu->path = path; + tu->filename = kstrdup(name, GFP_KERNEL); ++ if (!tu->filename) { ++ ret = -ENOMEM; ++ goto error; ++ } ++ + init_trace_event_call(tu, &tu->tp.call); + + if (set_print_fmt(&tu->tp, is_ret_probe(tu)) < 0) { + diff --git a/patches.suse/usbnet-Fix-linkwatch-use-after-free-on-disconnect.patch b/patches.suse/usbnet-Fix-linkwatch-use-after-free-on-disconnect.patch new file mode 100644 index 0000000..003a64f --- /dev/null +++ b/patches.suse/usbnet-Fix-linkwatch-use-after-free-on-disconnect.patch @@ -0,0 +1,89 @@ +From a69e617e533edddf3fa3123149900f36e0a6dc74 Mon Sep 17 00:00:00 2001 +From: Lukas Wunner +Date: Thu, 23 Jun 2022 14:50:59 +0200 +Subject: [PATCH] usbnet: Fix linkwatch use-after-free on disconnect +Git-commit: a69e617e533edddf3fa3123149900f36e0a6dc74 +References: git-fixes +Patch-mainline: v6.0-rc1 + +usbnet uses the work usbnet_deferred_kevent() to perform tasks which may +sleep. On disconnect, completion of the work was originally awaited in +->ndo_stop(). But in 2003, that was moved to ->disconnect() by historic +commit "[PATCH] USB: usbnet, prevent exotic rtnl deadlock": + + https://git.kernel.org/tglx/history/c/0f138bbfd83c + +The change was made because back then, the kernel's workqueue +implementation did not allow waiting for a single work. One had to wait +for completion of *all* work by calling flush_scheduled_work(), and that +could deadlock when waiting for usbnet_deferred_kevent() with rtnl_mutex +held in ->ndo_stop(). + +The commit solved one problem but created another: It causes a +use-after-free in USB Ethernet drivers aqc111.c, asix_devices.c, +ax88179_178a.c, ch9200.c and smsc75xx.c: + +* If the drivers receive a link change interrupt immediately before + disconnect, they raise EVENT_LINK_RESET in their (non-sleepable) + ->status() callback and schedule usbnet_deferred_kevent(). +* usbnet_deferred_kevent() invokes the driver's ->link_reset() callback, + which calls netif_carrier_{on,off}(). +* That in turn schedules the work linkwatch_event(). + +Because usbnet_deferred_kevent() is awaited after unregister_netdev(), +netif_carrier_{on,off}() may operate on an unregistered netdev and +linkwatch_event() may run after free_netdev(), causing a use-after-free. + +In 2010, usbnet was changed to only wait for a single instance of +usbnet_deferred_kevent() instead of *all* work by commit 23f333a2bfaf +("drivers/net: don't use flush_scheduled_work()"). + +Unfortunately the commit neglected to move the wait back to +->ndo_stop(). Rectify that omission at long last. + +Reported-by: Jann Horn +Link: https://lore.kernel.org/netdev/CAG48ez0MHBbENX5gCdHAUXZ7h7s20LnepBF-pa5M=7Bi-jZrEA@mail.gmail.com/ +Reported-by: Oleksij Rempel +Link: https://lore.kernel.org/netdev/20220315113841.GA22337@pengutronix.de/ +Signed-off-by: Lukas Wunner +Cc: stable@vger.kernel.org +Acked-by: Oliver Neukum +Link: https://lore.kernel.org/r/d1c87ebe9fc502bffcd1576e238d685ad08321e4.1655987888.git.lukas@wunner.de +Signed-off-by: Jakub Kicinski +Signed-off-by: Oliver Neukum +--- + drivers/net/usb/usbnet.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c +index dc79811535c2..713cfc2723b8 100644 +--- a/drivers/net/usb/usbnet.c ++++ b/drivers/net/usb/usbnet.c +@@ -849,13 +849,11 @@ int usbnet_stop (struct net_device *net) + + mpn = !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags); + +- /* deferred work (task, timer, softirq) must also stop. +- * can't flush_scheduled_work() until we drop rtnl (later), +- * else workers could deadlock; so make workers a NOP. +- */ ++ /* deferred work (timer, softirq, task) must also stop */ + dev->flags = 0; + del_timer_sync (&dev->delay); + tasklet_kill (&dev->bh); ++ cancel_work_sync(&dev->kevent); + if (!pm) + usb_autopm_put_interface(dev->intf); + +@@ -1619,8 +1617,6 @@ void usbnet_disconnect (struct usb_interface *intf) + net = dev->net; + unregister_netdev (net); + +- cancel_work_sync(&dev->kevent); +- + usb_scuttle_anchored_urbs(&dev->deferred); + + if (dev->driver_info->unbind) +-- +2.35.3 + diff --git a/patches.suse/x86-speculation-Add-RSB-VM-Exit-protections.patch b/patches.suse/x86-speculation-Add-RSB-VM-Exit-protections.patch index 94a1f45..ceabf7c 100644 --- a/patches.suse/x86-speculation-Add-RSB-VM-Exit-protections.patch +++ b/patches.suse/x86-speculation-Add-RSB-VM-Exit-protections.patch @@ -105,10 +105,10 @@ Signed-off-by: Borislav Petkov --- arch/x86/include/asm/cpufeatures.h | 2 + arch/x86/include/asm/msr-index.h | 4 ++ - arch/x86/include/asm/nospec-branch.h | 35 +++++++++++++++--- + arch/x86/include/asm/nospec-branch.h | 40 +++++++++++++++++---- arch/x86/kernel/cpu/bugs.c | 65 ++++++++++++++++++++++++++++++++++- arch/x86/kernel/cpu/common.c | 10 ++++- - 5 files changed, 106 insertions(+), 10 deletions(-) + 5 files changed, 111 insertions(+), 10 deletions(-) --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -142,11 +142,12 @@ Signed-off-by: Borislav Petkov #define L1D_FLUSH BIT(0) /* --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h -@@ -138,14 +138,28 @@ +@@ -140,14 +140,29 @@ #endif .endm +.macro ISSUE_UNBALANCED_RET_GUARD ++ ANNOTATE_INTRA_FUNCTION_CALL + call .Lunbalanced_ret_guard_\@ + int3 +.Lunbalanced_ret_guard_\@: @@ -172,7 +173,7 @@ Signed-off-by: Borislav Petkov .Lskip_rsb_\@: #endif .endm -@@ -284,13 +298,20 @@ static inline void vmexit_fill_RSB(void) +@@ -286,13 +301,24 @@ static inline void vmexit_fill_RSB(void) #ifdef CONFIG_RETPOLINE unsigned long loops; @@ -187,6 +188,10 @@ Signed-off-by: Borislav Petkov + "jmp .Lunbalanced", X86_FEATURE_RSB_VMEXIT_LITE) + __stringify(__FILL_RETURN_BUFFER(%0,RSB_CLEAR_LOOPS,%1)) + ".Lunbalanced:\n\t" ++ "999: \n\t" ++ ".pushsection .discard.intra_function_calls\n\t" ++ ".long 999b\n\t" ++ ".popsection\n\t" + "call .Lunbalanced_ret_guard\n\t" + "int3\n\t" + ".Lunbalanced_ret_guard:\n\t" diff --git a/patches.suse/x86-speculation-change-fill_return_buffer-to-work-with-objtool.patch b/patches.suse/x86-speculation-change-fill_return_buffer-to-work-with-objtool.patch index 72b60e0..612a847 100644 --- a/patches.suse/x86-speculation-change-fill_return_buffer-to-work-with-objtool.patch +++ b/patches.suse/x86-speculation-change-fill_return_buffer-to-work-with-objtool.patch @@ -31,8 +31,8 @@ Link: https://lkml.kernel.org/r/20200428191700.032079304@infradead.org Acked-by: Borislav Petkov --- - arch/x86/include/asm/nospec-branch.h | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) + arch/x86/include/asm/nospec-branch.h | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -50,7 +50,21 @@ Acked-by: Borislav Petkov /* * Fill the CPU return stack buffer. -@@ -50,9 +52,9 @@ +@@ -38,21 +40,23 @@ + #define __FILL_RETURN_BUFFER(reg, nr, sp) \ + mov $(nr/2), reg; \ + 771: \ ++ ANNOTATE_INTRA_FUNCTION_CALL \ + call 772f; \ + 773: /* speculation trap */ \ + pause; \ + lfence; \ + jmp 773b; \ + 772: \ ++ ANNOTATE_INTRA_FUNCTION_CALL \ + call 774f; \ + 775: /* speculation trap */ \ + pause; \ lfence; \ jmp 775b; \ 774: \ @@ -62,7 +76,7 @@ Acked-by: Borislav Petkov #ifdef __ASSEMBLY__ -@@ -142,10 +144,8 @@ +@@ -142,10 +146,8 @@ */ .macro FILL_RETURN_BUFFER reg:req nr:req ftr:req #ifdef CONFIG_RETPOLINE diff --git a/patches.suse/xen-xenbus-fix-return-type-in-xenbus_file_read.patch b/patches.suse/xen-xenbus-fix-return-type-in-xenbus_file_read.patch new file mode 100644 index 0000000..358c323 --- /dev/null +++ b/patches.suse/xen-xenbus-fix-return-type-in-xenbus_file_read.patch @@ -0,0 +1,50 @@ +Patch-mainline: v6.0-rc1 +Git-commit: 32ad11127b95236dfc52375f3707853194a7f4b4 +References: git-fixes +From: Dan Carpenter +Date: Thu, 4 Aug 2022 10:11:33 +0300 +Subject: [PATCH] xen/xenbus: fix return type in xenbus_file_read() + +This code tries to store -EFAULT in an unsigned int. The +xenbus_file_read() function returns type ssize_t so the negative value +is returned as a positive value to the user. + +This change forces another change to the min() macro. Originally, the +min() macro used "unsigned" type which checkpatch complains about. Also +unsigned type would break if "len" were not capped at MAX_RW_COUNT. Use +size_t for the min(). (No effect on runtime for the min_t() change). + +Fixes: 2fb3683e7b16 ("xen: Add xenbus device driver") +Signed-off-by: Dan Carpenter +Reviewed-by: Oleksandr Tyshchenko +Link: https://lore.kernel.org/r/YutxJUaUYRG/VLVc@kili +Signed-off-by: Juergen Gross +--- + drivers/xen/xenbus/xenbus_dev_frontend.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c +index 597af455a522..0792fda49a15 100644 +--- a/drivers/xen/xenbus/xenbus_dev_frontend.c ++++ b/drivers/xen/xenbus/xenbus_dev_frontend.c +@@ -128,7 +128,7 @@ static ssize_t xenbus_file_read(struct file *filp, + { + struct xenbus_file_priv *u = filp->private_data; + struct read_buffer *rb; +- unsigned i; ++ ssize_t i; + int ret; + + mutex_lock(&u->reply_mutex); +@@ -148,7 +148,7 @@ static ssize_t xenbus_file_read(struct file *filp, + rb = list_entry(u->read_buffers.next, struct read_buffer, list); + i = 0; + while (i < len) { +- unsigned sz = min((unsigned)len - i, rb->len - rb->cons); ++ size_t sz = min_t(size_t, len - i, rb->len - rb->cons); + + ret = copy_to_user(ubuf + i, &rb->msg[rb->cons], sz); + +-- +2.35.3 + diff --git a/patches.suse/xprtrdma-Fix-trace-point-use-after-free-race.patch b/patches.suse/xprtrdma-Fix-trace-point-use-after-free-race.patch new file mode 100644 index 0000000..9d2cffc --- /dev/null +++ b/patches.suse/xprtrdma-Fix-trace-point-use-after-free-race.patch @@ -0,0 +1,83 @@ +From: Chuck Lever +Date: Sun, 19 Apr 2020 20:03:05 -0400 +Subject: xprtrdma: Fix trace point use-after-free race +Git-commit: bdb2ce82818577ba6e57b7d68b698b8d17329281 +Patch-mainline: v5.7-rc4 +References: git-fixes + +It's not safe to use resources pointed to by the @send_wr of +ib_post_send() _after_ that function returns. Those resources are +typically freed by the Send completion handler, which can run before +ib_post_send() returns. + +Thus the trace points currently around ib_post_send() in the +client's RPC/RDMA transport are a hazard, even when they are +disabled. Rearrange them so that they touch the Work Request only +_before_ ib_post_send() is invoked. + +Fixes: ab03eff58eb5 ("xprtrdma: Add trace points in RPC Call transmit paths") +Signed-off-by: Chuck Lever +Signed-off-by: Anna Schumaker +Acked-by: Petr Pavlu +--- + include/trace/events/rpcrdma.h | 12 ++++-------- + net/sunrpc/xprtrdma/verbs.c | 2 +- + 2 files changed, 5 insertions(+), 9 deletions(-) + +diff --git a/include/trace/events/rpcrdma.h b/include/trace/events/rpcrdma.h +index 051f26fedc4d..72f043876019 100644 +--- a/include/trace/events/rpcrdma.h ++++ b/include/trace/events/rpcrdma.h +@@ -692,11 +692,10 @@ TRACE_EVENT(xprtrdma_prepsend_failed, + + TRACE_EVENT(xprtrdma_post_send, + TP_PROTO( +- const struct rpcrdma_req *req, +- int status ++ const struct rpcrdma_req *req + ), + +- TP_ARGS(req, status), ++ TP_ARGS(req), + + TP_STRUCT__entry( + __field(const void *, req) +@@ -705,7 +704,6 @@ TRACE_EVENT(xprtrdma_post_send, + __field(const void *, req) + __field(int, num_sge) + __field(int, signaled) +- __field(int, status) + ), + + TP_fast_assign( +@@ -718,13 +716,11 @@ TRACE_EVENT(xprtrdma_post_send, + __entry->num_sge = req->rl_sendctx->sc_wr.num_sge; + __entry->signaled = req->rl_sendctx->sc_wr.send_flags & + IB_SEND_SIGNALED; +- __entry->status = status; + ), + +- TP_printk("req=%p, %d SGEs%s, status=%d", ++ TP_printk("req=%p, %d SGEs%s", + __entry->req, __entry->num_sge, +- (__entry->signaled ? ", signaled" : ""), +- __entry->status ++ (__entry->signaled ? ", signaled" : "") + ) + ); + +diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c +index 29ae982d69cf..05c4d3a9cda2 100644 +--- a/net/sunrpc/xprtrdma/verbs.c ++++ b/net/sunrpc/xprtrdma/verbs.c +@@ -1356,8 +1356,8 @@ int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req) + --ep->rep_send_count; + } + ++ trace_xprtrdma_post_send(req); + rc = ia->ri_ops->ro_send(ia, req); +- trace_xprtrdma_post_send(req, rc); + if (rc) + return -ENOTCONN; + return 0; + diff --git a/series.conf b/series.conf index 2c052de..ee5c69d 100644 --- a/series.conf +++ b/series.conf @@ -29410,6 +29410,7 @@ patches.suse/0004-lib-raid6-altivec-Add-vpermxor-implementation-for-ra.patch patches.suse/0040-lib-raid6-Build-proper-raid6test-files-on-powerpc.patch patches.suse/powerpc-Remove-unused-flush_dcache_phys_range.patch + patches.suse/powerpc-Use-sizeof-foo-rather-than-sizeof-struct-foo.patch patches.suse/powerpc-Use-feature-bit-for-RTC-presence-rather-than.patch patches.suse/powerpc-Book-E-Remove-unused-CPU_FTR_L2CSR-bit.patch patches.suse/powerpc-Free-up-CPU-feature-bits-on-64-bit-machines.patch @@ -47943,6 +47944,7 @@ patches.suse/pinctrl-sh-pfc-sh73a0-Fix-fsic_spdif-pin-groups.patch patches.suse/platform_data-mlxreg-additions-for-Mellanox-watchdog.patch patches.suse/tracing-do-not-free-iter-trace-in-fail-path-of-tracing_open_pipe.patch + patches.suse/tracing-perf-Use-strndup_user-instead-of-buggy-open-coded-version.patch patches.suse/tracing-use-strncpy-instead-of-memcpy-for-string-keys-in-hist-triggers.patch patches.suse/0001-xen-pciback-Don-t-disable-PCI_COMMAND-on-PCI-device-.patch patches.suse/0001-x86-respect-memory-size-limiting-via-mem-parameter.patch @@ -48744,6 +48746,10 @@ patches.suse/perf-x86-intel-pt-remove-software-double-buffering-pmu-capability.patch patches.suse/tty-rocket-fix-incorrect-forward-declaration-of-rp_i.patch patches.suse/sched-x86-save-flags-on-context-switch.patch + patches.suse/objtool-Set-insn-func-for-alternatives.patch + patches.suse/objtool-Add-backtrace-support.patch + patches.suse/objtool-Rewrite-alt-skip_orig.patch + patches.suse/objtool-Fix-sibling-call-detection.patch patches.suse/cpu-speculation-add-mitigations-cmdline-option.patch patches.suse/x86-speculation-support-mitigations-cmdline-option.patch patches.suse/powerpc-speculation-support-mitigations-cmdline-option.patch @@ -49829,6 +49835,9 @@ patches.suse/powerpc-perf-init-pmu-from-core-book3s.patch patches.suse/powerpc-perf-Add-generic-compat-mode-pmu-driver.patch patches.suse/powerpc-perf-Remove-PM_BR_CMPL_ALT-from-power9-event.patch + patches.suse/powerpc-perf-Return-accordingly-on-invalid-chip-id-i.patch + patches.suse/powerpc-perf-Fix-loop-exit-condition-in-nest_imc_eve.patch + patches.suse/powerpc-perf-Add-privileged-access-check-for-thread_.patch patches.suse/powerpc-book3s-64-check-for-NULL-pointer-in-pgd_allo.patch patches.suse/pwm-Fix-deadlock-warning-when-removing-PWM-device.patch patches.suse/pwm-tiehrpwm-Update-shadow-register-for-disabling-PW.patch @@ -49967,6 +49976,7 @@ patches.suse/memory-tegra-Fix-integer-overflow-on-tick-value-calc.patch patches.suse/soc-mediatek-pwrap-Zero-initialize-rdata-in-pwrap_in.patch patches.suse/soc-rockchip-Set-the-proper-PWM-for-rk3288.patch + patches.suse/objtool-Don-t-use-ignore-flag-for-fake-jumps.patch patches.suse/objtool-fix-function-fallthrough-detection.patch patches.suse/0001-locking-rwsem-Prevent-decrement-of-reader-count-befo.patch patches.suse/perf-x86-amd-iommu-make-the-amd_iommu_attr_groups-symbol-static.patch @@ -51454,7 +51464,12 @@ patches.suse/kvm-svm-fix-detection-of-amd-errata-1096 patches.suse/kvm-x86-vpmu-refine-kvm_pmu-err-msg-when-event-creation-failed patches.suse/kvm-nvmx-do-not-use-dangling-shadow-vmcs-after-guest-reset + patches.suse/objtool-Use-Elf_Scn-typedef-instead-of-assuming-struct-name.patch + patches.suse/objtool-Rename-elf_open-to-prevent-conflict-with-libelf-from-elftoolchain.patch patches.suse/stacktrace-force-user_ds-for-stack_trace_save_user.patch + patches.suse/objtool-Track-original-function-across-branches.patch + patches.suse/objtool-Convert-insn-type-to-enum.patch + patches.suse/objtool-Support-conditional-retpolines.patch patches.suse/x86-boot-fix-memory-leak-in-default_get_smp_config.patch patches.suse/msft-hv-1901-x86-hyper-v-Zero-out-the-VP-ASSIST-PAGE-on-allocatio.patch patches.suse/Input-synaptics-whitelist-Lenovo-T580-SMBus-intertou.patch @@ -52951,6 +52966,7 @@ patches.suse/edac-ghes-fix-use-after-free-in-ghes_edac-remove-path.patch patches.suse/regulator-ti-abb-Fix-timeout-in-ti_abb_wait_txdone-t.patch patches.suse/regulator-pfuze100-regulator-Variable-val-in-pfuze10.patch + patches.suse/tracing-Fix-race-in-perf_trace_buf-initialization.patch patches.suse/ALSA-hda-realtek-Add-support-for-ALC711.patch patches.suse/ASoC-wm_adsp-Don-t-generate-kcontrols-without-READ-f.patch patches.suse/ASoc-rockchip-i2s-Fix-RPM-imbalance.patch @@ -55842,6 +55858,7 @@ patches.suse/dmaengine-dmatest-Fix-iteration-non-stop-logic.patch patches.suse/nfs-Fix-potential-posix_acl-refcnt-leak-in-nfs3_set_.patch patches.suse/NFSv4.1-fix-handling-of-backchannel-binding-in-BIND_.patch + patches.suse/xprtrdma-Fix-trace-point-use-after-free-race.patch patches.suse/PM-ACPI-Output-correct-message-on-target-power-state.patch patches.suse/PM-hibernate-Freeze-kernel-threads-in-software_resum.patch patches.suse/iommu-amd-fix-legacy-interrupt-remapping-for-x2apic-enabled-system @@ -56054,7 +56071,18 @@ patches.suse/printk-handle-blank-console-arguments-passed-in.patch patches.suse/objtool-clean-instruction-state-before-each-function-validation.patch patches.suse/objtool-ignore-empty-alternatives.patch + patches.suse/objtool-Support-multiple-stack_op-per-instruction.patch + patches.suse/objtool-Rename-struct-cfi_state.patch + patches.suse/objtool-Fix-CFI-insn_state-propagation.patch + patches.suse/objtool-Remove-check-preventing-branches-within-alternative.patch + patches.suse/objtool-Uniquely-identify-alternative-instruction-groups.patch + patches.suse/objtool-Fix-ORC-vs-alternatives.patch + patches.suse/objtool-Rework-allocating-stack_ops-on-decode.patch + patches.suse/objtool-Make-handle_insn_ops-unconditional.patch + patches.suse/objtool-Remove-INSN_STACK.patch + patches.suse/objtool-Add-support-for-intra-function-calls.patch patches.suse/x86-speculation-change-fill_return_buffer-to-work-with-objtool.patch + patches.suse/objtool-Allow-no-op-CFI-ops-in-alternatives.patch patches.suse/efi-efivars-Add-missing-kobject_put-in-sysfs-entry-c.patch patches.suse/x86-cpu-add-a-steppings-field-to-struct-x86_cpu_id.patch patches.suse/x86-cpu-amd-make-erratum-1054-a-legacy-erratum.patch @@ -59346,6 +59374,8 @@ patches.suse/net-mlx5e-Fix-error-path-for-ethtool-set-priv-flag.patch patches.suse/arm64-kdump-update-ppos-when-reading-elfcorehdr.patch patches.suse/RDMA-cxgb4-Fix-adapter-LE-hash-errors-while-destroyi.patch + patches.suse/squashfs-fix-inode-lookup-sanity-checks.patch + patches.suse/squashfs-fix-xattr-id-and-id-lookup-sanity-checks.patch patches.suse/drm-msm-fix-shutdown-hook-in-case-GPU-components-fai.patch patches.suse/bus-omap_l3_noc-mark-l3-irqs-as-IRQF_NO_THREAD.patch patches.suse/0009-dm-verity-fix-DM_VERITY_OPTS_MAX-value.patch @@ -60300,6 +60330,7 @@ patches.suse/ASoC-hisilicon-fix-missing-clk_disable_unprepare-on-.patch patches.suse/ASoC-tegra-Set-driver_name-tegra-for-all-machine-dri.patch patches.suse/ASoC-soc-core-Fix-the-error-return-code-in-snd_soc_o.patch + patches.suse/tracepoint-Add-tracepoint_probe_register_may_exist-for-BPF-tracing.patch patches.suse/0001-xarray-iov_iter_fault_in_readable-should-do-nothing-in-xarray-case.patch patches.suse/leds-ktd2692-Fix-an-error-handling-path.patch patches.suse/Input-usbtouchscreen-fix-control-request-directions.patch @@ -61216,6 +61247,7 @@ patches.suse/char-mwave-Adjust-io-port-register-size.patch patches.suse/PCI-Add-function-1-DMA-alias-quirk-for-Marvell-88SE9.patch patches.suse/livepatch-Avoid-CPU-hogging-with-cond_resched.patch + patches.suse/tracing-uprobes-Check-the-return-value-of-kstrdup-for-tu-filename.patch patches.suse/tracing-kprobes-nmissed-not-showed-correctly-for-kretprobe.patch patches.suse/Input-ti_am335x_tsc-set-ADCREFM-for-X-configuration.patch patches.suse/Input-ti_am335x_tsc-fix-STEPCONFIG-setup-for-Z2.patch @@ -61477,6 +61509,7 @@ patches.suse/drbd-fix-an-invalid-memory-access-caused-by-incorrect-use-of-list-iterator patches.suse/scsi-virtio-scsi-Eliminate-anonymous-module_init-module_exit patches.suse/scsi-zorro7xx-Fix-a-resource-leak-in-zorro7xx_remove_one + patches.suse/SUNRPC-Fix-the-svc_deferred_event-trace-class.patch patches.suse/veth-Ensure-eth-header-is-in-skb-s-linear-part.patch patches.suse/mm-page_alloc-fix-build_zonerefs_node.patch patches.suse/smp-Fix-offline-cpu-check-in-flush_smp_call_function.patch @@ -61683,7 +61716,11 @@ patches.suse/ACPI-CPPC-Do-not-prevent-CPPC-from-working-in-the-fu.patch patches.suse/crypto-arm64-gcm-Select-AEAD-for-GHASH_ARM64_CE.patch patches.suse/crypto-inside-secure-Add-missing-MODULE_DEVICE_TABLE.patch + patches.suse/usbnet-Fix-linkwatch-use-after-free-on-disconnect.patch patches.suse/usbnet-smsc95xx-Fix-deadlock-on-runtime-resume.patch + patches.suse/spmi-trace-fix-stack-out-of-bound-access-in-SPMI-tracing-functions.patch + patches.suse/KVM-x86-Mark-TSS-busy-during-LTR-emulation-_after_-a.patch + patches.suse/KVM-x86-Set-error-code-to-segment-selector-on-LLDT-L.patch patches.suse/KVM-nVMX-Set-UMIP-bit-CR4_FIXED1-MSR-when-emulating-.patch patches.suse/PCI-dwc-Deallocate-EPC-memory-on-dw_pcie_ep_init-err.patch patches.suse/scsi-qla2xxx-edif-Reduce-Initiator-Initiator-thrashi.patch @@ -61737,9 +61774,12 @@ patches.suse/powerpc-powernv-rename-remaining-rng-powernv_-functi.patch patches.suse/powerpc-xive-Fix-refcount-leak-in-xive_get_max_prio.patch patches.suse/iommu-vt-d-avoid-invalid-memory-access-via-node_online-NUMA_NO_N + patches.suse/fuse-limit-nsec.patch patches.suse/x86-speculation-Add-RSB-VM-Exit-protections.patch patches.suse/x86-speculation-Add-LFENCE-to-RSB-fill-sequence.patch + patches.suse/ceph-don-t-truncate-file-in-atomic_open.patch patches.suse/net_sched-cls_route-remove-from-list-when-handle-is-.patch + patches.suse/xen-xenbus-fix-return-type-in-xenbus_file_read.patch patches.suse/net_sched-cls_route-disallow-handle-of-0.patch patches.suse/af_key-Do-not-call-xfrm_probe_algs-in-parallel.patch