All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Patel <ripatel@wii.dev>
To: x86@kernel.org
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>,
	Yu-cheng Yu <yu-cheng.yu@intel.com>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
	Borislav Petkov <bp@alien8.de>, "H. Peter Anvin" <hpa@zytor.com>,
	Andy Lutomirski <luto@kernel.org>, Kees Cook <kees@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Shuah Khan <shuah@kernel.org>,
	linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 7/7] selftests/x86: test usermode IBT
Date: Sun, 17 May 2026 13:30:24 -0500	[thread overview]
Message-ID: <20260517183024.16292-8-ripatel@wii.dev> (raw)
In-Reply-To: <20260517183024.16292-1-ripatel@wii.dev>

Adds a basic selftest exercising a usermode IBT violation.

Signed-off-by: Richard Patel <ripatel@wii.dev>
---
 tools/testing/selftests/x86/Makefile   |   5 +-
 tools/testing/selftests/x86/user_ibt.c | 157 +++++++++++++++++++++++++
 2 files changed, 161 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/x86/user_ibt.c

diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index 434065215d12..203c3d9073f2 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -19,7 +19,8 @@ TARGETS_C_32BIT_ONLY := entry_from_vm86 test_syscall_vdso unwind_vdso \
 			test_FCMOV test_FCOMI test_FISTTP \
 			vdso_restorer
 TARGETS_C_64BIT_ONLY := fsgsbase sysret_rip syscall_numbering \
-			corrupt_xstate_header amx lam test_shadow_stack avx apx
+			corrupt_xstate_header amx lam test_shadow_stack avx apx \
+			user_ibt
 # Some selftests require 32bit support enabled also on 64bit systems
 TARGETS_C_32BIT_NEEDED := ldt_gdt ptrace_syscall
 
@@ -138,3 +139,5 @@ $(OUTPUT)/avx_64: CFLAGS += -mno-avx -mno-avx512f
 $(OUTPUT)/amx_64: EXTRA_FILES += xstate.c
 $(OUTPUT)/avx_64: EXTRA_FILES += xstate.c
 $(OUTPUT)/apx_64: EXTRA_FILES += xstate.c
