[PATCH v17 3/3] arm64: expose FAR_EL1 tag bits in siginfo
Eric W. Biederman
ebiederm at xmission.com
Tue Nov 17 08:39:40 EST 2020
Peter Collingbourne <pcc at google.com> writes:
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 8f34819e80de..16be62e6d341 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1650,6 +1650,15 @@ void force_sigsegv(int sig)
> force_sig(SIGSEGV);
> }
>
> +static void __user *get_si_addr(void __user *addr, unsigned long sig,
> + unsigned long si_code)
> +{
> + if (current->sighand->action[sig - 1].sa.sa_flags & SA_EXPOSE_TAGBITS)
> + return addr;
Apologies for not seeing this before but this part of the patch is
buggy.
It is using current->sighand->action when the destination task may not
be current. send_sig_fault and send_sig_mcerr may somewhat legitimately
be used to send faults to other processes.
Now that I think about it there are interactions with
PTRACE_GETSIGINFO/PTRACE_SETSIGINFO.
Can we move the masking into get_signal after the ptrace handling?
That way everything in the core of the kernel deals with unmasked
si_addr values and we only mask the address just before sending it to
userspace?
Eric
> + return arch_untagged_si_addr(addr, sig, si_code);
> +}
> +
> 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)
> @@ -1661,7 +1670,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> info.si_signo = sig;
> info.si_errno = 0;
> info.si_code = code;
> - info.si_addr = addr;
> + info.si_addr = get_si_addr(addr, sig, code);
> #ifdef __ARCH_SI_TRAPNO
> info.si_trapno = trapno;
> #endif
> @@ -1693,7 +1702,7 @@ int send_sig_fault(int sig, int code, void __user *addr
> info.si_signo = sig;
> info.si_errno = 0;
> info.si_code = code;
> - info.si_addr = addr;
> + info.si_addr = get_si_addr(addr, sig, code);
> #ifdef __ARCH_SI_TRAPNO
> info.si_trapno = trapno;
> #endif
> @@ -1714,7 +1723,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> info.si_signo = SIGBUS;
> info.si_errno = 0;
> info.si_code = code;
> - info.si_addr = addr;
> + info.si_addr = get_si_addr(addr, SIGBUS, code);
> info.si_addr_lsb = lsb;
> return force_sig_info(&info);
> }
> @@ -1728,7 +1737,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
> info.si_signo = SIGBUS;
> info.si_errno = 0;
> info.si_code = code;
> - info.si_addr = addr;
> + info.si_addr = get_si_addr(addr, SIGBUS, code);
> info.si_addr_lsb = lsb;
> return send_sig_info(info.si_signo, &info, t);
> }
> @@ -1742,7 +1751,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
> info.si_signo = SIGSEGV;
> info.si_errno = 0;
> info.si_code = SEGV_BNDERR;
> - info.si_addr = addr;
> + info.si_addr = get_si_addr(addr, SIGSEGV, SEGV_BNDERR);
> info.si_lower = lower;
> info.si_upper = upper;
> return force_sig_info(&info);
> @@ -1757,7 +1766,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
> info.si_signo = SIGSEGV;
> info.si_errno = 0;
> info.si_code = SEGV_PKUERR;
> - info.si_addr = addr;
> + info.si_addr = get_si_addr(addr, SIGSEGV, SEGV_PKUERR);
> info.si_pkey = pkey;
> return force_sig_info(&info);
> }
> @@ -1774,7 +1783,7 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
> info.si_signo = SIGTRAP;
> info.si_errno = errno;
> info.si_code = TRAP_HWBKPT;
> - info.si_addr = addr;
> + info.si_addr = get_si_addr(addr, SIGTRAP, TRAP_HWBKPT);
> return force_sig_info(&info);
> }
More information about the linux-arm-kernel
mailing list