From: Mark Rutland <mark.rutland@arm.com>
To: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: x86@kernel.org, linux-kernel@vger.kernel.org,
Peter Zijlstra <peterz@infradead.org>,
Jason Baron <jbaron@akamai.com>,
Steven Rostedt <rostedt@goodmis.org>,
Ard Biesheuvel <ardb@kernel.org>,
Christophe Leroy <christophe.leroy@csgroup.eu>,
Paolo Bonzini <pbonzini@redhat.com>,
Sean Christopherson <seanjc@google.com>,
Sami Tolvanen <samitolvanen@google.com>,
Nick Desaulniers <ndesaulniers@google.com>,
Will McVicker <willmcvicker@google.com>,
Kees Cook <keescook@chromium.org>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v2 08/11] arm64/static_call: Fix static call CFI violations
Date: Wed, 22 Mar 2023 12:22:07 +0000 [thread overview]
Message-ID: <ZBry75KS3F+a0VM0@FVFF77S0Q05N> (raw)
In-Reply-To: <3d8c9e67a7e29f3bed4e44429d953e1ac9c6d5be.1679456900.git.jpoimboe@kernel.org>
On Tue, Mar 21, 2023 at 09:00:14PM -0700, Josh Poimboeuf wrote:
> On arm64, with CONFIG_CFI_CLANG, it's trivial to trigger CFI violations
> by running "perf record -e sched:sched_switch -a":
>
> CFI failure at perf_misc_flags+0x34/0x70 (target: __static_call_return0+0x0/0xc; expected type: 0x837de525)
> WARNING: CPU: 3 PID: 32 at perf_misc_flags+0x34/0x70
> CPU: 3 PID: 32 Comm: ksoftirqd/3 Kdump: loaded Tainted: P 6.3.0-rc2 #8
> Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
> pstate: 904000c5 (NzcV daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> pc : perf_misc_flags+0x34/0x70
> lr : perf_event_output_forward+0x74/0xf0
> sp : ffff80000a98b970
> x29: ffff80000a98b970 x28: ffff00077bd34d00 x27: ffff8000097d2d00
> x26: fffffbffeff6a360 x25: ffff800009835a30 x24: ffff0000c2e8dca0
> x23: 0000000000000000 x22: 0000000000000080 x21: ffff00077bd31610
> x20: ffff0000c2e8dca0 x19: ffff00077bd31610 x18: ffff800008cd52f0
> x17: 00000000837de525 x16: 0000000072923c8f x15: 000000000000b67e
> x14: 000000000178797d x13: 0000000000000004 x12: 0000000070b5b3a8
> x11: 0000000000000015 x10: 0000000000000048 x9 : ffff80000829e2b4
> x8 : ffff80000829c6f0 x7 : 0000000000000000 x6 : 0000000000000000
> x5 : fffffbffeff6a340 x4 : ffff00077bd31610 x3 : ffff00077bd31610
> x2 : ffff800009833400 x1 : 0000000000000000 x0 : ffff00077bd31610
> Call trace:
> perf_misc_flags+0x34/0x70
> perf_event_output_forward+0x74/0xf0
> __perf_event_overflow+0x12c/0x1e8
> perf_swevent_event+0x98/0x1a0
> perf_tp_event+0x140/0x558
> perf_trace_run_bpf_submit+0x88/0xc8
> perf_trace_sched_switch+0x160/0x19c
> __schedule+0xabc/0x153c
> dynamic_cond_resched+0x48/0x68
> run_ksoftirqd+0x3c/0x138
> smpboot_thread_fn+0x26c/0x2f8
> kthread+0x108/0x1c4
> ret_from_fork+0x10/0x20
>
> The problem is that the __perf_guest_state() static call does an
> indirect branch to __static_call_return0(), which isn't CFI-compliant.
IIUC that'd be broken even with the old CFI mechanism, since commit:
87b940a0675e2526 ("perf/core: Use static_call to optimize perf_guest_info_callbacks")
If so, we probably want a Fixes tag?
> Fix that by generating custom CFI-compliant ret0 functions for each
> defined static key.
>
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
> ---
> arch/Kconfig | 4 ++
> arch/arm64/include/asm/static_call.h | 29 +++++++++++
> include/linux/static_call.h | 64 +++++++++++++++++++++----
> include/linux/static_call_types.h | 4 ++
> kernel/Makefile | 2 +-
> kernel/static_call.c | 2 +-
> tools/include/linux/static_call_types.h | 4 ++
> 7 files changed, 97 insertions(+), 12 deletions(-)
> create mode 100644 arch/arm64/include/asm/static_call.h
>
> diff --git a/arch/Kconfig b/arch/Kconfig
> index e3511afbb7f2..8800fe80a0f9 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -1348,6 +1348,10 @@ config HAVE_STATIC_CALL_INLINE
> depends on HAVE_STATIC_CALL
> select OBJTOOL
>
> +config CFI_WITHOUT_STATIC_CALL
> + def_bool y
> + depends on CFI_CLANG && !HAVE_STATIC_CALL
> +
> config HAVE_PREEMPT_DYNAMIC
> bool
>
> diff --git a/arch/arm64/include/asm/static_call.h b/arch/arm64/include/asm/static_call.h
> new file mode 100644
> index 000000000000..b3489cac7742
> --- /dev/null
> +++ b/arch/arm64/include/asm/static_call.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ASM_ARM64_STATIC_CALL_H
> +#define _ASM_ARM64_STATIC_CALL_H
> +
> +/*
> + * Make a dummy reference to a function pointer in C to force the compiler to
> + * emit a __kcfi_typeid_ symbol for asm to use.
> + */
> +#define GEN_CFI_SYM(func) \
> + static typeof(func) __used __section(".discard.cfi") *__UNIQUE_ID(cfi) = func
> +
> +
> +/* Generate a CFI-compliant static call NOP function */
> +#define __ARCH_DEFINE_STATIC_CALL_CFI(name, insns) \
> + asm(".align 4 \n" \
> + ".word __kcfi_typeid_" name " \n" \
> + ".globl " name " \n" \
> + name ": \n" \
> + "bti c \n" \
> + insns " \n" \
> + "ret \n" \
> + ".type " name ", @function \n" \
> + ".size " name ", . - " name " \n")
> +
> +#define __ARCH_DEFINE_STATIC_CALL_RET0_CFI(name) \
> + GEN_CFI_SYM(STATIC_CALL_RET0_CFI(name)); \
> + __ARCH_DEFINE_STATIC_CALL_CFI(STATIC_CALL_RET0_CFI_STR(name), "mov x0, xzr")
This looks correct, but given we're generating a regular functions it's
unfortunate we can't have the compiler generate the actual code with something
like:
#define __ARCH_DEFINE_STATIC_CALL_RET0_CFI(rettype, name, args...) \
rettype name(args) \
{ \
return (rettype)0; \
}
... but I guess passing the rettype and args around is painful.
Regardless, I gave this a spin atop v6.3-rc3 using LLVM 16.0.0 and CFI_CLANG,
and it does seem to work, so:
Tested-by: Mark Rutland <mark.rutland@arm.com>
Thanks,
Mark.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: Mark Rutland <mark.rutland@arm.com>
To: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: x86@kernel.org, linux-kernel@vger.kernel.org,
Peter Zijlstra <peterz@infradead.org>,
Jason Baron <jbaron@akamai.com>,
Steven Rostedt <rostedt@goodmis.org>,
Ard Biesheuvel <ardb@kernel.org>,
Christophe Leroy <christophe.leroy@csgroup.eu>,
Paolo Bonzini <pbonzini@redhat.com>,
Sean Christopherson <seanjc@google.com>,
Sami Tolvanen <samitolvanen@google.com>,
Nick Desaulniers <ndesaulniers@google.com>,
Will McVicker <willmcvicker@google.com>,
Kees Cook <keescook@chromium.org>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v2 08/11] arm64/static_call: Fix static call CFI violations
Date: Wed, 22 Mar 2023 12:22:07 +0000 [thread overview]
Message-ID: <ZBry75KS3F+a0VM0@FVFF77S0Q05N> (raw)
In-Reply-To: <3d8c9e67a7e29f3bed4e44429d953e1ac9c6d5be.1679456900.git.jpoimboe@kernel.org>
On Tue, Mar 21, 2023 at 09:00:14PM -0700, Josh Poimboeuf wrote:
> On arm64, with CONFIG_CFI_CLANG, it's trivial to trigger CFI violations
> by running "perf record -e sched:sched_switch -a":
>
> CFI failure at perf_misc_flags+0x34/0x70 (target: __static_call_return0+0x0/0xc; expected type: 0x837de525)
> WARNING: CPU: 3 PID: 32 at perf_misc_flags+0x34/0x70
> CPU: 3 PID: 32 Comm: ksoftirqd/3 Kdump: loaded Tainted: P 6.3.0-rc2 #8
> Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
> pstate: 904000c5 (NzcV daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> pc : perf_misc_flags+0x34/0x70
> lr : perf_event_output_forward+0x74/0xf0
> sp : ffff80000a98b970
> x29: ffff80000a98b970 x28: ffff00077bd34d00 x27: ffff8000097d2d00
> x26: fffffbffeff6a360 x25: ffff800009835a30 x24: ffff0000c2e8dca0
> x23: 0000000000000000 x22: 0000000000000080 x21: ffff00077bd31610
> x20: ffff0000c2e8dca0 x19: ffff00077bd31610 x18: ffff800008cd52f0
> x17: 00000000837de525 x16: 0000000072923c8f x15: 000000000000b67e
> x14: 000000000178797d x13: 0000000000000004 x12: 0000000070b5b3a8
> x11: 0000000000000015 x10: 0000000000000048 x9 : ffff80000829e2b4
> x8 : ffff80000829c6f0 x7 : 0000000000000000 x6 : 0000000000000000
> x5 : fffffbffeff6a340 x4 : ffff00077bd31610 x3 : ffff00077bd31610
> x2 : ffff800009833400 x1 : 0000000000000000 x0 : ffff00077bd31610
> Call trace:
> perf_misc_flags+0x34/0x70
> perf_event_output_forward+0x74/0xf0
> __perf_event_overflow+0x12c/0x1e8
> perf_swevent_event+0x98/0x1a0
> perf_tp_event+0x140/0x558
> perf_trace_run_bpf_submit+0x88/0xc8
> perf_trace_sched_switch+0x160/0x19c
> __schedule+0xabc/0x153c
> dynamic_cond_resched+0x48/0x68
> run_ksoftirqd+0x3c/0x138
> smpboot_thread_fn+0x26c/0x2f8
> kthread+0x108/0x1c4
> ret_from_fork+0x10/0x20
>
> The problem is that the __perf_guest_state() static call does an
> indirect branch to __static_call_return0(), which isn't CFI-compliant.
IIUC that'd be broken even with the old CFI mechanism, since commit:
87b940a0675e2526 ("perf/core: Use static_call to optimize perf_guest_info_callbacks")
If so, we probably want a Fixes tag?
> Fix that by generating custom CFI-compliant ret0 functions for each
> defined static key.
>
> Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
> ---
> arch/Kconfig | 4 ++
> arch/arm64/include/asm/static_call.h | 29 +++++++++++
> include/linux/static_call.h | 64 +++++++++++++++++++++----
> include/linux/static_call_types.h | 4 ++
> kernel/Makefile | 2 +-
> kernel/static_call.c | 2 +-
> tools/include/linux/static_call_types.h | 4 ++
> 7 files changed, 97 insertions(+), 12 deletions(-)
> create mode 100644 arch/arm64/include/asm/static_call.h
>
> diff --git a/arch/Kconfig b/arch/Kconfig
> index e3511afbb7f2..8800fe80a0f9 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -1348,6 +1348,10 @@ config HAVE_STATIC_CALL_INLINE
> depends on HAVE_STATIC_CALL
> select OBJTOOL
>
> +config CFI_WITHOUT_STATIC_CALL
> + def_bool y
> + depends on CFI_CLANG && !HAVE_STATIC_CALL
> +
> config HAVE_PREEMPT_DYNAMIC
> bool
>
> diff --git a/arch/arm64/include/asm/static_call.h b/arch/arm64/include/asm/static_call.h
> new file mode 100644
> index 000000000000..b3489cac7742
> --- /dev/null
> +++ b/arch/arm64/include/asm/static_call.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _ASM_ARM64_STATIC_CALL_H
> +#define _ASM_ARM64_STATIC_CALL_H
> +
> +/*
> + * Make a dummy reference to a function pointer in C to force the compiler to
> + * emit a __kcfi_typeid_ symbol for asm to use.
> + */
> +#define GEN_CFI_SYM(func) \
> + static typeof(func) __used __section(".discard.cfi") *__UNIQUE_ID(cfi) = func
> +
> +
> +/* Generate a CFI-compliant static call NOP function */
> +#define __ARCH_DEFINE_STATIC_CALL_CFI(name, insns) \
> + asm(".align 4 \n" \
> + ".word __kcfi_typeid_" name " \n" \
> + ".globl " name " \n" \
> + name ": \n" \
> + "bti c \n" \
> + insns " \n" \
> + "ret \n" \
> + ".type " name ", @function \n" \
> + ".size " name ", . - " name " \n")
> +
> +#define __ARCH_DEFINE_STATIC_CALL_RET0_CFI(name) \
> + GEN_CFI_SYM(STATIC_CALL_RET0_CFI(name)); \
> + __ARCH_DEFINE_STATIC_CALL_CFI(STATIC_CALL_RET0_CFI_STR(name), "mov x0, xzr")
This looks correct, but given we're generating a regular functions it's
unfortunate we can't have the compiler generate the actual code with something
like:
#define __ARCH_DEFINE_STATIC_CALL_RET0_CFI(rettype, name, args...) \
rettype name(args) \
{ \
return (rettype)0; \
}
... but I guess passing the rettype and args around is painful.
Regardless, I gave this a spin atop v6.3-rc3 using LLVM 16.0.0 and CFI_CLANG,
and it does seem to work, so:
Tested-by: Mark Rutland <mark.rutland@arm.com>
Thanks,
Mark.
next prev parent reply other threads:[~2023-03-22 12:23 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-22 4:00 [PATCH v2 00/11] static_call: Improve NULL/ret0 handling Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 4:00 ` [PATCH v2 01/11] static_call: Improve key type abstraction Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 4:53 ` Josh Poimboeuf
2023-03-22 4:53 ` Josh Poimboeuf
2023-03-22 5:02 ` [PATCH v2.1 " Josh Poimboeuf
2023-03-22 5:02 ` Josh Poimboeuf
2023-03-22 4:00 ` [PATCH v2 02/11] static_call: Flip key type union bit Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 5:03 ` [PATCH v2.1 " Josh Poimboeuf
2023-03-22 5:03 ` Josh Poimboeuf
2023-03-22 4:00 ` [PATCH v2 03/11] static_call: Remove static_call_mod_init() declaration Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 4:00 ` [PATCH v2 04/11] static_call: Remove static_call.h dependency on cpu.h Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 4:00 ` [PATCH v2 05/11] static_call: Make ARCH_ADD_TRAMP_KEY() generic Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 4:00 ` [PATCH v2 06/11] static_call: "EXPORT_STATIC_CALL_TRAMP" -> "EXPORT_STATIC_CALL_RO" Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 4:00 ` [PATCH v2 07/11] static_call: Reorganize static call headers Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 4:00 ` [PATCH v2 08/11] arm64/static_call: Fix static call CFI violations Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 12:22 ` Mark Rutland [this message]
2023-03-22 12:22 ` Mark Rutland
2023-03-22 14:19 ` Peter Zijlstra
2023-03-22 14:19 ` Peter Zijlstra
2023-03-22 18:26 ` Josh Poimboeuf
2023-03-22 18:26 ` Josh Poimboeuf
2023-03-22 18:09 ` Josh Poimboeuf
2023-03-22 18:09 ` Josh Poimboeuf
2023-03-22 18:07 ` Sami Tolvanen
2023-03-22 18:07 ` Sami Tolvanen
2023-03-22 18:33 ` Josh Poimboeuf
2023-03-22 18:33 ` Josh Poimboeuf
2023-03-22 4:00 ` [PATCH v2 09/11] static_call: Make NULL static calls consistent Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 14:45 ` Peter Zijlstra
2023-03-22 14:45 ` Peter Zijlstra
2023-03-22 14:59 ` Peter Zijlstra
2023-03-22 14:59 ` Peter Zijlstra
2023-03-22 18:35 ` Josh Poimboeuf
2023-03-22 18:35 ` Josh Poimboeuf
2023-03-22 15:04 ` Christophe Leroy
2023-03-22 15:04 ` Christophe Leroy
2023-03-22 4:00 ` [PATCH v2 10/11] static_call: Remove static_call_cond() Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 4:00 ` [PATCH v2 11/11] static_call: Remove DEFINE_STATIC_CALL_RET0() Josh Poimboeuf
2023-03-22 4:00 ` Josh Poimboeuf
2023-03-22 15:04 ` Christophe Leroy
2023-03-22 15:04 ` Christophe Leroy
2023-03-22 18:50 ` Josh Poimboeuf
2023-03-22 18:50 ` Josh Poimboeuf
2023-03-22 15:15 ` Peter Zijlstra
2023-03-22 15:15 ` Peter Zijlstra
2023-03-22 18:45 ` Josh Poimboeuf
2023-03-22 18:45 ` Josh Poimboeuf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZBry75KS3F+a0VM0@FVFF77S0Q05N \
--to=mark.rutland@arm.com \
--cc=ardb@kernel.org \
--cc=christophe.leroy@csgroup.eu \
--cc=jbaron@akamai.com \
--cc=jpoimboe@kernel.org \
--cc=keescook@chromium.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ndesaulniers@google.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=samitolvanen@google.com \
--cc=seanjc@google.com \
--cc=willmcvicker@google.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.