On Fri, Jul 18, 2025 at 11:37:38PM -0500, Jeremy Linton wrote: > @@ -159,11 +160,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; > + }
Nit: add an empty line here, I find it easier to read. > + /* > + * 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 I don't full get the first sentence. > + * 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; > + } Nit: another empty line here. > + put_user_gcs(trampoline_vaddr, (unsigned long __user *) gcspr, > &err); Nit: (... *)gcspr (no space after cast). > + 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; > } Reviewed-by: Catalin Marinas <catalin.mari...@arm.com>