From nobody Fri Sep 12 11:21:11 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 980F8C636D7 for ; Fri, 10 Feb 2023 22:42:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233953AbjBJWmT (ORCPT ); Fri, 10 Feb 2023 17:42:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36530 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233839AbjBJWmQ (ORCPT ); Fri, 10 Feb 2023 17:42:16 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81A2B7395D for ; Fri, 10 Feb 2023 14:42:12 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 0ED1061EBC for ; Fri, 10 Feb 2023 22:42:12 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1B9DEC433A0; Fri, 10 Feb 2023 22:42:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1676068931; bh=VHlvi54nMSSeZR3KfCUMR/kLCvhVDPgKk9UcONDfDm8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=twTpIs6/gPBDovstqkCNjR9XnBUuwvfcUiXVrfonYdkkmK1NbabLfgO2n+agqBx60 9LSLy4tbbOSMuwYgMUqIwzdKIlVTlWfgUw0RoL9tLjZ1XmEYZmFkLb++cbdr3jouZT Da3kfUsmdD9E+HFyieAzQP9XuTdvgz6bc7SrB6dE9AnOSI1BqMI4vlH7h9Mx482uSV bqMWabq3HEx5WTICR1vpiENvbn0y5pOFsWiWmo69zCfaCEaPF+YzUroHg0g53+ZuBe a7FcJm0QCBc7HL3U8eLL2cDdT8aSjfSAI72jp1Fh9G9K5iqu0ABXkyCowQZCGcTlN1 naFLFexHxaLyA== From: Josh Poimboeuf To: x86@kernel.org Cc: linux-kernel@vger.kernel.org, Peter Zijlstra , Chen Zhongjin , "Naveen N. Rao" , Anil S Keshavamurthy , "David S. Miller" , Masami Hiramatsu Subject: [PATCH 1/2] x86/unwind/orc: Add 'signal' field to ORC metadata Date: Fri, 10 Feb 2023 14:42:01 -0800 Message-Id: X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add a 'signal' field which allows unwind hints to specify whether the instruction pointer should be taken literally (like for most interrupts and exceptions) rather than decremented (like for call stack return addresses) when used to find the next ORC entry. Signed-off-by: Josh Poimboeuf --- arch/x86/include/asm/orc_types.h | 4 +++- arch/x86/include/asm/unwind_hints.h | 10 +++++----- arch/x86/kernel/unwind_orc.c | 5 ++--- include/linux/objtool.h | 11 +++++++---- tools/arch/x86/include/asm/orc_types.h | 4 +++- tools/include/linux/objtool.h | 11 +++++++---- tools/objtool/orc_dump.c | 4 ++-- 7 files changed, 29 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/orc_types.h b/arch/x86/include/asm/orc_ty= pes.h index 5a2baf28a1dc..1343a62106de 100644 --- a/arch/x86/include/asm/orc_types.h +++ b/arch/x86/include/asm/orc_types.h @@ -57,12 +57,14 @@ struct orc_entry { unsigned sp_reg:4; unsigned bp_reg:4; unsigned type:2; + unsigned signal:1; unsigned end:1; #elif defined(__BIG_ENDIAN_BITFIELD) unsigned bp_reg:4; unsigned sp_reg:4; - unsigned unused:5; + unsigned unused:4; unsigned end:1; + unsigned signal:1; unsigned type:2; #endif } __packed; diff --git a/arch/x86/include/asm/unwind_hints.h b/arch/x86/include/asm/unw= ind_hints.h index f66fbe6537dd..e7c71750b309 100644 --- a/arch/x86/include/asm/unwind_hints.h +++ b/arch/x86/include/asm/unwind_hints.h @@ -15,7 +15,7 @@ UNWIND_HINT type=3DUNWIND_HINT_TYPE_ENTRY end=3D1 .endm =20 -.macro UNWIND_HINT_REGS base=3D%rsp offset=3D0 indirect=3D0 extra=3D1 part= ial=3D0 +.macro UNWIND_HINT_REGS base=3D%rsp offset=3D0 indirect=3D0 extra=3D1 part= ial=3D0 signal=3D1 .if \base =3D=3D %rsp .if \indirect .set sp_reg, ORC_REG_SP_INDIRECT @@ -45,11 +45,11 @@ .set type, UNWIND_HINT_TYPE_REGS .endif =20 - UNWIND_HINT sp_reg=3Dsp_reg sp_offset=3Dsp_offset type=3Dtype + UNWIND_HINT sp_reg=3Dsp_reg sp_offset=3Dsp_offset type=3Dtype signal=3D\s= ignal .endm =20 -.macro UNWIND_HINT_IRET_REGS base=3D%rsp offset=3D0 - UNWIND_HINT_REGS base=3D\base offset=3D\offset partial=3D1 +.macro UNWIND_HINT_IRET_REGS base=3D%rsp offset=3D0 signal=3D1 + UNWIND_HINT_REGS base=3D\base offset=3D\offset partial=3D1 signal=3D\sign= al .endm =20 .macro UNWIND_HINT_FUNC @@ -67,7 +67,7 @@ #else =20 #define UNWIND_HINT_FUNC \ - UNWIND_HINT(ORC_REG_SP, 8, UNWIND_HINT_TYPE_FUNC, 0) + UNWIND_HINT(ORC_REG_SP, 8, UNWIND_HINT_TYPE_FUNC, 0, 0) =20 #endif /* __ASSEMBLY__ */ =20 diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index cdf6c6060170..37307b40f8da 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -484,6 +484,8 @@ bool unwind_next_frame(struct unwind_state *state) goto the_end; } =20 + state->signal =3D orc->signal; + /* Find the previous frame's stack: */ switch (orc->sp_reg) { case ORC_REG_SP: @@ -563,7 +565,6 @@ bool unwind_next_frame(struct unwind_state *state) state->sp =3D sp; state->regs =3D NULL; state->prev_regs =3D NULL; - state->signal =3D false; break; =20 case UNWIND_HINT_TYPE_REGS: @@ -587,7 +588,6 @@ bool unwind_next_frame(struct unwind_state *state) state->regs =3D (struct pt_regs *)sp; state->prev_regs =3D NULL; state->full_regs =3D true; - state->signal =3D true; break; =20 case UNWIND_HINT_TYPE_REGS_PARTIAL: @@ -604,7 +604,6 @@ bool unwind_next_frame(struct unwind_state *state) state->prev_regs =3D state->regs; state->regs =3D (void *)sp - IRET_FRAME_OFFSET; state->full_regs =3D false; - state->signal =3D true; break; =20 default: diff --git a/include/linux/objtool.h b/include/linux/objtool.h index 62c54ffbeeaa..9ac3df3fccf0 100644 --- a/include/linux/objtool.h +++ b/include/linux/objtool.h @@ -15,6 +15,7 @@ struct unwind_hint { s16 sp_offset; u8 sp_reg; u8 type; + u8 signal; u8 end; }; #endif @@ -49,7 +50,7 @@ struct unwind_hint { =20 #ifndef __ASSEMBLY__ =20 -#define UNWIND_HINT(sp_reg, sp_offset, type, end) \ +#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \ "987: \n\t" \ ".pushsection .discard.unwind_hints\n\t" \ /* struct unwind_hint */ \ @@ -57,6 +58,7 @@ struct unwind_hint { ".short " __stringify(sp_offset) "\n\t" \ ".byte " __stringify(sp_reg) "\n\t" \ ".byte " __stringify(type) "\n\t" \ + ".byte " __stringify(signal) "\n\t" \ ".byte " __stringify(end) "\n\t" \ ".balign 4 \n\t" \ ".popsection\n\t" @@ -129,7 +131,7 @@ struct unwind_hint { * the debuginfo as necessary. It will also warn if it sees any * inconsistencies. */ -.macro UNWIND_HINT type:req sp_reg=3D0 sp_offset=3D0 end=3D0 +.macro UNWIND_HINT type:req sp_reg=3D0 sp_offset=3D0 signal=3D0 end=3D0 .Lunwind_hint_ip_\@: .pushsection .discard.unwind_hints /* struct unwind_hint */ @@ -137,6 +139,7 @@ struct unwind_hint { .short \sp_offset .byte \sp_reg .byte \type + .byte \signal .byte \end .balign 4 .popsection @@ -174,7 +177,7 @@ struct unwind_hint { =20 #ifndef __ASSEMBLY__ =20 -#define UNWIND_HINT(sp_reg, sp_offset, type, end) \ +#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \ "\n\t" #define STACK_FRAME_NON_STANDARD(func) #define STACK_FRAME_NON_STANDARD_FP(func) @@ -182,7 +185,7 @@ struct unwind_hint { #define ASM_REACHABLE #else #define ANNOTATE_INTRA_FUNCTION_CALL -.macro UNWIND_HINT type:req sp_reg=3D0 sp_offset=3D0 end=3D0 +.macro UNWIND_HINT type:req sp_reg=3D0 sp_offset=3D0 signal=3D0 end=3D0 .endm .macro STACK_FRAME_NON_STANDARD func:req .endm diff --git a/tools/arch/x86/include/asm/orc_types.h b/tools/arch/x86/includ= e/asm/orc_types.h index 5a2baf28a1dc..1343a62106de 100644 --- a/tools/arch/x86/include/asm/orc_types.h +++ b/tools/arch/x86/include/asm/orc_types.h @@ -57,12 +57,14 @@ struct orc_entry { unsigned sp_reg:4; unsigned bp_reg:4; unsigned type:2; + unsigned signal:1; unsigned end:1; #elif defined(__BIG_ENDIAN_BITFIELD) unsigned bp_reg:4; unsigned sp_reg:4; - unsigned unused:5; + unsigned unused:4; unsigned end:1; + unsigned signal:1; unsigned type:2; #endif } __packed; diff --git a/tools/include/linux/objtool.h b/tools/include/linux/objtool.h index 62c54ffbeeaa..9ac3df3fccf0 100644 --- a/tools/include/linux/objtool.h +++ b/tools/include/linux/objtool.h @@ -15,6 +15,7 @@ struct unwind_hint { s16 sp_offset; u8 sp_reg; u8 type; + u8 signal; u8 end; }; #endif @@ -49,7 +50,7 @@ struct unwind_hint { =20 #ifndef __ASSEMBLY__ =20 -#define UNWIND_HINT(sp_reg, sp_offset, type, end) \ +#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \ "987: \n\t" \ ".pushsection .discard.unwind_hints\n\t" \ /* struct unwind_hint */ \ @@ -57,6 +58,7 @@ struct unwind_hint { ".short " __stringify(sp_offset) "\n\t" \ ".byte " __stringify(sp_reg) "\n\t" \ ".byte " __stringify(type) "\n\t" \ + ".byte " __stringify(signal) "\n\t" \ ".byte " __stringify(end) "\n\t" \ ".balign 4 \n\t" \ ".popsection\n\t" @@ -129,7 +131,7 @@ struct unwind_hint { * the debuginfo as necessary. It will also warn if it sees any * inconsistencies. */ -.macro UNWIND_HINT type:req sp_reg=3D0 sp_offset=3D0 end=3D0 +.macro UNWIND_HINT type:req sp_reg=3D0 sp_offset=3D0 signal=3D0 end=3D0 .Lunwind_hint_ip_\@: .pushsection .discard.unwind_hints /* struct unwind_hint */ @@ -137,6 +139,7 @@ struct unwind_hint { .short \sp_offset .byte \sp_reg .byte \type + .byte \signal .byte \end .balign 4 .popsection @@ -174,7 +177,7 @@ struct unwind_hint { =20 #ifndef __ASSEMBLY__ =20 -#define UNWIND_HINT(sp_reg, sp_offset, type, end) \ +#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \ "\n\t" #define STACK_FRAME_NON_STANDARD(func) #define STACK_FRAME_NON_STANDARD_FP(func) @@ -182,7 +185,7 @@ struct unwind_hint { #define ASM_REACHABLE #else #define ANNOTATE_INTRA_FUNCTION_CALL -.macro UNWIND_HINT type:req sp_reg=3D0 sp_offset=3D0 end=3D0 +.macro UNWIND_HINT type:req sp_reg=3D0 sp_offset=3D0 signal=3D0 end=3D0 .endm .macro STACK_FRAME_NON_STANDARD func:req .endm diff --git a/tools/objtool/orc_dump.c b/tools/objtool/orc_dump.c index 4f1211fec82c..2d8ebdcd1db3 100644 --- a/tools/objtool/orc_dump.c +++ b/tools/objtool/orc_dump.c @@ -211,8 +211,8 @@ int orc_dump(const char *_objname) =20 print_reg(orc[i].bp_reg, bswap_if_needed(&dummy_elf, orc[i].bp_offset)); =20 - printf(" type:%s end:%d\n", - orc_type_name(orc[i].type), orc[i].end); + printf(" type:%s signal:%d end:%d\n", + orc_type_name(orc[i].type), orc[i].signal, orc[i].end); } =20 elf_end(elf); --=20 2.39.1 From nobody Fri Sep 12 11:21:11 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 40D25C636D4 for ; Fri, 10 Feb 2023 22:42:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233803AbjBJWmZ (ORCPT ); Fri, 10 Feb 2023 17:42:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36728 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233954AbjBJWmT (ORCPT ); Fri, 10 Feb 2023 17:42:19 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8EBCF55E72 for ; Fri, 10 Feb 2023 14:42:14 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 360D7B82616 for ; Fri, 10 Feb 2023 22:42:13 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 90465C433A8; Fri, 10 Feb 2023 22:42:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1676068931; bh=LXh7cCWgskiu1lOCHbKoWebvfAUhqVsfAvFuxIYpy5k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FteLrbx76zQKCC/KPwhIke7oMow6ISwTy6SILIJCVjLWipk90bh3gczA4nnV6Y4vQ 216+36ARPC6NR/y0K9b9zoKJkjY0i2P4jbJVI9X0r0zK9EeT4jr6+7CcgKpgfkZWsy lFGbT1FgR12esskj57a+fCtomcG21FDzi70/neyUJ7dGk+ahSqSeQLgfwucmS9xmTo TsjJspy9Z7vf1HH/Fl9iC1BnRZ6bKMQhDG0ASF4q1rijWVOKl/wFzRwIePRTPFc52G 05a0Kjnsoq/97ko3FlHmi3B9kjYYOvqU32ViPEhUc8CytwUVpnNEHogOu3Im+O9WHU efJjvaauzJ/sw== From: Josh Poimboeuf To: x86@kernel.org Cc: linux-kernel@vger.kernel.org, Peter Zijlstra , Chen Zhongjin , "Naveen N. Rao" , Anil S Keshavamurthy , "David S. Miller" , Masami Hiramatsu Subject: [PATCH 2/2] x86/entry: Fix unwinding from kprobe on PUSH/POP instruction Date: Fri, 10 Feb 2023 14:42:02 -0800 Message-Id: X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" If a kprobe (INT3) is set on a stack-modifying single-byte instruction, like a single-byte PUSH/POP or a LEAVE, ORC fails to unwind past it: Call Trace: dump_stack_lvl+0x57/0x90 handler_pre+0x33/0x40 [kprobe_example] aggr_pre_handler+0x49/0x90 kprobe_int3_handler+0xe3/0x180 do_int3+0x3a/0x80 exc_int3+0x7d/0xc0 asm_exc_int3+0x35/0x40 RIP: 0010:kernel_clone+0xe/0x3a0 Code: cc e8 16 b2 bf 00 66 0f 1f 44 00 00 90 90 90 90 90 90 90 90 90 90 9= 0 90 90 90 90 90 0f 1f 44 00 00 41 57 41 56 41 55 41 54 cc <53> 48 89 fb 48= 83 ec 68 4c 8b 27 65 48 8b 04 25 28 00 00 00 48 89 RSP: 0018:ffffc9000074fda0 EFLAGS: 00000206 RAX: 0000000000808100 RBX: ffff888109de9d80 RCX: 0000000000000000 RDX: 0000000000000011 RSI: ffff888109de9d80 RDI: ffffc9000074fdc8 RBP: ffff8881019543c0 R08: ffffffff81127e30 R09: 00000000e71742a5 R10: ffff888104764a18 R11: 0000000071742a5e R12: ffff888100078800 R13: ffff888100126000 R14: 0000000000000000 R15: ffff888100126005 ? __pfx_call_usermodehelper_exec_async+0x10/0x10 ? kernel_clone+0xe/0x3a0 ? user_mode_thread+0x5b/0x80 ? __pfx_call_usermodehelper_exec_async+0x10/0x10 ? call_usermodehelper_exec_work+0x77/0xb0 ? process_one_work+0x299/0x5f0 ? worker_thread+0x4f/0x3a0 ? __pfx_worker_thread+0x10/0x10 ? kthread+0xf2/0x120 ? __pfx_kthread+0x10/0x10 ? ret_from_fork+0x29/0x50 The problem is that #BP saves the pointer to the instruction immediately *after* the INT3, rather than to the INT3 itself. The instruction replaced by the INT3 hasn't actually run, but ORC assumes otherwise and expects the wrong stack layout. Fix it by annotating the #BP exception as a non-signal stack frame, which tells the ORC unwinder to decrement the instruction pointer before looking up the corresponding ORC entry. Reported-by: Chen Zhongjin Signed-off-by: Josh Poimboeuf --- arch/x86/entry/entry_64.S | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 15739a2c0983..8d21881adf86 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -385,7 +385,14 @@ SYM_CODE_END(xen_error_entry) */ .macro idtentry vector asmsym cfunc has_error_code:req SYM_CODE_START(\asmsym) - UNWIND_HINT_IRET_REGS offset=3D\has_error_code*8 + + .if \vector =3D=3D X86_TRAP_BP + /* #BP advances %rip to the next instruction */ + UNWIND_HINT_IRET_REGS offset=3D\has_error_code*8 signal=3D0 + .else + UNWIND_HINT_IRET_REGS offset=3D\has_error_code*8 + .endif + ENDBR ASM_CLAC cld --=20 2.39.1