Commit adc3f554 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 318adf8e 1e29ab31
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/err.h> #include <linux/err.h>
typedef long (*syscall_fn_t)(struct pt_regs *regs); typedef long (*syscall_fn_t)(const struct pt_regs *regs);
extern const syscall_fn_t sys_call_table[]; extern const syscall_fn_t sys_call_table[];
......
...@@ -30,10 +30,10 @@ ...@@ -30,10 +30,10 @@
} \ } \
static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
#define COMPAT_SYSCALL_DEFINE0(sname) \ #define COMPAT_SYSCALL_DEFINE0(sname) \
asmlinkage long __arm64_compat_sys_##sname(void); \ asmlinkage long __arm64_compat_sys_##sname(const struct pt_regs *__unused); \
ALLOW_ERROR_INJECTION(__arm64_compat_sys_##sname, ERRNO); \ ALLOW_ERROR_INJECTION(__arm64_compat_sys_##sname, ERRNO); \
asmlinkage long __arm64_compat_sys_##sname(void) asmlinkage long __arm64_compat_sys_##sname(const struct pt_regs *__unused)
#define COND_SYSCALL_COMPAT(name) \ #define COND_SYSCALL_COMPAT(name) \
cond_syscall(__arm64_compat_sys_##name); cond_syscall(__arm64_compat_sys_##name);
...@@ -62,11 +62,11 @@ ...@@ -62,11 +62,11 @@
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
#ifndef SYSCALL_DEFINE0 #ifndef SYSCALL_DEFINE0
#define SYSCALL_DEFINE0(sname) \ #define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA(_##sname, 0); \ SYSCALL_METADATA(_##sname, 0); \
asmlinkage long __arm64_sys_##sname(void); \ asmlinkage long __arm64_sys_##sname(const struct pt_regs *__unused); \
ALLOW_ERROR_INJECTION(__arm64_sys_##sname, ERRNO); \ ALLOW_ERROR_INJECTION(__arm64_sys_##sname, ERRNO); \
asmlinkage long __arm64_sys_##sname(void) asmlinkage long __arm64_sys_##sname(const struct pt_regs *__unused)
#endif #endif
#ifndef COND_SYSCALL #ifndef COND_SYSCALL
......
...@@ -98,10 +98,10 @@ static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len) ...@@ -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 * 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 * relative and absolute relocations as having a range of [-2^15, 2^16)
* [-2^31, 2^32), respectively. However, in order to be able to detect * or [-2^31, 2^32), respectively. However, in order to be able to
* overflows reliably, we have to choose whether we interpret such * detect overflows reliably, we have to choose whether we interpret
* quantities as signed or as unsigned, and stick with it. * such quantities as signed or as unsigned, and stick with it.
* The way we organize our address space requires a signed * The way we organize our address space requires a signed
* interpretation of 32-bit relative references, so let's use that * interpretation of 32-bit relative references, so let's use that
* for all R_AARCH64_PRELxx relocations. This means our upper * 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) ...@@ -111,13 +111,35 @@ static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len)
switch (len) { switch (len) {
case 16: case 16:
*(s16 *)place = sval; *(s16 *)place = sval;
if (sval < S16_MIN || sval > S16_MAX) switch (op) {
return -ERANGE; 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; break;
case 32: case 32:
*(s32 *)place = sval; *(s32 *)place = sval;
if (sval < S32_MIN || sval > S32_MAX) switch (op) {
return -ERANGE; 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; break;
case 64: case 64:
*(s64 *)place = sval; *(s64 *)place = sval;
......
...@@ -47,22 +47,26 @@ SYSCALL_DEFINE1(arm64_personality, unsigned int, personality) ...@@ -47,22 +47,26 @@ SYSCALL_DEFINE1(arm64_personality, unsigned int, personality)
return ksys_personality(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. * Wrappers to pass the pt_regs argument.
*/ */
#define sys_personality sys_arm64_personality #define __arm64_sys_personality __arm64_sys_arm64_personality
asmlinkage long sys_ni_syscall(const struct pt_regs *);
#define __arm64_sys_ni_syscall sys_ni_syscall
#undef __SYSCALL #undef __SYSCALL
#define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *); #define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *);
#include <asm/unistd.h> #include <asm/unistd.h>
#undef __SYSCALL #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] = { 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> #include <asm/unistd.h>
}; };
...@@ -133,17 +133,14 @@ COMPAT_SYSCALL_DEFINE6(aarch32_fallocate, int, fd, int, mode, ...@@ -133,17 +133,14 @@ COMPAT_SYSCALL_DEFINE6(aarch32_fallocate, int, fd, int, mode,
return ksys_fallocate(fd, mode, arg_u64(offset), arg_u64(len)); 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 #undef __SYSCALL
#define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *); #define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *);
#include <asm/unistd32.h> #include <asm/unistd32.h>
#undef __SYSCALL #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] = { 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> #include <asm/unistd32.h>
}; };
...@@ -252,7 +252,10 @@ void arm64_force_sig_fault(int signo, int code, void __user *addr, ...@@ -252,7 +252,10 @@ void arm64_force_sig_fault(int signo, int code, void __user *addr,
const char *str) const char *str)
{ {
arm64_show_signal(signo, 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, void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment