linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/7]  arm64: Enable UPROBES with GCS
@ 2025-05-04 23:31 Jeremy Linton
  2025-05-04 23:31 ` [PATCH v3 1/7] arm64/gcs: task_gcs_el0_enable() should use passed task Jeremy Linton
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Jeremy Linton @ 2025-05-04 23:31 UTC (permalink / raw)
  To: linux-trace-kernel
  Cc: linux-perf-users, mhiramat, oleg, peterz, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, thiago.bauermann, broonie, yury.khrustalev,
	kristina.martsenko, liaochang1, catalin.marinas, will,
	linux-arm-kernel, linux-kernel, Jeremy Linton

Currently uprobes and the Arm Guarded Control Stack (GCS) feature are
exclusive of each other. This restriction needs to be lifted in order
to utilize GCS for generic Linux distro images where the expectation
is that core debugging features like uprobes work.

This series adds some user accessors to read/push/pop the userspace
shadow stack. It then utilizes those functions in the uprobe paths
as needed to synchronize GCS with the changes in control flow at
probe locations. 

The KCONFIG restriction is then dropped.

v2->v3: Cleanup RET logic to alwaays use LR, and not update IP if GCS aborts
	Correct generic uprobe_warn bug even though we aren't using it

v1->v2:
	Drop uprobe_warn() patch
	Fix copy_thread_gcs() bug created by fixing task_gcs_el0_enabled()
	Comments, now describe issues with reading userspace GCS pages
	Rebased to 6.15

Jeremy Linton (7):
  arm64/gcs: task_gcs_el0_enable() should use passed task
  arm64: probes: Break ret out from bl/blr
  arm64: uaccess: Add additional userspace GCS accessors
  arm64: probes: Add GCS support to bl/blr/ret
  arm64: uprobes: Add GCS support to uretprobes
  arm64: Kconfig: Remove GCS restrictions on UPROBES
  uprobes: uprobe_warn should use passed task

 arch/arm64/Kconfig                       |  1 -
 arch/arm64/include/asm/gcs.h             |  2 +-
 arch/arm64/include/asm/uaccess.h         | 42 ++++++++++++++++++++++++
 arch/arm64/kernel/probes/decode-insn.c   |  7 ++--
 arch/arm64/kernel/probes/simulate-insn.c | 41 ++++++++++++++++++++---
 arch/arm64/kernel/probes/simulate-insn.h |  3 +-
 arch/arm64/kernel/probes/uprobes.c       | 30 +++++++++++++++++
 arch/arm64/kernel/process.c              |  6 ++--
 kernel/events/uprobes.c                  |  2 +-
 9 files changed, 119 insertions(+), 15 deletions(-)

-- 
2.49.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v3 1/7] arm64/gcs: task_gcs_el0_enable() should use passed task
  2025-05-04 23:31 [PATCH v3 0/7] arm64: Enable UPROBES with GCS Jeremy Linton
@ 2025-05-04 23:31 ` Jeremy Linton
  2025-05-04 23:31 ` [PATCH v3 2/7] arm64: probes: Break ret out from bl/blr Jeremy Linton
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jeremy Linton @ 2025-05-04 23:31 UTC (permalink / raw)
  To: linux-trace-kernel
  Cc: linux-perf-users, mhiramat, oleg, peterz, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, thiago.bauermann, broonie, yury.khrustalev,
	kristina.martsenko, liaochang1, catalin.marinas, will,
	linux-arm-kernel, linux-kernel, Jeremy Linton

Mark Rutland noticed that the task parameter is ignored and
'current' is being used instead. Since this is usually
what its passed, it hasn't yet been causing problems but likely
will as the code gets more testing.

But, once this is fixed, it creates a new bug in copy_thread_gcs()
since the gcs_el_mode isn't yet set for the task before its being
checked. Move gcs_alloc_thread_stack() after the new task's
gcs_el0_mode initialization to avoid this.

Fixes: fc84bc5378a8 ("arm64/gcs: Context switch GCS state for EL0")
Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
---
 arch/arm64/include/asm/gcs.h | 2 +-
 arch/arm64/kernel/process.c  | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/gcs.h b/arch/arm64/include/asm/gcs.h
index f50660603ecf..5bc432234d3a 100644
--- a/arch/arm64/include/asm/gcs.h
+++ b/arch/arm64/include/asm/gcs.h
@@ -58,7 +58,7 @@ static inline u64 gcsss2(void)
 
 static inline bool task_gcs_el0_enabled(struct task_struct *task)
 {
-	return current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE;
+	return task->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE;
 }
 
 void gcs_set_el0_mode(struct task_struct *task);
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 42faebb7b712..68b7021cda77 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -305,13 +305,13 @@ static int copy_thread_gcs(struct task_struct *p,
 	p->thread.gcs_base = 0;
 	p->thread.gcs_size = 0;
 
+	p->thread.gcs_el0_mode = current->thread.gcs_el0_mode;
+	p->thread.gcs_el0_locked = current->thread.gcs_el0_locked;
+
 	gcs = gcs_alloc_thread_stack(p, args);
 	if (IS_ERR_VALUE(gcs))
 		return PTR_ERR((void *)gcs);
 
-	p->thread.gcs_el0_mode = current->thread.gcs_el0_mode;
-	p->thread.gcs_el0_locked = current->thread.gcs_el0_locked;
-
 	return 0;
 }
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 2/7] arm64: probes: Break ret out from bl/blr
  2025-05-04 23:31 [PATCH v3 0/7] arm64: Enable UPROBES with GCS Jeremy Linton
  2025-05-04 23:31 ` [PATCH v3 1/7] arm64/gcs: task_gcs_el0_enable() should use passed task Jeremy Linton
