From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7F51D3EDE60 for ; Wed, 1 Jul 2026 08:47:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782895671; cv=none; b=aJv7IOg4thqA4TouJO5KT/O/eH0FZHBP1U+ibdbKabhXjPJWvpSDLe5uPqi7PhZVJY4OGDlpzaHlpOPibUle1fTmPMHPLbS9b3A4Mn7vFe61kiDPsIE0FAk9MZyRlbLW5sMP82dBWNhGl71gWvv4TkXbH71iLaWL5WHQFckExEQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782895671; c=relaxed/simple; bh=w3pBCXjVMeki7Wa4icahZC8zG9Ej/FE71V+26Ug4VuY=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=kXLWeqLmlaRHIuF9eXRSlpx6tI1XsEaANy1jbg2DFD7LU4TNZhPwk0Zxs/jApPlTC8/qEfTJmfMhIrPC5oMcN0BubgrCRRH/K8QW1KR07ApA6uDdEWQpeGatD01/ZPJUICglhwj6hvea8GLeDMNqvsk8J42v5N2bbF1ojTwzZag= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=oijyqhpi; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="oijyqhpi" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3D6822364; Wed, 1 Jul 2026 01:47:44 -0700 (PDT) Received: from arm.com (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8DF533F85F; Wed, 1 Jul 2026 01:47:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1782895668; bh=w3pBCXjVMeki7Wa4icahZC8zG9Ej/FE71V+26Ug4VuY=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=oijyqhpiZolrj8beTQeecoSA0zspbl1mvtV57Ym/R4K+prPzDiGdBChIczbjcUaVV WrH9IXcx+TGFctE2AL5iKqnbDmSN5YsUBHGNi/t0TPwAWvtSKU7gFST9T4r0jQRS0P m2y/NYpIM86KyPvJ2VzEms1bntoWqq4kbJi9pZ6k= Date: Wed, 1 Jul 2026 09:47:46 +0100 From: Catalin Marinas To: Will Deacon Cc: Yiqi Sun , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, rmk+kernel@armlinux.org.uk, ruanjinjie@huawei.com, kees@kernel.org, mark.rutland@arm.com Subject: Re: [PATCH v2] arm64: ptrace: use live x0 for seccomp and audit after ptrace Message-ID: References: <20260529065444.1336608-1-sunyiqixm@gmail.com> <2f435bab0d61d0bf8fbaa54203525aae8e8f5371.1782384161.git.sunyiqixm@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: On Tue, Jun 30, 2026 at 06:29:29PM +0100, Catalin Marinas wrote: > I think we need to keep orig_x0 as our original arg0 throughout the > kernel and just fix the tracer path to sync it on the syscall entry. It > doesn't unclutter the code but it shouldn't break the ABI either (unless > someone relied on the ptrace change x0 and not being noticed by > seccomp). Something like below: > > ----------------8<----------------------------- > diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c > index 4d08598e2891..cd21b301e154 100644 > --- a/arch/arm64/kernel/ptrace.c > +++ b/arch/arm64/kernel/ptrace.c > @@ -2417,6 +2417,18 @@ int syscall_trace_enter(struct pt_regs *regs) > ret = report_syscall_entry(regs); > if (ret || (flags & _TIF_SYSCALL_EMU)) > return NO_SYSCALL; > + /* > + * Keep orig_x0 authoritative so that seccomp (via > + * syscall_get_arguments()), audit and the restart path all > + * see the same first argument the syscall is dispatched with, > + * even if it has been updated by a tracer. Skip this for > + * NO_SYSCALL (set either by the user or the tracer) as > + * regs[0] holds the return value (see the comment in > + * el0_svc_common()). For compat, orig_r0 is provided directly > + * through GPR index 17. > + */ > + if (!is_compat_task() && regs->syscallno != NO_SYSCALL) > + regs->orig_x0 = regs->regs[0]; > } > > /* Do the secure computing after ptrace; failures should be fast. */ > ----------------8<----------------------------- > > If we want to change the ABI, we could do like riscv and only set the > arguments via PTRACE_SET_SYSCALL_INFO while the GPR ptrace accesses > whatever is in regs[0] - either the original arg or the return value. I > think they changed this inadvertently in 2023 when they moved to the > generic syscall. Looking at some of the history, the ABI break on riscv was noticed, so definitely not an option for us. I think the change would have looked something like below. We could keep regs[0] match orig_x0 for entry but it gets out of sync later, so still confusing for gdb/lldb/strace. ---------------8<---------------------- diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h index 5e4c7fc44f73..c58ac8d25692 100644 --- a/arch/arm64/include/asm/syscall.h +++ b/arch/arm64/include/asm/syscall.h @@ -93,19 +93,12 @@ static inline void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, const unsigned long *args) { - regs->regs[0] = args[0]; + regs->orig_x0 = args[0]; regs->regs[1] = args[1]; regs->regs[2] = args[2]; regs->regs[3] = args[3]; regs->regs[4] = args[4]; regs->regs[5] = args[5]; - - /* - * Also copy the first argument into orig_x0 - * so that syscall_get_arguments() would return it - * instead of the previous value. - */ - regs->orig_x0 = regs->regs[0]; } /* diff --git a/arch/arm64/include/asm/syscall_wrapper.h b/arch/arm64/include/asm/syscall_wrapper.h index abb57bc54305..6b13d7c8ad95 100644 --- a/arch/arm64/include/asm/syscall_wrapper.h +++ b/arch/arm64/include/asm/syscall_wrapper.h @@ -12,7 +12,7 @@ #define SC_ARM64_REGS_TO_ARGS(x, ...) \ __MAP(x,__SC_ARGS \ - ,,regs->regs[0],,regs->regs[1],,regs->regs[2] \ + ,,regs->orig_x0,,regs->regs[1],,regs->regs[2] \ ,,regs->regs[3],,regs->regs[4],,regs->regs[5]) #ifdef CONFIG_COMPAT diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index 358ddfbf1401..a80596531a5c 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -66,6 +66,7 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, regs->orig_x0 = regs->regs[0]; regs->syscallno = scno; + syscall_set_return_value(current, regs, -ENOSYS, 0); /* * BTI note: @@ -111,8 +112,6 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, * setting the return value is unlikely to do anything sensible * anyway. */ - if (scno == NO_SYSCALL) - syscall_set_return_value(current, regs, -ENOSYS, 0); scno = syscall_trace_enter(regs); if (scno == NO_SYSCALL) goto trace_exit; -- Catalin