From 4181d22596f61d060139bb114724f89b3ad28c8d Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sun, 15 Apr 2018 19:40:02 -0500 Subject: signal: Remove ifdefs for BUS_MCEERR_AR and BUS_MCEERR_AO With the recent architecture cleanups these si_codes are always defined so there is no need to test for them. Signed-off-by: "Eric W. Biederman" --- fs/signalfd.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/signalfd.c b/fs/signalfd.c index d2187a813376..ff302bf50be4 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -117,26 +117,15 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, #ifdef __ARCH_SI_TRAPNO err |= __put_user(kinfo->si_trapno, &uinfo->ssi_trapno); #endif -#ifdef BUS_MCEERR_AO /* * 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_AO) + ((kinfo->si_code == BUS_MCEERR_AR) || + (kinfo->si_code == BUS_MCEERR_AO))) err |= __put_user((short) kinfo->si_addr_lsb, &uinfo->ssi_addr_lsb); -#endif -#ifdef BUS_MCEERR_AR - /* - * 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) - err |= __put_user((short) kinfo->si_addr_lsb, - &uinfo->ssi_addr_lsb); -#endif break; case SIL_CHLD: err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); -- cgit v1.2.3 From 5611f55ee4df70d947bf239c587e742efdab028b Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 24 Apr 2018 20:39:16 -0500 Subject: signal/signalfd: Remove __put_user from signalfd_copyinfo Put a signalfd_siginfo structure on the stack fully initializae it and then copy it to userspace. The code is a little less wordy, and this avoids a long series of the somewhat costly __put_user calls. Signed-off-by: "Eric W. Biederman" --- fs/signalfd.c | 56 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'fs') diff --git a/fs/signalfd.c b/fs/signalfd.c index ff302bf50be4..31e960209a08 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -81,41 +81,41 @@ static __poll_t signalfd_poll(struct file *file, poll_table *wait) static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, siginfo_t const *kinfo) { - long err; + struct signalfd_siginfo new; BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128); /* * Unused members should be zero ... */ - err = __clear_user(uinfo, sizeof(*uinfo)); + memset(&new, 0, sizeof(new)); /* * If you change siginfo_t structure, please be sure * this code is fixed accordingly. */ - err |= __put_user(kinfo->si_signo, &uinfo->ssi_signo); - err |= __put_user(kinfo->si_errno, &uinfo->ssi_errno); - err |= __put_user(kinfo->si_code, &uinfo->ssi_code); + new.ssi_signo = kinfo->si_signo; + new.ssi_errno = kinfo->si_errno; + new.ssi_code = kinfo->si_code; switch (siginfo_layout(kinfo->si_signo, kinfo->si_code)) { case SIL_KILL: - err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); - err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); + new.ssi_pid = kinfo->si_pid; + new.ssi_uid = kinfo->si_uid; break; case SIL_TIMER: - err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid); - err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun); - err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr); - err |= __put_user(kinfo->si_int, &uinfo->ssi_int); + new.ssi_tid = kinfo->si_tid; + new.ssi_overrun = kinfo->si_overrun; + new.ssi_ptr = (long) kinfo->si_ptr; + new.ssi_int = kinfo->si_int; break; case SIL_POLL: - err |= __put_user(kinfo->si_band, &uinfo->ssi_band); - err |= __put_user(kinfo->si_fd, &uinfo->ssi_fd); + new.ssi_band = kinfo->si_band; + new.ssi_fd = kinfo->si_fd; break; case SIL_FAULT: - err |= __put_user((long) kinfo->si_addr, &uinfo->ssi_addr); + new.ssi_addr = (long) kinfo->si_addr; #ifdef __ARCH_SI_TRAPNO - err |= __put_user(kinfo->si_trapno, &uinfo->ssi_trapno); + new.ssi_trapno = kinfo->si_trapno; #endif /* * Other callers might not initialize the si_lsb field, @@ -124,29 +124,31 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, if (kinfo->si_signo == SIGBUS && ((kinfo->si_code == BUS_MCEERR_AR) || (kinfo->si_code == BUS_MCEERR_AO))) - err |= __put_user((short) kinfo->si_addr_lsb, - &uinfo->ssi_addr_lsb); + new.ssi_addr_lsb = (short) kinfo->si_addr_lsb; break; case SIL_CHLD: - err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); - err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); - err |= __put_user(kinfo->si_status, &uinfo->ssi_status); - err |= __put_user(kinfo->si_utime, &uinfo->ssi_utime); - err |= __put_user(kinfo->si_stime, &uinfo->ssi_stime); + new.ssi_pid = kinfo->si_pid; + new.ssi_uid = kinfo->si_uid; + new.ssi_status = kinfo->si_status; + new.ssi_utime = kinfo->si_utime; + new.ssi_stime = kinfo->si_stime; break; case SIL_RT: default: /* * This case catches also the signals queued by sigqueue(). */ - err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); - err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); - err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr); - err |= __put_user(kinfo->si_int, &uinfo->ssi_int); + new.ssi_pid = kinfo->si_pid; + new.ssi_uid = kinfo->si_uid; + new.ssi_ptr = (long) kinfo->si_ptr; + new.ssi_int = kinfo->si_int; break; } - return err ? -EFAULT: sizeof(*uinfo); + if (copy_to_user(uinfo, &new, sizeof(struct signalfd_siginfo))) + return -EFAULT; + + return sizeof(*uinfo); } static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info, -- cgit v1.2.3 From 76b7f670730e87974f71df9f6129811e2769666e Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 24 Apr 2018 20:48:32 -0500 Subject: signal/signalfd: Add support for SIGSYS I don't know why signalfd has never grown support for SIGSYS but grow it now. This corrects an oversight and removes a need for a default in the switch statement. Allowing gcc to warn when future members are added to the enum siginfo_layout, and signalfd does not handle them. Signed-off-by: "Eric W. Biederman" --- fs/signalfd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/signalfd.c b/fs/signalfd.c index 31e960209a08..f652249f59f9 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -134,7 +134,6 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, new.ssi_stime = kinfo->si_stime; break; case SIL_RT: - default: /* * This case catches also the signals queued by sigqueue(). */ @@ -143,6 +142,11 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, new.ssi_ptr = (long) kinfo->si_ptr; new.ssi_int = kinfo->si_int; break; + case SIL_SYS: + new.ssi_call_addr = (long) kinfo->si_call_addr; + new.ssi_syscall = kinfo->si_syscall; + new.ssi_arch = kinfo->si_arch; + break; } if (copy_to_user(uinfo, &new, sizeof(struct signalfd_siginfo))) -- cgit v1.2.3 From 31931c93dfe05a76385a443ed28244a50e915a46 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 24 Apr 2018 20:59:47 -0500 Subject: 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" --- fs/signalfd.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/signalfd.c b/fs/signalfd.c index f652249f59f9..cbb42f77a2bd 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -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; -- cgit v1.2.3