Thread (2 messages) 2 messages, 2 authors, 2020-11-17

Re: [PATCH v17 3/3] arm64: expose FAR_EL1 tag bits in siginfo

flat view

From: Eric W. Biederman <hidden>
Date: 2020-11-17 13:40:45
Also in: linux-arm-kernel

Peter Collingbourne [off-list ref] writes:
quoted hunk
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
quoted hunk
+	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);
 }
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help