Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 5 May 2017 18:49:39 +0000 (UTC)
From:      Brooks Davis <brooks@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r317845 - in head: lib/libc/sys sys/compat/freebsd32 sys/kern sys/sys
Message-ID:  <201705051849.v45IndZM002719@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: brooks
Date: Fri May  5 18:49:39 2017
New Revision: 317845
URL: https://svnweb.freebsd.org/changeset/base/317845

Log:
  Provide a freebsd32 implementation of sigqueue()
  
  The previous misuse of sys_sigqueue() was sending random register or
  stack garbage to 64-bit targets.  The freebsd32 implementation preserves
  the sival_int member of value when signaling a 64-bit process.
  
  Document the mixed ABI implementation of union sigval and the
  incompability of sival_ptr with pointer integrity schemes.
  
  Reviewed by:	kib, wblock
  MFC after:	1 week
  Sponsored by:	DARPA, AFRL
  Differential Revision:	https://reviews.freebsd.org/D10605

Modified:
  head/lib/libc/sys/sigqueue.2
  head/sys/compat/freebsd32/freebsd32_misc.c
  head/sys/compat/freebsd32/syscalls.master
  head/sys/kern/kern_sig.c
  head/sys/sys/syscallsubr.h

Modified: head/lib/libc/sys/sigqueue.2
==============================================================================
--- head/lib/libc/sys/sigqueue.2	Fri May  5 18:36:41 2017	(r317844)
+++ head/lib/libc/sys/sigqueue.2	Fri May  5 18:49:39 2017	(r317845)
@@ -27,7 +27,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 10, 2012
+.Dd May 5, 2017
 .Dt SIGQUEUE 2
 .Os
 .Sh NAME
@@ -129,7 +129,6 @@ does not exist.
 .Xr kill 2 ,
 .Xr sigaction 2 ,
 .Xr sigpending 2 ,
-.Xr sigqueue 2 ,
 .Xr sigsuspend 2 ,
 .Xr sigtimedwait 2 ,
 .Xr sigwait 2 ,
@@ -147,3 +146,18 @@ Support for
 .Tn POSIX
 realtime signal queue first appeared in
 .Fx 7.0 .
+.Sh CAVEATS
+When using
+.Nm
+to send signals to a process which might have a different ABI
+(for instance, one is 32-bit and the other 64-bit),
+the
+.Va sival_int
+member of
+.Fa value
+can be delivered reliably, but the
+.Va sival_ptr
+may be truncated in endian dependent ways and must not be relied on.
+Further, many pointer integrity schemes disallow sending pointers to other
+processes, and this technique should not be used in programs intended to
+be portable.

Modified: head/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_misc.c	Fri May  5 18:36:41 2017	(r317844)
+++ head/sys/compat/freebsd32/freebsd32_misc.c	Fri May  5 18:49:39 2017	(r317845)
@@ -2477,6 +2477,32 @@ siginfo_to_siginfo32(const siginfo_t *sr
 	dst->si_overrun = src->si_overrun;
 }
 
+#ifndef _FREEBSD32_SYSPROTO_H_
+struct freebsd32_sigqueue_args {
+        pid_t pid;
+        int signum;
+        /* union sigval32 */ int value;
+};
+#endif
+int
+freebsd32_sigqueue(struct thread *td, struct freebsd32_sigqueue_args *uap)
+{
+	union sigval sv;
+
+	/*
+	 * On 32-bit ABIs, sival_int and sival_ptr are the same.
+	 * On 64-bit little-endian ABIs, the low bits are the same.
+	 * In 64-bit big-endian ABIs, sival_int overlaps with
+	 * sival_ptr's HIGH bits.  We choose to support sival_int
+	 * rather than sival_ptr in this case as it seems to be
+	 * more common.
+	 */
+	bzero(&sv, sizeof(sv));
+	sv.sival_int = uap->value;
+
+	return (kern_sigqueue(td, uap->pid, uap->signum, &sv));
+}
+
 int
 freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
 {

Modified: head/sys/compat/freebsd32/syscalls.master
==============================================================================
--- head/sys/compat/freebsd32/syscalls.master	Fri May  5 18:36:41 2017	(r317844)
+++ head/sys/compat/freebsd32/syscalls.master	Fri May  5 18:49:39 2017	(r317845)
@@ -819,8 +819,8 @@
 455	AUE_THR_NEW	STD	{ int freebsd32_thr_new(	\
 				    struct thr_param32 *param,	\
 				    int param_size); }
-456	AUE_NULL	NOPROTO	{ int sigqueue(pid_t pid, int signum, \
-				    void *value); }
+456	AUE_NULL	STD	{ int freebsd32_sigqueue(pid_t pid, \
+				    int signum, int value); }
 457	AUE_MQ_OPEN	NOSTD	{ int freebsd32_kmq_open( \
 				    const char *path, int flags, mode_t mode, \
 				    const struct mq_attr32 *attr); }

Modified: head/sys/kern/kern_sig.c
==============================================================================
--- head/sys/kern/kern_sig.c	Fri May  5 18:36:41 2017	(r317844)
+++ head/sys/kern/kern_sig.c	Fri May  5 18:49:39 2017	(r317845)
@@ -1844,33 +1844,43 @@ struct sigqueue_args {
 int
 sys_sigqueue(struct thread *td, struct sigqueue_args *uap)
 {
+	union sigval sv;
+
+	sv.sival_ptr = uap->value;
+
+	return (kern_sigqueue(td, uap->pid, uap->signum, &sv));
+}
+
+int
+kern_sigqueue(struct thread *td, pid_t pid, int signum, union sigval *value)
+{
 	ksiginfo_t ksi;
 	struct proc *p;
 	int error;
 
-	if ((u_int)uap->signum > _SIG_MAXSIG)
+	if ((u_int)signum > _SIG_MAXSIG)
 		return (EINVAL);
 
 	/*
 	 * Specification says sigqueue can only send signal to
 	 * single process.
 	 */
-	if (uap->pid <= 0)
+	if (pid <= 0)
 		return (EINVAL);
 
-	if ((p = pfind(uap->pid)) == NULL) {
-		if ((p = zpfind(uap->pid)) == NULL)
+	if ((p = pfind(pid)) == NULL) {
+		if ((p = zpfind(pid)) == NULL)
 			return (ESRCH);
 	}
-	error = p_cansignal(td, p, uap->signum);
-	if (error == 0 && uap->signum != 0) {
+	error = p_cansignal(td, p, signum);
+	if (error == 0 && signum != 0) {
 		ksiginfo_init(&ksi);
 		ksi.ksi_flags = KSI_SIGQ;
-		ksi.ksi_signo = uap->signum;
+		ksi.ksi_signo = signum;
 		ksi.ksi_code = SI_QUEUE;
 		ksi.ksi_pid = td->td_proc->p_pid;
 		ksi.ksi_uid = td->td_ucred->cr_ruid;
-		ksi.ksi_value.sival_ptr = uap->value;
+		ksi.ksi_value = *value;
 		error = pksignal(p, ksi.ksi_signo, &ksi);
 	}
 	PROC_UNLOCK(p);

Modified: head/sys/sys/syscallsubr.h
==============================================================================
--- head/sys/sys/syscallsubr.h	Fri May  5 18:36:41 2017	(r317844)
+++ head/sys/sys/syscallsubr.h	Fri May  5 18:49:39 2017	(r317845)
@@ -249,6 +249,8 @@ int	kern_sigprocmask(struct thread *td, 
 int	kern_sigsuspend(struct thread *td, sigset_t mask);
 int	kern_sigtimedwait(struct thread *td, sigset_t waitset,
 	    struct ksiginfo *ksi, struct timespec *timeout);
+int	kern_sigqueue(struct thread *td, pid_t pid, int signum,
+	    union sigval *value);
 int	kern_socket(struct thread *td, int domain, int type, int protocol);
 int	kern_statat(struct thread *td, int flag, int fd, char *path,
 	    enum uio_seg pathseg, struct stat *sbp,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705051849.v45IndZM002719>