Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Will Deacon: "The fixes are still trickling in for arm64, but the only really significant one here is actually fixing a regression in the botched module relocation range checking merged for -rc2. Hopefully we've nailed it this time. - Fix implementation of our set_personality() system call, which wasn't being wrapped properly - Fix system call function types to keep CFI happy - Fix siginfo layout when delivering SIGKILL after a kernel fault - Really fix module relocation range checking" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: use the correct function type for __arm64_sys_ni_syscall arm64: use the correct function type in SYSCALL_DEFINE0 arm64: fix syscall_fn_t type signal/arm64: Use force_sig not force_sig_fault for SIGKILL arm64/module: revert to unsigned interpretation of ABS16/32 relocations arm64: Fix the arm64_personality() syscall wrapper redirection
This commit is contained in:
@@ -98,10 +98,10 @@ static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len)
|
||||
|
||||
/*
|
||||
* The ELF psABI for AArch64 documents the 16-bit and 32-bit place
|
||||
* relative relocations as having a range of [-2^15, 2^16) or
|
||||
* [-2^31, 2^32), respectively. However, in order to be able to detect
|
||||
* overflows reliably, we have to choose whether we interpret such
|
||||
* quantities as signed or as unsigned, and stick with it.
|
||||
* relative and absolute relocations as having a range of [-2^15, 2^16)
|
||||
* or [-2^31, 2^32), respectively. However, in order to be able to
|
||||
* detect overflows reliably, we have to choose whether we interpret
|
||||
* such quantities as signed or as unsigned, and stick with it.
|
||||
* The way we organize our address space requires a signed
|
||||
* interpretation of 32-bit relative references, so let's use that
|
||||
* for all R_AARCH64_PRELxx relocations. This means our upper
|
||||
@@ -111,13 +111,35 @@ static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len)
|
||||
switch (len) {
|
||||
case 16:
|
||||
*(s16 *)place = sval;
|
||||
if (sval < S16_MIN || sval > S16_MAX)
|
||||
return -ERANGE;
|
||||
switch (op) {
|
||||
case RELOC_OP_ABS:
|
||||
if (sval < 0 || sval > U16_MAX)
|
||||
return -ERANGE;
|
||||
break;
|
||||
case RELOC_OP_PREL:
|
||||
if (sval < S16_MIN || sval > S16_MAX)
|
||||
return -ERANGE;
|
||||
break;
|
||||
default:
|
||||
pr_err("Invalid 16-bit data relocation (%d)\n", op);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
*(s32 *)place = sval;
|
||||
if (sval < S32_MIN || sval > S32_MAX)
|
||||
return -ERANGE;
|
||||
switch (op) {
|
||||
case RELOC_OP_ABS:
|
||||
if (sval < 0 || sval > U32_MAX)
|
||||
return -ERANGE;
|
||||
break;
|
||||
case RELOC_OP_PREL:
|
||||
if (sval < S32_MIN || sval > S32_MAX)
|
||||
return -ERANGE;
|
||||
break;
|
||||
default:
|
||||
pr_err("Invalid 32-bit data relocation (%d)\n", op);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 64:
|
||||
*(s64 *)place = sval;
|
||||
|
@@ -47,22 +47,26 @@ SYSCALL_DEFINE1(arm64_personality, unsigned int, personality)
|
||||
return ksys_personality(personality);
|
||||
}
|
||||
|
||||
asmlinkage long sys_ni_syscall(void);
|
||||
|
||||
asmlinkage long __arm64_sys_ni_syscall(const struct pt_regs *__unused)
|
||||
{
|
||||
return sys_ni_syscall();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
#define __arm64_sys_personality __arm64_sys_arm64_personality
|
||||
|
||||
#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,
|
||||
#define __SYSCALL(nr, sym) [nr] = __arm64_##sym,
|
||||
|
||||
const syscall_fn_t sys_call_table[__NR_syscalls] = {
|
||||
[0 ... __NR_syscalls - 1] = (syscall_fn_t)sys_ni_syscall,
|
||||
[0 ... __NR_syscalls - 1] = __arm64_sys_ni_syscall,
|
||||
#include <asm/unistd.h>
|
||||
};
|
||||
|
@@ -133,17 +133,14 @@ COMPAT_SYSCALL_DEFINE6(aarch32_fallocate, int, fd, int, mode,
|
||||
return ksys_fallocate(fd, mode, arg_u64(offset), arg_u64(len));
|
||||
}
|
||||
|
||||
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/unistd32.h>
|
||||
|
||||
#undef __SYSCALL
|
||||
#define __SYSCALL(nr, sym) [nr] = (syscall_fn_t)__arm64_##sym,
|
||||
#define __SYSCALL(nr, sym) [nr] = __arm64_##sym,
|
||||
|
||||
const syscall_fn_t compat_sys_call_table[__NR_compat_syscalls] = {
|
||||
[0 ... __NR_compat_syscalls - 1] = (syscall_fn_t)sys_ni_syscall,
|
||||
[0 ... __NR_compat_syscalls - 1] = __arm64_sys_ni_syscall,
|
||||
#include <asm/unistd32.h>
|
||||
};
|
||||
|
@@ -252,7 +252,10 @@ void arm64_force_sig_fault(int signo, int code, void __user *addr,
|
||||
const char *str)
|
||||
{
|
||||
arm64_show_signal(signo, str);
|
||||
force_sig_fault(signo, code, addr, current);
|
||||
if (signo == SIGKILL)
|
||||
force_sig(SIGKILL, current);
|
||||
else
|
||||
force_sig_fault(signo, code, addr, current);
|
||||
}
|
||||
|
||||
void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
|
||||
|
Reference in New Issue
Block a user