signal: Extend siginfo_layout with SIL_FAULT_{MCEERR|BNDERR|PKUERR}
Update the siginfo_layout function and enum siginfo_layout to represent all of the possible field layouts of struct siginfo. This allows the uses of siginfo_layout in um and arm64 where they are testing for SIL_FAULT to be more accurate as this rules out the other cases. Further this allows the switch statements on siginfo_layout to be simpler if perhaps a little more wordy. Making it easier to understand what is actually going on. As SIL_FAULT_BNDERR and SIL_FAULT_PKUERR are never expected to appear in signalfd just treat them as SIL_FAULT. To include them would take 20 extra bytes an pretty much fill up what is left of signalfd_siginfo. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
parent
36a4ca3d9b
commit
31931c93df
|
@ -112,19 +112,27 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
|
|||
new.ssi_band = kinfo->si_band;
|
||||
new.ssi_fd = kinfo->si_fd;
|
||||
break;
|
||||
case SIL_FAULT_BNDERR:
|
||||
case SIL_FAULT_PKUERR:
|
||||
/*
|
||||
* Fall through to the SIL_FAULT case. Both SIL_FAULT_BNDERR
|
||||
* and SIL_FAULT_PKUERR are only generated by faults that
|
||||
* deliver them synchronously to userspace. In case someone
|
||||
* injects one of these signals and signalfd catches it treat
|
||||
* it as SIL_FAULT.
|
||||
*/
|
||||
case SIL_FAULT:
|
||||
new.ssi_addr = (long) kinfo->si_addr;
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.ssi_trapno = kinfo->si_trapno;
|
||||
#endif
|
||||
/*
|
||||
* Other callers might not initialize the si_lsb field,
|
||||
* so check explicitly for the right codes here.
|
||||
*/
|
||||
if (kinfo->si_signo == SIGBUS &&
|
||||
((kinfo->si_code == BUS_MCEERR_AR) ||
|
||||
(kinfo->si_code == BUS_MCEERR_AO)))
|
||||
new.ssi_addr_lsb = (short) kinfo->si_addr_lsb;
|
||||
break;
|
||||
case SIL_FAULT_MCEERR:
|
||||
new.ssi_addr = (long) kinfo->si_addr;
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.ssi_trapno = kinfo->si_trapno;
|
||||
#endif
|
||||
new.ssi_addr_lsb = (short) kinfo->si_addr_lsb;
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
new.ssi_pid = kinfo->si_pid;
|
||||
|
|
|
@ -28,6 +28,9 @@ enum siginfo_layout {
|
|||
SIL_TIMER,
|
||||
SIL_POLL,
|
||||
SIL_FAULT,
|
||||
SIL_FAULT_MCEERR,
|
||||
SIL_FAULT_BNDERR,
|
||||
SIL_FAULT_PKUERR,
|
||||
SIL_CHLD,
|
||||
SIL_RT,
|
||||
SIL_SYS,
|
||||
|
|
|
@ -2820,8 +2820,19 @@ enum siginfo_layout siginfo_layout(int sig, int si_code)
|
|||
[SIGPOLL] = { NSIGPOLL, SIL_POLL },
|
||||
[SIGSYS] = { NSIGSYS, SIL_SYS },
|
||||
};
|
||||
if ((sig < ARRAY_SIZE(filter)) && (si_code <= filter[sig].limit))
|
||||
if ((sig < ARRAY_SIZE(filter)) && (si_code <= filter[sig].limit)) {
|
||||
layout = filter[sig].layout;
|
||||
/* Handle the exceptions */
|
||||
if ((sig == SIGBUS) &&
|
||||
(si_code >= BUS_MCEERR_AR) && (si_code <= BUS_MCEERR_AO))
|
||||
layout = SIL_FAULT_MCEERR;
|
||||
else if ((sig == SIGSEGV) && (si_code == SEGV_BNDERR))
|
||||
layout = SIL_FAULT_BNDERR;
|
||||
#ifdef SEGV_PKUERR
|
||||
else if ((sig == SIGSEGV) && (si_code == SEGV_PKUERR))
|
||||
layout = SIL_FAULT_PKUERR;
|
||||
#endif
|
||||
}
|
||||
else if (si_code <= NSIGPOLL)
|
||||
layout = SIL_POLL;
|
||||
} else {
|
||||
|
@ -2878,19 +2889,28 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
|
|||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.si_trapno = from->si_trapno;
|
||||
#endif
|
||||
if ((from->si_signo == SIGBUS) &&
|
||||
((from->si_code == BUS_MCEERR_AR) ||
|
||||
(from->si_code == BUS_MCEERR_AO)))
|
||||
new.si_addr_lsb = from->si_addr_lsb;
|
||||
|
||||
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);
|
||||
}
|
||||
if ((from->si_signo == SIGSEGV) &&
|
||||
(from->si_code == SEGV_PKUERR))
|
||||
new.si_pkey = from->si_pkey;
|
||||
break;
|
||||
case SIL_FAULT_MCEERR:
|
||||
new.si_addr = ptr_to_compat(from->si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.si_trapno = from->si_trapno;
|
||||
#endif
|
||||
new.si_addr_lsb = from->si_addr_lsb;
|
||||
break;
|
||||
case SIL_FAULT_BNDERR:
|
||||
new.si_addr = ptr_to_compat(from->si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.si_trapno = from->si_trapno;
|
||||
#endif
|
||||
new.si_lower = ptr_to_compat(from->si_lower);
|
||||
new.si_upper = ptr_to_compat(from->si_upper);
|
||||
break;
|
||||
case SIL_FAULT_PKUERR:
|
||||
new.si_addr = ptr_to_compat(from->si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.si_trapno = from->si_trapno;
|
||||
#endif
|
||||
new.si_pkey = from->si_pkey;
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
new.si_pid = from->si_pid;
|
||||
|
@ -2956,17 +2976,28 @@ int copy_siginfo_from_user32(struct siginfo *to,
|
|||
#ifdef __ARCH_SI_TRAPNO
|
||||
to->si_trapno = from.si_trapno;
|
||||
#endif
|
||||
if ((from.si_signo == SIGBUS) &&
|
||||
((from.si_code == BUS_MCEERR_AR) ||
|
||||
(from.si_code == BUS_MCEERR_AO)))
|
||||
to->si_addr_lsb = from.si_addr_lsb;
|
||||
|
||||
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);
|
||||
}
|
||||
if ((from.si_signo == SIGSEGV) && (from.si_code == SEGV_PKUERR))
|
||||
to->si_pkey = from.si_pkey;
|
||||
break;
|
||||
case SIL_FAULT_MCEERR:
|
||||
to->si_addr = compat_ptr(from.si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
to->si_trapno = from.si_trapno;
|
||||
#endif
|
||||
to->si_addr_lsb = from.si_addr_lsb;
|
||||
break;
|
||||
case SIL_FAULT_BNDERR:
|
||||
to->si_addr = compat_ptr(from.si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
to->si_trapno = from.si_trapno;
|
||||
#endif
|
||||
to->si_lower = compat_ptr(from.si_lower);
|
||||
to->si_upper = compat_ptr(from.si_upper);
|
||||
break;
|
||||
case SIL_FAULT_PKUERR:
|
||||
to->si_addr = compat_ptr(from.si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
to->si_trapno = from.si_trapno;
|
||||
#endif
|
||||
to->si_pkey = from.si_pkey;
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
to->si_pid = from.si_pid;
|
||||
|
|
Loading…
Reference in New Issue