mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Linus Walleij <linus.walleij@linaro.org>
To: Dmitry Vyukov <dvyukov@google.com>,
	Oleg Nesterov <oleg@redhat.com>,
	 Russell King <linux@armlinux.org.uk>,
	Kees Cook <kees@kernel.org>,
	 Andy Lutomirski <luto@amacapital.net>,
	Will Drewry <wad@chromium.org>,
	 Frederic Weisbecker <frederic@kernel.org>,
	 "Paul E. McKenney" <paulmck@kernel.org>,
	 Jinjie Ruan <ruanjinjie@huawei.com>,
	Arnd Bergmann <arnd@arndb.de>,  Ard Biesheuvel <ardb@kernel.org>,
	Al Viro <viro@zeniv.linux.org.uk>
Cc: linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org,
	 Linus Walleij <linus.walleij@linaro.org>,
	 Thomas Gleixner <tglx@linutronix.de>
Subject: [PATCH v6 31/31] ARM: entry: Reimplement local restart in C
Date: Sun, 20 Apr 2025 00:36:18 +0200	[thread overview]
Message-ID: <20250420-arm-generic-entry-v6-31-95f1fcdfeeb2@linaro.org> (raw)
In-Reply-To: <20250420-arm-generic-entry-v6-0-95f1fcdfeeb2@linaro.org>

The former local restart hack to restart syscalls inside
the kernel if we get restart signals while processing a
system call was deleted when converting the architecture
to generic entry.

This makes strace tests fail so the hack is necessary.

Now, after the conversion to generic entry, restore the
order by reimplementing this with two TIF flags that
help us to issue system call restarts immediately in the
kernel.

This is essentially a reimplementation of commit 81783786d5cf
"ARM: 7473/1: deal with handlerless restarts without leaving
the kernel" from 2012, but in C, on top of generic entry.

Link: http://lists.infradead.org/pipermail/linux-arm-kernel/2012-June/104733.html
Link: https://lore.kernel.org/all/1340377626-17075-1-git-send-email-will.deacon@arm.com/
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/include/asm/thread_info.h |  4 ++++
 arch/arm/kernel/signal.c           | 17 +++++++++++++----
 arch/arm/kernel/syscall.c          | 22 ++++++++++++++++++++++
 3 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 84e58a9cdab63ad264c2cd2bad64239d1912cbe7..09dcaeef645a4ab45f40a14f8d7b46f408225f81 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -150,6 +150,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	19
+#define TIF_LOCAL_RESTART	20
+#define TIF_LOCAL_RESTART_BLOCK	21
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
@@ -157,6 +159,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp *,
 #define _TIF_UPROBE		(1 << TIF_UPROBE)
 #define _TIF_NOTIFY_SIGNAL	(1 << TIF_NOTIFY_SIGNAL)
 #define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
+#define _TIF_LOCAL_RESTART	(1 << TIF_LOCAL_RESTART)
+#define _TIF_LOCAL_RESTART_BLOCK (1 << TIF_LOCAL_RESTART_BLOCK)
 
 #define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
 				 _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 35d2bb3cd2b442dac164548037262e065fbfe12a..a4fc6522124fd3ac3df7149ba38cf4b097196e06 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -541,7 +541,8 @@ void arch_do_signal_or_restart(struct pt_regs *regs)
 	unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
 	bool syscall = (syscall_get_nr(current, regs) != -1);
 	struct ksignal ksig;
-	int restart = 0;
+	bool restart = false;
+	bool restart_block = false;
 
 	/*
 	 * If we were from a system call, check for system call restarting...
@@ -557,12 +558,12 @@ void arch_do_signal_or_restart(struct pt_regs *regs)
 		 */
 		switch (retval) {
 		case -ERESTART_RESTARTBLOCK:
-			restart -= 2;
+			restart_block = true;
 			fallthrough;
 		case -ERESTARTNOHAND:
 		case -ERESTARTSYS:
 		case -ERESTARTNOINTR:
-			restart++;
+			restart = true;
 			regs->ARM_r0 = regs->ARM_ORIG_r0;
 			regs->ARM_pc = restart_addr;
 			break;
@@ -593,8 +594,16 @@ void arch_do_signal_or_restart(struct pt_regs *regs)
 	} else {
 		/* no handler */
 		restore_saved_sigmask();
-		if (unlikely(restart) && regs->ARM_pc == restart_addr)
+		if (unlikely(restart) && regs->ARM_pc == restart_addr) {
+			/*
+			 * These flags will be picked up in the syscall invocation code,
+			 * and a local restart will be issued without exiting the kernel.
+			 */
+			set_thread_flag(TIF_LOCAL_RESTART);
+			if (restart_block)
+				set_thread_flag(TIF_LOCAL_RESTART_BLOCK);
 			regs->ARM_pc = continue_addr;
+		}
 	}
 	return;
 }
diff --git a/arch/arm/kernel/syscall.c b/arch/arm/kernel/syscall.c
index ed3ab51283c06c1398ece2ad3ee1fae16cd03ee8..20b59f5dfdc8d2e8c168ac04c2244cb6371e5672 100644
--- a/arch/arm/kernel/syscall.c
+++ b/arch/arm/kernel/syscall.c
@@ -11,6 +11,7 @@ __visible void invoke_syscall(void *table, struct pt_regs *regs, int scno)
 {
 	int ret;
 
+local_restart:
 	scno = syscall_enter_from_user_mode(regs, scno);
 	/* When tracing syscall -1 means "skip syscall" */
 	if (scno < 0) {
@@ -34,4 +35,25 @@ __visible void invoke_syscall(void *table, struct pt_regs *regs, int scno)
 	syscall_set_return_value(current, regs, 0, ret);
 
 	syscall_exit_to_user_mode(regs);
+
+	/*
+	 * Handle local restart: this means that when generic entry
+	 * calls arch_do_signal_or_restart() because a signal to
+	 * restart the syscall arrived while processing a system call,
+	 * we set these flags for the thread so that we don't even
+	 * exit the kernel, we just restart right here and clear
+	 * the restart condition.
+	 *
+	 * This is done because of signal race issues on ARM.
+	 */
+	if (test_thread_flag(TIF_LOCAL_RESTART)) {
+		if (test_thread_flag(TIF_LOCAL_RESTART_BLOCK)) {
+			scno = __NR_restart_syscall - __NR_SYSCALL_BASE;
+			/* Make this change visible to tracers */
+			task_thread_info(current)->abi_syscall = scno;
+			clear_thread_flag(TIF_LOCAL_RESTART_BLOCK);
+		}
+		clear_thread_flag(TIF_LOCAL_RESTART);
+		goto local_restart;
+	}
 }

-- 
2.49.0


      parent reply	other threads:[~2025-04-19 22:36 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-19 22:35 [PATCH v6 00/31] ARM: Switch to generic entry Linus Walleij
2025-04-19 22:35 ` [PATCH v6 01/31] ARM: Prepare includes for " Linus Walleij
2025-04-19 22:35 ` [PATCH v6 02/31] ARM: ptrace: Split report_syscall() Linus Walleij
2025-04-19 22:35 ` [PATCH v6 03/31] ARM: entry: Skip ret_slow_syscall label Linus Walleij
2025-04-19 22:35 ` [PATCH v6 04/31] ARM: process: Rewrite ret_from_fork i C Linus Walleij
2025-04-19 22:35 ` [PATCH v6 05/31] ARM: process: Remove local restart Linus Walleij
2025-04-19 22:35 ` [PATCH v6 06/31] ARM: entry: Invoke syscalls using C Linus Walleij
2025-04-19 22:35 ` [PATCH v6 07/31] ARM: entry: Rewrite two asm calls in C Linus Walleij
2025-04-19 22:35 ` [PATCH v6 08/31] ARM: entry: Move trace entry to C function Linus Walleij
2025-04-19 22:35 ` [PATCH v6 09/31] ARM: entry: save the syscall sp in thread_info Linus Walleij
2025-04-19 22:35 ` [PATCH v6 10/31] ARM: entry: move all tracing invocation to C Linus Walleij
2025-04-19 22:35 ` [PATCH v6 11/31] ARM: entry: Merge the common and trace entry code Linus Walleij
2025-04-19 22:35 ` [PATCH v6 12/31] ARM: entry: Rename syscall invocation Linus Walleij
2025-04-19 22:36 ` [PATCH v6 13/31] ARM: entry: Create user_mode_enter/exit Linus Walleij
2025-04-19 22:36 ` [PATCH v6 14/31] ARM: entry: Drop trace argument from usr_entry macro Linus Walleij
2025-04-19 22:36 ` [PATCH v6 15/31] ARM: entry: Separate call path for syscall SWI entry Linus Walleij
2025-04-19 22:36 ` [PATCH v6 16/31] ARM: entry: Drop argument to asm_irqentry macros Linus Walleij
2025-04-19 22:36 ` [PATCH v6 17/31] ARM: entry: Implement syscall_exit_to_user_mode() Linus Walleij
2025-04-19 22:36 ` [PATCH v6 18/31] ARM: entry: Drop the superfast ret_fast_syscall Linus Walleij
2025-04-19 22:36 ` [PATCH v6 19/31] ARM: entry: Remove fast and offset register restore Linus Walleij
2025-04-19 22:36 ` [PATCH v6 20/31] ARM: entry: Untangle ret_fast_syscall/to_user Linus Walleij
2025-04-19 22:36 ` [PATCH v6 21/31] ARM: entry: Do not double-call exit functions Linus Walleij
2025-04-19 22:36 ` [PATCH v6 22/31] ARM: entry: Move work processing to C Linus Walleij
2025-04-19 22:36 ` [PATCH v6 23/31] ARM: entry: Stop exiting syscalls like IRQs Linus Walleij
2025-04-19 22:36 ` [PATCH v6 24/31] ARM: entry: Complete syscall and IRQ transition to C Linus Walleij
2025-04-19 22:36 ` [PATCH v6 25/31] ARM: entry: Create irqentry calls from kernel mode Linus Walleij
2025-04-19 22:36 ` [PATCH v6 26/31] ARM: entry: Move in-kernel hardirq tracing to C Linus Walleij
2025-04-19 22:36 ` [PATCH v6 27/31] ARM: irq: Add irqstack helper Linus Walleij
2025-04-19 22:36 ` [PATCH v6 28/31] ARM: entry: Convert to generic entry Linus Walleij
2025-04-19 22:36 ` [PATCH v6 29/31] ARM: entry: Handle dabt, pabt, and und as interrupts Linus Walleij
2025-04-19 22:36 ` [PATCH v6 30/31] ARM: entry: Block IRQs in early IRQ context Linus Walleij
2025-04-19 22:36 ` Linus Walleij [this message]

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=20250420-arm-generic-entry-v6-31-95f1fcdfeeb2@linaro.org \
    --to=linus.walleij@linaro.org \
    --cc=ardb@kernel.org \
    --cc=arnd@arndb.de \
    --cc=dvyukov@google.com \
    --cc=frederic@kernel.org \
    --cc=kees@kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=luto@amacapital.net \
    --cc=oleg@redhat.com \
    --cc=paulmck@kernel.org \
    --cc=ruanjinjie@huawei.com \
    --cc=tglx@linutronix.de \
    --cc=viro@zeniv.linux.org.uk \
    --cc=wad@chromium.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

all inboxes | Powered by JetHome®