@ 2025-05-04 23:31 ` Jeremy Linton
  2025-05-04 23:31 ` [PATCH v3 3/7] arm64: uaccess: Add additional userspace GCS accessors Jeremy Linton
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jeremy Linton @ 2025-05-04 23:31 UTC (permalink / raw)
  To: linux-trace-kernel
  Cc: linux-perf-users, mhiramat, oleg, peterz, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, thiago.bauermann, broonie, yury.khrustalev,
	kristina.martsenko, liaochang1, catalin.marinas, will,
	linux-arm-kernel, linux-kernel, Jeremy Linton

Prepare for GCS by breaking RET out into its own function, where
it makes more sense to encapsulate the new behavior independent
from the branch instructions.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/kernel/probes/decode-insn.c   |  7 ++++---
 arch/arm64/kernel/probes/simulate-insn.c | 10 +++++++++-
 arch/arm64/kernel/probes/simulate-insn.h |  3 ++-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kernel/probes/decode-insn.c b/arch/arm64/kernel/probes/decode-insn.c
index 6438bf62e753..4137cc5ef031 100644
--- a/arch/arm64/kernel/probes/decode-insn.c
+++ b/arch/arm64/kernel/probes/decode-insn.c
@@ -108,9 +108,10 @@ arm_probe_decode_insn(u32 insn, struct arch_probe_insn *api)
 	    aarch64_insn_is_bl(insn)) {
 		api->handler = simulate_b_bl;
 	} else if (aarch64_insn_is_br(insn) ||
-	    aarch64_insn_is_blr(insn) ||
-	    aarch64_insn_is_ret(insn)) {
-		api->handler = simulate_br_blr_ret;
+		aarch64_insn_is_blr(insn)) {
+		api->handler = simulate_br_blr;
+	} else if (aarch64_insn_is_ret(insn)) {
+		api->handler = simulate_ret;
 	} else {
 		/*
 		 * Instruction cannot be stepped out-of-line and we don't
diff --git a/arch/arm64/kernel/probes/simulate-insn.c b/arch/arm64/kernel/probes/simulate-insn.c
index 4c6d2d712fbd..09a0b36122d0 100644
--- a/arch/arm64/kernel/probes/simulate-insn.c
+++ b/arch/arm64/kernel/probes/simulate-insn.c
@@ -126,7 +126,7 @@ simulate_b_cond(u32 opcode, long addr, struct pt_regs *regs)
 }
 
 void __kprobes
-simulate_br_blr_ret(u32 opcode, long addr, struct pt_regs *regs)
+simulate_br_blr(u32 opcode, long addr, struct pt_regs *regs)
 {
 	int xn = (opcode >> 5) & 0x1f;
 
@@ -138,6 +138,14 @@ simulate_br_blr_ret(u32 opcode, long addr, struct pt_regs *regs)
 		set_x_reg(regs, 30, addr + 4);
 }
 
+void __kprobes
+simulate_ret(u32 opcode, long addr, struct pt_regs *regs)
+{
+	int xn = (opcode >> 5) & 0x1f;
+
+	instruction_pointer_set(regs, get_x_reg(regs, xn));
+}
+
 void __kprobes
 simulate_cbz_cbnz(u32 opcode, long addr, struct pt_regs *regs)
 {
diff --git a/arch/arm64/kernel/probes/simulate-insn.h b/arch/arm64/kernel/probes/simulate-insn.h
index efb2803ec943..9e772a292d56 100644
--- a/arch/arm64/kernel/probes/simulate-insn.h
+++ b/arch/arm64/kernel/probes/simulate-insn.h
@@ -11,7 +11,8 @@
 void simulate_adr_adrp(u32 opcode, long addr, struct pt_regs *regs);
 void simulate_b_bl(u32 opcode, long addr, struct pt_regs *regs);
 void simulate_b_cond(u32 opcode, long addr, struct pt_regs *regs);
-void simulate_br_blr_ret(u32 opcode, long addr, struct pt_regs *regs);
+void simulate_br_blr(u32 opcode, long addr, struct pt_regs *regs);
+void simulate_ret(u32 opcode, long addr, struct pt_regs *regs);
 void simulate_cbz_cbnz(u32 opcode, long addr, struct pt_regs *regs);
 void simulate_tbz_tbnz(u32 opcode, long addr, struct pt_regs *regs);
 void simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 3/7] arm64: uaccess: Add additional userspace GCS accessors
  2025-05-04 23:31 [PATCH v3 0/7] arm64: Enable UPROBES with GCS Jeremy Linton
  2025-05-04 23:31 ` [PATCH v3 1/7] arm64/gcs: task_gcs_el0_enable() should use passed task Jeremy Linton
  2025-05-04 23:31 ` [PATCH v3 2/7] arm64: probes: Break ret out from bl/blr Jeremy Linton
@ 2025-05-04 23:31 ` Jeremy Linton
  2025-05-04 23:32 ` [PATCH v3 4/7] arm64: probes: Add GCS support to bl/blr/ret Jeremy Linton
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Jeremy Linton @ 2025-05-04 23:31 UTC (permalink / raw)
  To: linux-trace-kernel
  Cc: linux-perf-users, mhiramat, oleg, peterz, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, thiago.bauermann, broonie, yury.khrustalev,
	kristina.martsenko, liaochang1, catalin.marinas, will,
	linux-arm-kernel, linux-kernel, Jeremy Linton

Uprobes need more advanced read, push, and pop userspace GCS
functionality. Implement those features using the existing gcsstr()
and copy_from_user().

Its important to note that GCS pages can be read by normal
instructions, but the hardware validates that pages used by GCS
specific operations, have a GCS privilege set. We aren't validating this
in load_user_gcs because it requires stabilizing the VMA over the read
which may fault.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/include/asm/uaccess.h | 42 ++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 5b91803201ef..34a8b2cc8935 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -20,6 +20,7 @@
 
 #include <asm/asm-extable.h>
 #include <asm/cpufeature.h>
+#include <asm/gcs.h>
 #include <asm/mmu.h>
 #include <asm/mte.h>
 #include <asm/ptrace.h>
@@ -539,6 +540,47 @@ static inline void put_user_gcs(unsigned long val, unsigned long __user *addr,
 	uaccess_ttbr0_disable();
 }
 
+static __always_inline unsigned long __must_check
+copy_from_user(void *to, const void __user *from, unsigned long n);
+
+/*
+ * Unlike put_user_gcs() above, the use of copy_from_user() may provide
+ * an opening for non GCS pages to be used to source data. Therefore this
+ * should only be used in contexts where that is acceptable.
+ */
+static inline u64 load_user_gcs(unsigned long __user *addr, int *err)
+{
+	unsigned long ret;
+	u64 load = 0;
+
+	gcsb_dsync();
+	ret = copy_from_user(&load, addr, sizeof(load));
+	if (ret != 0)
+		*err = ret;
+	return load;
+}
+
+static inline void push_user_gcs(unsigned long val, int *err)
+{
+	u64 gcspr = read_sysreg_s(SYS_GCSPR_EL0);
+
+	gcspr -= sizeof(u64);
+	put_user_gcs(val, (unsigned long __user *)gcspr, err);
+	if (!*err)
+		write_sysreg_s(gcspr, SYS_GCSPR_EL0);
+}
+
+static inline u64 pop_user_gcs(int *err)
+{
+	u64 gcspr = read_sysreg_s(SYS_GCSPR_EL0);
+	u64 read_val;
+
+	read_val = load_user_gcs((unsigned long __user *)gcspr, err);
+	if (!*err)
+		write_sysreg_s(gcspr + sizeof(u64), SYS_GCSPR_EL0);
+
+	return read_val;
+}
 
 #endif /* CONFIG_ARM64_GCS */
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 4/7] arm64: probes: Add GCS support to bl/blr/ret
  2025-05-04 23:31 [PATCH v3 0/7] arm64: Enable UPROBES with GCS Jeremy Linton
                   ` (2 preceding siblings ...)
  2025-05-04 23:31 ` [PATCH v3 3/7] arm64: uaccess: Add additional userspace GCS accessors Jeremy Linton
@ 2025-05-04 23:32 ` Jeremy Linton
  2025-05-09 11:56   ` kernel test robot
  2025-05-04 23:32 ` [PATCH v3 5/7] arm64: uprobes: Add GCS support to uretprobes Jeremy Linton
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 9+ messages in thread
From: Jeremy Linton @ 2025-05-04 23:32 UTC (permalink / raw)
  To: linux-trace-kernel
  Cc: linux-perf-users, mhiramat, oleg, peterz, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, thiago.bauermann, broonie, yury.khrustalev,
	kristina.martsenko, liaochang1, catalin.marinas, will,
	linux-arm-kernel, linux-kernel, Jeremy Linton

The arm64 probe simulation doesn't currently have logic in place
to deal with GCS and this results in core dumps if probes are inserted
at control flow locations. Fix-up bl, blr and ret to manipulate the
shadow stack as needed.

While we manipulate and validate the shadow stack correctly, the
hardware provides additional security by only allowing GCS operations
against pages which are marked to support GCS. For writing there is
gcssttr() which enforces this, but there isn't an equivalent for
reading. This means that uprobe users should be aware that probing on
control flow instructions which require reading the shadow stack (ex:
ret) offers lower security guarantees than what is achieved without
the uprobe active.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/kernel/probes/simulate-insn.c | 35 ++++++++++++++++++++----
 1 file changed, 29 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kernel/probes/simulate-insn.c b/arch/arm64/kernel/probes/simulate-insn.c
index 09a0b36122d0..c75dce7bbe13 100644
--- a/arch/arm64/kernel/probes/simulate-insn.c
+++ b/arch/arm64/kernel/probes/simulate-insn.c
@@ -13,6 +13,7 @@
 #include <asm/traps.h>
 
 #include "simulate-insn.h"
+#include "asm/gcs.h"
 
 #define bbl_displacement(insn)		\
 	sign_extend32(((insn) & 0x3ffffff) << 2, 27)
@@ -49,6 +50,20 @@ static inline u32 get_w_reg(struct pt_regs *regs, int reg)
 	return lower_32_bits(pt_regs_read_reg(regs, reg));
 }
 
+static inline void update_lr(struct pt_regs *regs, long addr)
+{
+	int err = 0;
+
+	if (user_mode(regs) && task_gcs_el0_enabled(current)) {
+		push_user_gcs(addr + 4,	 &err);
+		if (err) {
+			force_sig(SIGSEGV);
+			return;
+		}
+	}
+	procedure_link_pointer_set(regs, addr + 4);
+}
+
 static bool __kprobes check_cbz(u32 opcode, struct pt_regs *regs)
 {
 	int xn = opcode & 0x1f;
@@ -107,9 +122,8 @@ simulate_b_bl(u32 opcode, long addr, struct pt_regs *regs)
 {
 	int disp = bbl_displacement(opcode);
 
-	/* Link register is x30 */
 	if (opcode & (1 << 31))
-		set_x_reg(regs, 30, addr + 4);
+		update_lr(regs, addr);
 
 	instruction_pointer_set(regs, addr + disp);
 }
@@ -133,17 +147,26 @@ simulate_br_blr(u32 opcode, long addr, struct pt_regs *regs)
 	/* update pc first in case we're doing a "blr lr" */
 	instruction_pointer_set(regs, get_x_reg(regs, xn));
 
-	/* Link register is x30 */
 	if (((opcode >> 21) & 0x3) == 1)
-		set_x_reg(regs, 30, addr + 4);
+		update_lr(regs, addr);
 }
 
 void __kprobes
 simulate_ret(u32 opcode, long addr, struct pt_regs *regs)
 {
-	int xn = (opcode >> 5) & 0x1f;
+	u64 ret_addr;
+	int err = 0;
+	unsigned long lr = procedure_link_pointer(regs);
 
-	instruction_pointer_set(regs, get_x_reg(regs, xn));
+	if (user_mode(regs) && task_gcs_el0_enabled(current)) {
+		ret_addr = pop_user_gcs(&err);
+		if (err || ret_addr != lr) {
+			force_sig(SIGSEGV);
+			return;
+		}
+	}
+
+	instruction_pointer_set(regs, lr);
 }
 
 void __kprobes
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 5/7] arm64: uprobes: Add GCS support to uretprobes
  2025-05-04 23:31 [PATCH v3 0/7] arm64: Enable UPROBES with GCS Jeremy Linton
                   ` (3 preceding siblings ...)
  2025-05-04 23:32 ` [PATCH v3 4/7] arm64: probes: Add GCS support to bl/blr/ret Jeremy Linton
@ 2025-05-04 23:32 ` Jeremy Linton
  2025-05-04 23:32 ` [PATCH v3 6/7] arm64: Kconfig: Remove GCS restrictions on UPROBES Jeremy Linton
  2025-05-04 23:32 ` [PATCH v3 7/7] uprobes: uprobe_warn should use passed task Jeremy Linton
  6 siblings, 0 replies; 9+ messages in thread
From: Jeremy Linton @ 2025-05-04 23:32 UTC (permalink / raw)
  To: linux-trace-kernel
  Cc: linux-perf-users, mhiramat, oleg, peterz, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, thiago.bauermann, broonie, yury.khrustalev,
	kristina.martsenko, liaochang1, catalin.marinas, will,
	linux-arm-kernel, linux-kernel, Jeremy Linton, Steve Capper

Ret probes work by changing the value in the link register at
the probe location to return to the probe rather than the calling
routine. Thus the GCS needs to be updated with this address as well.

Since its possible to insert probes at locations where the
current value of the LR doesn't match the GCS state this needs
to be detected and handled in order to maintain the existing
no-fault behavior.

Co-developed-by: Steve Capper <steve.capper@arm.com>
Signed-off-by: Steve Capper <steve.capper@arm.com>
(updated to use new gcs accessors, and handle LR/GCS mismatches)
Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/kernel/probes/uprobes.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c
index cb3d05af36e3..5e72409a255a 100644
--- a/arch/arm64/kernel/probes/uprobes.c
+++ b/arch/arm64/kernel/probes/uprobes.c
@@ -159,11 +159,41 @@ arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
 				  struct pt_regs *regs)
 {
 	unsigned long orig_ret_vaddr;
+	unsigned long gcs_ret_vaddr;
+	int err = 0;
+	u64 gcspr;
 
 	orig_ret_vaddr = procedure_link_pointer(regs);
+
+	if (task_gcs_el0_enabled(current)) {
+		gcspr = read_sysreg_s(SYS_GCSPR_EL0);
+		gcs_ret_vaddr = load_user_gcs((unsigned long __user *)gcspr, &err);
+		if (err) {
+			force_sig(SIGSEGV);
+			goto out;
+		}
+		/*
+		 * If the LR and GCS entry don't match, then some kind of PAC/control
+		 * flow happened. Likely because the user is attempting to retprobe
+		 * on something that isn't a function boundary or inside a leaf
+		 * function. Explicitly abort this retprobe because it will generate
+		 * a GCS exception.
+		 */
+		if (gcs_ret_vaddr != orig_ret_vaddr)	{
+			orig_ret_vaddr = -1;
+			goto out;
+		}
+		put_user_gcs(trampoline_vaddr, (unsigned long __user *) gcspr, &err);
+		if (err) {
+			force_sig(SIGSEGV);
+			goto out;
+		}
+	}
+
 	/* Replace the return addr with trampoline addr */
 	procedure_link_pointer_set(regs, trampoline_vaddr);
 
+out:
 	return orig_ret_vaddr;
 }
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 6/7] arm64: Kconfig: Remove GCS restrictions on UPROBES
  2025-05-04 23:31 [PATCH v3 0/7] arm64: Enable UPROBES with GCS Jeremy Linton
                   ` (4 preceding siblings ...)
  2025-05-04 23:32 ` [PATCH v3 5/7] arm64: uprobes: Add GCS support to uretprobes Jeremy Linton
@ 2025-05-04 23:32 ` Jeremy Linton
  2025-05-04 23:32 ` [PATCH v3 7/7] uprobes: uprobe_warn should use passed task Jeremy Linton
  6 siblings, 0 replies; 9+ messages in thread
From: Jeremy Linton @ 2025-05-04 23:32 UTC (permalink / raw)
  To: linux-trace-kernel
  Cc: linux-perf-users, mhiramat, oleg, peterz, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, thiago.bauermann, broonie, yury.khrustalev,
	kristina.martsenko, liaochang1, catalin.marinas, will,
	linux-arm-kernel, linux-kernel, Jeremy Linton

Now that the uprobe paths have been made GCS compatible
drop the Kconfig restriction.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index a182295e6f08..b962a1321ebf 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2236,7 +2236,6 @@ config ARM64_GCS
 	default y
 	select ARCH_HAS_USER_SHADOW_STACK
 	select ARCH_USES_HIGH_VMA_FLAGS
-	depends on !UPROBES
 	help
 	  Guarded Control Stack (GCS) provides support for a separate
 	  stack with restricted access which contains only return
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v3 7/7] uprobes: uprobe_warn should use passed task
  2025-05-04 23:31 [PATCH v3 0/7] arm64: Enable UPROBES with GCS Jeremy Linton
                   ` (5 preceding siblings ...)
  2025-05-04 23:32 ` [PATCH v3 6/7] arm64: Kconfig: Remove GCS restrictions on UPROBES Jeremy Linton
