Skip to content

Commit

Permalink
Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/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
  ...
  • Loading branch information
torvalds committed Jan 30, 2018
2 parents 0aebc6a + c0f4555 commit d417302
Show file tree
Hide file tree
Showing 76 changed files with 855 additions and 1,808 deletions.
14 changes: 8 additions & 6 deletions arch/arc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);\
}

Expand Down
13 changes: 13 additions & 0 deletions arch/arm/include/uapi/asm/siginfo.h
Original file line number Diff line number Diff line change
@@ -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
8 changes: 1 addition & 7 deletions arch/arm/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,20 +390,14 @@ 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)
break;

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

/*
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/vfp/vfpmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
64 changes: 0 additions & 64 deletions arch/arm64/include/asm/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

/*
Expand Down
21 changes: 21 additions & 0 deletions arch/arm64/include/uapi/asm/siginfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
13 changes: 7 additions & 6 deletions arch/arm64/kernel/debug-monitors.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/fpsimd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
42 changes: 21 additions & 21 deletions arch/arm64/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

#ifdef CONFIG_COMPAT
int i;
clear_siginfo(&info);
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_HWBKPT;
info.si_addr = (void __user *)(bkpt->trigger);

if (!is_compat_task())
goto send_sig;
#ifdef CONFIG_COMPAT
if (is_compat_task()) {
int si_errno = 0;
int i;

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);
}
Expand Down
80 changes: 0 additions & 80 deletions arch/arm64/kernel/signal32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
Loading

0 comments on commit d417302

Please sign in to comment.