arm64 fixes for -rc3

- 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
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEPxTL6PPUbjXGY88ct6xw3ITBYzQFAlzvv3EACgkQt6xw3ITB
 YzQviwf9Gw3VrBZpS9nwz0MQCf9W7+Vpy8XBsY7HJyUNQ4+8ZNR5HoZ3BcJX2HWk
 WKwSw721MllzLfJaRMqNV2+C7lm+EypcZApKFpPo7Vs9g78WcUdNZ4YM4XfAX45T
 cVPxeSGOj2aswyOn2Xa3UjKZj8deP8nAC/JgJY7t9L6qKObwUldmxBPRnZdclclw
 S8sQSMvLc9Q43jmEysPLixExZ6jzmq1i8xxPcyqFUz8DHYPf1irLxtpS7DYA+nk5
 nwQ/lnz6Tu8TBXcvgvXayKL8aa8SIsl0cOii2FWsZMkFXz3OZ08hdujvMYsPSSHO
 q3rMub7F/0znm00sBGXgTGRjy++v+A==
 =pyp4
 -----END PGP SIGNATURE-----

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:
Linus Torvalds 2019-05-30 21:05:23 -07:00
commit adc3f554fa
6 changed files with 56 additions and 30 deletions

View File

@ -20,7 +20,7 @@
#include <linux/compat.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[];

View File

@ -30,10 +30,10 @@
} \
static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
#define COMPAT_SYSCALL_DEFINE0(sname) \
asmlinkage long __arm64_compat_sys_##sname(void); \
ALLOW_ERROR_INJECTION(__arm64_compat_sys_##sname, ERRNO); \
asmlinkage long __arm64_compat_sys_##sname(void)
#define COMPAT_SYSCALL_DEFINE0(sname) \
asmlinkage long __arm64_compat_sys_##sname(const struct pt_regs *__unused); \
ALLOW_ERROR_INJECTION(__arm64_compat_sys_##sname, ERRNO); \
asmlinkage long __arm64_compat_sys_##sname(const struct pt_regs *__unused)
#define COND_SYSCALL_COMPAT(name) \
cond_syscall(__arm64_compat_sys_##name);
@ -62,11 +62,11 @@
static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))
#ifndef SYSCALL_DEFINE0
#define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA(_##sname, 0); \
asmlinkage long __arm64_sys_##sname(void); \
ALLOW_ERROR_INJECTION(__arm64_sys_##sname, ERRNO); \
asmlinkage long __arm64_sys_##sname(void)
#define SYSCALL_DEFINE0(sname) \
SYSCALL_METADATA(_##sname, 0); \
asmlinkage long __arm64_sys_##sname(const struct pt_regs *__unused); \
ALLOW_ERROR_INJECTION(__arm64_sys_##sname, ERRNO); \
asmlinkage long __arm64_sys_##sname(const struct pt_regs *__unused)
#endif
#ifndef COND_SYSCALL

View File

@ -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;

View File

@ -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>
};

View File

@ -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>
};

View File

@ -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,