提交 1a05669b 编写于 作者: Y Yury Norov 提交者: Yang Yingliang

arm64: ilp32: introduce syscall table for ILP32

hulk inclusion
category: feature
bugzilla: NA
CVE: NA
---------------------------

Depending on the personality of the task, syscalls has to be dispatched
to either aarch64, aarch32 or aarch64/ilp32 syscall handlers. We add
the support of ILP32 mode in this series, therefore introduce
corresponding syscall table.

Some system calls are wired to aarch32 syscall handlers, as listed in
arch/arm64/kernel/sys_ilp32.c.

For aarch64/ilp32, top halves of syscall arguments are meaningless
anthough not zeroed by hardware. Do that in the delouse_pt_regs()
routine to avoid passing garbage by userspace.
Signed-off-by: NYury Norov <ynorov@caviumnetworks.com>
Signed-off-by: NXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: NHanjun Guo &lt;guohanjun@huawei.com <mailto:guohanjun@huawei.com&gt;>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 90046ca2
...@@ -28,6 +28,10 @@ extern const syscall_fn_t sys_call_table[]; ...@@ -28,6 +28,10 @@ extern const syscall_fn_t sys_call_table[];
extern const syscall_fn_t a32_sys_call_table[]; extern const syscall_fn_t a32_sys_call_table[];
#endif #endif
#ifdef CONFIG_ARM64_ILP32
extern const syscall_fn_t ilp32_sys_call_table[];
#endif
static inline int syscall_get_nr(struct task_struct *task, static inline int syscall_get_nr(struct task_struct *task,
struct pt_regs *regs) struct pt_regs *regs)
{ {
......
...@@ -13,12 +13,16 @@ ...@@ -13,12 +13,16 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef CONFIG_AARCH32_EL0
#ifdef CONFIG_COMPAT
#define __ARCH_WANT_COMPAT_STAT64 #define __ARCH_WANT_COMPAT_STAT64
#define __ARCH_WANT_SYS_LLSEEK
#endif
#ifdef CONFIG_AARCH32_EL0
#define __ARCH_WANT_SYS_GETHOSTNAME #define __ARCH_WANT_SYS_GETHOSTNAME
#define __ARCH_WANT_SYS_PAUSE #define __ARCH_WANT_SYS_PAUSE
#define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_GETPGRP
#define __ARCH_WANT_SYS_LLSEEK
#define __ARCH_WANT_SYS_NICE #define __ARCH_WANT_SYS_NICE
#define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_SIGPROCMASK
......
...@@ -15,7 +15,19 @@ ...@@ -15,7 +15,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/*
* Use AARCH32 interface for sys_sync_file_range() as it passes 64-bit arguments.
*/
#if defined(__ILP32__) || defined(__SYSCALL_COMPAT)
#define __ARCH_WANT_SYNC_FILE_RANGE2
#endif
/*
* AARCH64/ILP32 is introduced after next syscalls were deprecated.
*/
#if !(defined(__ILP32__) || defined(__SYSCALL_COMPAT))
#define __ARCH_WANT_RENAMEAT #define __ARCH_WANT_RENAMEAT
#define __ARCH_WANT_SET_GET_RLIMIT #define __ARCH_WANT_SET_GET_RLIMIT
#endif
#include <asm-generic/unistd.h> #include <asm-generic/unistd.h>
...@@ -29,7 +29,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE ...@@ -29,7 +29,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE
arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \ arm64-obj-$(CONFIG_AARCH32_EL0) += sys32.o kuser32.o signal32.o \
sys_compat.o binfmt_elf32.o sys_compat.o binfmt_elf32.o
arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o arm64-obj-$(CONFIG_ARM64_ILP32) += binfmt_ilp32.o sys_ilp32.o
arm64-obj-$(CONFIG_COMPAT) += sys32_common.o arm64-obj-$(CONFIG_COMPAT) += sys32_common.o
arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o
arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o
......
// SPDX-License-Identifier: GPL-2.0+
/*
* AArch64- ILP32 specific system calls implementation
* Copyright (C) 2018 Marvell.
*/
#define __SYSCALL_COMPAT
#include <linux/compat.h>
#include <linux/compiler.h>
#include <linux/syscalls.h>
#include <asm/syscall.h>
/*
* AARCH32 requires 4-page alignment for shared memory,
* but AARCH64 - only 1 page. This is the only difference
* between compat and native sys_shmat(). So ILP32 just pick
* AARCH64 version.
*/
#define __arm64_compat_sys_shmat __arm64_sys_shmat
/*
* ILP32 needs special handling for some ptrace requests.
*/
#define __arm64_sys_ptrace __arm64_compat_sys_ptrace
/*
* Using AARCH32 interface for syscalls that take 64-bit
* parameters in registers.
*/
#define __arm64_compat_sys_fadvise64_64 __arm64_compat_sys_aarch32_fadvise64_64
#define __arm64_compat_sys_fallocate __arm64_compat_sys_aarch32_fallocate
#define __arm64_compat_sys_ftruncate64 __arm64_compat_sys_aarch32_ftruncate64
#define __arm64_compat_sys_pread64 __arm64_compat_sys_aarch32_pread64
#define __arm64_compat_sys_pwrite64 __arm64_compat_sys_aarch32_pwrite64
#define __arm64_compat_sys_readahead __arm64_compat_sys_aarch32_readahead
#define __arm64_compat_sys_sync_file_range2 __arm64_compat_sys_aarch32_sync_file_range2
#define __arm64_compat_sys_truncate64 __arm64_compat_sys_aarch32_truncate64
#define __arm64_sys_mmap2 __arm64_compat_sys_aarch32_mmap2
/*
* Using AARCH32 interface for syscalls that take the size of
* struct statfs as an argument, as it's calculated differently
* in kernel and user spaces.
*/
#define __arm64_compat_sys_fstatfs64 __arm64_compat_sys_aarch32_fstatfs64
#define __arm64_compat_sys_statfs64 __arm64_compat_sys_aarch32_statfs64
/*
* Wrappers to pass the pt_regs argument.
*/
#define sys_personality sys_arm64_personality
asmlinkage long sys_ni_syscall(const struct pt_regs *);
#define __arm64_sys_ni_syscall sys_ni_syscall
#undef __SYSCALL
#define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *);
#include <asm/unistd.h>
#undef __SYSCALL
#define __SYSCALL(nr, sym) [nr] = (syscall_fn_t)__arm64_##sym,
const syscall_fn_t ilp32_sys_call_table[__NR_syscalls] = {
[0 ... __NR_syscalls - 1] = (syscall_fn_t)sys_ni_syscall,
#include <asm/unistd.h>
};
...@@ -157,10 +157,33 @@ static inline void sve_user_discard(void) ...@@ -157,10 +157,33 @@ static inline void sve_user_discard(void)
sve_user_disable(); sve_user_disable();
} }
#ifdef CONFIG_ARM64_ILP32
static inline void delouse_pt_regs(struct pt_regs *regs)
{
regs->regs[0] &= UINT_MAX;
regs->regs[1] &= UINT_MAX;
regs->regs[2] &= UINT_MAX;
regs->regs[3] &= UINT_MAX;
regs->regs[4] &= UINT_MAX;
regs->regs[5] &= UINT_MAX;
regs->regs[6] &= UINT_MAX;
regs->regs[7] &= UINT_MAX;
}
#endif
asmlinkage void el0_svc_handler(struct pt_regs *regs) asmlinkage void el0_svc_handler(struct pt_regs *regs)
{ {
const syscall_fn_t *t = sys_call_table;
#ifdef CONFIG_ARM64_ILP32
if (is_ilp32_compat_task()) {
t = ilp32_sys_call_table;
delouse_pt_regs(regs);
}
#endif
sve_user_discard(); sve_user_discard();
el0_svc_common(regs, regs->regs[8], __NR_syscalls, sys_call_table); el0_svc_common(regs, regs->regs[8], __NR_syscalls, t);
} }
#ifdef CONFIG_AARCH32_EL0 #ifdef CONFIG_AARCH32_EL0
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册