@ 2025-05-04 23:32 ` Jeremy Linton
  6 siblings, 0 replies; 9+ messages in thread
From: Jeremy Linton @ 2025-05-04 23:32 UTC (permalink / raw)
  To: linux-trace-kernel
  Cc: linux-perf-users, mhiramat, oleg, peterz, acme, namhyung,
	mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	kan.liang, thiago.bauermann, broonie, yury.khrustalev,
	kristina.martsenko, liaochang1, catalin.marinas, will,
	linux-arm-kernel, linux-kernel, Jeremy Linton

uprobe_warn() is passed a task structure, yet its using current. For
the most part this shouldn't matter, but since a task structure is
provided, lets use it.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 kernel/events/uprobes.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 8d783b5882b6..6552d9815292 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -120,7 +120,7 @@ struct xol_area {
 
 static void uprobe_warn(struct task_struct *t, const char *msg)
 {
-	pr_warn("uprobe: %s:%d failed to %s\n", current->comm, current->pid, msg);
+	pr_warn("uprobe: %s:%d failed to %s\n", t->comm, t->pid, msg);
 }
 
 /*
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v3 4/7] arm64: probes: Add GCS support to bl/blr/ret
  2025-05-04 23:32 ` [PATCH v3 4/7] arm64: probes: Add GCS support to bl/blr/ret Jeremy Linton