+
+$(OUTPUT)/user_ibt_64: CFLAGS += -fcf-protection=branch
diff --git a/tools/testing/selftests/x86/user_ibt.c b/tools/testing/selftests/x86/user_ibt.c
new file mode 100644
index 000000000000..795011503335
--- /dev/null
+++ b/tools/testing/selftests/x86/user_ibt.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test kernel support for userspace Indirect Branch Tracking (IBT).
+ * Enables IBT manually via prctl(). Must be compiled with
+ * -fcf-protection=branch to enable ENDBR64 instrumentation.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/signal.h>
+#include <sys/syscall.h>
+#include <linux/const.h>
+#include <linux/prctl.h>
+#include <unistd.h>
+#include "../kselftest.h"
+
+/*
+ * Allow building this test with old kernel headers.
+ */
+#ifndef PR_SET_CFI
+#define PR_GET_CFI			80
+#define PR_SET_CFI			81
+#endif
+#ifndef PR_CFI_ENABLE
+#define PR_CFI_ENABLE			(1UL << 0)
+#define PR_CFI_DISABLE			(1UL << 1)
+#endif
+#ifndef PR_CFI_BRANCH_LANDING_PADS
+#define PR_CFI_BRANCH_LANDING_PADS	0
+#endif
+#ifndef SEGV_CPERR
+#define SEGV_CPERR			10
+#endif
+
+#if !defined(__CET__) || (__CET__ & 1) != 1
+int main(int argc, char *argv[])
+{
+	ksft_print_header();
+	ksft_exit_skip("Compiler does not support CET.\n");
+	return 0;
+}
+#else
+void __attribute__((naked)) valid_target(void)
+{
+	asm volatile (
+		"endbr64\n"
+		"ret\n"
+	);
+}
+
+void __attribute__((nocf_check, naked)) invalid_target(void)
+{
+	asm volatile ("ret\n");
+}
+
+void __attribute__((naked)) user_ibt_basic_test(void)
+{
+	asm volatile (
+		"leaq valid_target(%rip), %rax\n"
+		"call *%rax\n"
+		"ret\n"
+	);
+}
+
+void __attribute__((naked)) user_ibt_notrack_test(void)
+{
+	asm volatile (
+		"leaq invalid_target(%rip), %rax\n"
+		"notrack call *%rax\n"
+		"ret\n"
+	);
+}
+
+static sigjmp_buf jmpbuf;
+static sig_atomic_t got_signal;
+static sig_atomic_t got_cperr;
+
+static void segv_handler(int signum, siginfo_t *si, void *uc)
+{
+	got_signal = true;
+	got_cperr = si->si_code == SEGV_CPERR;
+	siglongjmp(jmpbuf, 1);
+}
+
+int user_ibt_violation_test(void)
+{
+	struct sigaction sa = {};
+	struct sigaction oldsa;
+	size_t volatile ptr;
+
+	got_signal = false;
+	got_cperr = false;
+
+	sa.sa_sigaction = segv_handler;
+	sa.sa_flags = SA_SIGINFO;
+	if (sigaction(SIGSEGV, &sa, &oldsa)) {
+		ksft_perror("SIGSEGV handler setup failed");
+		return 1;
+	}
+
+	if (!sigsetjmp(jmpbuf, 1)) {
+		/*
+		 * Force an indirect call and drop 'nocf_check' attribute.
+		 * Obfuscate cast through a temp local to suppress
+		 * -Wincompatible-pointer-types (which correctly detects
+		 * the nocf_check attribute mismatch)
+		 */
+		ptr = (size_t)invalid_target;
+		((void (* volatile)(void))ptr)();
+		/* Fall through in case this didn't SIGSEGV */
+	}
+
+	if (sigaction(SIGSEGV, &oldsa, NULL)) {
+		ksft_perror("SIGSEGV handler restore failed");
+		return 1;
+	}
+
+	if (!got_signal) {
+		ksft_print_msg("IBT violation did not generate SIGSEGV\n");
+		return 1;
+	}
+	if (!got_cperr) {
+		ksft_print_msg("IBT violation generated unknown segfault\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	unsigned long lpad_status = PR_CFI_ENABLE;
+
+	ksft_print_header();
+	ksft_set_plan(3);
+
+	if (syscall(__NR_prctl, PR_SET_CFI, PR_CFI_BRANCH_LANDING_PADS, lpad_status, 0, 0)) {
+		if (errno == EINVAL || errno == EOPNOTSUPP)
+			ksft_exit_skip("User IBT is not supported.\n");
+		ksft_exit_fail_perror("Failed to enable user IBT");
+	}
+
+	user_ibt_basic_test();
+	ksft_test_result_pass("valid indirect call with endbr64\n");
+
+	user_ibt_notrack_test();
+	ksft_test_result_pass("notrack indirect call to non-endbr target\n");
+
+	ksft_test_result(!user_ibt_violation_test(),
+			 "indirect call to non-endbr target raises SIGSEGV\n");
+
+	ksft_finished();
+}
+#endif
-- 
2.47.3


  parent reply	other threads:[~2026-05-17 18:36 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-17 18:30 [PATCH 0/7] Usermode Indirect Branch Tracking Richard Patel
2026-05-17 18:30 ` [PATCH 1/7] x86: add userspace IBT config option Richard Patel
2026-05-17 18:30 ` [PATCH 2/7] x86: shstk: don't clobber IBT bits in U_CET MSR Richard Patel
2026-05-17 18:30 ` [PATCH 3/7] x86: signal handler support for IBT Richard Patel
2026-05-17 18:30 ` [PATCH 4/7] x86: ban 32-bit sigreturn when user IBT enabled Richard Patel
2026-05-18 20:22   ` H. Peter Anvin
2026-05-19  0:14     ` Richard Patel
2026-05-24 21:53     ` Richard Patel
2026-05-25 11:05       ` David Laight
2026-05-17 18:30 ` [PATCH 5/7] x86: expose user IBT via PR_CFI_BRANCH_LANDING_PADS Richard Patel
2026-05-18  6:46   ` Richard Patel
2026-05-17 18:30 ` [PATCH 6/7] x86/entry/vdso: build with IBT support Richard Patel
2026-05-17 18:30 ` Richard Patel [this message]
2026-05-18  7:36 ` [PATCH 0/7] Usermode Indirect Branch Tracking Peter Zijlstra
2026-05-18 16:25   ` Richard Patel
2026-05-18 19:31     ` Peter Zijlstra
2026-05-19  9:33 ` David Laight
2026-05-19  9:40   ` Peter Zijlstra
2026-05-19 13:14   ` Richard Patel
2026-05-19 13:28     ` David Laight
2026-05-19 14:18       ` Richard Patel
2026-05-19 14:42         ` Peter Zijlstra

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=20260517183024.16292-8-ripatel@wii.dev \
    --to=ripatel@wii.dev \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=kees@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rick.p.edgecombe@intel.com \
    --cc=shuah@kernel.org \
    --cc=tglx@kernel.org \
    --cc=x86@kernel.org \
    --cc=yu-cheng.yu@intel.com \
    /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.