The following commit has been merged in the master branch: commit 48983701a1e0e252faa4aab274ba14419cb286fa Merge: 477f70cd2a67904e04c2c2b9bd0fa2e95222f2f6 ee53488cc74143cadbe752d5332b1e3fd87eed49 Author: Linus Torvalds torvalds@linux-foundation.org Date: Wed Sep 1 14:42:36 2021 -0700
Merge branch 'siginfo-si_trapno-for-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull siginfo si_trapno updates from Eric Biederman: "The full set of si_trapno changes was not appropriate as a fix for the newly added SIGTRAP TRAP_PERF, and so I postponed the rest of the related cleanups.
This is the rest of the cleanups for si_trapno that reduces it from being a really weird arch special case that is expect to be always present (but isn't) on the architectures that support it to being yet another field in the _sigfault union of struct siginfo.
The changes have been reviewed and marinated in linux-next. With the removal of this awkward special case new code (like SIGTRAP TRAP_PERF) that works across architectures should be easier to write and maintain"
* 'siginfo-si_trapno-for-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: signal: Rename SIL_PERF_EVENT SIL_FAULT_PERF_EVENT for consistency signal: Verify the alignment and size of siginfo_t signal: Remove the generic __ARCH_SI_TRAPNO support signal/alpha: si_trapno is only used with SIGFPE and SIGTRAP TRAP_UNK signal/sparc: si_trapno is only used with SIGILL ILL_ILLTRP arm64: Add compile-time asserts for siginfo_t offsets arm: Add compile-time asserts for siginfo_t offsets sparc64: Add compile-time asserts for siginfo_t offsets
diff --combined arch/alpha/kernel/osf_sys.c index d31167e3269c,bbdb1a9a5fd8..8bbeebb73cf0 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@@ -834,7 -834,7 +834,7 @@@ SYSCALL_DEFINE5(osf_setsysinfo, unsigne return -EFAULT; state = ¤t_thread_info()->ieee_state;
- /* Update softare trap enable bits. */ + /* Update software trap enable bits. */ *state = (*state & ~IEEE_SW_MASK) | (swcr & IEEE_SW_MASK);
/* Update the real fpcr. */ @@@ -854,7 -854,7 +854,7 @@@ state = ¤t_thread_info()->ieee_state; exc &= IEEE_STATUS_MASK;
- /* Update softare trap enable bits. */ + /* Update software trap enable bits. */ swcr = (*state & IEEE_SW_MASK) | exc; *state |= exc;
@@@ -876,7 -876,7 +876,7 @@@ if (fex & IEEE_TRAP_ENABLE_DZE) si_code = FPE_FLTDIV; if (fex & IEEE_TRAP_ENABLE_INV) si_code = FPE_FLTINV;
- send_sig_fault(SIGFPE, si_code, + send_sig_fault_trapno(SIGFPE, si_code, (void __user *)NULL, /* FIXME */ 0, current); } diff --combined arch/alpha/kernel/traps.c index 5398f982bdd1,e9e3de18793b..e805106409f7 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@@ -227,7 -227,7 +227,7 @@@ do_entArith(unsigned long summary, unsi } die_if_kernel("Arithmetic fault", regs, 0, NULL);
- send_sig_fault(SIGFPE, si_code, (void __user *) regs->pc, 0, current); + send_sig_fault_trapno(SIGFPE, si_code, (void __user *) regs->pc, 0, current); }
asmlinkage void @@@ -268,13 -268,13 +268,13 @@@ do_entIF(unsigned long type, struct pt_ regs->pc -= 4; /* make pc point to former bpt */ }
- send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc, 0, + send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc, current); return;
case 1: /* bugcheck */ - send_sig_fault(SIGTRAP, TRAP_UNK, (void __user *) regs->pc, 0, - current); + send_sig_fault_trapno(SIGTRAP, TRAP_UNK, + (void __user *) regs->pc, 0, current); return; case 2: /* gentrap */ @@@ -335,8 -335,8 +335,8 @@@ break; }
- send_sig_fault(signo, code, (void __user *) regs->pc, regs->r16, - current); + send_sig_fault_trapno(signo, code, (void __user *) regs->pc, + regs->r16, current); return;
case 4: /* opDEC */ @@@ -360,9 -360,9 +360,9 @@@ if (si_code == 0) return; if (si_code > 0) { - send_sig_fault(SIGFPE, si_code, - (void __user *) regs->pc, 0, - current); + send_sig_fault_trapno(SIGFPE, si_code, + (void __user *) regs->pc, + 0, current); return; } } @@@ -387,7 -387,7 +387,7 @@@ ; }
- send_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc, 0, current); + send_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc, current); }
/* There is an ifdef in the PALcode in MILO that enables a @@@ -402,7 -402,7 +402,7 @@@ do_entDbg(struct pt_regs *regs { die_if_kernel("Instruction fault", regs, 0, NULL);
- force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc, 0); + force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc); }
@@@ -730,7 -730,7 +730,7 @@@ do_entUnaUser(void __user * va, unsigne long error;
/* Check the UAC bits to decide what the user wants us to do - with the unaliged access. */ + with the unaligned access. */
if (!(current_thread_info()->status & TS_UAC_NOPRINT)) { if (__ratelimit(&ratelimit)) { @@@ -964,12 -964,12 +964,12 @@@ give_sigsegv si_code = SEGV_MAPERR; mmap_read_unlock(mm); } - send_sig_fault(SIGSEGV, si_code, va, 0, current); + send_sig_fault(SIGSEGV, si_code, va, current); return;
give_sigbus: regs->pc -= 4; - send_sig_fault(SIGBUS, BUS_ADRALN, va, 0, current); + send_sig_fault(SIGBUS, BUS_ADRALN, va, current); return; }
diff --combined arch/arm64/kernel/signal.c index 23036334f4dc,d3721e01441b..1a0e2b56378b --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@@ -29,7 -29,6 +29,7 @@@ #include <asm/unistd.h> #include <asm/fpsimd.h> #include <asm/ptrace.h> +#include <asm/syscall.h> #include <asm/signal32.h> #include <asm/traps.h> #include <asm/vdso.h> @@@ -891,7 -890,7 +891,7 @@@ static void do_signal(struct pt_regs *r retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS && !(ksig.ka.sa.sa_flags & SA_RESTART)))) { - regs->regs[0] = -EINTR; + syscall_set_return_value(current, regs, -EINTR, 0); regs->pc = continue_addr; }
@@@ -1000,3 -999,42 +1000,42 @@@ void __init minsigstksz_setup(void round_up(sizeof(struct frame_record), 16) + 16; /* max alignment padding */ } + + /* + * Compile-time assertions for siginfo_t offsets. Check NSIG* as well, as + * changes likely come with new fields that should be added below. + */ + static_assert(NSIGILL == 11); + static_assert(NSIGFPE == 15); + static_assert(NSIGSEGV == 9); + static_assert(NSIGBUS == 5); + static_assert(NSIGTRAP == 6); + static_assert(NSIGCHLD == 6); + static_assert(NSIGSYS == 2); + static_assert(sizeof(siginfo_t) == 128); + static_assert(__alignof__(siginfo_t) == 8); + static_assert(offsetof(siginfo_t, si_signo) == 0x00); + static_assert(offsetof(siginfo_t, si_errno) == 0x04); + static_assert(offsetof(siginfo_t, si_code) == 0x08); + static_assert(offsetof(siginfo_t, si_pid) == 0x10); + static_assert(offsetof(siginfo_t, si_uid) == 0x14); + static_assert(offsetof(siginfo_t, si_tid) == 0x10); + static_assert(offsetof(siginfo_t, si_overrun) == 0x14); + static_assert(offsetof(siginfo_t, si_status) == 0x18); + static_assert(offsetof(siginfo_t, si_utime) == 0x20); + static_assert(offsetof(siginfo_t, si_stime) == 0x28); + static_assert(offsetof(siginfo_t, si_value) == 0x18); + static_assert(offsetof(siginfo_t, si_int) == 0x18); + static_assert(offsetof(siginfo_t, si_ptr) == 0x18); + static_assert(offsetof(siginfo_t, si_addr) == 0x10); + static_assert(offsetof(siginfo_t, si_addr_lsb) == 0x18); + static_assert(offsetof(siginfo_t, si_lower) == 0x20); + static_assert(offsetof(siginfo_t, si_upper) == 0x28); + static_assert(offsetof(siginfo_t, si_pkey) == 0x20); + static_assert(offsetof(siginfo_t, si_perf_data) == 0x18); + static_assert(offsetof(siginfo_t, si_perf_type) == 0x20); + static_assert(offsetof(siginfo_t, si_band) == 0x10); + static_assert(offsetof(siginfo_t, si_fd) == 0x18); + static_assert(offsetof(siginfo_t, si_call_addr) == 0x10); + static_assert(offsetof(siginfo_t, si_syscall) == 0x18); + static_assert(offsetof(siginfo_t, si_arch) == 0x1c); diff --combined include/linux/sched/signal.h index 0310a5add9ab,928e0025d358..548986c7d233 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@@ -298,11 -298,6 +298,6 @@@ static inline void kernel_signal_stop(v
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 @@@ -310,14 -305,11 +305,11 @@@ #endif
int force_sig_fault_to_task(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_fault(int sig, int code, void __user *addr - ___ARCH_SI_TRAPNO(int trapno) ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)); 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);
@@@ -329,6 -321,9 +321,9 @@@ int force_sig_pkuerr(void __user *addr int force_sig_perf(void __user *addr, u32 type, u64 sig_data);
int force_sig_ptrace_errno_trap(int errno, void __user *addr); + int force_sig_fault_trapno(int sig, int code, void __user *addr, int trapno); + int send_sig_fault_trapno(int sig, int code, void __user *addr, int trapno, + struct task_struct *t);
extern int send_sig_info(int, struct kernel_siginfo *, struct task_struct *); extern void force_sigsegv(int sig); @@@ -714,12 -709,6 +709,12 @@@ static inline void unlock_task_sighand( spin_unlock_irqrestore(&task->sighand->siglock, *flags); }
+#ifdef CONFIG_LOCKDEP +extern void lockdep_assert_task_sighand_held(struct task_struct *task); +#else +static inline void lockdep_assert_task_sighand_held(struct task_struct *task) { } +#endif + static inline unsigned long task_rlimit(const struct task_struct *task, unsigned int limit) { diff --combined kernel/signal.c index 52b6abec0ff8,332b21f2fe72..65a54118ac9e --- a/kernel/signal.c +++ b/kernel/signal.c @@@ -1213,7 -1213,7 +1213,7 @@@ static inline bool has_si_pid_and_uid(s case SIL_FAULT_MCEERR: case SIL_FAULT_BNDERR: case SIL_FAULT_PKUERR: - case SIL_PERF_EVENT: + case SIL_FAULT_PERF_EVENT: case SIL_SYS: ret = false; break; @@@ -1413,21 -1413,6 +1413,21 @@@ struct sighand_struct *__lock_task_sigh return sighand; }
+#ifdef CONFIG_LOCKDEP +void lockdep_assert_task_sighand_held(struct task_struct *task) +{ + struct sighand_struct *sighand; + + rcu_read_lock(); + sighand = rcu_dereference(task->sighand); + if (sighand) + lockdep_assert_held(&sighand->siglock); + else + WARN_ON_ONCE(1); + rcu_read_unlock(); +} +#endif + /* * send signal info to all the members of a group */ @@@ -1681,7 -1666,6 +1681,6 @@@ void force_sigsegv(int sig }
int force_sig_fault_to_task(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) { @@@ -1692,9 -1676,6 +1691,6 @@@ 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; @@@ -1704,16 -1685,13 +1700,13 @@@ }
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)) { return force_sig_fault_to_task(sig, code, addr - ___ARCH_SI_TRAPNO(trapno) ___ARCH_SI_IA64(imm, flags, isr), current); }
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) { @@@ -1724,9 -1702,6 +1717,6 @@@ 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; @@@ -1823,6 -1798,39 +1813,39 @@@ int force_sig_ptrace_errno_trap(int err return force_sig_info(&info); }
+ /* For the rare architectures that include trap information using + * si_trapno. + */ + int force_sig_fault_trapno(int sig, int code, void __user *addr, int trapno) + { + struct kernel_siginfo info; + + clear_siginfo(&info); + info.si_signo = sig; + info.si_errno = 0; + info.si_code = code; + info.si_addr = addr; + info.si_trapno = trapno; + return force_sig_info(&info); + } + + /* For the rare architectures that include trap information using + * si_trapno. + */ + int send_sig_fault_trapno(int sig, int code, void __user *addr, int trapno, + struct task_struct *t) + { + struct kernel_siginfo info; + + clear_siginfo(&info); + info.si_signo = sig; + info.si_errno = 0; + info.si_code = code; + info.si_addr = addr; + info.si_trapno = trapno; + return send_sig_info(info.si_signo, &info, t); + } + int kill_pgrp(struct pid *pid, int sig, int priv) { int ret; @@@ -2572,7 -2580,7 +2595,7 @@@ static void hide_si_addr_tag_bits(struc case SIL_FAULT_MCEERR: case SIL_FAULT_BNDERR: case SIL_FAULT_PKUERR: - case SIL_PERF_EVENT: + case SIL_FAULT_PERF_EVENT: ksig->info.si_addr = arch_untagged_si_addr( ksig->info.si_addr, ksig->sig, ksig->info.si_code); break; @@@ -3257,11 -3265,14 +3280,14 @@@ enum siginfo_layout siginfo_layout(unsi layout = SIL_FAULT_PKUERR; #endif else if ((sig == SIGTRAP) && (si_code == TRAP_PERF)) - layout = SIL_PERF_EVENT; - #ifdef __ARCH_SI_TRAPNO - else if (layout == SIL_FAULT) + layout = SIL_FAULT_PERF_EVENT; + else if (IS_ENABLED(CONFIG_SPARC) && + (sig == SIGILL) && (si_code == ILL_ILLTRP)) + layout = SIL_FAULT_TRAPNO; + else if (IS_ENABLED(CONFIG_ALPHA) && + ((sig == SIGFPE) || + ((sig == SIGTRAP) && (si_code == TRAP_UNK)))) layout = SIL_FAULT_TRAPNO; - #endif } else if (si_code <= NSIGPOLL) layout = SIL_POLL; @@@ -3383,7 -3394,7 +3409,7 @@@ void copy_siginfo_to_external32(struct to->si_addr = ptr_to_compat(from->si_addr); to->si_pkey = from->si_pkey; break; - case SIL_PERF_EVENT: + case SIL_FAULT_PERF_EVENT: to->si_addr = ptr_to_compat(from->si_addr); to->si_perf_data = from->si_perf_data; to->si_perf_type = from->si_perf_type; @@@ -3460,7 -3471,7 +3486,7 @@@ static int post_copy_siginfo_from_user3 to->si_addr = compat_ptr(from->si_addr); to->si_pkey = from->si_pkey; break; - case SIL_PERF_EVENT: + case SIL_FAULT_PERF_EVENT: to->si_addr = compat_ptr(from->si_addr); to->si_perf_data = from->si_perf_data; to->si_perf_type = from->si_perf_type;
linux-merge@lists.open-mesh.org