Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31931c93 authored by Eric W. Biederman's avatar Eric W. Biederman
Browse files

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: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
parent 36a4ca3d
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -112,18 +112,26 @@ 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)))
		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:
+3 −0
Original line number Diff line number Diff line
@@ -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,
+56 −25
Original line number Diff line number Diff line
@@ -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,18 +2889,27 @@ 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)))
		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;

		if ((from->si_signo == SIGSEGV) &&
		    (from->si_code == SEGV_BNDERR)) {
		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);
		}
		if ((from->si_signo == SIGSEGV) &&
		    (from->si_code == SEGV_PKUERR))
		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:
@@ -2956,16 +2976,27 @@ 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)))
		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;

		if ((from.si_signo == SIGSEGV) && (from.si_code == SEGV_BNDERR)) {
		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);
		}
		if ((from.si_signo == SIGSEGV) && (from.si_code == SEGV_PKUERR))
		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: