From: Amanieu d'Antras <amanieu@gmail.com> To: unlisted-recipients:; (no To-header on input) Cc: Amanieu d'Antras <amanieu@gmail.com>, Ryan Houdek <Houdek.Ryan@fex-emu.org>, Catalin Marinas <catalin.marinas@arm.com>, Will Deacon <will@kernel.org>, Mark Rutland <mark.rutland@arm.com>, Steven Price <steven.price@arm.com>, Arnd Bergmann <arnd@kernel.org>, David Laight <David.Laight@aculab.com>, Mark Brown <broonie@kernel.org>, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [RESEND PATCH v4 8/8] arm64: Allow 64-bit tasks to invoke compat syscalls Date: Tue, 18 May 2021 10:06:58 +0100 [thread overview] Message-ID: <20210518090658.9519-9-amanieu@gmail.com> (raw) In-Reply-To: <20210518090658.9519-1-amanieu@gmail.com> Setting bit 31 in x8 when performing a syscall will do the following: - The remainder of x8 is treated as a compat syscall number and is used to index the compat syscall table. - in_compat_syscall will return true for the duration of the syscall. - VM allocations performed by the syscall will be located in the lower 4G of the address space. - Interrupted syscalls are properly restarted as compat syscalls. - Seccomp will treats the syscall as having AUDIT_ARCH_ARM instead of AUDIT_ARCH_AARCH64. This affects the arch value seen by seccomp filters and reported by SIGSYS. - PTRACE_GET_SYSCALL_INFO also treats the syscall as having AUDIT_ARCH_ARM. Recent versions of strace will correctly report the system call name and parameters when an AArch64 task mixes 32-bit and 64-bit syscalls. Previously, setting bit 31 of the syscall number would always cause the sygscall to return ENOSYS. This allows user programs to reliably detect kernel support for compat syscall by trying a simple syscall such as getpid. The AArch32-private compat syscalls (__ARM_NR_compat_*) are not exposed through this interface. These syscalls do not make sense in the context of an AArch64 task. Signed-off-by: Amanieu d'Antras <amanieu@gmail.com> Co-developed-by: Ryan Houdek <Houdek.Ryan@fex-emu.org> Signed-off-by: Ryan Houdek <Houdek.Ryan@fex-emu.org> --- arch/arm64/include/uapi/asm/unistd.h | 2 ++ arch/arm64/kernel/signal.c | 5 +++++ arch/arm64/kernel/syscall.c | 21 ++++++++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h index f83a70e07df8..5574bc6ab0a3 100644 --- a/arch/arm64/include/uapi/asm/unistd.h +++ b/arch/arm64/include/uapi/asm/unistd.h @@ -15,6 +15,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define __ARM64_COMPAT_SYSCALL_BIT 0x80000000 + #define __ARCH_WANT_RENAMEAT #define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_SET_GET_RLIMIT diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 6237486ff6bb..463c8a82050e 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -795,6 +795,11 @@ static void setup_restart_syscall(struct pt_regs *regs) { if (is_compat_task()) compat_setup_restart_syscall(regs); +#ifdef COMPAT + else if (in_compat_syscall()) + regs->regs[8] = __ARM64_COMPAT_SYSCALL_BIT | + __NR_compat_restart_syscall; +#endif else regs->regs[8] = __NR_restart_syscall; } diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index e0e9d54de0a2..83747cf4b5b7 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -118,6 +118,11 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, * user-issued syscall(-1). However, requesting a skip and not * setting the return value is unlikely to do anything sensible * anyway. + * + * This edge case goes away with CONFIG_COMPAT since a + * user-issued syscall(-1) is interpreted as a + * compat_syscall(0x7fffffff) which still ends up returning + * -ENOSYS in x0. */ if (scno == NO_SYSCALL) regs->regs[0] = -ENOSYS; @@ -165,7 +170,21 @@ static inline void sve_user_discard(void) void do_el0_svc(struct pt_regs *regs) { sve_user_discard(); - el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table); + +#ifdef CONFIG_COMPAT + /* + * Setting bit 31 of x8 allows a 64-bit processe to perform compat + * syscalls. + */ + if (regs->regs[8] & __ARM64_COMPAT_SYSCALL_BIT) { + current_thread_info()->use_compat_syscall = true; + el0_svc_common(regs, + regs->regs[8] & ~__ARM64_COMPAT_SYSCALL_BIT, + __NR_compat_syscalls, compat_sys_call_table); + current_thread_info()->use_compat_syscall = false; + } else +#endif + el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table); } #ifdef CONFIG_COMPAT -- 2.31.1
WARNING: multiple messages have this Message-ID (diff)
From: Amanieu d'Antras <amanieu@gmail.com> Cc: Amanieu d'Antras <amanieu@gmail.com>, Ryan Houdek <Houdek.Ryan@fex-emu.org>, Catalin Marinas <catalin.marinas@arm.com>, Will Deacon <will@kernel.org>, Mark Rutland <mark.rutland@arm.com>, Steven Price <steven.price@arm.com>, Arnd Bergmann <arnd@kernel.org>, David Laight <David.Laight@aculab.com>, Mark Brown <broonie@kernel.org>, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [RESEND PATCH v4 8/8] arm64: Allow 64-bit tasks to invoke compat syscalls Date: Tue, 18 May 2021 10:06:58 +0100 [thread overview] Message-ID: <20210518090658.9519-9-amanieu@gmail.com> (raw) In-Reply-To: <20210518090658.9519-1-amanieu@gmail.com> Setting bit 31 in x8 when performing a syscall will do the following: - The remainder of x8 is treated as a compat syscall number and is used to index the compat syscall table. - in_compat_syscall will return true for the duration of the syscall. - VM allocations performed by the syscall will be located in the lower 4G of the address space. - Interrupted syscalls are properly restarted as compat syscalls. - Seccomp will treats the syscall as having AUDIT_ARCH_ARM instead of AUDIT_ARCH_AARCH64. This affects the arch value seen by seccomp filters and reported by SIGSYS. - PTRACE_GET_SYSCALL_INFO also treats the syscall as having AUDIT_ARCH_ARM. Recent versions of strace will correctly report the system call name and parameters when an AArch64 task mixes 32-bit and 64-bit syscalls. Previously, setting bit 31 of the syscall number would always cause the sygscall to return ENOSYS. This allows user programs to reliably detect kernel support for compat syscall by trying a simple syscall such as getpid. The AArch32-private compat syscalls (__ARM_NR_compat_*) are not exposed through this interface. These syscalls do not make sense in the context of an AArch64 task. Signed-off-by: Amanieu d'Antras <amanieu@gmail.com> Co-developed-by: Ryan Houdek <Houdek.Ryan@fex-emu.org> Signed-off-by: Ryan Houdek <Houdek.Ryan@fex-emu.org> --- arch/arm64/include/uapi/asm/unistd.h | 2 ++ arch/arm64/kernel/signal.c | 5 +++++ arch/arm64/kernel/syscall.c | 21 ++++++++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/uapi/asm/unistd.h b/arch/arm64/include/uapi/asm/unistd.h index f83a70e07df8..5574bc6ab0a3 100644 --- a/arch/arm64/include/uapi/asm/unistd.h +++ b/arch/arm64/include/uapi/asm/unistd.h @@ -15,6 +15,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define __ARM64_COMPAT_SYSCALL_BIT 0x80000000 + #define __ARCH_WANT_RENAMEAT #define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_SET_GET_RLIMIT diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 6237486ff6bb..463c8a82050e 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -795,6 +795,11 @@ static void setup_restart_syscall(struct pt_regs *regs) { if (is_compat_task()) compat_setup_restart_syscall(regs); +#ifdef COMPAT + else if (in_compat_syscall()) + regs->regs[8] = __ARM64_COMPAT_SYSCALL_BIT | + __NR_compat_restart_syscall; +#endif else regs->regs[8] = __NR_restart_syscall; } diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index e0e9d54de0a2..83747cf4b5b7 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -118,6 +118,11 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, * user-issued syscall(-1). However, requesting a skip and not * setting the return value is unlikely to do anything sensible * anyway. + * + * This edge case goes away with CONFIG_COMPAT since a + * user-issued syscall(-1) is interpreted as a + * compat_syscall(0x7fffffff) which still ends up returning + * -ENOSYS in x0. */ if (scno == NO_SYSCALL) regs->regs[0] = -ENOSYS; @@ -165,7 +170,21 @@ static inline void sve_user_discard(void) void do_el0_svc(struct pt_regs *regs) { sve_user_discard(); - el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table); + +#ifdef CONFIG_COMPAT + /* + * Setting bit 31 of x8 allows a 64-bit processe to perform compat + * syscalls. + */ + if (regs->regs[8] & __ARM64_COMPAT_SYSCALL_BIT) { + current_thread_info()->use_compat_syscall = true; + el0_svc_common(regs, + regs->regs[8] & ~__ARM64_COMPAT_SYSCALL_BIT, + __NR_compat_syscalls, compat_sys_call_table); + current_thread_info()->use_compat_syscall = false; + } else +#endif + el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table); } #ifdef CONFIG_COMPAT -- 2.31.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2021-05-18 9:08 UTC|newest] Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-05-18 9:06 [RESEND PATCH v4 0/8] arm64: Allow 64-bit tasks to invoke compat syscalls Amanieu d'Antras 2021-05-18 9:06 ` Amanieu d'Antras 2021-05-18 9:06 ` [RESEND PATCH v4 1/8] mm: Add arch_get_mmap_base_topdown macro Amanieu d'Antras 2021-05-18 9:06 ` Amanieu d'Antras 2021-05-18 9:06 ` [RESEND PATCH v4 2/8] hugetlbfs: Use arch_get_mmap_* macros Amanieu d'Antras 2021-05-18 9:06 ` Amanieu d'Antras 2021-05-18 9:06 ` [RESEND PATCH v4 3/8] mm: Support mmap_compat_base with the generic layout Amanieu d'Antras 2021-05-18 9:06 ` Amanieu d'Antras 2021-05-18 9:06 ` [RESEND PATCH v4 4/8] arm64: Separate in_compat_syscall from is_compat_task Amanieu d'Antras 2021-05-18 9:06 ` Amanieu d'Antras 2021-05-18 9:06 ` [RESEND PATCH v4 5/8] arm64: mm: Use HAVE_ARCH_COMPAT_MMAP_BASES Amanieu d'Antras 2021-05-18 9:06 ` Amanieu d'Antras 2021-05-18 9:06 ` [RESEND PATCH v4 6/8] arm64: Add a compat syscall flag to thread_info Amanieu d'Antras 2021-05-18 9:06 ` Amanieu d'Antras 2021-05-18 9:06 ` [RESEND PATCH v4 7/8] arm64: Forbid calling compat sigreturn from 64-bit tasks Amanieu d'Antras 2021-05-18 9:06 ` Amanieu d'Antras 2021-05-18 9:06 ` Amanieu d'Antras [this message] 2021-05-18 9:06 ` [RESEND PATCH v4 8/8] arm64: Allow 64-bit tasks to invoke compat syscalls Amanieu d'Antras 2021-05-18 13:02 ` Arnd Bergmann 2021-05-18 13:02 ` Arnd Bergmann 2021-05-18 20:26 ` David Laight 2021-05-18 20:26 ` David Laight 2021-05-18 22:41 ` Ryan Houdek 2021-05-18 22:41 ` Ryan Houdek 2021-05-18 23:51 ` Amanieu d'Antras 2021-05-18 23:51 ` Amanieu d'Antras 2021-05-19 15:30 ` Steven Price 2021-05-19 15:30 ` Steven Price 2021-05-19 16:14 ` Amanieu d'Antras 2021-05-19 16:14 ` Amanieu d'Antras 2021-05-21 8:51 ` Steven Price 2021-05-21 8:51 ` Steven Price 2021-05-21 19:18 ` Amanieu d'Antras 2021-05-21 19:18 ` Amanieu d'Antras 2021-05-24 11:20 ` Steven Price 2021-05-24 11:20 ` Steven Price 2021-05-24 12:38 ` David Laight 2021-05-24 12:38 ` David Laight 2021-05-18 23:52 ` Ryan Houdek 2021-05-18 23:52 ` Ryan Houdek
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=20210518090658.9519-9-amanieu@gmail.com \ --to=amanieu@gmail.com \ --cc=David.Laight@aculab.com \ --cc=Houdek.Ryan@fex-emu.org \ --cc=arnd@kernel.org \ --cc=broonie@kernel.org \ --cc=catalin.marinas@arm.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=mark.rutland@arm.com \ --cc=steven.price@arm.com \ --cc=will@kernel.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: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.