@ 2025-05-09 11:56   ` kernel test robot
  0 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2025-05-09 11:56 UTC (permalink / raw)
  To: Jeremy Linton, linux-trace-kernel
  Cc: oe-kbuild-all, linux-perf-users, mhiramat, oleg, peterz, acme,
	namhyung, mark.rutland, alexander.shishkin, jolsa, irogers,
	adrian.hunter, kan.liang, thiago.bauermann, broonie,
	yury.khrustalev, kristina.martsenko, liaochang1, catalin.marinas,
	will, linux-arm-kernel, linux-kernel, Jeremy Linton

Hi Jeremy,

kernel test robot noticed the following build errors:

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on perf-tools-next/perf-tools-next tip/perf/core perf-tools/perf-tools linus/master v6.15-rc5 next-20250508]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Jeremy-Linton/arm64-gcs-task_gcs_el0_enable-should-use-passed-task/20250505-122838
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20250504233203.616587-5-jeremy.linton%40arm.com
patch subject: [PATCH v3 4/7] arm64: probes: Add GCS support to bl/blr/ret
config: arm64-randconfig-001-20250509 (https://download.01.org/0day-ci/archive/20250509/202505091926.PBPRfjKb-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 7.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250509/202505091926.PBPRfjKb-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505091926.PBPRfjKb-lkp@intel.com/

All errors (new ones prefixed by >>):

   arch/arm64/kernel/probes/simulate-insn.c: In function 'update_lr':
>> arch/arm64/kernel/probes/simulate-insn.c:58:3: error: implicit declaration of function 'push_user_gcs'; did you mean 'task_user_tls'? [-Werror=implicit-function-declaration]
      push_user_gcs(addr + 4,  &err);
      ^~~~~~~~~~~~~
      task_user_tls
   arch/arm64/kernel/probes/simulate-insn.c: In function 'simulate_ret':
>> arch/arm64/kernel/probes/simulate-insn.c:162:14: error: implicit declaration of function 'pop_user_gcs'; did you mean 'pin_user_pages'? [-Werror=implicit-function-declaration]
      ret_addr = pop_user_gcs(&err);
                 ^~~~~~~~~~~~
                 pin_user_pages
   cc1: some warnings being treated as errors


vim +58 arch/arm64/kernel/probes/simulate-insn.c

    52	
    53	static inline void update_lr(struct pt_regs *regs, long addr)
    54	{
    55		int err = 0;
    56	
    57		if (user_mode(regs) && task_gcs_el0_enabled(current)) {
  > 58			push_user_gcs(addr + 4,	 &err);
    59			if (err) {
    60				force_sig(SIGSEGV);
    61				return;
    62			}
    63		}
    64		procedure_link_pointer_set(regs, addr + 4);
    65	}
    66	
    67	static bool __kprobes check_cbz(u32 opcode, struct pt_regs *regs)
    68	{
    69		int xn = opcode & 0x1f;
    70	
    71		return (opcode & (1 << 31)) ?
    72		    (get_x_reg(regs, xn) == 0) : (get_w_reg(regs, xn) == 0);
    73	}
    74	
    75	static bool __kprobes check_cbnz(u32 opcode, struct pt_regs *regs)
    76	{
    77		int xn = opcode & 0x1f;
    78	
    79		return (opcode & (1 << 31)) ?
    80		    (get_x_reg(regs, xn) != 0) : (get_w_reg(regs, xn) != 0);
    81	}
    82	
    83	static bool __kprobes check_tbz(u32 opcode, struct pt_regs *regs)
    84	{
    85		int xn = opcode & 0x1f;
    86		int bit_pos = ((opcode & (1 << 31)) >> 26) | ((opcode >> 19) & 0x1f);
    87	
    88		return ((get_x_reg(regs, xn) >> bit_pos) & 0x1) == 0;
    89	}
    90	
    91	static bool __kprobes check_tbnz(u32 opcode, struct pt_regs *regs)
    92	{
    93		int xn = opcode & 0x1f;
    94		int bit_pos = ((opcode & (1 << 31)) >> 26) | ((opcode >> 19) & 0x1f);
    95	
    96		return ((get_x_reg(regs, xn) >> bit_pos) & 0x1) != 0;
    97	}
    98	
    99	/*
   100	 * instruction simulation functions
   101	 */
   102	void __kprobes
   103	simulate_adr_adrp(u32 opcode, long addr, struct pt_regs *regs)
   104	{
   105		long imm, xn, val;
   106	
   107		xn = opcode & 0x1f;
   108		imm = ((opcode >> 3) & 0x1ffffc) | ((opcode >> 29) & 0x3);
   109		imm = sign_extend64(imm, 20);
   110		if (opcode & 0x80000000)
   111			val = (imm<<12) + (addr & 0xfffffffffffff000);
   112		else
   113			val = imm + addr;
   114	
   115		set_x_reg(regs, xn, val);
   116	
   117		instruction_pointer_set(regs, instruction_pointer(regs) + 4);
   118	}
   119	
   120	void __kprobes
   121	simulate_b_bl(u32 opcode, long addr, struct pt_regs *regs)
   122	{
   123		int disp = bbl_displacement(opcode);
   124	
   125		if (opcode & (1 << 31))
   126			update_lr(regs, addr);
   127	
   128		instruction_pointer_set(regs, addr + disp);
   129	}
   130	
   131	void __kprobes
   132	simulate_b_cond(u32 opcode, long addr, struct pt_regs *regs)
   133	{
   134		int disp = 4;
   135	
   136		if (aarch32_opcode_cond_checks[opcode & 0xf](regs->pstate & 0xffffffff))
   137			disp = bcond_displacement(opcode);
   138	
   139		instruction_pointer_set(regs, addr + disp);
   140	}
   141	
   142	void __kprobes
   143	simulate_br_blr(u32 opcode, long addr, struct pt_regs *regs)
   144	{
   145		int xn = (opcode >> 5) & 0x1f;
   146	
   147		/* update pc first in case we're doing a "blr lr" */
   148		instruction_pointer_set(regs, get_x_reg(regs, xn));
   149	
   150		if (((opcode >> 21) & 0x3) == 1)
   151			update_lr(regs, addr);
   152	}
   153	
   154	void __kprobes
   155	simulate_ret(u32 opcode, long addr, struct pt_regs *regs)
   156	{
   157		u64 ret_addr;
   158		int err = 0;
   159		unsigned long lr = procedure_link_pointer(regs);
   160	
   161		if (user_mode(regs) && task_gcs_el0_enabled(current)) {
 > 162			ret_addr = pop_user_gcs(&err);
   163			if (err || ret_addr != lr) {
   164				force_sig(SIGSEGV);
   165				return;
   166			}
   167		}
   168	
   169		instruction_pointer_set(regs, lr);
   170	}
   171	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-05-09 11:57 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-04 23:31 [PATCH v3 0/7] arm64: Enable UPROBES with GCS Jeremy Linton
2025-05-04 23:31 ` [PATCH v3 1/7] arm64/gcs: task_gcs_el0_enable() should use passed task Jeremy Linton
2025-05-04 23:31 ` [PATCH v3 2/7] arm64: probes: Break ret out from bl/blr Jeremy Linton
2025-05-04 23:31 ` [PATCH v3 3/7] arm64: uaccess: Add additional userspace GCS accessors Jeremy Linton
2025-05-04 23:32 ` [PATCH v3 4/7] arm64: probes: Add GCS support to bl/blr/ret Jeremy Linton
2025-05-09 11:56   ` kernel test robot
2025-05-04 23:32 ` [PATCH v3 5/7] arm64: uprobes: Add GCS support to uretprobes Jeremy Linton
2025-05-04 23:32 ` [PATCH v3 6/7] arm64: Kconfig: Remove GCS restrictions on UPROBES Jeremy Linton
2025-05-04 23:32 ` [PATCH v3 7/7] uprobes: uprobe_warn should use passed task Jeremy Linton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).