Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull siginfo cleanups from Eric Biederman: "Long ago when 2.4 was just a testing release copy_siginfo_to_user was made to copy individual fields to userspace, possibly for efficiency and to ensure initialized values were not copied to userspace. Unfortunately the design was complex, it's assumptions unstated, and humans are fallible and so while it worked much of the time that design failed to ensure unitialized memory is not copied to userspace. This set of changes is part of a new design to clean up siginfo and simplify things, and hopefully make the siginfo handling robust enough that a simple inspection of the code can be made to ensure we don't copy any unitializied fields to userspace. The design is to unify struct siginfo and struct compat_siginfo into a single definition that is shared between all architectures so that anyone adding to the set of information shared with struct siginfo can see the whole picture. Hopefully ensuring all future si_code assignments are arch independent. The design is to unify copy_siginfo_to_user32 and copy_siginfo_from_user32 so that those function are complete and cope with all of the different cases documented in signinfo_layout. I don't think there was a single implementation of either of those functions that was complete and correct before my changes unified them. The design is to introduce a series of helpers including force_siginfo_fault that take the values that are needed in struct siginfo and build the siginfo structure for their callers. Ensuring struct siginfo is built correctly. The remaining work for 4.17 (unless someone thinks it is post -rc1 material) is to push usage of those helpers down into the architectures so that architecture specific code will not need to deal with the fiddly work of intializing struct siginfo, and then when struct siginfo is guaranteed to be fully initialized change copy siginfo_to_user into a simple wrapper around copy_to_user. Further there is work in progress on the issues that have been documented requires arch specific knowledge to sort out. The changes below fix or at least document all of the issues that have been found with siginfo generation. Then proceed to unify struct siginfo the 32 bit helpers that copy siginfo to and from userspace, and generally clean up anything that is not arch specific with regards to siginfo generation. It is a lot but with the unification you can of siginfo you can already see the code reduction in the kernel" * 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (45 commits) signal/memory-failure: Use force_sig_mceerr and send_sig_mceerr mm/memory_failure: Remove unused trapno from memory_failure signal/ptrace: Add force_sig_ptrace_errno_trap and use it where needed signal/powerpc: Remove unnecessary signal_code parameter of do_send_trap signal: Helpers for faults with specialized siginfo layouts signal: Add send_sig_fault and force_sig_fault signal: Replace memset(info,...) with clear_siginfo for clarity signal: Don't use structure initializers for struct siginfo signal/arm64: Better isolate the COMPAT_TASK portion of ptrace_hbptriggered ptrace: Use copy_siginfo in setsiginfo and getsiginfo signal: Unify and correct copy_siginfo_to_user32 signal: Remove the code to clear siginfo before calling copy_siginfo_from_user32 signal: Unify and correct copy_siginfo_from_user32 signal/blackfin: Remove pointless UID16_SIGINFO_COMPAT_NEEDED signal/blackfin: Move the blackfin specific si_codes to asm-generic/siginfo.h signal/tile: Move the tile specific si_codes to asm-generic/siginfo.h signal/frv: Move the frv specific si_codes to asm-generic/siginfo.h signal/ia64: Move the ia64 specific si_codes to asm-generic/siginfo.h signal/powerpc: Remove redefinition of NSIGTRAP on powerpc signal: Move addr_lsb into the _sigfault union for clarity ...
This commit is contained in:
commit
d4173023e6
|
@ -65,12 +65,14 @@ unhandled_exception(const char *str, struct pt_regs *regs, siginfo_t *info)
|
|||
#define DO_ERROR_INFO(signr, str, name, sicode) \
|
||||
int name(unsigned long address, struct pt_regs *regs) \
|
||||
{ \
|
||||
siginfo_t info = { \
|
||||
.si_signo = signr, \
|
||||
.si_errno = 0, \
|
||||
.si_code = sicode, \
|
||||
.si_addr = (void __user *)address, \
|
||||
}; \
|
||||
siginfo_t info; \
|
||||
\
|
||||
clear_siginfo(&info); \
|
||||
info.si_signo = signr; \
|
||||
info.si_errno = 0; \
|
||||
info.si_code = sicode; \
|
||||
info.si_addr = (void __user *)address; \
|
||||
\
|
||||
return unhandled_exception(str, regs, &info);\
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef __ASM_SIGINFO_H
|
||||
#define __ASM_SIGINFO_H
|
||||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define FPE_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
|
@ -390,7 +390,6 @@ static void ptrace_hbptriggered(struct perf_event *bp,
|
|||
struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
|
||||
long num;
|
||||
int i;
|
||||
siginfo_t info;
|
||||
|
||||
for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i)
|
||||
if (current->thread.debug.hbp[i] == bp)
|
||||
|
@ -398,12 +397,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
|
|||
|
||||
num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i);
|
||||
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = (int)num;
|
||||
info.si_code = TRAP_HWBKPT;
|
||||
info.si_addr = (void __user *)(bkpt->trigger);
|
||||
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
force_sig_ptrace_errno_trap((int)num, (void __user *)(bkpt->trigger));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -257,7 +257,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
|
|||
|
||||
if (exceptions == VFP_EXCEPTION_ERROR) {
|
||||
vfp_panic("unhandled bounce", inst);
|
||||
vfp_raise_sigfpe(0, regs);
|
||||
vfp_raise_sigfpe(FPE_FIXME, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,70 +150,6 @@ typedef u32 compat_old_sigset_t;
|
|||
|
||||
typedef u32 compat_sigset_word;
|
||||
|
||||
typedef union compat_sigval {
|
||||
compat_int_t sival_int;
|
||||
compat_uptr_t sival_ptr;
|
||||
} compat_sigval_t;
|
||||
|
||||
typedef struct compat_siginfo {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
|
||||
union {
|
||||
int _pad[128/sizeof(int) - 3];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
compat_pid_t _pid; /* sender's pid */
|
||||
__compat_uid32_t _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
compat_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
compat_sigval_t _sigval; /* same as below */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
compat_pid_t _pid; /* sender's pid */
|
||||
__compat_uid32_t _uid; /* sender's uid */
|
||||
compat_sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
compat_pid_t _pid; /* which child */
|
||||
__compat_uid32_t _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_clock_t _utime;
|
||||
compat_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
struct {
|
||||
compat_uptr_t _addr; /* faulting insn/memory ref. */
|
||||
short _addr_lsb; /* LSB of the reported address */
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
|
||||
/* SIGSYS */
|
||||
struct {
|
||||
compat_uptr_t _call_addr; /* calling user insn */
|
||||
int _syscall; /* triggering system call number */
|
||||
compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */
|
||||
} _sigsys;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
/*
|
||||
|
|
|
@ -21,4 +21,25 @@
|
|||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define FPE_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
* SIGBUS si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define BUS_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
* SIGTRAP si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define TRAP_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -209,12 +209,13 @@ NOKPROBE_SYMBOL(call_step_hook);
|
|||
static void send_user_sigtrap(int si_code)
|
||||
{
|
||||
struct pt_regs *regs = current_pt_regs();
|
||||
siginfo_t info = {
|
||||
.si_signo = SIGTRAP,
|
||||
.si_errno = 0,
|
||||
.si_code = si_code,
|
||||
.si_addr = (void __user *)instruction_pointer(regs),
|
||||
};
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = (void __user *)instruction_pointer(regs);
|
||||
|
||||
if (WARN_ON(!user_mode(regs)))
|
||||
return;
|
||||
|
|
|
@ -867,7 +867,7 @@ asmlinkage void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs)
|
|||
asmlinkage void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
unsigned int si_code = 0;
|
||||
unsigned int si_code = FPE_FIXME;
|
||||
|
||||
if (esr & FPEXC_IOF)
|
||||
si_code = FPE_FLTINV;
|
||||
|
|
|
@ -180,34 +180,34 @@ static void ptrace_hbptriggered(struct perf_event *bp,
|
|||
struct pt_regs *regs)
|
||||
{
|
||||
struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
|
||||
siginfo_t info = {
|
||||
.si_signo = SIGTRAP,
|
||||
.si_errno = 0,
|
||||
.si_code = TRAP_HWBKPT,
|
||||
.si_addr = (void __user *)(bkpt->trigger),
|
||||
};
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_HWBKPT;
|
||||
info.si_addr = (void __user *)(bkpt->trigger);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
int i;
|
||||
if (is_compat_task()) {
|
||||
int si_errno = 0;
|
||||
int i;
|
||||
|
||||
if (!is_compat_task())
|
||||
goto send_sig;
|
||||
|
||||
for (i = 0; i < ARM_MAX_BRP; ++i) {
|
||||
if (current->thread.debug.hbp_break[i] == bp) {
|
||||
info.si_errno = (i << 1) + 1;
|
||||
break;
|
||||
for (i = 0; i < ARM_MAX_BRP; ++i) {
|
||||
if (current->thread.debug.hbp_break[i] == bp) {
|
||||
si_errno = (i << 1) + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARM_MAX_WRP; ++i) {
|
||||
if (current->thread.debug.hbp_watch[i] == bp) {
|
||||
info.si_errno = -((i << 1) + 1);
|
||||
break;
|
||||
for (i = 0; i < ARM_MAX_WRP; ++i) {
|
||||
if (current->thread.debug.hbp_watch[i] == bp) {
|
||||
si_errno = -((i << 1) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
force_sig_ptrace_errno_trap(si_errno, (void __user *)bkpt->trigger);
|
||||
}
|
||||
|
||||
send_sig:
|
||||
#endif
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
}
|
||||
|
|
|
@ -125,86 +125,6 @@ static inline int get_sigset_t(sigset_t *set,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, to, sizeof(*to)))
|
||||
return -EFAULT;
|
||||
|
||||
/* If you change siginfo_t structure, please be sure
|
||||
* this code is fixed accordingly.
|
||||
* It should never copy any pad contained in the structure
|
||||
* to avoid security leaks, but must copy the generic
|
||||
* 3 ints plus the relevant union member.
|
||||
* This routine must convert siginfo from 64bit to 32bit as well
|
||||
* at the same time.
|
||||
*/
|
||||
err = __put_user(from->si_signo, &to->si_signo);
|
||||
err |= __put_user(from->si_errno, &to->si_errno);
|
||||
err |= __put_user(from->si_code, &to->si_code);
|
||||
if (from->si_code < 0)
|
||||
err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad,
|
||||
SI_PAD_SIZE);
|
||||
else switch (siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_KILL:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
err |= __put_user(from->si_tid, &to->si_tid);
|
||||
err |= __put_user(from->si_overrun, &to->si_overrun);
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __put_user(from->si_band, &to->si_band);
|
||||
err |= __put_user(from->si_fd, &to->si_fd);
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr,
|
||||
&to->si_addr);
|
||||
#ifdef BUS_MCEERR_AO
|
||||
/*
|
||||
* Other callers might not initialize the si_lsb field,
|
||||
* so check explicitly for the right codes here.
|
||||
*/
|
||||
if (from->si_signo == SIGBUS &&
|
||||
(from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
|
||||
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
|
||||
#endif
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_status, &to->si_status);
|
||||
err |= __put_user(from->si_utime, &to->si_utime);
|
||||
err |= __put_user(from->si_stime, &to->si_stime);
|
||||
break;
|
||||
case SIL_RT:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
break;
|
||||
case SIL_SYS:
|
||||
err |= __put_user((compat_uptr_t)(unsigned long)
|
||||
from->si_call_addr, &to->si_call_addr);
|
||||
err |= __put_user(from->si_syscall, &to->si_syscall);
|
||||
err |= __put_user(from->si_arch, &to->si_arch);
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
|
||||
{
|
||||
if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
|
||||
copy_from_user(to->_sifields._pad,
|
||||
from->_sifields._pad, SI_PAD_SIZE))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* VFP save/restore code.
|
||||
*
|
||||
|
|
|
@ -596,7 +596,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
|
|||
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = 0;
|
||||
info.si_code = BUS_FIXME;
|
||||
if (esr & ESR_ELx_FnV)
|
||||
info.si_addr = NULL;
|
||||
else
|
||||
|
@ -607,70 +607,70 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
|
|||
}
|
||||
|
||||
static const struct fault_info fault_info[] = {
|
||||
{ do_bad, SIGBUS, 0, "ttbr address size fault" },
|
||||
{ do_bad, SIGBUS, 0, "level 1 address size fault" },
|
||||
{ do_bad, SIGBUS, 0, "level 2 address size fault" },
|
||||
{ do_bad, SIGBUS, 0, "level 3 address size fault" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "ttbr address size fault" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "level 1 address size fault" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "level 2 address size fault" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "level 3 address size fault" },
|
||||
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 0 translation fault" },
|
||||
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 1 translation fault" },
|
||||
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 2 translation fault" },
|
||||
{ do_translation_fault, SIGSEGV, SEGV_MAPERR, "level 3 translation fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 8" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 8" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 access flag fault" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 access flag fault" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 access flag fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 12" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 12" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
|
||||
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
|
||||
{ do_sea, SIGBUS, 0, "synchronous external abort" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 17" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 18" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 19" },
|
||||
{ do_sea, SIGBUS, 0, "level 0 (translation table walk)" },
|
||||
{ do_sea, SIGBUS, 0, "level 1 (translation table walk)" },
|
||||
{ do_sea, SIGBUS, 0, "level 2 (translation table walk)" },
|
||||
{ do_sea, SIGBUS, 0, "level 3 (translation table walk)" },
|
||||
{ do_sea, SIGBUS, 0, "synchronous parity or ECC error" }, // Reserved when RAS is implemented
|
||||
{ do_bad, SIGBUS, 0, "unknown 25" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 26" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 27" },
|
||||
{ do_sea, SIGBUS, 0, "level 0 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
|
||||
{ do_sea, SIGBUS, 0, "level 1 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
|
||||
{ do_sea, SIGBUS, 0, "level 2 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
|
||||
{ do_sea, SIGBUS, 0, "level 3 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
|
||||
{ do_bad, SIGBUS, 0, "unknown 32" },
|
||||
{ do_sea, SIGBUS, BUS_FIXME, "synchronous external abort" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 17" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 18" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 19" },
|
||||
{ do_sea, SIGBUS, BUS_FIXME, "level 0 (translation table walk)" },
|
||||
{ do_sea, SIGBUS, BUS_FIXME, "level 1 (translation table walk)" },
|
||||
{ do_sea, SIGBUS, BUS_FIXME, "level 2 (translation table walk)" },
|
||||
{ do_sea, SIGBUS, BUS_FIXME, "level 3 (translation table walk)" },
|
||||
{ do_sea, SIGBUS, BUS_FIXME, "synchronous parity or ECC error" }, // Reserved when RAS is implemented
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 25" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 26" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 27" },
|
||||
{ do_sea, SIGBUS, BUS_FIXME, "level 0 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
|
||||
{ do_sea, SIGBUS, BUS_FIXME, "level 1 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
|
||||
{ do_sea, SIGBUS, BUS_FIXME, "level 2 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
|
||||
{ do_sea, SIGBUS, BUS_FIXME, "level 3 synchronous parity error (translation table walk)" }, // Reserved when RAS is implemented
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 32" },
|
||||
{ do_alignment_fault, SIGBUS, BUS_ADRALN, "alignment fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 34" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 35" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 36" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 37" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 38" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 39" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 40" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 41" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 42" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 43" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 44" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 45" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 46" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 47" },
|
||||
{ do_bad, SIGBUS, 0, "TLB conflict abort" },
|
||||
{ do_bad, SIGBUS, 0, "Unsupported atomic hardware update fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 50" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 51" },
|
||||
{ do_bad, SIGBUS, 0, "implementation fault (lockdown abort)" },
|
||||
{ do_bad, SIGBUS, 0, "implementation fault (unsupported exclusive)" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 54" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 55" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 56" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 57" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 58" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 59" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 60" },
|
||||
{ do_bad, SIGBUS, 0, "section domain fault" },
|
||||
{ do_bad, SIGBUS, 0, "page domain fault" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 63" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 34" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 35" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 36" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 37" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 38" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 39" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 40" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 41" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 42" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 43" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 44" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 45" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 46" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 47" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "TLB conflict abort" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "Unsupported atomic hardware update fault" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 50" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 51" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "implementation fault (lockdown abort)" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "implementation fault (unsupported exclusive)" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 54" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 55" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 56" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 57" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 58" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 59" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 60" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "section domain fault" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "page domain fault" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 63" },
|
||||
};
|
||||
|
||||
int handle_guest_sea(phys_addr_t addr, unsigned int esr)
|
||||
|
@ -756,11 +756,11 @@ static struct fault_info __refdata debug_fault_info[] = {
|
|||
{ do_bad, SIGTRAP, TRAP_HWBKPT, "hardware breakpoint" },
|
||||
{ do_bad, SIGTRAP, TRAP_HWBKPT, "hardware single-step" },
|
||||
{ do_bad, SIGTRAP, TRAP_HWBKPT, "hardware watchpoint" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 3" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 3" },
|
||||
{ do_bad, SIGTRAP, TRAP_BRKPT, "aarch32 BKPT" },
|
||||
{ do_bad, SIGTRAP, 0, "aarch32 vector catch" },
|
||||
{ do_bad, SIGTRAP, TRAP_FIXME, "aarch32 vector catch" },
|
||||
{ early_brk64, SIGTRAP, TRAP_BRKPT, "aarch64 BRK" },
|
||||
{ do_bad, SIGBUS, 0, "unknown 7" },
|
||||
{ do_bad, SIGBUS, BUS_FIXME, "unknown 7" },
|
||||
};
|
||||
|
||||
void __init hook_debug_fault_code(int nr,
|
||||
|
|
|
@ -11,40 +11,6 @@
|
|||
#include <linux/types.h>
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
#define UID16_SIGINFO_COMPAT_NEEDED
|
||||
|
||||
#define si_uid16 _sifields._kill._uid
|
||||
|
||||
#define ILL_ILLPARAOP 2 /* illegal opcode combine ********** */
|
||||
#define ILL_ILLEXCPT 4 /* unrecoverable exception ********** */
|
||||
#define ILL_CPLB_VI 9 /* D/I CPLB protect violation ******** */
|
||||
#define ILL_CPLB_MISS 10 /* D/I CPLB miss ******** */
|
||||
#define ILL_CPLB_MULHIT 11 /* D/I CPLB multiple hit ******** */
|
||||
#undef NSIGILL
|
||||
#define NSIGILL 11
|
||||
|
||||
/*
|
||||
* SIGBUS si_codes
|
||||
*/
|
||||
#define BUS_OPFETCH 4 /* error from instruction fetch ******** */
|
||||
#undef NSIGBUS
|
||||
#define NSIGBUS 4
|
||||
|
||||
/*
|
||||
* SIGTRAP si_codes
|
||||
*/
|
||||
#define TRAP_STEP 1 /* single-step breakpoint************* */
|
||||
#define TRAP_TRACEFLOW 2 /* trace buffer overflow ************* */
|
||||
#define TRAP_WATCHPT 3 /* watchpoint match ************* */
|
||||
#define TRAP_ILLTRAP 4 /* illegal trap ************* */
|
||||
#undef NSIGTRAP
|
||||
#define NSIGTRAP 4
|
||||
|
||||
/*
|
||||
* SIGSEGV si_codes
|
||||
*/
|
||||
#define SEGV_STACKFLOW 3 /* stack overflow */
|
||||
#undef NSIGSEGV
|
||||
#define NSIGSEGV 3
|
||||
|
||||
#endif /* _UAPI_BFIN_SIGINFO_H */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# UAPI Header export list
|
||||
include include/uapi/asm-generic/Kbuild.asm
|
||||
|
||||
generic-y += siginfo.h
|
||||
generic-y += bpf_perf_event.h
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _ASM_SIGINFO_H
|
||||
#define _ASM_SIGINFO_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
#define FPE_MDAOVF 9 /* media overflow */
|
||||
#undef NSIGFPE
|
||||
#define NSIGFPE 9
|
||||
|
||||
#endif
|
||||
|
|
@ -11,77 +11,8 @@
|
|||
|
||||
#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
|
||||
|
||||
#define HAVE_ARCH_SIGINFO_T
|
||||
#define HAVE_ARCH_COPY_SIGINFO_TO_USER
|
||||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
typedef struct siginfo {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
int __pad0;
|
||||
|
||||
union {
|
||||
int _pad[SI_PAD_SIZE];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
pid_t _pid; /* sender's pid */
|
||||
uid_t _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
char _pad[sizeof(__ARCH_SI_UID_T) - sizeof(int)];
|
||||
sigval_t _sigval; /* must overlay ._rt._sigval! */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
pid_t _pid; /* sender's pid */
|
||||
uid_t _uid; /* sender's uid */
|
||||
sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
pid_t _pid; /* which child */
|
||||
uid_t _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
clock_t _utime;
|
||||
clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
struct {
|
||||
void __user *_addr; /* faulting insn/memory ref. */
|
||||
int _imm; /* immediate value for "break" */
|
||||
unsigned int _flags; /* see below */
|
||||
unsigned long _isr; /* isr */
|
||||
short _addr_lsb; /* lsb of faulting address */
|
||||
union {
|
||||
/* used when si_code=SEGV_BNDERR */
|
||||
struct {
|
||||
void __user *_lower;
|
||||
void __user *_upper;
|
||||
} _addr_bnd;
|
||||
/* used when si_code=SEGV_PKUERR */
|
||||
__u32 _pkey;
|
||||
};
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
long _band; /* POLL_IN, POLL_OUT, POLL_MSG (XPG requires a "long") */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
} _sifields;
|
||||
} siginfo_t;
|
||||
|
||||
#define si_imm _sifields._sigfault._imm /* as per UNIX SysV ABI spec */
|
||||
#define si_flags _sifields._sigfault._flags
|
||||
/*
|
||||
|
@ -96,38 +27,11 @@ typedef struct siginfo {
|
|||
#define __ISR_VALID_BIT 0
|
||||
#define __ISR_VALID (1 << __ISR_VALID_BIT)
|
||||
|
||||
/*
|
||||
* SIGILL si_codes
|
||||
*/
|
||||
#define ILL_BADIADDR 9 /* unimplemented instruction address */
|
||||
#define __ILL_BREAK 10 /* illegal break */
|
||||
#define __ILL_BNDMOD 11 /* bundle-update (modification) in progress */
|
||||
#undef NSIGILL
|
||||
#define NSIGILL 11
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define FPE_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
#define __FPE_DECOVF 9 /* decimal overflow */
|
||||
#define __FPE_DECDIV 10 /* decimal division by zero */
|
||||
#define __FPE_DECERR 11 /* packed decimal error */
|
||||
#define __FPE_INVASC 12 /* invalid ASCII digit */
|
||||
#define __FPE_INVDEC 13 /* invalid decimal digit */
|
||||
#undef NSIGFPE
|
||||
#define NSIGFPE 13
|
||||
|
||||
/*
|
||||
* SIGSEGV si_codes
|
||||
*/
|
||||
#define __SEGV_PSTKOVF 4 /* paragraph stack overflow */
|
||||
#undef NSIGSEGV
|
||||
#define NSIGSEGV 4
|
||||
|
||||
#undef NSIGTRAP
|
||||
#define NSIGTRAP 4
|
||||
|
||||
|
||||
#endif /* _UAPI_ASM_IA64_SIGINFO_H */
|
||||
|
|
|
@ -105,58 +105,6 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
|
|||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
copy_siginfo_to_user (siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t)))
|
||||
return -EFAULT;
|
||||
if (from->si_code < 0) {
|
||||
if (__copy_to_user(to, from, sizeof(siginfo_t)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
} else {
|
||||
int err;
|
||||
|
||||
/*
|
||||
* If you change siginfo_t structure, please be sure this code is fixed
|
||||
* accordingly. It should never copy any pad contained in the structure
|
||||
* to avoid security leaks, but must copy the generic 3 ints plus the
|
||||
* relevant union member.
|
||||
*/
|
||||
err = __put_user(from->si_signo, &to->si_signo);
|
||||
err |= __put_user(from->si_errno, &to->si_errno);
|
||||
err |= __put_user(from->si_code, &to->si_code);
|
||||
switch (siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_FAULT:
|
||||
err |= __put_user(from->si_flags, &to->si_flags);
|
||||
err |= __put_user(from->si_isr, &to->si_isr);
|
||||
case SIL_POLL:
|
||||
err |= __put_user(from->si_addr, &to->si_addr);
|
||||
err |= __put_user(from->si_imm, &to->si_imm);
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
err |= __put_user(from->si_tid, &to->si_tid);
|
||||
err |= __put_user(from->si_overrun, &to->si_overrun);
|
||||
err |= __put_user(from->si_ptr, &to->si_ptr);
|
||||
break;
|
||||
case SIL_RT:
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_ptr, &to->si_ptr);
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
err |= __put_user(from->si_utime, &to->si_utime);
|
||||
err |= __put_user(from->si_stime, &to->si_stime);
|
||||
err |= __put_user(from->si_status, &to->si_status);
|
||||
case SIL_KILL:
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
long
|
||||
ia64_rt_sigreturn (struct sigscratch *scr)
|
||||
{
|
||||
|
|
|
@ -21,8 +21,9 @@ extern void die_if_kernel(char *, struct pt_regs *, long);
|
|||
|
||||
int send_fault_sig(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t siginfo = { 0, 0, 0, };
|
||||
siginfo_t siginfo;
|
||||
|
||||
clear_siginfo(&siginfo);
|
||||
siginfo.si_signo = current->thread.signo;
|
||||
siginfo.si_code = current->thread.code;
|
||||
siginfo.si_addr = (void *)current->thread.faddr;
|
||||
|
|
|
@ -6,4 +6,11 @@
|
|||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define FPE_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -735,7 +735,7 @@ TBIRES fpe_handler(TBIRES State, int SigNum, int Triggers, int Inst, PTBI pTBI)
|
|||
else if (error_state & TXSTAT_FPE_INEXACT_BIT)
|
||||
info.si_code = FPE_FLTRES;
|
||||
else
|
||||
info.si_code = 0;
|
||||
info.si_code = FPE_FIXME;
|
||||
info.si_errno = 0;
|
||||
info.si_addr = (__force void __user *)regs->ctx.CurrPC;
|
||||
force_sig_info(SIGFPE, &info, current);
|
||||
|
|
|
@ -126,79 +126,6 @@ typedef u32 compat_old_sigset_t; /* at least 32 bits */
|
|||
|
||||
typedef u32 compat_sigset_word;
|
||||
|
||||
typedef union compat_sigval {
|
||||
compat_int_t sival_int;
|
||||
compat_uptr_t sival_ptr;
|
||||
} compat_sigval_t;
|
||||
|
||||
/* Can't use the generic version because si_code and si_errno are swapped */
|
||||
|
||||
#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
|
||||
|
||||
typedef struct compat_siginfo {
|
||||
int si_signo;
|
||||
int si_code;
|
||||
int si_errno;
|
||||
|
||||
union {
|
||||
int _pad[128 / sizeof(int) - 3];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
compat_pid_t _pid; /* sender's pid */
|
||||
__compat_uid32_t _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
compat_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
compat_sigval_t _sigval; /* same as below */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
compat_pid_t _pid; /* sender's pid */
|
||||
__compat_uid32_t _uid; /* sender's uid */
|
||||
compat_sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
compat_pid_t _pid; /* which child */
|
||||
__compat_uid32_t _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_clock_t _utime;
|
||||
compat_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
struct {
|
||||
compat_uptr_t _addr; /* faulting insn/memory ref. */
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
int _trapno; /* TRAP # which caused the signal */
|
||||
#endif
|
||||
short _addr_lsb; /* LSB of the reported address */
|
||||
struct {
|
||||
compat_uptr_t _lower;
|
||||
compat_uptr_t _upper;
|
||||
} _addr_bnd;
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
|
||||
struct {
|
||||
compat_uptr_t _call_addr; /* calling insn */
|
||||
int _syscall; /* triggering system call number */
|
||||
compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */
|
||||
} _sigsys;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
/*
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
#define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(long) + 2*sizeof(int))
|
||||
#undef __ARCH_SI_TRAPNO /* exception code needs to fill this ... */
|
||||
|
||||
#define HAVE_ARCH_SIGINFO_T
|
||||
|
||||
/*
|
||||
* Careful to keep union _sifields from shifting ...
|
||||
*/
|
||||
|
@ -27,92 +25,10 @@
|
|||
#error _MIPS_SZLONG neither 32 nor 64
|
||||
#endif
|
||||
|
||||
#define __ARCH_SIGSYS
|
||||
#define __ARCH_HAS_SWAPPED_SIGINFO
|
||||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
/* We can't use generic siginfo_t, because our si_code and si_errno are swapped */
|
||||
typedef struct siginfo {
|
||||
int si_signo;
|
||||
int si_code;
|
||||
int si_errno;
|
||||
int __pad0[SI_MAX_SIZE / sizeof(int) - SI_PAD_SIZE - 3];
|
||||
|
||||
union {
|
||||
int _pad[SI_PAD_SIZE];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
__kernel_pid_t _pid; /* sender's pid */
|
||||
__ARCH_SI_UID_T _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
__kernel_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
|
||||
sigval_t _sigval; /* same as below */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
__kernel_pid_t _pid; /* sender's pid */
|
||||
__ARCH_SI_UID_T _uid; /* sender's uid */
|
||||
sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
__kernel_pid_t _pid; /* which child */
|
||||
__ARCH_SI_UID_T _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
__kernel_clock_t _utime;
|
||||
__kernel_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* IRIX SIGCHLD */
|
||||
struct {
|
||||
__kernel_pid_t _pid; /* which child */
|
||||
__kernel_clock_t _utime;
|
||||
int _status; /* exit code */
|
||||
__kernel_clock_t _stime;
|
||||
} _irix_sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
struct {
|
||||
void __user *_addr; /* faulting insn/memory ref. */
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
int _trapno; /* TRAP # which caused the signal */
|
||||
#endif
|
||||
short _addr_lsb;
|
||||
union {
|
||||
/* used when si_code=SEGV_BNDERR */
|
||||
struct {
|
||||
void __user *_lower;
|
||||
void __user *_upper;
|
||||
} _addr_bnd;
|
||||
/* used when si_code=SEGV_PKUERR */
|
||||
__u32 _pkey;
|
||||
};
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL, SIGXFSZ (To do ...) */
|
||||
struct {
|
||||
__ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
|
||||
/* SIGSYS */
|
||||
struct {
|
||||
void __user *_call_addr; /* calling user insn */
|
||||
int _syscall; /* triggering system call number */
|
||||
unsigned int _arch; /* AUDIT_ARCH_* of syscall */
|
||||
} _sigsys;
|
||||
} _sifields;
|
||||
} siginfo_t;
|
||||
|
||||
/*
|
||||
* si_code values
|
||||
* Again these have been chosen to be IRIX compatible.
|
||||
|
|
|
@ -76,70 +76,3 @@ SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
|
||||
return -EFAULT;
|
||||
|
||||
/* If you change siginfo_t structure, please be sure
|
||||
this code is fixed accordingly.
|
||||
It should never copy any pad contained in the structure
|
||||
to avoid security leaks, but must copy the generic
|
||||
3 ints plus the relevant union member.
|
||||
This routine must convert siginfo from 64bit to 32bit as well
|
||||
at the same time. */
|
||||
err = __put_user(from->si_signo, &to->si_signo);
|
||||
err |= __put_user(from->si_errno, &to->si_errno);
|
||||
err |= __put_user(from->si_code, &to->si_code);
|
||||
if (from->si_code < 0)
|
||||
err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
|
||||
else {
|
||||
switch (siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_TIMER:
|
||||
err |= __put_user(from->si_tid, &to->si_tid);
|
||||
err |= __put_user(from->si_overrun, &to->si_overrun);
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
err |= __put_user(from->si_utime, &to->si_utime);
|
||||
err |= __put_user(from->si_stime, &to->si_stime);
|
||||
err |= __put_user(from->si_status, &to->si_status);
|
||||
case SIL_KILL:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __put_user(from->si_band, &to->si_band);
|
||||
err |= __put_user(from->si_fd, &to->si_fd);
|
||||
break;
|
||||
case SIL_RT:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
break;
|
||||
case SIL_SYS:
|
||||
err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr,
|
||||
sizeof(compat_uptr_t));
|
||||
err |= __put_user(from->si_syscall, &to->si_syscall);
|
||||
err |= __put_user(from->si_arch, &to->si_arch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
|
||||
{
|
||||
if (copy_from_user(to, from, 3*sizeof(int)) ||
|
||||
copy_from_user(to->_sifields._pad,
|
||||
from->_sifields._pad, SI_PAD_SIZE32))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -699,11 +699,12 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
|
|||
asmlinkage void do_ov(struct pt_regs *regs)
|
||||
{
|
||||
enum ctx_state prev_state;
|
||||
siginfo_t info = {
|
||||
.si_signo = SIGFPE,
|
||||
.si_code = FPE_INTOVF,
|
||||
.si_addr = (void __user *)regs->cp0_epc,
|
||||
};
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_code = FPE_INTOVF;
|
||||
info.si_addr = (void __user *)regs->cp0_epc;
|
||||
|
||||
prev_state = exception_enter();
|
||||
die_if_kernel("Integer overflow", regs);
|
||||
|
@ -721,7 +722,11 @@ asmlinkage void do_ov(struct pt_regs *regs)
|
|||
void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
struct siginfo si = { .si_addr = fault_addr, .si_signo = SIGFPE };
|
||||
struct siginfo si;
|
||||
|
||||
clear_siginfo(&si);
|
||||
si.si_addr = fault_addr;
|
||||
si.si_signo = SIGFPE;
|
||||
|
||||
if (fcr31 & FPU_CSR_INV_X)
|
||||
si.si_code = FPE_FLTINV;
|
||||
|
@ -739,9 +744,10 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
|
|||
|
||||
int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
|
||||
{
|
||||
struct siginfo si = { 0 };
|
||||
struct siginfo si;
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
clear_siginfo(&si);
|
||||
switch (sig) {
|
||||
case 0:
|
||||
return 0;
|
||||
|
@ -890,9 +896,10 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
|
|||
void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
|
||||
const char *str)
|
||||
{
|
||||
siginfo_t info = { 0 };
|
||||
siginfo_t info;
|
||||
char b[40];
|
||||
|
||||
clear_siginfo(&info);
|
||||
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
|
||||
if (kgdb_ll_trap(DIE_TRAP, str, regs, code, current->thread.trap_nr,
|
||||
SIGTRAP) == NOTIFY_STOP)
|
||||
|
@ -1499,9 +1506,13 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
|
|||
*/
|
||||
asmlinkage void do_watch(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT };
|
||||
siginfo_t info;
|
||||
enum ctx_state prev_state;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_code = TRAP_HWBKPT;
|
||||
|
||||
prev_state = exception_enter();
|
||||
/*
|
||||
* Clear WP (bit 22) bit of cause register so we don't loop
|
||||
|
|
|
@ -437,7 +437,7 @@ asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code)
|
|||
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = 0;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
info.si_addr = (void *) regs->pc;
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
return;
|
||||
|
|
|
@ -266,12 +266,12 @@ asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
|
|||
siginfo_t info;
|
||||
|
||||
if (user_mode(regs)) {
|
||||
/* Send a SIGSEGV */
|
||||
info.si_signo = SIGSEGV;
|
||||
/* Send a SIGBUS */
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
/* info.si_code has been set above */
|
||||
info.si_addr = (void *)address;
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = (void __user *)address;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
} else {
|
||||
printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
|
||||
show_registers(regs);
|
||||
|
|
|
@ -130,70 +130,6 @@ typedef u32 compat_old_sigset_t; /* at least 32 bits */
|
|||
|
||||
typedef u32 compat_sigset_word;
|
||||
|
||||
typedef union compat_sigval {
|
||||
compat_int_t sival_int;
|
||||
compat_uptr_t sival_ptr;
|
||||
} compat_sigval_t;
|
||||
|
||||
typedef struct compat_siginfo {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
|
||||
union {
|
||||
int _pad[128/sizeof(int) - 3];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
unsigned int _pid; /* sender's pid */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
compat_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
char _pad[sizeof(unsigned int) - sizeof(int)];
|
||||
compat_sigval_t _sigval; /* same as below */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
unsigned int _pid; /* sender's pid */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
compat_sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
unsigned int _pid; /* which child */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_clock_t _utime;
|
||||
compat_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
struct {
|
||||
unsigned int _addr; /* faulting insn/memory ref. */
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
|
||||
/* SIGSYS */
|
||||
struct {
|
||||
compat_uptr_t _call_addr; /* calling user insn */
|
||||
int _syscall; /* triggering system call number */
|
||||
compat_uint_t _arch; /* AUDIT_ARCH_* of syscall */
|
||||
} _sigsys;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
struct compat_ipc64_perm {
|
||||
|
|
|
@ -8,4 +8,11 @@
|
|||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define FPE_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -325,7 +325,7 @@ static int pdt_mainloop(void *unused)
|
|||
#ifdef CONFIG_MEMORY_FAILURE
|
||||
if ((pde & PDT_ADDR_PERM_ERR) ||
|
||||
((pde & PDT_ADDR_SINGLE_ERR) == 0))
|
||||
memory_failure(pde >> PAGE_SHIFT, 0, 0);
|
||||
memory_failure(pde >> PAGE_SHIFT, 0);
|
||||
else
|
||||
soft_offline_page(
|
||||
pfn_to_page(pde >> PAGE_SHIFT), 0);
|
||||
|
|
|
@ -260,109 +260,3 @@ setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
|
||||
{
|
||||
compat_uptr_t addr;
|
||||
int err;
|
||||
|
||||
if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
|
||||
return -EFAULT;
|
||||
|
||||
err = __get_user(to->si_signo, &from->si_signo);
|
||||
err |= __get_user(to->si_errno, &from->si_errno);
|
||||
err |= __get_user(to->si_code, &from->si_code);
|
||||
|
||||
if (to->si_code < 0)
|
||||
err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
|
||||
else {
|
||||
switch (siginfo_layout(to->si_signo, to->si_code)) {
|
||||
case SIL_CHLD:
|
||||
err |= __get_user(to->si_utime, &from->si_utime);
|
||||
err |= __get_user(to->si_stime, &from->si_stime);
|
||||
err |= __get_user(to->si_status, &from->si_status);
|
||||
default:
|
||||
case SIL_KILL:
|
||||
err |= __get_user(to->si_pid, &from->si_pid);
|
||||
err |= __get_user(to->si_uid, &from->si_uid);
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
err |= __get_user(addr, &from->si_addr);
|
||||
to->si_addr = compat_ptr(addr);
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __get_user(to->si_band, &from->si_band);
|
||||
err |= __get_user(to->si_fd, &from->si_fd);
|
||||
break;
|
||||
case SIL_RT:
|
||||
err |= __get_user(to->si_pid, &from->si_pid);
|
||||
err |= __get_user(to->si_uid, &from->si_uid);
|
||||
err |= __get_user(to->si_int, &from->si_int);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
compat_uptr_t addr;
|
||||
compat_int_t val;
|
||||
int err;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
|
||||
return -EFAULT;
|
||||
|
||||
/* If you change siginfo_t structure, please be sure
|
||||
this code is fixed accordingly.
|
||||
It should never copy any pad contained in the structure
|
||||
to avoid security leaks, but must copy the generic
|
||||
3 ints plus the relevant union member.
|
||||
This routine must convert siginfo from 64bit to 32bit as well
|
||||
at the same time. */
|
||||
err = __put_user(from->si_signo, &to->si_signo);
|
||||
err |= __put_user(from->si_errno, &to->si_errno);
|
||||
err |= __put_user(from->si_code, &to->si_code);
|
||||
if (from->si_code < 0)
|
||||
err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
|
||||
else {
|
||||
switch (siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_CHLD:
|
||||
err |= __put_user(from->si_utime, &to->si_utime);
|
||||
err |= __put_user(from->si_stime, &to->si_stime);
|
||||
err |= __put_user(from->si_status, &to->si_status);
|
||||
case SIL_KILL:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
addr = ptr_to_compat(from->si_addr);
|
||||
err |= __put_user(addr, &to->si_addr);
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __put_user(from->si_band, &to->si_band);
|
||||
err |= __put_user(from->si_fd, &to->si_fd);
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
err |= __put_user(from->si_tid, &to->si_tid);
|
||||
err |= __put_user(from->si_overrun, &to->si_overrun);
|
||||
val = (compat_int_t)from->si_int;
|
||||
err |= __put_user(val, &to->si_int);
|
||||
break;
|
||||
case SIL_RT:
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
val = (compat_int_t)from->si_int;
|
||||
err |= __put_user(val, &to->si_int);
|
||||
break;
|
||||
case SIL_SYS:
|
||||
err |= __put_user(ptr_to_compat(from->si_call_addr), &to->si_call_addr);
|
||||
err |= __put_user(from->si_syscall, &to->si_syscall);
|
||||
err |= __put_user(from->si_arch, &to->si_arch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -34,9 +34,6 @@ struct compat_ucontext {
|
|||
|
||||
/* ELF32 signal handling */
|
||||
|
||||
int copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from);
|
||||
int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from);
|
||||
|
||||
/* In a deft move of uber-hackery, we decide to carry the top half of all
|
||||
* 64-bit registers in a non-portable, non-ABI, hidden structure.
|
||||
* Userspace can read the hidden structure if it *wants* but is never
|
||||
|
|
|
@ -629,7 +629,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
|||
si.si_signo = SIGFPE;
|
||||
/* Set to zero, and let the userspace app figure it out from
|
||||
the insn pointed to by si_addr */
|
||||
si.si_code = 0;
|
||||
si.si_code = FPE_FIXME;
|
||||
si.si_addr = (void __user *) regs->iaoq[0];
|
||||
force_sig_info(SIGFPE, &si, current);
|
||||
return;
|
||||
|
|
|
@ -119,71 +119,6 @@ typedef u32 compat_old_sigset_t;
|
|||
|
||||
typedef u32 compat_sigset_word;
|
||||
|
||||
typedef union compat_sigval {
|
||||
compat_int_t sival_int;
|
||||
compat_uptr_t sival_ptr;
|
||||
} compat_sigval_t;
|
||||
|
||||
#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
|
||||
|
||||
typedef struct compat_siginfo {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
|
||||
union {
|
||||
int _pad[SI_PAD_SIZE32];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
compat_pid_t _pid; /* sender's pid */
|
||||
__compat_uid_t _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
compat_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
compat_sigval_t _sigval; /* same as below */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
compat_pid_t _pid; /* sender's pid */
|
||||
__compat_uid_t _uid; /* sender's uid */
|
||||
compat_sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
compat_pid_t _pid; /* which child */
|
||||
__compat_uid_t _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_clock_t _utime;
|
||||
compat_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
|
||||
struct {
|
||||
unsigned int _addr; /* faulting insn/memory ref. */
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
|
||||
/* SIGSYS */
|
||||
struct {
|
||||
unsigned int _call_addr; /* calling insn */
|
||||
int _syscall; /* triggering system call number */
|
||||
unsigned int _arch; /* AUDIT_ARCH_* of syscall */
|
||||
} _sigsys;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
/*
|
||||
|
|
|
@ -49,7 +49,7 @@ void set_breakpoint(struct arch_hw_breakpoint *brk);
|
|||
void __set_breakpoint(struct arch_hw_breakpoint *brk);
|
||||
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
|
||||
extern void do_send_trap(struct pt_regs *regs, unsigned long address,
|
||||
unsigned long error_code, int signal_code, int brkpt);
|
||||
unsigned long error_code, int brkpt);
|
||||
#else
|
||||
|
||||
extern void do_break(struct pt_regs *regs, unsigned long address,
|
||||
|
|
|
@ -15,7 +15,19 @@
|
|||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
#undef NSIGTRAP
|
||||
#define NSIGTRAP 4
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define FPE_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
* SIGTRAP si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define TRAP_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
||||
#endif /* _ASM_POWERPC_SIGINFO_H */
|
||||
|
|
|
@ -273,7 +273,7 @@ static void machine_process_ue_event(struct work_struct *work)
|
|||
|
||||
pfn = evt->u.ue_error.physical_address >>
|
||||
PAGE_SHIFT;
|
||||
memory_failure(pfn, SIGBUS, 0);
|
||||
memory_failure(pfn, 0);
|
||||
} else
|
||||
pr_warn("Failed to identify bad address from "
|
||||
"where the uncorrectable error (UE) "
|
||||
|
|
|
@ -601,21 +601,16 @@ EXPORT_SYMBOL(flush_all_to_thread);
|
|||
|
||||
#ifdef CONFIG_PPC_ADV_DEBUG_REGS
|
||||
void do_send_trap(struct pt_regs *regs, unsigned long address,
|
||||
unsigned long error_code, int signal_code, int breakpt)
|
||||
unsigned long error_code, int breakpt)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
current->thread.trap_nr = signal_code;
|
||||
current->thread.trap_nr = TRAP_HWBKPT;
|
||||
if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
|
||||
11, SIGSEGV) == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
/* Deliver the signal to userspace */
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = breakpt; /* breakpoint or watchpoint id */
|
||||
info.si_code = signal_code;
|
||||
info.si_addr = (void __user *)address;
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
force_sig_ptrace_errno_trap(breakpt, /* breakpoint or watchpoint id */
|
||||
(void __user *)address);
|
||||
}
|
||||
#else /* !CONFIG_PPC_ADV_DEBUG_REGS */
|
||||
void do_break (struct pt_regs *regs, unsigned long address,
|
||||
|
|
|
@ -873,75 +873,9 @@ static long restore_tm_user_regs(struct pt_regs *regs,
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
int copy_siginfo_to_user32(struct compat_siginfo __user *d, const siginfo_t *s)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!access_ok (VERIFY_WRITE, d, sizeof(*d)))
|
||||
return -EFAULT;
|
||||
|
||||
/* If you change siginfo_t structure, please be sure
|
||||
* this code is fixed accordingly.
|
||||
* It should never copy any pad contained in the structure
|
||||
* to avoid security leaks, but must copy the generic
|
||||
* 3 ints plus the relevant union member.
|
||||
* This routine must convert siginfo from 64bit to 32bit as well
|
||||
* at the same time.
|
||||
*/
|
||||
err = __put_user(s->si_signo, &d->si_signo);
|
||||
err |= __put_user(s->si_errno, &d->si_errno);
|
||||
err |= __put_user(s->si_code, &d->si_code);
|
||||
if (s->si_code < 0)
|
||||
err |= __copy_to_user(&d->_sifields._pad, &s->_sifields._pad,
|
||||
SI_PAD_SIZE32);
|
||||
else switch(siginfo_layout(s->si_signo, s->si_code)) {
|
||||
case SIL_CHLD:
|
||||
err |= __put_user(s->si_pid, &d->si_pid);
|
||||
err |= __put_user(s->si_uid, &d->si_uid);
|
||||
err |= __put_user(s->si_utime, &d->si_utime);
|
||||
err |= __put_user(s->si_stime, &d->si_stime);
|
||||
err |= __put_user(s->si_status, &d->si_status);
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
err |= __put_user((unsigned int)(unsigned long)s->si_addr,
|
||||
&d->si_addr);
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __put_user(s->si_band, &d->si_band);
|
||||
err |= __put_user(s->si_fd, &d->si_fd);
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
err |= __put_user(s->si_tid, &d->si_tid);
|
||||
err |= __put_user(s->si_overrun, &d->si_overrun);
|
||||
err |= __put_user(s->si_int, &d->si_int);
|
||||
break;
|
||||
case SIL_SYS:
|
||||
err |= __put_user(ptr_to_compat(s->si_call_addr), &d->si_call_addr);
|
||||
err |= __put_user(s->si_syscall, &d->si_syscall);
|
||||
err |= __put_user(s->si_arch, &d->si_arch);
|
||||
break;
|
||||
case SIL_RT:
|
||||
err |= __put_user(s->si_int, &d->si_int);
|
||||
/* fallthrough */
|
||||
case SIL_KILL:
|
||||
err |= __put_user(s->si_pid, &d->si_pid);
|
||||
err |= __put_user(s->si_uid, &d->si_uid);
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#define copy_siginfo_to_user copy_siginfo_to_user32
|
||||
|
||||
int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
|
||||
{
|
||||
if (copy_from_user(to, from, 3*sizeof(int)) ||
|
||||
copy_from_user(to->_sifields._pad,
|
||||
from->_sifields._pad, SI_PAD_SIZE32))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
/*
|
||||
|
|
|
@ -917,7 +917,7 @@ void unknown_exception(struct pt_regs *regs)
|
|||
printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
|
||||
regs->nip, regs->msr, regs->trap);
|
||||
|
||||
_exception(SIGTRAP, regs, 0, 0);
|
||||
_exception(SIGTRAP, regs, TRAP_FIXME, 0);
|
||||
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
@ -939,7 +939,7 @@ void instruction_breakpoint_exception(struct pt_regs *regs)
|
|||
|
||||
void RunModeException(struct pt_regs *regs)
|
||||
{
|
||||
_exception(SIGTRAP, regs, 0, 0);
|
||||
_exception(SIGTRAP, regs, TRAP_FIXME, 0);
|
||||
}
|
||||
|
||||
void single_step_exception(struct pt_regs *regs)
|
||||
|
@ -978,7 +978,7 @@ static void emulate_single_step(struct pt_regs *regs)
|
|||
|
||||
static inline int __parse_fpscr(unsigned long fpscr)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = FPE_FIXME;
|
||||
|
||||
/* Invalid operation */
|
||||
if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX))
|
||||
|
@ -1750,34 +1750,34 @@ static void handle_debug(struct pt_regs *regs, unsigned long debug_status)
|
|||
#ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE
|
||||
current->thread.debug.dbcr2 &= ~DBCR2_DAC12MODE;
|
||||
#endif
|
||||
do_send_trap(regs, mfspr(SPRN_DAC1), debug_status, TRAP_HWBKPT,
|
||||
do_send_trap(regs, mfspr(SPRN_DAC1), debug_status,
|
||||
5);
|
||||
changed |= 0x01;
|
||||
} else if (debug_status & (DBSR_DAC2R | DBSR_DAC2W)) {
|
||||
dbcr_dac(current) &= ~(DBCR_DAC2R | DBCR_DAC2W);
|
||||
do_send_trap(regs, mfspr(SPRN_DAC2), debug_status, TRAP_HWBKPT,
|
||||
do_send_trap(regs, mfspr(SPRN_DAC2), debug_status,
|
||||
6);
|
||||
changed |= 0x01;
|
||||
} else if (debug_status & DBSR_IAC1) {
|
||||
current->thread.debug.dbcr0 &= ~DBCR0_IAC1;
|
||||
dbcr_iac_range(current) &= ~DBCR_IAC12MODE;
|
||||
do_send_trap(regs, mfspr(SPRN_IAC1), debug_status, TRAP_HWBKPT,
|
||||
do_send_trap(regs, mfspr(SPRN_IAC1), debug_status,
|
||||
1);
|
||||
changed |= 0x01;
|
||||
} else if (debug_status & DBSR_IAC2) {
|
||||
current->thread.debug.dbcr0 &= ~DBCR0_IAC2;
|
||||
do_send_trap(regs, mfspr(SPRN_IAC2), debug_status, TRAP_HWBKPT,
|
||||
do_send_trap(regs, mfspr(SPRN_IAC2), debug_status,
|
||||
2);
|
||||
changed |= 0x01;
|
||||
} else if (debug_status & DBSR_IAC3) {
|
||||
current->thread.debug.dbcr0 &= ~DBCR0_IAC3;
|
||||
dbcr_iac_range(current) &= ~DBCR_IAC34MODE;
|
||||
do_send_trap(regs, mfspr(SPRN_IAC3), debug_status, TRAP_HWBKPT,
|
||||
do_send_trap(regs, mfspr(SPRN_IAC3), debug_status,
|
||||
3);
|
||||
changed |= 0x01;
|
||||
} else if (debug_status & DBSR_IAC4) {
|
||||
current->thread.debug.dbcr0 &= ~DBCR0_IAC4;
|
||||
do_send_trap(regs, mfspr(SPRN_IAC4), debug_status, TRAP_HWBKPT,
|
||||
do_send_trap(regs, mfspr(SPRN_IAC4), debug_status,
|
||||
4);
|
||||
changed |= 0x01;
|
||||
}
|
||||
|
@ -1929,7 +1929,7 @@ void SPEFloatingPointException(struct pt_regs *regs)
|
|||
extern int do_spe_mathemu(struct pt_regs *regs);
|
||||
unsigned long spefscr;
|
||||
int fpexc_mode;
|
||||
int code = 0;
|
||||
int code = FPE_FIXME;
|
||||
int err;
|
||||
|
||||
flush_spe_to_thread(current);
|
||||
|
@ -1998,7 +1998,7 @@ void SPEFloatingPointRoundException(struct pt_regs *regs)
|
|||
printk(KERN_ERR "unrecognized spe instruction "
|
||||
"in %s at %lx\n", current->comm, regs->nip);
|
||||
} else {
|
||||
_exception(SIGFPE, regs, 0, regs->nip);
|
||||
_exception(SIGFPE, regs, FPE_FIXME, regs->nip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ static void handle_memory_error_event(struct OpalMemoryErrorData *merr_evt)
|
|||
}
|
||||
|
||||
for (; paddr_start < paddr_end; paddr_start += PAGE_SIZE) {
|
||||
memory_failure(paddr_start >> PAGE_SHIFT, 0, 0);
|
||||
memory_failure(paddr_start >> PAGE_SHIFT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -189,79 +189,6 @@ typedef u32 compat_old_sigset_t; /* at least 32 bits */
|
|||
|
||||
typedef u32 compat_sigset_word;
|
||||
|
||||
typedef union compat_sigval {
|
||||
compat_int_t sival_int;
|
||||
compat_uptr_t sival_ptr;
|
||||
} compat_sigval_t;
|
||||
|
||||
typedef struct compat_siginfo {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
|
||||
union {
|
||||
int _pad[128/sizeof(int) - 3];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
pid_t _pid; /* sender's pid */
|
||||
uid_t _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
compat_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
compat_sigval_t _sigval; /* same as below */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
pid_t _pid; /* sender's pid */
|
||||
uid_t _uid; /* sender's uid */
|
||||
compat_sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
pid_t _pid; /* which child */
|
||||
uid_t _uid; /* sender's uid */
|
||||
int _status;/* exit code */
|
||||
compat_clock_t _utime;
|
||||
compat_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
struct {
|
||||
__u32 _addr; /* faulting insn/memory ref. - pointer */
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
/*
|
||||
* How these fields are to be accessed.
|
||||
*/
|
||||
#define si_pid _sifields._kill._pid
|
||||
#define si_uid _sifields._kill._uid
|
||||
#define si_status _sifields._sigchld._status
|
||||
#define si_utime _sifields._sigchld._utime
|
||||
#define si_stime _sifields._sigchld._stime
|
||||
#define si_value _sifields._rt._sigval
|
||||
#define si_int _sifields._rt._sigval.sival_int
|
||||
#define si_ptr _sifields._rt._sigval.sival_ptr
|
||||
#define si_addr _sifields._sigfault._addr
|
||||
#define si_band _sifields._sigpoll._band
|
||||
#define si_fd _sifields._sigpoll._fd
|
||||
#define si_tid _sifields._timer._tid
|
||||
#define si_overrun _sifields._timer._overrun
|
||||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
/*
|
||||
|
|
|
@ -50,106 +50,6 @@ typedef struct
|
|||
struct ucontext32 uc;
|
||||
} rt_sigframe32;
|
||||
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* If you change siginfo_t structure, please be sure
|
||||
this code is fixed accordingly.
|
||||
It should never copy any pad contained in the structure
|
||||
to avoid security leaks, but must copy the generic
|
||||
3 ints plus the relevant union member.
|
||||
This routine must convert siginfo from 64bit to 32bit as well
|
||||
at the same time. */
|
||||
err = __put_user(from->si_signo, &to->si_signo);
|
||||
err |= __put_user(from->si_errno, &to->si_errno);
|
||||
err |= __put_user(from->si_code, &to->si_code);
|
||||
if (from->si_code < 0)
|
||||
err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
|
||||
else {
|
||||
switch (siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_RT:
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
/* fallthrough */
|
||||
case SIL_KILL:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_utime, &to->si_utime);
|
||||
err |= __put_user(from->si_stime, &to->si_stime);
|
||||
err |= __put_user(from->si_status, &to->si_status);
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
err |= __put_user((unsigned long) from->si_addr,
|
||||
&to->si_addr);
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __put_user(from->si_band, &to->si_band);
|
||||
err |= __put_user(from->si_fd, &to->si_fd);
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
err |= __put_user(from->si_tid, &to->si_tid);
|
||||
err |= __put_user(from->si_overrun, &to->si_overrun);
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
|
||||
{
|
||||
int err;
|
||||
u32 tmp;
|
||||
|
||||
err = __get_user(to->si_signo, &from->si_signo);
|
||||
err |= __get_user(to->si_errno, &from->si_errno);
|
||||
err |= __get_user(to->si_code, &from->si_code);
|
||||
|
||||
if (to->si_code < 0)
|
||||
err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
|
||||
else {
|
||||
switch (siginfo_layout(to->si_signo, to->si_code)) {
|
||||
case SIL_RT:
|
||||
err |= __get_user(to->si_int, &from->si_int);
|
||||
/* fallthrough */
|
||||
case SIL_KILL:
|
||||
err |= __get_user(to->si_pid, &from->si_pid);
|
||||
err |= __get_user(to->si_uid, &from->si_uid);
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
err |= __get_user(to->si_pid, &from->si_pid);
|
||||
err |= __get_user(to->si_uid, &from->si_uid);
|
||||
err |= __get_user(to->si_utime, &from->si_utime);
|
||||
err |= __get_user(to->si_stime, &from->si_stime);
|
||||
err |= __get_user(to->si_status, &from->si_status);
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
err |= __get_user(tmp, &from->si_addr);
|
||||
to->si_addr = (void __force __user *)
|
||||
(u64) (tmp & PSW32_ADDR_INSN);
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __get_user(to->si_band, &from->si_band);
|
||||
err |= __get_user(to->si_fd, &from->si_fd);
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
err |= __get_user(to->si_tid, &from->si_tid);
|
||||
err |= __get_user(to->si_overrun, &from->si_overrun);
|
||||
err |= __get_user(to->si_int, &from->si_int);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
/* Store registers needed to create the signal frame */
|
||||
static void store_sigregs(void)
|
||||
{
|
||||
|
|
|
@ -609,7 +609,8 @@ asmlinkage void do_divide_error(unsigned long r4)
|
|||
break;
|
||||
}
|
||||
|
||||
force_sig_info(SIGFPE, &info, current);
|
||||
info.si_signo = SIGFPE;
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -149,65 +149,6 @@ typedef u32 compat_old_sigset_t;
|
|||
|
||||
typedef u32 compat_sigset_word;
|
||||
|
||||
typedef union compat_sigval {
|
||||
compat_int_t sival_int;
|
||||
compat_uptr_t sival_ptr;
|
||||
} compat_sigval_t;
|
||||
|
||||
#define SI_PAD_SIZE32 (128/sizeof(int) - 3)
|
||||
|
||||
typedef struct compat_siginfo {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
|
||||
union {
|
||||
int _pad[SI_PAD_SIZE32];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
compat_pid_t _pid; /* sender's pid */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
compat_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
compat_sigval_t _sigval; /* same as below */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
compat_pid_t _pid; /* sender's pid */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
compat_sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
compat_pid_t _pid; /* which child */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_clock_t _utime;
|
||||
compat_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
|
||||
struct {
|
||||
u32 _addr; /* faulting insn/memory ref. */
|
||||
int _trapno;
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
/*
|
||||
|
|
|
@ -70,75 +70,6 @@ struct rt_signal_frame32 {
|
|||
/* __siginfo_rwin_t * */u32 rwin_save;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
|
||||
return -EFAULT;
|
||||
|
||||
/* If you change siginfo_t structure, please be sure
|
||||
this code is fixed accordingly.
|
||||
It should never copy any pad contained in the structure
|
||||
to avoid security leaks, but must copy the generic
|
||||
3 ints plus the relevant union member.
|
||||
This routine must convert siginfo from 64bit to 32bit as well
|
||||
at the same time. */
|
||||
err = __put_user(from->si_signo, &to->si_signo);
|
||||
err |= __put_user(from->si_errno, &to->si_errno);
|
||||
err |= __put_user(from->si_code, &to->si_code);
|
||||
if (from->si_code < 0)
|
||||
err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
|
||||
else {
|
||||
switch (siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_TIMER:
|
||||
err |= __put_user(from->si_tid, &to->si_tid);
|
||||
err |= __put_user(from->si_overrun, &to->si_overrun);
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
err |= __put_user(from->si_utime, &to->si_utime);
|
||||
err |= __put_user(from->si_stime, &to->si_stime);
|
||||
err |= __put_user(from->si_status, &to->si_status);
|
||||
default:
|
||||
case SIL_KILL:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
err |= __put_user(from->si_trapno, &to->si_trapno);
|
||||
err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __put_user(from->si_band, &to->si_band);
|
||||
err |= __put_user(from->si_fd, &to->si_fd);
|
||||
break;
|
||||
case SIL_RT:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* CAUTION: This is just a very minimalist implementation for the
|
||||
* sake of compat_sys_rt_sigqueueinfo()
|
||||
*/
|
||||
int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
|
||||
{
|
||||
if (!access_ok(VERIFY_WRITE, from, sizeof(compat_siginfo_t)))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_from_user(to, from, 3*sizeof(int)) ||
|
||||
copy_from_user(to->_sifields._pad, from->_sifields._pad,
|
||||
SI_PAD_SIZE))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Checks if the fp is valid. We always build signal frames which are
|
||||
* 16-byte aligned, therefore we can always enforce that the restore
|
||||
* frame has that property as well.
|
||||
|
|
|
@ -110,68 +110,6 @@ struct compat_flock64 {
|
|||
|
||||
typedef u32 compat_sigset_word;
|
||||
|
||||
typedef union compat_sigval {
|
||||
compat_int_t sival_int;
|
||||
compat_uptr_t sival_ptr;
|
||||
} compat_sigval_t;
|
||||
|
||||
#define COMPAT_SI_PAD_SIZE (128/sizeof(int) - 3)
|
||||
|
||||
typedef struct compat_siginfo {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
|
||||
union {
|
||||
int _pad[COMPAT_SI_PAD_SIZE];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
unsigned int _pid; /* sender's pid */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
compat_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
compat_sigval_t _sigval; /* same as below */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
int _overrun_incr; /* amount to add to overrun */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
unsigned int _pid; /* sender's pid */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
compat_sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
unsigned int _pid; /* which child */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_clock_t _utime;
|
||||
compat_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
struct {
|
||||
unsigned int _addr; /* faulting insn/memory ref. */
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
int _trapno; /* TRAP # which caused the signal */
|
||||
#endif
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
struct compat_ipc64_perm {
|
||||
|
|
|
@ -24,12 +24,4 @@
|
|||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
/*
|
||||
* Additional Tile-specific SIGILL si_codes
|
||||
*/
|
||||
#define ILL_DBLFLT 9 /* double fault */
|
||||
#define ILL_HARDWALL 10 /* user networks hardwall violation */
|
||||
#undef NSIGILL
|
||||
#define NSIGILL 10
|
||||
|
||||
#endif /* _ASM_TILE_SIGINFO_H */
|
||||
|
|
|
@ -50,79 +50,6 @@ struct compat_rt_sigframe {
|
|||
struct compat_ucontext uc;
|
||||
};
|
||||
|
||||
int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo)))
|
||||
return -EFAULT;
|
||||
|
||||
/* If you change siginfo_t structure, please make sure that
|
||||
this code is fixed accordingly.
|
||||
It should never copy any pad contained in the structure
|
||||
to avoid security leaks, but must copy the generic
|
||||
3 ints plus the relevant union member. */
|
||||
err = __put_user(from->si_signo, &to->si_signo);
|
||||
err |= __put_user(from->si_errno, &to->si_errno);
|
||||
err |= __put_user(from->si_code, &to->si_code);
|
||||
|
||||
if (from->si_code < 0) {
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
} else {
|
||||
/*
|
||||
* First 32bits of unions are always present:
|
||||
* si_pid === si_band === si_tid === si_addr(LS half)
|
||||
*/
|
||||
err |= __put_user(from->_sifields._pad[0],
|
||||
&to->_sifields._pad[0]);
|
||||
switch (siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_FAULT:
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
err |= __put_user(from->si_utime, &to->si_utime);
|
||||
err |= __put_user(from->si_stime, &to->si_stime);
|
||||
err |= __put_user(from->si_status, &to->si_status);
|
||||
/* FALL THROUGH */
|
||||
default:
|
||||
case SIL_KILL:
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __put_user(from->si_fd, &to->si_fd);
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
err |= __put_user(from->si_overrun, &to->si_overrun);
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
break;
|
||||
case SIL_RT:
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_int, &to->si_int);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
|
||||
return -EFAULT;
|
||||
|
||||
err = __get_user(to->si_signo, &from->si_signo);
|
||||
err |= __get_user(to->si_errno, &from->si_errno);
|
||||
err |= __get_user(to->si_code, &from->si_code);
|
||||
|
||||
err |= __get_user(to->si_pid, &from->si_pid);
|
||||
err |= __get_user(to->si_uid, &from->si_uid);
|
||||
err |= __get_user(to->si_int, &from->si_int);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* The assembly shim for this function arranges to ignore the return value. */
|
||||
long compat_sys_rt_sigreturn(void)
|
||||
{
|
||||
|
|
|
@ -163,11 +163,13 @@ static tilepro_bundle_bits rewrite_load_store_unaligned(
|
|||
* actual bad address in an SPR, which it doesn't.
|
||||
*/
|
||||
if (align_ctl == 0) {
|
||||
siginfo_t info = {
|
||||
.si_signo = SIGBUS,
|
||||
.si_code = BUS_ADRALN,
|
||||
.si_addr = addr
|
||||
};
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = addr;
|
||||
|
||||
trace_unhandled_signal("unaligned trap", regs,
|
||||
(unsigned long)addr, SIGBUS);
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
|
@ -210,11 +212,13 @@ static tilepro_bundle_bits rewrite_load_store_unaligned(
|
|||
}
|
||||
|
||||
if (err) {
|
||||
siginfo_t info = {
|
||||
.si_signo = SIGBUS,
|
||||
.si_code = BUS_ADRALN,
|
||||
.si_addr = addr
|
||||
};
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = addr;
|
||||
|
||||
trace_unhandled_signal("bad address for unaligned fixup", regs,
|
||||
(unsigned long)addr, SIGBUS);
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
|
|
|
@ -256,12 +256,14 @@ static int do_bpt(struct pt_regs *regs)
|
|||
void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
||||
unsigned long reason)
|
||||
{
|
||||
siginfo_t info = { 0 };
|
||||
siginfo_t info;
|
||||
int signo, code;
|
||||
unsigned long address = 0;
|
||||
tile_bundle_bits instr;
|
||||
int is_kernel = !user_mode(regs);
|
||||
|
||||
clear_siginfo(&info);
|
||||
|
||||
/* Handle breakpoints, etc. */
|
||||
if (is_kernel && fault_num == INT_ILL && do_bpt(regs))
|
||||
return;
|
||||
|
|
|
@ -980,11 +980,13 @@ void jit_bundle_gen(struct pt_regs *regs, tilegx_bundle_bits bundle,
|
|||
}
|
||||
|
||||
if ((align_ctl == 0) || unexpected) {
|
||||
siginfo_t info = {
|
||||
.si_signo = SIGBUS,
|
||||
.si_code = BUS_ADRALN,
|
||||
.si_addr = (unsigned char __user *)0
|
||||
};
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = (unsigned char __user *)0;
|
||||
|
||||
if (unaligned_printk)
|
||||
pr_info("Unalign bundle: unexp @%llx, %llx\n",
|
||||
(unsigned long long)regs->pc,
|
||||
|
@ -1396,11 +1398,12 @@ void jit_bundle_gen(struct pt_regs *regs, tilegx_bundle_bits bundle,
|
|||
&frag, sizeof(frag));
|
||||
if (status) {
|
||||
/* Fail to copy JIT into user land. send SIGSEGV. */
|
||||
siginfo_t info = {
|
||||
.si_signo = SIGSEGV,
|
||||
.si_code = SEGV_MAPERR,
|
||||
.si_addr = (void __user *)&jit_code_area[idx]
|
||||
};
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
info.si_addr = (void __user *)&jit_code_area[idx];
|
||||
|
||||
pr_warn("Unalign fixup: pid=%d %s jit_code_area=%llx\n",
|
||||
current->pid, current->comm,
|
||||
|
@ -1511,11 +1514,12 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
|
|||
* If so, we will trigger SIGBUS.
|
||||
*/
|
||||
if ((regs->sp & 0x7) || (regs->ex1) || (align_ctl < 0)) {
|
||||
siginfo_t info = {
|
||||
.si_signo = SIGBUS,
|
||||
.si_code = BUS_ADRALN,
|
||||
.si_addr = (unsigned char __user *)0
|
||||
};
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = (unsigned char __user *)0;
|
||||
|
||||
if (unaligned_printk)
|
||||
pr_info("Unalign fixup: %d %llx @%llx\n",
|
||||
|
@ -1535,11 +1539,13 @@ void do_unaligned(struct pt_regs *regs, int vecnum)
|
|||
pc = (tilegx_bundle_bits __user *)(regs->pc);
|
||||
if (get_user(bundle, pc) != 0) {
|
||||
/* Probably never be here since pc is valid user address.*/
|
||||
siginfo_t info = {
|
||||
.si_signo = SIGSEGV,
|
||||
.si_code = SEGV_MAPERR,
|
||||
.si_addr = (void __user *)pc
|
||||
};
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
info.si_addr = (void __user *)pc;
|
||||
|
||||
pr_err("Couldn't read instruction at %p trying to step\n", pc);
|
||||
trace_unhandled_signal("segfault in unalign fixup", regs,
|
||||
(unsigned long)info.si_addr, SIGSEGV);
|
||||
|
|
|
@ -306,7 +306,7 @@ void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)
|
|||
|
||||
arch_examine_signal(sig, regs);
|
||||
|
||||
memset(&clean_si, 0, sizeof(clean_si));
|
||||
clear_siginfo(&clean_si);
|
||||
clean_si.si_signo = si->si_signo;
|
||||
clean_si.si_errno = si->si_errno;
|
||||
clean_si.si_code = si->si_code;
|
||||
|
|
|
@ -127,88 +127,6 @@ typedef u32 compat_old_sigset_t; /* at least 32 bits */
|
|||
|
||||
typedef u32 compat_sigset_word;
|
||||
|
||||
typedef union compat_sigval {
|
||||
compat_int_t sival_int;
|
||||
compat_uptr_t sival_ptr;
|
||||
} compat_sigval_t;
|
||||
|
||||
typedef struct compat_siginfo {
|
||||
int si_signo;
|
||||
int si_errno;
|
||||
int si_code;
|
||||
|
||||
union {
|
||||
int _pad[128/sizeof(int) - 3];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
unsigned int _pid; /* sender's pid */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
compat_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
compat_sigval_t _sigval; /* same as below */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
int _overrun_incr; /* amount to add to overrun */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
unsigned int _pid; /* sender's pid */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
compat_sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
unsigned int _pid; /* which child */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_clock_t _utime;
|
||||
compat_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGCHLD (x32 version) */
|
||||
struct {
|
||||
unsigned int _pid; /* which child */
|
||||
unsigned int _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_s64 _utime;
|
||||
compat_s64 _stime;
|
||||
} _sigchld_x32;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
struct {
|
||||
unsigned int _addr; /* faulting insn/memory ref. */
|
||||
short int _addr_lsb; /* Valid LSB of the reported address. */
|
||||
union {
|
||||
/* used when si_code=SEGV_BNDERR */
|
||||
struct {
|
||||
compat_uptr_t _lower;
|
||||
compat_uptr_t _upper;
|
||||
} _addr_bnd;
|
||||
/* used when si_code=SEGV_PKUERR */
|
||||
compat_u32 _pkey;
|
||||
};
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
|
||||
struct {
|
||||
unsigned int _call_addr; /* calling insn */
|
||||
int _syscall; /* triggering system call number */
|
||||
unsigned int _arch; /* AUDIT_ARCH_* of syscall */
|
||||
} _sigsys;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
struct compat_ipc64_perm {
|
||||
|
@ -331,4 +249,8 @@ static inline bool in_compat_syscall(void)
|
|||
}
|
||||
#define in_compat_syscall in_compat_syscall /* override the generic impl */
|
||||
|
||||
struct compat_siginfo;
|
||||
int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
|
||||
const siginfo_t *from, bool x32_ABI);
|
||||
|
||||
#endif /* _ASM_X86_COMPAT_H */
|
||||
|
|
|
@ -20,12 +20,6 @@ int ia32_setup_frame(int sig, struct ksignal *ksig,
|
|||
# define ia32_setup_rt_frame __setup_rt_frame
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
int __copy_siginfo_to_user32(compat_siginfo_t __user *to,
|
||||
const siginfo_t *from, bool x32_ABI);
|
||||
#endif
|
||||
|
||||
|
||||
extern void convert_from_fxsr(struct user_i387_ia32_struct *env,
|
||||
struct task_struct *tsk);
|
||||
extern void convert_to_fxsr(struct task_struct *tsk,
|
||||
|
|
|
@ -591,7 +591,7 @@ static int srao_decode_notifier(struct notifier_block *nb, unsigned long val,
|
|||
|
||||
if (mce_usable_address(mce) && (mce->severity == MCE_AO_SEVERITY)) {
|
||||
pfn = mce->addr >> PAGE_SHIFT;
|
||||
memory_failure(pfn, MCE_VECTOR, 0);
|
||||
memory_failure(pfn, 0);
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
|
@ -1055,7 +1055,7 @@ static int do_memory_failure(struct mce *m)
|
|||
pr_err("Uncorrected hardware memory error in user-access at %llx", m->addr);
|
||||
if (!(m->mcgstatus & MCG_STATUS_RIPV))
|
||||
flags |= MF_MUST_KILL;
|
||||
ret = memory_failure(m->addr >> PAGE_SHIFT, MCE_VECTOR, flags);
|
||||
ret = memory_failure(m->addr >> PAGE_SHIFT, flags);
|
||||
if (ret)
|
||||
pr_err("Memory error not recovered");
|
||||
return ret;
|
||||
|
@ -1334,7 +1334,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
|
|||
EXPORT_SYMBOL_GPL(do_machine_check);
|
||||
|
||||
#ifndef CONFIG_MEMORY_FAILURE
|
||||
int memory_failure(unsigned long pfn, int vector, int flags)
|
||||
int memory_failure(unsigned long pfn, int flags)
|
||||
{
|
||||
/* mce_severity() should not hand us an ACTION_REQUIRED error */
|
||||
BUG_ON(flags & MF_ACTION_REQUIRED);
|
||||
|
|
|
@ -25,8 +25,8 @@ static inline void signal_compat_build_tests(void)
|
|||
* limits also have to look at this code. Make sure any
|
||||
* new fields are handled in copy_siginfo_to_user32()!
|
||||
*/
|
||||
BUILD_BUG_ON(NSIGILL != 8);
|
||||
BUILD_BUG_ON(NSIGFPE != 8);
|
||||
BUILD_BUG_ON(NSIGILL != 11);
|
||||
BUILD_BUG_ON(NSIGFPE != 13);
|
||||
BUILD_BUG_ON(NSIGSEGV != 4);
|
||||
BUILD_BUG_ON(NSIGBUS != 5);
|
||||
BUILD_BUG_ON(NSIGTRAP != 4);
|
||||
|
@ -64,7 +64,7 @@ static inline void signal_compat_build_tests(void)
|
|||
CHECK_SI_SIZE (_kill, 2*sizeof(int));
|
||||
|
||||
CHECK_CSI_OFFSET(_timer);
|
||||
CHECK_CSI_SIZE (_timer, 5*sizeof(int));
|
||||
CHECK_CSI_SIZE (_timer, 3*sizeof(int));
|
||||
CHECK_SI_SIZE (_timer, 6*sizeof(int));
|
||||
|
||||
CHECK_CSI_OFFSET(_rt);
|
||||
|
@ -75,9 +75,11 @@ static inline void signal_compat_build_tests(void)
|
|||
CHECK_CSI_SIZE (_sigchld, 5*sizeof(int));
|
||||
CHECK_SI_SIZE (_sigchld, 8*sizeof(int));
|
||||
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
CHECK_CSI_OFFSET(_sigchld_x32);
|
||||
CHECK_CSI_SIZE (_sigchld_x32, 7*sizeof(int));
|
||||
/* no _sigchld_x32 in the generic siginfo_t */
|
||||
#endif
|
||||
|
||||
CHECK_CSI_OFFSET(_sigfault);
|
||||
CHECK_CSI_SIZE (_sigfault, 4*sizeof(int));
|
||||
|
@ -96,6 +98,8 @@ static inline void signal_compat_build_tests(void)
|
|||
|
||||
void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
|
||||
{
|
||||
signal_compat_build_tests();
|
||||
|
||||
/* Don't leak in-kernel non-uapi flags to user-space */
|
||||
if (oact)
|
||||
oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
|
||||
|
@ -111,116 +115,3 @@ void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
|
|||
if (in_x32_syscall())
|
||||
act->sa.sa_flags |= SA_X32_ABI;
|
||||
}
|
||||
|
||||
int __copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from,
|
||||
bool x32_ABI)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
signal_compat_build_tests();
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
|
||||
return -EFAULT;
|
||||
|
||||
put_user_try {
|
||||
/* If you change siginfo_t structure, please make sure that
|
||||
this code is fixed accordingly.
|
||||
It should never copy any pad contained in the structure
|
||||
to avoid security leaks, but must copy the generic
|
||||
3 ints plus the relevant union member. */
|
||||
put_user_ex(from->si_signo, &to->si_signo);
|
||||
put_user_ex(from->si_errno, &to->si_errno);
|
||||
put_user_ex(from->si_code, &to->si_code);
|
||||
|
||||
if (from->si_code < 0) {
|
||||
put_user_ex(from->si_pid, &to->si_pid);
|
||||
put_user_ex(from->si_uid, &to->si_uid);
|
||||
put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
|
||||
} else {
|
||||
/*
|
||||
* First 32bits of unions are always present:
|
||||
* si_pid === si_band === si_tid === si_addr(LS half)
|
||||
*/
|
||||
put_user_ex(from->_sifields._pad[0],
|
||||
&to->_sifields._pad[0]);
|
||||
switch (siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_FAULT:
|
||||
if (from->si_signo == SIGBUS &&
|
||||
(from->si_code == BUS_MCEERR_AR ||
|
||||
from->si_code == BUS_MCEERR_AO))
|
||||
put_user_ex(from->si_addr_lsb, &to->si_addr_lsb);
|
||||
|
||||
if (from->si_signo == SIGSEGV) {
|
||||
if (from->si_code == SEGV_BNDERR) {
|
||||
compat_uptr_t lower = (unsigned long)from->si_lower;
|
||||
compat_uptr_t upper = (unsigned long)from->si_upper;
|
||||
put_user_ex(lower, &to->si_lower);
|
||||
put_user_ex(upper, &to->si_upper);
|
||||
}
|
||||
if (from->si_code == SEGV_PKUERR)
|
||||
put_user_ex(from->si_pkey, &to->si_pkey);
|
||||
}
|
||||
break;
|
||||
case SIL_SYS:
|
||||
put_user_ex(from->si_syscall, &to->si_syscall);
|
||||
put_user_ex(from->si_arch, &to->si_arch);
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
if (!x32_ABI) {
|
||||
put_user_ex(from->si_utime, &to->si_utime);
|
||||
put_user_ex(from->si_stime, &to->si_stime);
|
||||
} else {
|
||||
put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime);
|
||||
put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime);
|
||||
}
|
||||
put_user_ex(from->si_status, &to->si_status);
|
||||
/* FALL THROUGH */
|
||||
case SIL_KILL:
|
||||
put_user_ex(from->si_uid, &to->si_uid);
|
||||
break;
|
||||
case SIL_POLL:
|
||||
put_user_ex(from->si_fd, &to->si_fd);
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
put_user_ex(from->si_overrun, &to->si_overrun);
|
||||
put_user_ex(ptr_to_compat(from->si_ptr),
|
||||
&to->si_ptr);
|
||||
break;
|
||||
case SIL_RT:
|
||||
put_user_ex(from->si_uid, &to->si_uid);
|
||||
put_user_ex(from->si_int, &to->si_int);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} put_user_catch(err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* from syscall's path, where we know the ABI */
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
return __copy_siginfo_to_user32(to, from, in_x32_syscall());
|
||||
}
|
||||
|
||||
int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
|
||||
{
|
||||
int err = 0;
|
||||
u32 ptr32;
|
||||
|
||||
if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
|
||||
return -EFAULT;
|
||||
|
||||
get_user_try {
|
||||
get_user_ex(to->si_signo, &from->si_signo);
|
||||
get_user_ex(to->si_errno, &from->si_errno);
|
||||
get_user_ex(to->si_code, &from->si_code);
|
||||
|
||||
get_user_ex(to->si_pid, &from->si_pid);
|
||||
get_user_ex(to->si_uid, &from->si_uid);
|
||||
get_user_ex(ptr32, &from->si_ptr);
|
||||
to->si_ptr = compat_ptr(ptr32);
|
||||
} get_user_catch(err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -278,7 +278,6 @@ static void ptrace_hbptriggered(struct perf_event *bp,
|
|||
struct pt_regs *regs)
|
||||
{
|
||||
int i;
|
||||
siginfo_t info;
|
||||
struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
|
||||
|
||||
if (bp->attr.bp_type & HW_BREAKPOINT_X) {
|
||||
|
@ -293,12 +292,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
|
|||
i = (i << 1) | 1;
|
||||
}
|
||||
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = i;
|
||||
info.si_code = TRAP_HWBKPT;
|
||||
info.si_addr = (void __user *)bkpt->address;
|
||||
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
force_sig_ptrace_errno_trap(i, (void __user *)bkpt->address);
|
||||
}
|
||||
|
||||
static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
|
||||
|
|
|
@ -410,7 +410,7 @@ static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int
|
|||
flags = 0;
|
||||
|
||||
if (flags != -1)
|
||||
memory_failure_queue(pfn, 0, flags);
|
||||
memory_failure_queue(pfn, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -569,7 +569,7 @@ store_hard_offline_page(struct device *dev,
|
|||
if (kstrtoull(buf, 0, &pfn) < 0)
|
||||
return -EINVAL;
|
||||
pfn >>= PAGE_SHIFT;
|
||||
ret = memory_failure(pfn, 0, 0);
|
||||
ret = memory_failure(pfn, 0);
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
|
|
|
@ -327,7 +327,7 @@ int cec_add_elem(u64 pfn)
|
|||
} else {
|
||||
/* We have reached max count for this page, soft-offline it. */
|
||||
pr_err("Soft-offlining pfn: 0x%llx\n", pfn);
|
||||
memory_failure_queue(pfn, 0, MF_SOFT_OFFLINE);
|
||||
memory_failure_queue(pfn, MF_SOFT_OFFLINE);
|
||||
ca->pfns_poisoned++;
|
||||
}
|
||||
|
||||
|
|
|
@ -595,7 +595,7 @@ static void async_completed(struct urb *urb)
|
|||
as->status = urb->status;
|
||||
signr = as->signr;
|
||||
if (signr) {
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
clear_siginfo(&sinfo);
|
||||
sinfo.si_signo = as->signr;
|
||||
sinfo.si_errno = as->status;
|
||||
sinfo.si_code = SI_ASYNCIO;
|
||||
|
@ -2613,7 +2613,7 @@ static void usbdev_remove(struct usb_device *udev)
|
|||
wake_up_all(&ps->wait);
|
||||
list_del_init(&ps->list);
|
||||
if (ps->discsignr) {
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
clear_siginfo(&sinfo);
|
||||
sinfo.si_signo = ps->discsignr;
|
||||
sinfo.si_errno = EPIPE;
|
||||
sinfo.si_code = SI_ASYNCIO;
|
||||
|
|
|
@ -737,6 +737,7 @@ static void send_sigio_to_task(struct task_struct *p,
|
|||
delivered even if we can't queue. Failure to
|
||||
queue in this case _should_ be reported; we fall
|
||||
back to SIGIO in that case. --sct */
|
||||
clear_siginfo(&si);
|
||||
si.si_signo = signum;
|
||||
si.si_errno = 0;
|
||||
si.si_code = reason;
|
||||
|
|
|
@ -157,6 +157,104 @@ struct compat_sigaction {
|
|||
compat_sigset_t sa_mask __packed;
|
||||
};
|
||||
|
||||
typedef union compat_sigval {
|
||||
compat_int_t sival_int;
|
||||
compat_uptr_t sival_ptr;
|
||||
} compat_sigval_t;
|
||||
|
||||
typedef struct compat_siginfo {
|
||||
int si_signo;
|
||||
#ifndef __ARCH_HAS_SWAPPED_SIGINFO
|
||||
int si_errno;
|
||||
int si_code;
|
||||
#else
|
||||
int si_code;
|
||||
int si_errno;
|
||||
#endif
|
||||
|
||||
union {
|
||||
int _pad[128/sizeof(int) - 3];
|
||||
|
||||
/* kill() */
|
||||
struct {
|
||||
compat_pid_t _pid; /* sender's pid */
|
||||
__compat_uid32_t _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
compat_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
compat_sigval_t _sigval; /* same as below */
|
||||
} _timer;
|
||||
|
||||
/* POSIX.1b signals */
|
||||
struct {
|
||||
compat_pid_t _pid; /* sender's pid */
|
||||
__compat_uid32_t _uid; /* sender's uid */
|
||||
compat_sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
compat_pid_t _pid; /* which child */
|
||||
__compat_uid32_t _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_clock_t _utime;
|
||||
compat_clock_t _stime;
|
||||
} _sigchld;
|
||||
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
/* SIGCHLD (x32 version) */
|
||||
struct {
|
||||
compat_pid_t _pid; /* which child */
|
||||
__compat_uid32_t _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
compat_s64 _utime;
|
||||
compat_s64 _stime;
|
||||
} _sigchld_x32;
|
||||
#endif
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT */
|
||||
struct {
|
||||
compat_uptr_t _addr; /* faulting insn/memory ref. */
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
int _trapno; /* TRAP # which caused the signal */
|
||||
#endif
|
||||
union {
|
||||
/*
|
||||
* used when si_code=BUS_MCEERR_AR or
|
||||
* used when si_code=BUS_MCEERR_AO
|
||||
*/
|
||||
short int _addr_lsb; /* Valid LSB of the reported address. */
|
||||
/* used when si_code=SEGV_BNDERR */
|
||||
struct {
|
||||
short _dummy_bnd;
|
||||
compat_uptr_t _lower;
|
||||
compat_uptr_t _upper;
|
||||
} _addr_bnd;
|
||||
/* used when si_code=SEGV_PKUERR */
|
||||
struct {
|
||||
short _dummy_pkey;
|
||||
u32 _pkey;
|
||||
} _addr_pkey;
|
||||
};
|
||||
} _sigfault;
|
||||
|
||||
/* SIGPOLL */
|
||||
struct {
|
||||
compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
int _fd;
|
||||
} _sigpoll;
|
||||
|
||||
struct {
|
||||
compat_uptr_t _call_addr; /* calling user insn */
|
||||
int _syscall; /* triggering system call number */
|
||||
unsigned int _arch; /* AUDIT_ARCH_* of syscall */
|
||||
} _sigsys;
|
||||
} _sifields;
|
||||
} compat_siginfo_t;
|
||||
|
||||
/*
|
||||
* These functions operate on 32- or 64-bit specs depending on
|
||||
* COMPAT_USE_64BIT_TIME, hence the void user pointer arguments.
|
||||
|
@ -412,7 +510,7 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
|||
unsigned long bitmap_size);
|
||||
long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
|
||||
unsigned long bitmap_size);
|
||||
int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from);
|
||||
int copy_siginfo_from_user32(siginfo_t *to, const struct compat_siginfo __user *from);
|
||||
int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from);
|
||||
int get_compat_sigevent(struct sigevent *event,
|
||||
const struct compat_sigevent __user *u_event);
|
||||
|
|
|
@ -2570,8 +2570,8 @@ enum mf_flags {
|
|||
MF_MUST_KILL = 1 << 2,
|
||||
MF_SOFT_OFFLINE = 1 << 3,
|
||||
};
|
||||
extern int memory_failure(unsigned long pfn, int trapno, int flags);
|
||||
extern void memory_failure_queue(unsigned long pfn, int trapno, int flags);
|
||||
extern int memory_failure(unsigned long pfn, int flags);
|
||||
extern void memory_failure_queue(unsigned long pfn, int flags);
|
||||
extern int unpoison_memory(unsigned long pfn);
|
||||
extern int get_hwpoison_page(struct page *page);
|
||||
#define put_hwpoison_page(page) put_page(page)
|
||||
|
|
|
@ -285,6 +285,34 @@ static inline void kernel_signal_stop(void)
|
|||
|
||||
schedule();
|
||||
}
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
# define ___ARCH_SI_TRAPNO(_a1) , _a1
|
||||
#else
|
||||
# define ___ARCH_SI_TRAPNO(_a1)
|
||||
#endif
|
||||
#ifdef __ia64__
|
||||
# define ___ARCH_SI_IA64(_a1, _a2, _a3) , _a1, _a2, _a3
|
||||
#else
|
||||
# define ___ARCH_SI_IA64(_a1, _a2, _a3)
|
||||
#endif
|
||||
|
||||
int force_sig_fault(int sig, int code, void __user *addr
|
||||
___ARCH_SI_TRAPNO(int trapno)
|
||||
___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
|
||||
, struct task_struct *t);
|
||||
int send_sig_fault(int sig, int code, void __user *addr
|
||||
___ARCH_SI_TRAPNO(int trapno)
|
||||
___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
|
||||
, struct task_struct *t);
|
||||
|
||||
int force_sig_mceerr(int code, void __user *, short, struct task_struct *);
|
||||
int send_sig_mceerr(int code, void __user *, short, struct task_struct *);
|
||||
|
||||
int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper);
|
||||
int force_sig_pkuerr(void __user *addr, u32 pkey);
|
||||
|
||||
int force_sig_ptrace_errno_trap(int errno, void __user *addr);
|
||||
|
||||
extern int send_sig_info(int, struct siginfo *, struct task_struct *);
|
||||
extern int force_sigsegv(int, struct task_struct *);
|
||||
extern int force_sig_info(int, struct siginfo *, struct task_struct *);
|
||||
|
|
|
@ -11,13 +11,14 @@ struct task_struct;
|
|||
/* for sysctl */
|
||||
extern int print_fatal_signals;
|
||||
|
||||
static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
|
||||
static inline void copy_siginfo(struct siginfo *to, const struct siginfo *from)
|
||||
{
|
||||
if (from->si_code < 0)
|
||||
memcpy(to, from, sizeof(*to));
|
||||
else
|
||||
/* _sigchld is currently the largest know union member */
|
||||
memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
|
||||
memcpy(to, from, sizeof(*to));
|
||||
}
|
||||
|
||||
static inline void clear_siginfo(struct siginfo *info)
|
||||
{
|
||||
memset(info, 0, sizeof(*info));
|
||||
}
|
||||
|
||||
int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from);
|
||||
|
@ -29,9 +30,7 @@ enum siginfo_layout {
|
|||
SIL_FAULT,
|
||||
SIL_CHLD,
|
||||
SIL_RT,
|
||||
#ifdef __ARCH_SIGSYS
|
||||
SIL_SYS,
|
||||
#endif
|
||||
};
|
||||
|
||||
enum siginfo_layout siginfo_layout(int sig, int si_code);
|
||||
|
|
|
@ -23,10 +23,6 @@ typedef union sigval {
|
|||
#define SI_PAD_SIZE ((SI_MAX_SIZE - __ARCH_SI_PREAMBLE_SIZE) / sizeof(int))
|
||||
#endif
|
||||
|
||||
#ifndef __ARCH_SI_UID_T
|
||||
#define __ARCH_SI_UID_T __kernel_uid32_t
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The default "si_band" type is "long", as specified by POSIX.
|
||||
* However, some architectures want to override this to "int"
|
||||
|
@ -44,12 +40,15 @@ typedef union sigval {
|
|||
#define __ARCH_SI_ATTRIBUTES
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ARCH_SIGINFO_T
|
||||
|
||||
typedef struct siginfo {
|
||||
int si_signo;
|
||||
#ifndef __ARCH_HAS_SWAPPED_SIGINFO
|
||||
int si_errno;
|
||||
int si_code;
|
||||
#else
|
||||
int si_code;
|
||||
int si_errno;
|
||||
#endif
|
||||
|
||||
union {
|
||||
int _pad[SI_PAD_SIZE];
|
||||
|
@ -57,14 +56,13 @@ typedef struct siginfo {
|
|||
/* kill() */
|
||||
struct {
|
||||
__kernel_pid_t _pid; /* sender's pid */
|
||||
__ARCH_SI_UID_T _uid; /* sender's uid */
|
||||
__kernel_uid32_t _uid; /* sender's uid */
|
||||
} _kill;
|
||||
|
||||
/* POSIX.1b timers */
|
||||
struct {
|
||||
__kernel_timer_t _tid; /* timer id */
|
||||
int _overrun; /* overrun count */
|
||||
char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
|
||||
sigval_t _sigval; /* same as below */
|
||||
int _sys_private; /* not to be passed to user */
|
||||
} _timer;
|
||||
|
@ -72,34 +70,47 @@ typedef struct siginfo {
|
|||
/* POSIX.1b signals */
|
||||
struct {
|
||||
__kernel_pid_t _pid; /* sender's pid */
|
||||
__ARCH_SI_UID_T _uid; /* sender's uid */
|
||||
__kernel_uid32_t _uid; /* sender's uid */
|
||||
sigval_t _sigval;
|
||||
} _rt;
|
||||
|
||||
/* SIGCHLD */
|
||||
struct {
|
||||
__kernel_pid_t _pid; /* which child */
|
||||
__ARCH_SI_UID_T _uid; /* sender's uid */
|
||||
__kernel_uid32_t _uid; /* sender's uid */
|
||||
int _status; /* exit code */
|
||||
__ARCH_SI_CLOCK_T _utime;
|
||||
__ARCH_SI_CLOCK_T _stime;
|
||||
} _sigchld;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT */
|
||||
struct {
|
||||
void __user *_addr; /* faulting insn/memory ref. */
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
int _trapno; /* TRAP # which caused the signal */
|
||||
#endif
|
||||
short _addr_lsb; /* LSB of the reported address */
|
||||
#ifdef __ia64__
|
||||
int _imm; /* immediate value for "break" */
|
||||
unsigned int _flags; /* see ia64 si_flags */
|
||||
unsigned long _isr; /* isr */
|
||||
#endif
|
||||
union {
|
||||
/*
|
||||
* used when si_code=BUS_MCEERR_AR or
|
||||
* used when si_code=BUS_MCEERR_AO
|
||||
*/
|
||||
short _addr_lsb; /* LSB of the reported address */
|
||||
/* used when si_code=SEGV_BNDERR */
|
||||
struct {
|
||||
short _dummy_bnd;
|
||||
void __user *_lower;
|
||||
void __user *_upper;
|
||||
} _addr_bnd;
|
||||
/* used when si_code=SEGV_PKUERR */
|
||||
__u32 _pkey;
|
||||
struct {
|
||||
short _dummy_pkey;
|
||||
__u32 _pkey;
|
||||
} _addr_pkey;
|
||||
};
|
||||
} _sigfault;
|
||||
|
||||
|
@ -118,10 +129,6 @@ typedef struct siginfo {
|
|||
} _sifields;
|
||||
} __ARCH_SI_ATTRIBUTES siginfo_t;
|
||||
|
||||
/* If the arch shares siginfo, then it has SIGSYS. */
|
||||
#define __ARCH_SIGSYS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How these fields are to be accessed.
|
||||
*/
|
||||
|
@ -143,14 +150,12 @@ typedef struct siginfo {
|
|||
#define si_addr_lsb _sifields._sigfault._addr_lsb
|
||||
#define si_lower _sifields._sigfault._addr_bnd._lower
|
||||
#define si_upper _sifields._sigfault._addr_bnd._upper
|
||||
#define si_pkey _sifields._sigfault._pkey
|
||||
#define si_pkey _sifields._sigfault._addr_pkey._pkey
|
||||
#define si_band _sifields._sigpoll._band
|
||||
#define si_fd _sifields._sigpoll._fd
|
||||
#ifdef __ARCH_SIGSYS
|
||||
#define si_call_addr _sifields._sigsys._call_addr
|
||||
#define si_syscall _sifields._sigsys._syscall
|
||||
#define si_arch _sifields._sigsys._arch
|
||||
#endif
|
||||
|
||||
/*
|
||||
* si_code values
|
||||
|
@ -165,6 +170,7 @@ typedef struct siginfo {
|
|||
#define SI_SIGIO -5 /* sent by queued SIGIO */
|
||||
#define SI_TKILL -6 /* sent by tkill system call */
|
||||
#define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */
|
||||
#define SI_ASYNCNL -60 /* sent by glibc async name lookup completion */
|
||||
|
||||
#define SI_FROMUSER(siptr) ((siptr)->si_code <= 0)
|
||||
#define SI_FROMKERNEL(siptr) ((siptr)->si_code > 0)
|
||||
|
@ -173,14 +179,34 @@ typedef struct siginfo {
|
|||
* SIGILL si_codes
|
||||
*/
|
||||
#define ILL_ILLOPC 1 /* illegal opcode */
|
||||
#ifdef __bfin__
|
||||
# define ILL_ILLPARAOP 2 /* illegal opcode combine */
|
||||
#endif
|
||||
#define ILL_ILLOPN 2 /* illegal operand */
|
||||
#define ILL_ILLADR 3 /* illegal addressing mode */
|
||||
#define ILL_ILLTRP 4 /* illegal trap */
|
||||
#ifdef __bfin__
|
||||
# define ILL_ILLEXCPT 4 /* unrecoverable exception */
|
||||
#endif
|
||||
#define ILL_PRVOPC 5 /* privileged opcode */
|
||||
#define ILL_PRVREG 6 /* privileged register */
|
||||
#define ILL_COPROC 7 /* coprocessor error */
|
||||
#define ILL_BADSTK 8 /* internal stack error */
|
||||
#define NSIGILL 8
|
||||
#ifdef __bfin__
|
||||
# define ILL_CPLB_VI 9 /* D/I CPLB protect violation */
|
||||
# define ILL_CPLB_MISS 10 /* D/I CPLB miss */
|
||||
# define ILL_CPLB_MULHIT 11 /* D/I CPLB multiple hit */
|
||||
#endif
|
||||
#ifdef __tile__
|
||||
# define ILL_DBLFLT 9 /* double fault */
|
||||
# define ILL_HARDWALL 10 /* user networks hardwall violation */
|
||||
#endif
|
||||
#ifdef __ia64__
|
||||
# define ILL_BADIADDR 9 /* unimplemented instruction address */
|
||||
# define __ILL_BREAK 10 /* illegal break */
|
||||
# define __ILL_BNDMOD 11 /* bundle-update (modification) in progress */
|
||||
#endif
|
||||
#define NSIGILL 11
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
|
@ -193,15 +219,33 @@ typedef struct siginfo {
|
|||
#define FPE_FLTRES 6 /* floating point inexact result */
|
||||
#define FPE_FLTINV 7 /* floating point invalid operation */
|
||||
#define FPE_FLTSUB 8 /* subscript out of range */
|
||||
#define NSIGFPE 8
|
||||
#ifdef __frv__
|
||||
# define FPE_MDAOVF 9 /* media overflow */
|
||||
#endif
|
||||
#ifdef __ia64__
|
||||
# define __FPE_DECOVF 9 /* decimal overflow */
|
||||
# define __FPE_DECDIV 10 /* decimal division by zero */
|
||||
# define __FPE_DECERR 11 /* packed decimal error */
|
||||
# define __FPE_INVASC 12 /* invalid ASCII digit */
|
||||
# define __FPE_INVDEC 13 /* invalid decimal digit */
|
||||
#endif
|
||||
#define NSIGFPE 13
|
||||
|
||||
/*
|
||||
* SIGSEGV si_codes
|
||||
*/
|
||||
#define SEGV_MAPERR 1 /* address not mapped to object */
|
||||
#define SEGV_ACCERR 2 /* invalid permissions for mapped object */
|
||||
#define SEGV_BNDERR 3 /* failed address bound checks */
|
||||
#define SEGV_PKUERR 4 /* failed protection key checks */
|
||||
#ifdef __bfin__
|
||||
# define SEGV_STACKFLOW 3 /* stack overflow */
|
||||
#else
|
||||
# define SEGV_BNDERR 3 /* failed address bound checks */
|
||||
#endif
|
||||
#ifdef __ia64__
|
||||
# define __SEGV_PSTKOVF 4 /* paragraph stack overflow */
|
||||
#else
|
||||
# define SEGV_PKUERR 4 /* failed protection key checks */
|
||||
#endif
|
||||
#define NSIGSEGV 4
|
||||
|
||||
/*
|
||||
|
@ -210,8 +254,12 @@ typedef struct siginfo {
|
|||
#define BUS_ADRALN 1 /* invalid address alignment */
|
||||
#define BUS_ADRERR 2 /* non-existent physical address */
|
||||
#define BUS_OBJERR 3 /* object specific hardware error */
|
||||
#ifdef __bfin__
|
||||
# define BUS_OPFETCH 4 /* error from instruction fetch */
|
||||
#else
|
||||
/* hardware memory error consumed on a machine check: action required */
|
||||
#define BUS_MCEERR_AR 4
|
||||
# define BUS_MCEERR_AR 4
|
||||
#endif
|
||||
/* hardware memory error detected in process but not consumed: action optional*/
|
||||
#define BUS_MCEERR_AO 5
|
||||
#define NSIGBUS 5
|
||||
|
@ -223,8 +271,19 @@ typedef struct siginfo {
|
|||
#define TRAP_TRACE 2 /* process trace trap */
|
||||
#define TRAP_BRANCH 3 /* process taken branch trap */
|
||||
#define TRAP_HWBKPT 4 /* hardware breakpoint/watchpoint */
|
||||
#ifdef __bfin__
|
||||
# define TRAP_STEP 1 /* single-step breakpoint */
|
||||
# define TRAP_TRACEFLOW 2 /* trace buffer overflow */
|
||||
# define TRAP_WATCHPT 3 /* watchpoint match */
|
||||
# define TRAP_ILLTRAP 4 /* illegal trap */
|
||||
#endif
|
||||
#define NSIGTRAP 4
|
||||
|
||||
/*
|
||||
* There are an additional set of SIGTRAP si_codes used by ptrace
|
||||
* that of the form: ((PTRACE_EVENT_XXX << 8) | SIGTRAP)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SIGCHLD si_codes
|
||||
*/
|
||||
|
|
|
@ -639,6 +639,7 @@ static void __do_notify(struct mqueue_inode_info *info)
|
|||
case SIGEV_SIGNAL:
|
||||
/* sends signal */
|
||||
|
||||
clear_siginfo(&sig_i);
|
||||
sig_i.si_signo = info->notify.sigev_signo;
|
||||
sig_i.si_errno = 0;
|
||||
sig_i.si_code = SI_MESGQ;
|
||||
|
|
|
@ -2441,7 +2441,6 @@ static int kdb_kill(int argc, const char **argv)
|
|||
long sig, pid;
|
||||
char *endp;
|
||||
struct task_struct *p;
|
||||
struct siginfo info;
|
||||
|
||||
if (argc != 2)
|
||||
return KDB_ARGCOUNT;
|
||||
|
@ -2449,7 +2448,7 @@ static int kdb_kill(int argc, const char **argv)
|
|||
sig = simple_strtol(argv[1], &endp, 0);
|
||||
if (*endp)
|
||||
return KDB_BADINT;
|
||||
if (sig >= 0) {
|
||||
if ((sig >= 0) || !valid_signal(-sig)) {
|
||||
kdb_printf("Invalid signal parameter.<-signal>\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -2470,12 +2469,7 @@ static int kdb_kill(int argc, const char **argv)
|
|||
return 0;
|
||||
}
|
||||
p = p->group_leader;
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = SI_USER;
|
||||
info.si_pid = pid; /* same capabilities as process being signalled */
|
||||
info.si_uid = 0; /* kdb has root authority */
|
||||
kdb_send_sig_info(p, &info);
|
||||
kdb_send_sig(p, sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ extern unsigned long kdb_task_state(const struct task_struct *p,
|
|||
extern void kdb_ps_suppressed(void);
|
||||
extern void kdb_ps1(const struct task_struct *p);
|
||||
extern void kdb_print_nameval(const char *name, unsigned long val);
|
||||
extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info);
|
||||
extern void kdb_send_sig(struct task_struct *p, int sig);
|
||||
extern void kdb_meminfo_proc_show(void);
|
||||
extern char *kdb_getstr(char *, size_t, const char *);
|
||||
extern void kdb_gdb_state_pass(char *buf);
|
||||
|
|
|
@ -659,7 +659,7 @@ static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info)
|
|||
if (lock_task_sighand(child, &flags)) {
|
||||
error = -EINVAL;
|
||||
if (likely(child->last_siginfo != NULL)) {
|
||||
*info = *child->last_siginfo;
|
||||
copy_siginfo(info, child->last_siginfo);
|
||||
error = 0;
|
||||
}
|
||||
unlock_task_sighand(child, &flags);
|
||||
|
@ -675,7 +675,7 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
|
|||
if (lock_task_sighand(child, &flags)) {
|
||||
error = -EINVAL;
|
||||
if (likely(child->last_siginfo != NULL)) {
|
||||
*child->last_siginfo = *info;
|
||||
copy_siginfo(child->last_siginfo, info);
|
||||
error = 0;
|
||||
}
|
||||
unlock_task_sighand(child, &flags);
|
||||
|
@ -1226,7 +1226,6 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
|
|||
break;
|
||||
|
||||
case PTRACE_SETSIGINFO:
|
||||
memset(&siginfo, 0, sizeof siginfo);
|
||||
if (copy_siginfo_from_user32(
|
||||
&siginfo, (struct compat_siginfo __user *) datap))
|
||||
ret = -EFAULT;
|
||||
|
|
|
@ -515,7 +515,7 @@ void put_seccomp_filter(struct task_struct *tsk)
|
|||
|
||||
static void seccomp_init_siginfo(siginfo_t *info, int syscall, int reason)
|
||||
{
|
||||
memset(info, 0, sizeof(*info));
|
||||
clear_siginfo(info);
|
||||
info->si_signo = SIGSYS;
|
||||
info->si_code = SYS_SECCOMP;
|
||||
info->si_call_addr = (void __user *)KSTK_EIP(current);
|
||||
|
|
350
kernel/signal.c
350
kernel/signal.c
|
@ -549,6 +549,7 @@ static void collect_signal(int sig, struct sigpending *list, siginfo_t *info,
|
|||
* a fast-pathed signal or we must have been
|
||||
* out of queue space. So zero out the info.
|
||||
*/
|
||||
clear_siginfo(info);
|
||||
info->si_signo = sig;
|
||||
info->si_errno = 0;
|
||||
info->si_code = SI_USER;
|
||||
|
@ -642,6 +643,9 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
|
|||
spin_unlock(&tsk->sighand->siglock);
|
||||
posixtimer_rearm(info);
|
||||
spin_lock(&tsk->sighand->siglock);
|
||||
|
||||
/* Don't expose the si_sys_private value to userspace */
|
||||
info->si_sys_private = 0;
|
||||
}
|
||||
#endif
|
||||
return signr;
|
||||
|
@ -1043,6 +1047,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
|
|||
list_add_tail(&q->list, &pending->list);
|
||||
switch ((unsigned long) info) {
|
||||
case (unsigned long) SEND_SIG_NOINFO:
|
||||
clear_siginfo(&q->info);
|
||||
q->info.si_signo = sig;
|
||||
q->info.si_errno = 0;
|
||||
q->info.si_code = SI_USER;
|
||||
|
@ -1051,6 +1056,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
|
|||
q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
|
||||
break;
|
||||
case (unsigned long) SEND_SIG_PRIV:
|
||||
clear_siginfo(&q->info);
|
||||
q->info.si_signo = sig;
|
||||
q->info.si_errno = 0;
|
||||
q->info.si_code = SI_KERNEL;
|
||||
|
@ -1485,6 +1491,129 @@ force_sigsegv(int sig, struct task_struct *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int force_sig_fault(int sig, int code, void __user *addr
|
||||
___ARCH_SI_TRAPNO(int trapno)
|
||||
___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
|
||||
, struct task_struct *t)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info.si_addr = addr;
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
info.si_trapno = trapno;
|
||||
#endif
|
||||
#ifdef __ia64__
|
||||
info.si_imm = imm;
|
||||
info.si_flags = flags;
|
||||
info.si_isr = isr;
|
||||
#endif
|
||||
return force_sig_info(info.si_signo, &info, t);
|
||||
}
|
||||
|
||||
int send_sig_fault(int sig, int code, void __user *addr
|
||||
___ARCH_SI_TRAPNO(int trapno)
|
||||
___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
|
||||
, struct task_struct *t)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info.si_addr = addr;
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
info.si_trapno = trapno;
|
||||
#endif
|
||||
#ifdef __ia64__
|
||||
info.si_imm = imm;
|
||||
info.si_flags = flags;
|
||||
info.si_isr = isr;
|
||||
#endif
|
||||
return send_sig_info(info.si_signo, &info, t);
|
||||
}
|
||||
|
||||
#if defined(BUS_MCEERR_AO) && defined(BUS_MCEERR_AR)
|
||||
int force_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *t)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
||||
WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info.si_addr = addr;
|
||||
info.si_addr_lsb = lsb;
|
||||
return force_sig_info(info.si_signo, &info, t);
|
||||
}
|
||||
|
||||
int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *t)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
||||
WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info.si_addr = addr;
|
||||
info.si_addr_lsb = lsb;
|
||||
return send_sig_info(info.si_signo, &info, t);
|
||||
}
|
||||
EXPORT_SYMBOL(send_sig_mceerr);
|
||||
#endif
|
||||
|
||||
#ifdef SEGV_BNDERR
|
||||
int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = SEGV_BNDERR;
|
||||
info.si_addr = addr;
|
||||
info.si_lower = lower;
|
||||
info.si_upper = upper;
|
||||
return force_sig_info(info.si_signo, &info, current);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SEGV_PKUERR
|
||||
int force_sig_pkuerr(void __user *addr, u32 pkey)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = SEGV_PKUERR;
|
||||
info.si_addr = addr;
|
||||
info.si_pkey = pkey;
|
||||
return force_sig_info(info.si_signo, &info, current);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* For the crazy architectures that include trap information in
|
||||
* the errno field, instead of an actual errno value.
|
||||
*/
|
||||
int force_sig_ptrace_errno_trap(int errno, void __user *addr)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = errno;
|
||||
info.si_code = TRAP_HWBKPT;
|
||||
info.si_addr = addr;
|
||||
return force_sig_info(info.si_signo, &info, current);
|
||||
}
|
||||
|
||||
int kill_pgrp(struct pid *pid, int sig, int priv)
|
||||
{
|
||||
int ret;
|
||||
|
@ -1623,6 +1752,7 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
|
|||
sig = SIGCHLD;
|
||||
}
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
/*
|
||||
|
@ -1717,6 +1847,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
|
|||
parent = tsk->real_parent;
|
||||
}
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGCHLD;
|
||||
info.si_errno = 0;
|
||||
/*
|
||||
|
@ -1929,7 +2060,7 @@ static void ptrace_do_notify(int signr, int exit_code, int why)
|
|||
{
|
||||
siginfo_t info;
|
||||
|
||||
memset(&info, 0, sizeof info);
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = signr;
|
||||
info.si_code = exit_code;
|
||||
info.si_pid = task_pid_vnr(current);
|
||||
|
@ -2136,6 +2267,7 @@ static int ptrace_signal(int signr, siginfo_t *info)
|
|||
* have updated *info via PTRACE_SETSIGINFO.
|
||||
*/
|
||||
if (signr != info->si_signo) {
|
||||
clear_siginfo(info);
|
||||
info->si_signo = signr;
|
||||
info->si_errno = 0;
|
||||
info->si_code = SI_USER;
|
||||
|
@ -2688,9 +2820,7 @@ enum siginfo_layout siginfo_layout(int sig, int si_code)
|
|||
#endif
|
||||
[SIGCHLD] = { NSIGCHLD, SIL_CHLD },
|
||||
[SIGPOLL] = { NSIGPOLL, SIL_POLL },
|
||||
#ifdef __ARCH_SIGSYS
|
||||
[SIGSYS] = { NSIGSYS, SIL_SYS },
|
||||
#endif
|
||||
};
|
||||
if ((sig < ARRAY_SIZE(filter)) && (si_code <= filter[sig].limit))
|
||||
layout = filter[sig].layout;
|
||||
|
@ -2711,13 +2841,15 @@ enum siginfo_layout siginfo_layout(int sig, int si_code)
|
|||
#ifdef FPE_FIXME
|
||||
if ((sig == SIGFPE) && (si_code == FPE_FIXME))
|
||||
layout = SIL_FAULT;
|
||||
#endif
|
||||
#ifdef BUS_FIXME
|
||||
if ((sig == SIGBUS) && (si_code == BUS_FIXME))
|
||||
layout = SIL_FAULT;
|
||||
#endif
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
#ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER
|
||||
|
||||
int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
@ -2756,13 +2888,21 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
|
|||
#ifdef __ARCH_SI_TRAPNO
|
||||
err |= __put_user(from->si_trapno, &to->si_trapno);
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AO
|
||||
#ifdef __ia64__
|
||||
err |= __put_user(from->si_imm, &to->si_imm);
|
||||
err |= __put_user(from->si_flags, &to->si_flags);
|
||||
err |= __put_user(from->si_isr, &to->si_isr);
|
||||
#endif
|
||||
/*
|
||||
* Other callers might not initialize the si_lsb field,
|
||||
* so check explicitly for the right codes here.
|
||||
*/
|
||||
if (from->si_signo == SIGBUS &&
|
||||
(from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
|
||||
#ifdef BUS_MCEERR_AR
|
||||
if (from->si_signo == SIGBUS && from->si_code == BUS_MCEERR_AR)
|
||||
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AO
|
||||
if (from->si_signo == SIGBUS && from->si_code == BUS_MCEERR_AO)
|
||||
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
|
||||
#endif
|
||||
#ifdef SEGV_BNDERR
|
||||
|
@ -2788,18 +2928,185 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
|
|||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_ptr, &to->si_ptr);
|
||||
break;
|
||||
#ifdef __ARCH_SIGSYS
|
||||
case SIL_SYS:
|
||||
err |= __put_user(from->si_call_addr, &to->si_call_addr);
|
||||
err |= __put_user(from->si_syscall, &to->si_syscall);
|
||||
err |= __put_user(from->si_arch, &to->si_arch);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
int copy_siginfo_to_user32(struct compat_siginfo __user *to,
|
||||
const struct siginfo *from)
|
||||
#if defined(CONFIG_X86_X32_ABI) || defined(CONFIG_IA32_EMULATION)
|
||||
{
|
||||
return __copy_siginfo_to_user32(to, from, in_x32_syscall());
|
||||
}
|
||||
int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
|
||||
const struct siginfo *from, bool x32_ABI)
|
||||
#endif
|
||||
{
|
||||
struct compat_siginfo new;
|
||||
memset(&new, 0, sizeof(new));
|
||||
|
||||
new.si_signo = from->si_signo;
|
||||
new.si_errno = from->si_errno;
|
||||
new.si_code = from->si_code;
|
||||
switch(siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_KILL:
|
||||
new.si_pid = from->si_pid;
|
||||
new.si_uid = from->si_uid;
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
new.si_tid = from->si_tid;
|
||||
new.si_overrun = from->si_overrun;
|
||||
new.si_int = from->si_int;
|
||||
break;
|
||||
case SIL_POLL:
|
||||
new.si_band = from->si_band;
|
||||
new.si_fd = from->si_fd;
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
new.si_addr = ptr_to_compat(from->si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.si_trapno = from->si_trapno;
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AR
|
||||
if ((from->si_signo == SIGBUS) && (from->si_code == BUS_MCEERR_AR))
|
||||
new.si_addr_lsb = from->si_addr_lsb;
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AO
|
||||
if ((from->si_signo == SIGBUS) && (from->si_code == BUS_MCEERR_AO))
|
||||
new.si_addr_lsb = from->si_addr_lsb;
|
||||
#endif
|
||||
#ifdef SEGV_BNDERR
|
||||
if ((from->si_signo == SIGSEGV) &&
|
||||
(from->si_code == SEGV_BNDERR)) {
|
||||
new.si_lower = ptr_to_compat(from->si_lower);
|
||||
new.si_upper = ptr_to_compat(from->si_upper);
|
||||
}
|
||||
#endif
|
||||
#ifdef SEGV_PKUERR
|
||||
if ((from->si_signo == SIGSEGV) &&
|
||||
(from->si_code == SEGV_PKUERR))
|
||||
new.si_pkey = from->si_pkey;
|
||||
#endif
|
||||
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
new.si_pid = from->si_pid;
|
||||
new.si_uid = from->si_uid;
|
||||
new.si_status = from->si_status;
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
if (x32_ABI) {
|
||||
new._sifields._sigchld_x32._utime = from->si_utime;
|
||||
new._sifields._sigchld_x32._stime = from->si_stime;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
new.si_utime = from->si_utime;
|
||||
new.si_stime = from->si_stime;
|
||||
}
|
||||
break;
|
||||
case SIL_RT:
|
||||
new.si_pid = from->si_pid;
|
||||
new.si_uid = from->si_uid;
|
||||
new.si_int = from->si_int;
|
||||
break;
|
||||
case SIL_SYS:
|
||||
new.si_call_addr = ptr_to_compat(from->si_call_addr);
|
||||
new.si_syscall = from->si_syscall;
|
||||
new.si_arch = from->si_arch;
|
||||
break;
|
||||
}
|
||||
|
||||
if (copy_to_user(to, &new, sizeof(struct compat_siginfo)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int copy_siginfo_from_user32(struct siginfo *to,
|
||||
const struct compat_siginfo __user *ufrom)
|
||||
{
|
||||
struct compat_siginfo from;
|
||||
|
||||
if (copy_from_user(&from, ufrom, sizeof(struct compat_siginfo)))
|
||||
return -EFAULT;
|
||||
|
||||
clear_siginfo(to);
|
||||
to->si_signo = from.si_signo;
|
||||
to->si_errno = from.si_errno;
|
||||
to->si_code = from.si_code;
|
||||
switch(siginfo_layout(from.si_signo, from.si_code)) {
|
||||
case SIL_KILL:
|
||||
to->si_pid = from.si_pid;
|
||||
to->si_uid = from.si_uid;
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
to->si_tid = from.si_tid;
|
||||
to->si_overrun = from.si_overrun;
|
||||
to->si_int = from.si_int;
|
||||
break;
|
||||
case SIL_POLL:
|
||||
to->si_band = from.si_band;
|
||||
to->si_fd = from.si_fd;
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
to->si_addr = compat_ptr(from.si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
to->si_trapno = from.si_trapno;
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AR
|
||||
if ((from.si_signo == SIGBUS) && (from.si_code == BUS_MCEERR_AR))
|
||||
to->si_addr_lsb = from.si_addr_lsb;
|
||||
#endif
|
||||
#ifdef BUS_MCEER_AO
|
||||
if ((from.si_signo == SIGBUS) && (from.si_code == BUS_MCEERR_AO))
|
||||
to->si_addr_lsb = from.si_addr_lsb;
|
||||
#endif
|
||||
#ifdef SEGV_BNDERR
|
||||
if ((from.si_signo == SIGSEGV) && (from.si_code == SEGV_BNDERR)) {
|
||||
to->si_lower = compat_ptr(from.si_lower);
|
||||
to->si_upper = compat_ptr(from.si_upper);
|
||||
}
|
||||
#endif
|
||||
#ifdef SEGV_PKUERR
|
||||
if ((from.si_signo == SIGSEGV) && (from.si_code == SEGV_PKUERR))
|
||||
to->si_pkey = from.si_pkey;
|
||||
#endif
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
to->si_pid = from.si_pid;
|
||||
to->si_uid = from.si_uid;
|
||||
to->si_status = from.si_status;
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
if (in_x32_syscall()) {
|
||||
to->si_utime = from._sifields._sigchld_x32._utime;
|
||||
to->si_stime = from._sifields._sigchld_x32._stime;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
to->si_utime = from.si_utime;
|
||||
to->si_stime = from.si_stime;
|
||||
}
|
||||
break;
|
||||
case SIL_RT:
|
||||
to->si_pid = from.si_pid;
|
||||
to->si_uid = from.si_uid;
|
||||
to->si_int = from.si_int;
|
||||
break;
|
||||
case SIL_SYS:
|
||||
to->si_call_addr = compat_ptr(from.si_call_addr);
|
||||
to->si_syscall = from.si_syscall;
|
||||
to->si_arch = from.si_arch;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
/**
|
||||
* do_sigtimedwait - wait for queued signals specified in @which
|
||||
|
@ -2937,6 +3244,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
|
|||
{
|
||||
struct siginfo info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = SI_USER;
|
||||
|
@ -2978,8 +3286,9 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
|
|||
|
||||
static int do_tkill(pid_t tgid, pid_t pid, int sig)
|
||||
{
|
||||
struct siginfo info = {};
|
||||
struct siginfo info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = SI_TKILL;
|
||||
|
@ -3060,7 +3369,7 @@ COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo,
|
|||
int, sig,
|
||||
struct compat_siginfo __user *, uinfo)
|
||||
{
|
||||
siginfo_t info = {};
|
||||
siginfo_t info;
|
||||
int ret = copy_siginfo_from_user32(&info, uinfo);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
@ -3104,7 +3413,7 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo,
|
|||
int, sig,
|
||||
struct compat_siginfo __user *, uinfo)
|
||||
{
|
||||
siginfo_t info = {};
|
||||
siginfo_t info;
|
||||
|
||||
if (copy_siginfo_from_user32(&info, uinfo))
|
||||
return -EFAULT;
|
||||
|
@ -3677,6 +3986,7 @@ void __init signals_init(void)
|
|||
/* If this check fails, the __ARCH_SI_PREAMBLE_SIZE value is wrong! */
|
||||
BUILD_BUG_ON(__ARCH_SI_PREAMBLE_SIZE
|
||||
!= offsetof(struct siginfo, _sifields._pad));
|
||||
BUILD_BUG_ON(sizeof(struct siginfo) != SI_MAX_SIZE);
|
||||
|
||||
sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC);
|
||||
}
|
||||
|
@ -3684,26 +3994,25 @@ void __init signals_init(void)
|
|||
#ifdef CONFIG_KGDB_KDB
|
||||
#include <linux/kdb.h>
|
||||
/*
|
||||
* kdb_send_sig_info - Allows kdb to send signals without exposing
|
||||
* kdb_send_sig - Allows kdb to send signals without exposing
|
||||
* signal internals. This function checks if the required locks are
|
||||
* available before calling the main signal code, to avoid kdb
|
||||
* deadlocks.
|
||||
*/
|
||||
void
|
||||
kdb_send_sig_info(struct task_struct *t, struct siginfo *info)
|
||||
void kdb_send_sig(struct task_struct *t, int sig)
|
||||
{
|
||||
static struct task_struct *kdb_prev_t;
|
||||
int sig, new_t;
|
||||
int new_t, ret;
|
||||
if (!spin_trylock(&t->sighand->siglock)) {
|
||||
kdb_printf("Can't do kill command now.\n"
|
||||
"The sigmask lock is held somewhere else in "
|
||||
"kernel, try again later\n");
|
||||
return;
|
||||
}
|
||||
spin_unlock(&t->sighand->siglock);
|
||||
new_t = kdb_prev_t != t;
|
||||
kdb_prev_t = t;
|
||||
if (t->state != TASK_RUNNING && new_t) {
|
||||
spin_unlock(&t->sighand->siglock);
|
||||
kdb_printf("Process is not RUNNING, sending a signal from "
|
||||
"kdb risks deadlock\n"
|
||||
"on the run queue locks. "
|
||||
|
@ -3712,8 +4021,9 @@ kdb_send_sig_info(struct task_struct *t, struct siginfo *info)
|
|||
"the deadlock.\n");
|
||||
return;
|
||||
}
|
||||
sig = info->si_signo;
|
||||
if (send_sig_info(sig, info, t))
|
||||
ret = send_signal(sig, SEND_SIG_PRIV, t, false);
|
||||
spin_unlock(&t->sighand->siglock);
|
||||
if (ret)
|
||||
kdb_printf("Fail to deliver Signal %d to process %d.\n",
|
||||
sig, t->pid);
|
||||
else
|
||||
|
|
|
@ -462,7 +462,7 @@ static struct k_itimer * alloc_posix_timer(void)
|
|||
kmem_cache_free(posix_timers_cache, tmr);
|
||||
return NULL;
|
||||
}
|
||||
memset(&tmr->sigq->info, 0, sizeof(siginfo_t));
|
||||
clear_siginfo(&tmr->sigq->info);
|
||||
return tmr;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ static int hwpoison_inject(void *data, u64 val)
|
|||
|
||||
inject:
|
||||
pr_info("Injecting memory failure at pfn %#lx\n", pfn);
|
||||
return memory_failure(pfn, 18, MF_COUNT_INCREASED);
|
||||
return memory_failure(pfn, MF_COUNT_INCREASED);
|
||||
put_out:
|
||||
put_hwpoison_page(p);
|
||||
return 0;
|
||||
|
|
|
@ -661,7 +661,7 @@ static int madvise_inject_error(int behavior,
|
|||
pr_info("Injecting memory failure for pfn %#lx at process virtual address %#lx\n",
|
||||
page_to_pfn(page), start);
|
||||
|
||||
ret = memory_failure(page_to_pfn(page), 0, MF_COUNT_INCREASED);
|
||||
ret = memory_failure(page_to_pfn(page), MF_COUNT_INCREASED);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -178,25 +178,19 @@ EXPORT_SYMBOL_GPL(hwpoison_filter);
|
|||
* ``action optional'' if they are not immediately affected by the error
|
||||
* ``action required'' if error happened in current execution context
|
||||
*/
|
||||
static int kill_proc(struct task_struct *t, unsigned long addr, int trapno,
|
||||
static int kill_proc(struct task_struct *t, unsigned long addr,
|
||||
unsigned long pfn, struct page *page, int flags)
|
||||
{
|
||||
struct siginfo si;
|
||||
short addr_lsb;
|
||||
int ret;
|
||||
|
||||
pr_err("Memory failure: %#lx: Killing %s:%d due to hardware memory corruption\n",
|
||||
pfn, t->comm, t->pid);
|
||||
si.si_signo = SIGBUS;
|
||||
si.si_errno = 0;
|
||||
si.si_addr = (void *)addr;
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
si.si_trapno = trapno;
|
||||
#endif
|
||||
si.si_addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT;
|
||||
addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT;
|
||||
|
||||
if ((flags & MF_ACTION_REQUIRED) && t->mm == current->mm) {
|
||||
si.si_code = BUS_MCEERR_AR;
|
||||
ret = force_sig_info(SIGBUS, &si, current);
|
||||
ret = force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr,
|
||||
addr_lsb, current);
|
||||
} else {
|
||||
/*
|
||||
* Don't use force here, it's convenient if the signal
|
||||
|
@ -204,8 +198,8 @@ static int kill_proc(struct task_struct *t, unsigned long addr, int trapno,
|
|||
* This could cause a loop when the user sets SIGBUS
|
||||
* to SIG_IGN, but hopefully no one will do that?
|
||||
*/
|
||||
si.si_code = BUS_MCEERR_AO;
|
||||
ret = send_sig_info(SIGBUS, &si, t); /* synchronous? */
|
||||
ret = send_sig_mceerr(BUS_MCEERR_AO, (void __user *)addr,
|
||||
addr_lsb, t); /* synchronous? */
|
||||
}
|
||||
if (ret < 0)
|
||||
pr_info("Memory failure: Error sending signal to %s:%d: %d\n",
|
||||
|
@ -323,7 +317,7 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
|
|||
* Also when FAIL is set do a force kill because something went
|
||||
* wrong earlier.
|
||||
*/
|
||||
static void kill_procs(struct list_head *to_kill, int forcekill, int trapno,
|
||||
static void kill_procs(struct list_head *to_kill, int forcekill,
|
||||
bool fail, struct page *page, unsigned long pfn,
|
||||
int flags)
|
||||
{
|
||||
|
@ -348,7 +342,7 @@ static void kill_procs(struct list_head *to_kill, int forcekill, int trapno,
|
|||
* check for that, but we need to tell the
|
||||
* process anyways.
|
||||
*/
|
||||
else if (kill_proc(tk->tsk, tk->addr, trapno,
|
||||
else if (kill_proc(tk->tsk, tk->addr,
|
||||
pfn, page, flags) < 0)
|
||||
pr_err("Memory failure: %#lx: Cannot send advisory machine check signal to %s:%d\n",
|
||||
pfn, tk->tsk->comm, tk->tsk->pid);
|
||||
|
@ -927,7 +921,7 @@ EXPORT_SYMBOL_GPL(get_hwpoison_page);
|
|||
* the pages and send SIGBUS to the processes if the data was dirty.
|
||||
*/
|
||||
static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
|
||||
int trapno, int flags, struct page **hpagep)
|
||||
int flags, struct page **hpagep)
|
||||
{
|
||||
enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
|
||||
struct address_space *mapping;
|
||||
|
@ -1017,7 +1011,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
|
|||
* any accesses to the poisoned memory.
|
||||
*/
|
||||
forcekill = PageDirty(hpage) || (flags & MF_MUST_KILL);
|
||||
kill_procs(&tokill, forcekill, trapno, !unmap_success, p, pfn, flags);
|
||||
kill_procs(&tokill, forcekill, !unmap_success, p, pfn, flags);
|
||||
|
||||
return unmap_success;
|
||||
}
|
||||
|
@ -1045,7 +1039,7 @@ static int identify_page_state(unsigned long pfn, struct page *p,
|
|||
return page_action(ps, p, pfn);
|
||||
}
|
||||
|
||||
static int memory_failure_hugetlb(unsigned long pfn, int trapno, int flags)
|
||||
static int memory_failure_hugetlb(unsigned long pfn, int flags)
|
||||
{
|
||||
struct page *p = pfn_to_page(pfn);
|
||||
struct page *head = compound_head(p);
|
||||
|
@ -1090,7 +1084,7 @@ static int memory_failure_hugetlb(unsigned long pfn, int trapno, int flags)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!hwpoison_user_mappings(p, pfn, trapno, flags, &head)) {
|
||||
if (!hwpoison_user_mappings(p, pfn, flags, &head)) {
|
||||
action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED);
|
||||
res = -EBUSY;
|
||||
goto out;
|
||||
|
@ -1105,7 +1099,6 @@ static int memory_failure_hugetlb(unsigned long pfn, int trapno, int flags)
|
|||
/**
|
||||
* memory_failure - Handle memory failure of a page.
|
||||
* @pfn: Page Number of the corrupted page
|
||||
* @trapno: Trap number reported in the signal to user space.
|
||||
* @flags: fine tune action taken
|
||||
*
|
||||
* This function is called by the low level machine check code
|
||||
|
@ -1120,7 +1113,7 @@ static int memory_failure_hugetlb(unsigned long pfn, int trapno, int flags)
|
|||
* Must run in process context (e.g. a work queue) with interrupts
|
||||
* enabled and no spinlocks hold.
|
||||
*/
|
||||
int memory_failure(unsigned long pfn, int trapno, int flags)
|
||||
int memory_failure(unsigned long pfn, int flags)
|
||||
{
|
||||
struct page *p;
|
||||
struct page *hpage;
|
||||
|
@ -1129,7 +1122,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
|
|||
unsigned long page_flags;
|
||||
|
||||
if (!sysctl_memory_failure_recovery)
|
||||
panic("Memory failure from trap %d on page %lx", trapno, pfn);
|
||||
panic("Memory failure on page %lx", pfn);
|
||||
|
||||
if (!pfn_valid(pfn)) {
|
||||
pr_err("Memory failure: %#lx: memory outside kernel control\n",
|
||||
|
@ -1139,7 +1132,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
|
|||
|
||||
p = pfn_to_page(pfn);
|
||||
if (PageHuge(p))
|
||||
return memory_failure_hugetlb(pfn, trapno, flags);
|
||||
return memory_failure_hugetlb(pfn, flags);
|
||||
if (TestSetPageHWPoison(p)) {
|
||||
pr_err("Memory failure: %#lx: already hardware poisoned\n",
|
||||
pfn);
|
||||
|
@ -1268,7 +1261,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
|
|||
* When the raw error page is thp tail page, hpage points to the raw
|
||||
* page after thp split.
|
||||
*/
|
||||
if (!hwpoison_user_mappings(p, pfn, trapno, flags, &hpage)) {
|
||||
if (!hwpoison_user_mappings(p, pfn, flags, &hpage)) {
|
||||
action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED);
|
||||
res = -EBUSY;
|
||||
goto out;
|
||||
|
@ -1296,7 +1289,6 @@ EXPORT_SYMBOL_GPL(memory_failure);
|
|||
|
||||
struct memory_failure_entry {
|
||||
unsigned long pfn;
|
||||
int trapno;
|
||||
int flags;
|
||||
};
|
||||
|
||||
|
@ -1312,7 +1304,6 @@ static DEFINE_PER_CPU(struct memory_failure_cpu, memory_failure_cpu);
|
|||
/**
|
||||
* memory_failure_queue - Schedule handling memory failure of a page.
|
||||
* @pfn: Page Number of the corrupted page
|
||||
* @trapno: Trap number reported in the signal to user space.
|
||||
* @flags: Flags for memory failure handling
|
||||
*
|
||||
* This function is called by the low level hardware error handler
|
||||
|
@ -1326,13 +1317,12 @@ static DEFINE_PER_CPU(struct memory_failure_cpu, memory_failure_cpu);
|
|||
*
|
||||
* Can run in IRQ context.
|
||||
*/
|
||||
void memory_failure_queue(unsigned long pfn, int trapno, int flags)
|
||||
void memory_failure_queue(unsigned long pfn, int flags)
|
||||
{
|
||||
struct memory_failure_cpu *mf_cpu;
|
||||
unsigned long proc_flags;
|
||||
struct memory_failure_entry entry = {
|
||||
.pfn = pfn,
|
||||
.trapno = trapno,
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
|
@ -1365,7 +1355,7 @@ static void memory_failure_work_func(struct work_struct *work)
|
|||
if (entry.flags & MF_SOFT_OFFLINE)
|
||||
soft_offline_page(pfn_to_page(entry.pfn), entry.flags);
|
||||
else
|
||||
memory_failure(entry.pfn, entry.trapno, entry.flags);
|
||||
memory_failure(entry.pfn, entry.flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue