Thread (53 messages) 53 messages, 4 authors, 2018-06-20

[PATCHv3 08/19] arm64: convert raw syscall invocation to C

From: mark.rutland@arm.com (Mark Rutland)
Date: 2018-06-19 14:48:50
Also in: linux-fsdevel

On Tue, Jun 19, 2018 at 03:21:25PM +0100, Catalin Marinas wrote:
On Mon, Jun 18, 2018 at 01:02:59PM +0100, Mark Rutland wrote:
quoted
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
new file mode 100644
index 000000000000..b463b962d597
--- /dev/null
+++ b/arch/arm64/kernel/syscall.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/nospec.h>
+#include <linux/ptrace.h>
+
+long do_ni_syscall(struct pt_regs *regs);
+
+typedef long (*syscall_fn_t)(unsigned long, unsigned long,
+			     unsigned long, unsigned long,
+			     unsigned long, unsigned long);
+
+static void __invoke_syscall(struct pt_regs *regs, syscall_fn_t syscall_fn)
+{
+	regs->regs[0] = syscall_fn(regs->regs[0], regs->regs[1],
+				   regs->regs[2], regs->regs[3],
+				   regs->regs[4], regs->regs[5]);
+}
+
+asmlinkage void invoke_syscall(struct pt_regs *regs, unsigned int scno,
+			       unsigned int sc_nr,
+			       syscall_fn_t syscall_table[])
+{
+	if (scno < sc_nr) {
+		syscall_fn_t syscall_fn;
+		syscall_fn = syscall_table[array_index_nospec(scno, sc_nr)];
+		__invoke_syscall(regs, syscall_fn);
+	} else {
+		regs->regs[0] = do_ni_syscall(regs);
+	}
+}
While reviewing the subsequent patch, it crossed my mind that we no
longer have any callers to do_ni_syscall() outside this file. Can we not
more it here and have a similar implementation to __invoke_syscall() for
consistency, i.e. set regs->regs[0].
I think so, though it complicates the logic in do_ni_syscall(), since
there are two places we may return a value.

Would you be happy if instead I made __invoke_syscall() return the
result, and have invoke_syscall() place the result in regs->regs[0] in
either case, e.g. as below?

Thanks,
Mark.

---->8----
// SPDX-License-Identifier: GPL-2.0

#include <linux/errno.h>
#include <linux/nospec.h>
#include <linux/ptrace.h>
#include <linux/syscalls.h>

#include <asm/compat.h>

long compat_arm_syscall(struct pt_regs *regs);

static long do_ni_syscall(struct pt_regs *regs)
{
#ifdef CONFIG_COMPAT
	long ret;
	if (is_compat_task()) {
		ret = compat_arm_syscall(regs);
		if (ret != -ENOSYS)
			return ret;
	}
#endif

	return sys_ni_syscall();
}

typedef long (*syscall_fn_t)(unsigned long, unsigned long,
			     unsigned long, unsigned long,
			     unsigned long, unsigned long);

static long __invoke_syscall(struct pt_regs *regs, syscall_fn_t syscall_fn)
{
	return syscall_fn(regs->regs[0], regs->regs[1], regs->regs[2],
			  regs->regs[3], regs->regs[4], regs->regs[5]);
}

asmlinkage void invoke_syscall(struct pt_regs *regs, unsigned int scno,
			       unsigned int sc_nr,
			       syscall_fn_t syscall_table[])
{
	long ret;

	if (scno < sc_nr) {
		syscall_fn_t syscall_fn;
		syscall_fn = syscall_table[array_index_nospec(scno, sc_nr)];
		ret = __invoke_syscall(regs, syscall_fn);
	} else {
		ret = do_ni_syscall(regs);
	}

	regs->regs[0] = ret;
}
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help