Author: brooks
Date: Mon May 15 22:50:54 2017
New Revision: 318323
URL: https://svnweb.freebsd.org/changeset/base/318323

Log:
  MFC r317845-r317846
  
  r317845:
  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
  Sponsored by: DARPA, AFRL
  Differential Revision:        https://reviews.freebsd.org/D10605
  
  r317846:
  Regen post r317845.
  
  MFC with:     r317845
  Sponsored by: DARPA, AFRL

Modified:
  stable/10/lib/libc/sys/sigqueue.2
  stable/10/sys/compat/freebsd32/freebsd32_misc.c
  stable/10/sys/compat/freebsd32/freebsd32_proto.h
  stable/10/sys/compat/freebsd32/freebsd32_syscall.h
  stable/10/sys/compat/freebsd32/freebsd32_syscalls.c
  stable/10/sys/compat/freebsd32/freebsd32_sysent.c
  stable/10/sys/compat/freebsd32/freebsd32_systrace_args.c
  stable/10/sys/compat/freebsd32/syscalls.master
  stable/10/sys/kern/kern_sig.c
  stable/10/sys/sys/syscallsubr.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/sys/sigqueue.2
==============================================================================
--- stable/10/lib/libc/sys/sigqueue.2   Mon May 15 22:41:01 2017        
(r318322)
+++ stable/10/lib/libc/sys/sigqueue.2   Mon May 15 22:50:54 2017        
(r318323)
@@ -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: stable/10/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- stable/10/sys/compat/freebsd32/freebsd32_misc.c     Mon May 15 22:41:01 
2017        (r318322)
+++ stable/10/sys/compat/freebsd32/freebsd32_misc.c     Mon May 15 22:50:54 
2017        (r318323)
@@ -2581,6 +2581,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: stable/10/sys/compat/freebsd32/freebsd32_proto.h
==============================================================================
--- stable/10/sys/compat/freebsd32/freebsd32_proto.h    Mon May 15 22:41:01 
2017        (r318322)
+++ stable/10/sys/compat/freebsd32/freebsd32_proto.h    Mon May 15 22:50:54 
2017        (r318323)
@@ -395,6 +395,11 @@ struct freebsd32_thr_new_args {
        char param_l_[PADL_(struct thr_param32 *)]; struct thr_param32 * param; 
char param_r_[PADR_(struct thr_param32 *)];
        char param_size_l_[PADL_(int)]; int param_size; char 
param_size_r_[PADR_(int)];
 };
+struct freebsd32_sigqueue_args {
+       char pid_l_[PADL_(pid_t)]; pid_t pid; char pid_r_[PADR_(pid_t)];
+       char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)];
+       char value_l_[PADL_(int)]; int value; char value_r_[PADR_(int)];
+};
 struct freebsd32_kmq_open_args {
        char path_l_[PADL_(const char *)]; const char * path; char 
path_r_[PADR_(const char *)];
        char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
@@ -785,6 +790,7 @@ int freebsd32_ksem_timedwait(struct thre
 int    freebsd32_thr_suspend(struct thread *, struct 
freebsd32_thr_suspend_args *);
 int    freebsd32_umtx_op(struct thread *, struct freebsd32_umtx_op_args *);
 int    freebsd32_thr_new(struct thread *, struct freebsd32_thr_new_args *);
+int    freebsd32_sigqueue(struct thread *, struct freebsd32_sigqueue_args *);
 int    freebsd32_kmq_open(struct thread *, struct freebsd32_kmq_open_args *);
 int    freebsd32_kmq_setattr(struct thread *, struct 
freebsd32_kmq_setattr_args *);
 int    freebsd32_kmq_timedreceive(struct thread *, struct 
freebsd32_kmq_timedreceive_args *);
@@ -1216,6 +1222,7 @@ int       freebsd7_freebsd32_shmctl(struct thr
 #define        FREEBSD32_SYS_AUE_freebsd32_thr_suspend AUE_NULL
 #define        FREEBSD32_SYS_AUE_freebsd32_umtx_op     AUE_NULL
 #define        FREEBSD32_SYS_AUE_freebsd32_thr_new     AUE_NULL
+#define        FREEBSD32_SYS_AUE_freebsd32_sigqueue    AUE_NULL
 #define        FREEBSD32_SYS_AUE_freebsd32_kmq_open    AUE_NULL
 #define        FREEBSD32_SYS_AUE_freebsd32_kmq_setattr AUE_NULL
 #define        FREEBSD32_SYS_AUE_freebsd32_kmq_timedreceive    AUE_NULL

Modified: stable/10/sys/compat/freebsd32/freebsd32_syscall.h
==============================================================================
--- stable/10/sys/compat/freebsd32/freebsd32_syscall.h  Mon May 15 22:41:01 
2017        (r318322)
+++ stable/10/sys/compat/freebsd32/freebsd32_syscall.h  Mon May 15 22:50:54 
2017        (r318323)
@@ -359,7 +359,7 @@
 #define        FREEBSD32_SYS_auditctl  453
 #define        FREEBSD32_SYS_freebsd32_umtx_op 454
 #define        FREEBSD32_SYS_freebsd32_thr_new 455
-#define        FREEBSD32_SYS_sigqueue  456
+#define        FREEBSD32_SYS_freebsd32_sigqueue        456
 #define        FREEBSD32_SYS_freebsd32_kmq_open        457
 #define        FREEBSD32_SYS_freebsd32_kmq_setattr     458
 #define        FREEBSD32_SYS_freebsd32_kmq_timedreceive        459

Modified: stable/10/sys/compat/freebsd32/freebsd32_syscalls.c
==============================================================================
--- stable/10/sys/compat/freebsd32/freebsd32_syscalls.c Mon May 15 22:41:01 
2017        (r318322)
+++ stable/10/sys/compat/freebsd32/freebsd32_syscalls.c Mon May 15 22:50:54 
2017        (r318323)
@@ -465,7 +465,7 @@ const char *freebsd32_syscallnames[] = {
        "auditctl",                     /* 453 = auditctl */
        "freebsd32_umtx_op",                    /* 454 = freebsd32_umtx_op */
        "freebsd32_thr_new",                    /* 455 = freebsd32_thr_new */
-       "sigqueue",                     /* 456 = sigqueue */
+       "freebsd32_sigqueue",                   /* 456 = freebsd32_sigqueue */
        "freebsd32_kmq_open",                   /* 457 = freebsd32_kmq_open */
        "freebsd32_kmq_setattr",                        /* 458 = 
freebsd32_kmq_setattr */
        "freebsd32_kmq_timedreceive",                   /* 459 = 
freebsd32_kmq_timedreceive */

Modified: stable/10/sys/compat/freebsd32/freebsd32_sysent.c
==============================================================================
--- stable/10/sys/compat/freebsd32/freebsd32_sysent.c   Mon May 15 22:41:01 
2017        (r318322)
+++ stable/10/sys/compat/freebsd32/freebsd32_sysent.c   Mon May 15 22:50:54 
2017        (r318323)
@@ -502,7 +502,7 @@ struct sysent freebsd32_sysent[] = {
        { AS(auditctl_args), (sy_call_t *)sys_auditctl, AUE_AUDITCTL, NULL, 0, 
0, 0, SY_THR_STATIC },   /* 453 = auditctl */
        { AS(freebsd32_umtx_op_args), (sy_call_t *)freebsd32_umtx_op, AUE_NULL, 
NULL, 0, 0, 0, SY_THR_STATIC }, /* 454 = freebsd32_umtx_op */
        { AS(freebsd32_thr_new_args), (sy_call_t *)freebsd32_thr_new, AUE_NULL, 
NULL, 0, 0, 0, SY_THR_STATIC }, /* 455 = freebsd32_thr_new */
-       { AS(sigqueue_args), (sy_call_t *)sys_sigqueue, AUE_NULL, NULL, 0, 0, 
0, SY_THR_STATIC },       /* 456 = sigqueue */
+       { AS(freebsd32_sigqueue_args), (sy_call_t *)freebsd32_sigqueue, 
AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },       /* 456 = freebsd32_sigqueue */
        { AS(freebsd32_kmq_open_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 
0, 0, 0, SY_THR_ABSENT },        /* 457 = freebsd32_kmq_open */
        { AS(freebsd32_kmq_setattr_args), (sy_call_t *)lkmressys, AUE_NULL, 
NULL, 0, 0, 0, SY_THR_ABSENT },     /* 458 = freebsd32_kmq_setattr */
        { AS(freebsd32_kmq_timedreceive_args), (sy_call_t *)lkmressys, 
AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },        /* 459 = 
freebsd32_kmq_timedreceive */

Modified: stable/10/sys/compat/freebsd32/freebsd32_systrace_args.c
==============================================================================
--- stable/10/sys/compat/freebsd32/freebsd32_systrace_args.c    Mon May 15 
22:41:01 2017        (r318322)
+++ stable/10/sys/compat/freebsd32/freebsd32_systrace_args.c    Mon May 15 
22:50:54 2017        (r318323)
@@ -2397,12 +2397,12 @@ systrace_args(int sysnum, void *params, 
                *n_args = 2;
                break;
        }
-       /* sigqueue */
+       /* freebsd32_sigqueue */
        case 456: {
-               struct sigqueue_args *p = params;
+               struct freebsd32_sigqueue_args *p = params;
                iarg[0] = p->pid; /* pid_t */
                iarg[1] = p->signum; /* int */
-               uarg[2] = (intptr_t) p->value; /* void * */
+               iarg[2] = p->value; /* int */
                *n_args = 3;
                break;
        }
@@ -7206,7 +7206,7 @@ systrace_entry_setargdesc(int sysnum, in
                        break;
                };
                break;
-       /* sigqueue */
+       /* freebsd32_sigqueue */
        case 456:
                switch(ndx) {
                case 0:
@@ -7216,7 +7216,7 @@ systrace_entry_setargdesc(int sysnum, in
                        p = "int";
                        break;
                case 2:
-                       p = "void *";
+                       p = "int";
                        break;
                default:
                        break;
@@ -10366,7 +10366,7 @@ systrace_return_setargdesc(int sysnum, i
                if (ndx == 0 || ndx == 1)
                        p = "int";
                break;
-       /* sigqueue */
+       /* freebsd32_sigqueue */
        case 456:
                if (ndx == 0 || ndx == 1)
                        p = "int";

Modified: stable/10/sys/compat/freebsd32/syscalls.master
==============================================================================
--- stable/10/sys/compat/freebsd32/syscalls.master      Mon May 15 22:41:01 
2017        (r318322)
+++ stable/10/sys/compat/freebsd32/syscalls.master      Mon May 15 22:50:54 
2017        (r318323)
@@ -816,8 +816,8 @@
 455    AUE_NULL        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_NULL        NOSTD   { int freebsd32_kmq_open( \
                                    const char *path, int flags, mode_t mode, \
                                    const struct mq_attr32 *attr); }

Modified: stable/10/sys/kern/kern_sig.c
==============================================================================
--- stable/10/sys/kern/kern_sig.c       Mon May 15 22:41:01 2017        
(r318322)
+++ stable/10/sys/kern/kern_sig.c       Mon May 15 22:50:54 2017        
(r318323)
@@ -1846,33 +1846,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: stable/10/sys/sys/syscallsubr.h
==============================================================================
--- stable/10/sys/sys/syscallsubr.h     Mon May 15 22:41:01 2017        
(r318322)
+++ stable/10/sys/sys/syscallsubr.h     Mon May 15 22:50:54 2017        
(r318323)
@@ -242,6 +242,8 @@ int kern_sigtimedwait(struct thread *td,
            struct ksiginfo *ksi, struct timespec *timeout);
 int    kern_stat(struct thread *td, char *path, enum uio_seg pathseg,
            struct stat *sbp);
+int    kern_sigqueue(struct thread *td, pid_t pid, int signum,
+           union sigval *value);
 int    kern_statat(struct thread *td, int flag, int fd, char *path,
            enum uio_seg pathseg, struct stat *sbp);
 int    kern_statat_vnhook(struct thread *td, int flag, int fd, char *path,
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to