Alpha arch development list
 help / color / mirror / Atom feed
From: Magnus Lindholm <linmag7@gmail.com>
To: richard.henderson@linaro.org, mattst88@gmail.com,
	linux-kernel@vger.kernel.org, linux-alpha@vger.kernel.org
Cc: linmag7@gmail.com
Subject: [PATCH 05/14] alpha: distinguish skipped syscalls from invalid numbers
Date: Tue,  3 Nov 2026 22:35:11 +0100	[thread overview]
Message-ID: <20261103214120.1099893-6-linmag7@gmail.com> (raw)
In-Reply-To: <20261103214120.1099893-1-linmag7@gmail.com>

An out-of-range syscall number other than -1 must return ENOSYS even
when a tracer has changed the return registers. Keep explicit results
only when entry work rejects dispatch or the number is the -1 abort
sentinel. The generic-entry conversion incorrectly treats both cases
as skipped calls and preserves tracer results for invalid numbers.

Track explicitly supplied r0 values instead of inferring them from
register contents. Alpha cannot preset its complete ENOSYS return state
before entry work because r19 is still argument 4. Value comparisons
can overwrite legitimate results, including -1, the original syscall
number and a seccomp errno matching the entry registers.

Mark results supplied by syscall_set_return_value(), scalar ptrace
result writes and regset writes covering r0. Keep number-only aborts
returning ENOSYS. After a legacy r0=-1 abort, subsequent r0 writes are
results, not another syscall-number substitution. Honor the supplied
r19 error flag for regsets instead of turning small successes into
errors. Writes outside r0 and empty regset writes must not mark it.

Preserve seccomp return values, SIGSYS rollback and saved restart
arguments. The existing per-syscall metadata reset prevents a supplied
result from carrying over to another syscall.

Fixes: 83bd31c2840b ("alpha: enable GENERIC_ENTRY")
Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
---
 arch/alpha/include/asm/syscall.h     |  2 +-
 arch/alpha/include/asm/thread_info.h |  1 +
 arch/alpha/kernel/ptrace.c           | 25 +++++++++---------------
 arch/alpha/kernel/signal.c           | 37 ++++++++----------------------------
 4 files changed, 19 insertions(+), 46 deletions(-)

diff --git a/arch/alpha/include/asm/syscall.h b/arch/alpha/include/asm/syscall.h
index 22315b932f854a71fd3babf6565dda443c6c7a77..52fa96ea57caba5f04c2c0c3d9ea31b909eb9f60 100644
--- a/arch/alpha/include/asm/syscall.h
+++ b/arch/alpha/include/asm/syscall.h
@@ -94,7 +94,7 @@ static inline void syscall_set_return_value(struct task_struct *task,
 					struct pt_regs *regs,
 					int error, long val)
 {
-
+	task_thread_info(task)->syscall_meta |= ALPHA_SYSCALL_META_RESULT;
 	if (error) {
 		/* error is negative errno in this tree */
 		regs->r0  = (unsigned long)(-error);  /* positive errno */
diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h
index 49bc08f3b5a98fbcb1d4ac919001bf70c3db614b..78f9f60d4ad197c27cd05bfd6a5c20af22bee7a3 100644
--- a/arch/alpha/include/asm/thread_info.h
+++ b/arch/alpha/include/asm/thread_info.h
@@ -58,6 +58,7 @@ register unsigned long *current_stack_pointer __asm__ ("$30");
 #define ALPHA_SYSCALL_META_SKIP			0x2
 #define ALPHA_SYSCALL_META_FORCE_SUCCESS	0x4
 #define ALPHA_SYSCALL_META_ROLLBACK		0x10
+#define ALPHA_SYSCALL_META_RESULT			0x20
 
 /*
  * Thread information flags:
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index dba7e9905cfa842dbfe851b3e6ab996c94f7ee46..08e2401cb7e005795a04e169f0c53cf9ed35adb5 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -280,21 +280,6 @@ static void alpha_elf_gregs_set(struct task_struct *child,
 
 	if (nwords > 32)
 		ti->pcb.unique = src[32];
-
-/*
- * PTRACE_SETREGSET can be used at a syscall-entry stop to skip the
- * syscall by setting the syscall number to -1.  The seccomp/ptrace
- * selftests use this to synthesize errno returns.
- *
- * Alpha uses r19/a3 as the error flag, so a skipped syscall with a
- * small positive r0 and a clear r19 must be normalized to an error
- * return.
- */
-	if (pt->r1 == (unsigned long)-1 &&
-	    pt->r19 == 0 &&
-	    pt->r0 > 0 &&
-	    pt->r0 < MAX_ERRNO)
-		pt->r19 = 1;
 }
 
 static int
@@ -328,7 +313,8 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
 	 * mutable syscall number in regs->r1.
 	 */
 
-	if (regno == 0 && regs->r1 == old_r0 &&
+	if (regno == 0 && regs->r1 != (unsigned long)-1 &&
+	    regs->r1 == old_r0 &&
 		(data == (unsigned long)-1 ||
 		(regs->r19 == 0 && data < NR_syscalls))) {
 		regs->r1 = data;
@@ -339,6 +325,9 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
 	 */
 		if (data == (unsigned long)-1)
 			regs->r19 = 0;
+	} else if (regno == 0) {
+		/* Once dispatch is cancelled, even -1 is a valid result. */
+		task_thread_info(task)->syscall_meta |= ALPHA_SYSCALL_META_RESULT;
 	}
 	return 0;
 }
@@ -535,6 +524,7 @@ static int alpha_regset_set(struct task_struct *target,
 {
 	elf_gregset_t gregs;
 	unsigned int nwords;
+	bool writes_r0 = count && pos < sizeof(elf_greg_t);
 
 	if (pos + count > sizeof(gregs))
 		return -EIO;
@@ -551,6 +541,9 @@ static int alpha_regset_set(struct task_struct *target,
 
 	nwords = sizeof(gregs) / sizeof(elf_greg_t);
 	alpha_elf_gregs_set(target, gregs, nwords);
+	/* Only count r0 bytes actually supplied, not the preserved registers. */
+	if (writes_r0)
+		task_thread_info(target)->syscall_meta |= ALPHA_SYSCALL_META_RESULT;
 
 	return 0;
 }
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index ab32affa09c41152eabd1f3be92a126a85fb7a2d..f972f690eb678b9201e340624a60fe26ad7f23c8 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -567,7 +567,6 @@ asmlinkage unsigned long
 alpha_syscall_enter_select(struct pt_regs *regs, long syscall)
 {
 	struct thread_info *ti = current_thread_info();
-	unsigned long saved_r0 = regs->r0;
 	unsigned long saved_r19 = regs->r19;
 	unsigned long fn = (unsigned long)sys_ni_syscall;
 	long nr = syscall;
@@ -584,22 +583,20 @@ alpha_syscall_enter_select(struct pt_regs *regs, long syscall)
 
 	permit = syscall_enter_from_user_mode_randomize_stack(regs, &nr);
 
-	/*
-	 * Alpha cannot preset the full -ENOSYS return state before generic
-	 * entry handling, because r19 is still syscall argument 4 on the
-	 * normal dispatch path. So provide the default -ENOSYS result only
-	 * here, after we know no real syscall will be invoked, and only if
-	 * entry work did not already change the return state.
-	 */
-	if (unlikely(!permit || (unsigned long)nr >= NR_syscalls)) {
-		if (!(ti->syscall_meta & ALPHA_SYSCALL_META_ROLLBACK) &&
-		    regs->r0 == saved_r0 && regs->r19 == saved_r19)
+	if (unlikely(!permit || nr == -1)) {
+		/* r19 is still argument 4 unless a hook supplied a result. */
+		if (!(ti->syscall_meta & (ALPHA_SYSCALL_META_RESULT |
+					 ALPHA_SYSCALL_META_ROLLBACK)))
 			syscall_set_return_value(current, regs, -ENOSYS, 0);
 
 		ti->syscall_meta |= ALPHA_SYSCALL_META_SKIP;
 		return fn;	/* ignored by asm when SKIP is set */
 	}
 
+	/* Invalid numbers other than -1 must invoke sys_ni_syscall(). */
+	if (unlikely((unsigned long)nr >= NR_syscalls))
+		return fn;
+
 	instrumentation_begin();
 	{
 		unsigned long index;
@@ -633,24 +630,6 @@ alpha_finish_syscall_to_user_mode(struct pt_regs *regs, long ret)
 	}
 
 	if (meta & ALPHA_SYSCALL_META_SKIP) {
-	/*
-	 * Skip-dispatch path: ptrace/seccomp may already have installed
-	 * the return state in r0/r19. Preserve it unless the syscall was
-	 * skipped with no explicit return value.
-	 *
-	 * Generic PTRACE_SET_SYSCALL_INFO changes only the syscall-number
-	 * shadow, so r1 == -1 while r0 still contains the original Alpha
-	 * syscall number. Legacy PTRACE_POKEUSR based skipping can leave
-	 * r0 == -1 with a3/r19 still indicating success. Both represent
-	 * an unhandled skipped syscall and should become ENOSYS/a3=1.
-	 */
-		if (regs->r1 == (unsigned long)-1 &&
-		   (regs->r0 == ti->syscall_saved_nr ||
-		    regs->r0 == (unsigned long)-1)) {
-			regs->r0 = ENOSYS;
-			regs->r19 = 1;
-		}
-
 		instrumentation_end();
 
 		syscall_exit_to_user_mode(regs);
-- 
2.43.0


  parent reply	other threads:[~2026-11-03 21:43 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-03 21:35 [PATCH 00/14] alpha: fix entry bugs and consolidate generic helpers Magnus Lindholm
2026-11-03 21:35 ` [PATCH 01/14] alpha: fix saved registers in page-fault oops dumps Magnus Lindholm
2026-11-03 21:35 ` [PATCH 02/14] alpha: report syscall errors correctly to audit Magnus Lindholm
2026-11-03 21:35 ` [PATCH 03/14] alpha: preserve rolled-back registers for SIGSYS Magnus Lindholm
2026-11-03 21:35 ` [PATCH 04/14] alpha: fix syscall restart eligibility Magnus Lindholm
2026-11-03 21:35 ` Magnus Lindholm [this message]
2026-11-03 21:35 ` [PATCH 06/14] alpha: dispatch system calls from C Magnus Lindholm
2026-11-03 21:35 ` [PATCH 07/14] alpha: use generic entry helpers for interrupts and exceptions Magnus Lindholm
2026-11-03 21:35 ` [PATCH 08/14] alpha: use generic syscall exit for new tasks Magnus Lindholm
2026-11-03 21:35 ` [PATCH 09/14] alpha: remove obsolete core dump register hooks Magnus Lindholm
2026-11-03 21:35 ` [PATCH 10/14] alpha: use generic syscall audit classification Magnus Lindholm
2026-11-03 21:35 ` [PATCH 11/14] alpha: use generic ptrace memory writes Magnus Lindholm
2026-11-03 21:35 ` [PATCH 12/14] alpha: use memparse for memory size options Magnus Lindholm
2026-11-03 21:35 ` [PATCH 13/14] alpha: use generic getrusage for OSF resource accounting Magnus Lindholm
2026-11-03 21:35 ` [PATCH 14/14] alpha: use generic CPU device registration Magnus Lindholm
2026-11-04 19:35 ` [PATCH 00/14] alpha: fix entry bugs and consolidate generic helpers Matt Turner

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=20261103214120.1099893-6-linmag7@gmail.com \
    --to=linmag7@gmail.com \
    --cc=linux-alpha@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mattst88@gmail.com \
    --cc=richard.henderson@linaro.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox