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
This commit is contained in:
parent
7748ab43a3
commit
f19351aad8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=317845
@ -27,7 +27,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd March 10, 2012
|
.Dd May 5, 2017
|
||||||
.Dt SIGQUEUE 2
|
.Dt SIGQUEUE 2
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -129,7 +129,6 @@ does not exist.
|
|||||||
.Xr kill 2 ,
|
.Xr kill 2 ,
|
||||||
.Xr sigaction 2 ,
|
.Xr sigaction 2 ,
|
||||||
.Xr sigpending 2 ,
|
.Xr sigpending 2 ,
|
||||||
.Xr sigqueue 2 ,
|
|
||||||
.Xr sigsuspend 2 ,
|
.Xr sigsuspend 2 ,
|
||||||
.Xr sigtimedwait 2 ,
|
.Xr sigtimedwait 2 ,
|
||||||
.Xr sigwait 2 ,
|
.Xr sigwait 2 ,
|
||||||
@ -147,3 +146,18 @@ Support for
|
|||||||
.Tn POSIX
|
.Tn POSIX
|
||||||
realtime signal queue first appeared in
|
realtime signal queue first appeared in
|
||||||
.Fx 7.0 .
|
.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.
|
||||||
|
@ -2477,6 +2477,32 @@ siginfo_to_siginfo32(const siginfo_t *src, struct siginfo32 *dst)
|
|||||||
dst->si_overrun = src->si_overrun;
|
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
|
int
|
||||||
freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
|
freebsd32_sigtimedwait(struct thread *td, struct freebsd32_sigtimedwait_args *uap)
|
||||||
{
|
{
|
||||||
|
@ -819,8 +819,8 @@
|
|||||||
455 AUE_THR_NEW STD { int freebsd32_thr_new( \
|
455 AUE_THR_NEW STD { int freebsd32_thr_new( \
|
||||||
struct thr_param32 *param, \
|
struct thr_param32 *param, \
|
||||||
int param_size); }
|
int param_size); }
|
||||||
456 AUE_NULL NOPROTO { int sigqueue(pid_t pid, int signum, \
|
456 AUE_NULL STD { int freebsd32_sigqueue(pid_t pid, \
|
||||||
void *value); }
|
int signum, int value); }
|
||||||
457 AUE_MQ_OPEN NOSTD { int freebsd32_kmq_open( \
|
457 AUE_MQ_OPEN NOSTD { int freebsd32_kmq_open( \
|
||||||
const char *path, int flags, mode_t mode, \
|
const char *path, int flags, mode_t mode, \
|
||||||
const struct mq_attr32 *attr); }
|
const struct mq_attr32 *attr); }
|
||||||
|
@ -1843,34 +1843,44 @@ struct sigqueue_args {
|
|||||||
#endif
|
#endif
|
||||||
int
|
int
|
||||||
sys_sigqueue(struct thread *td, struct sigqueue_args *uap)
|
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;
|
ksiginfo_t ksi;
|
||||||
struct proc *p;
|
struct proc *p;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if ((u_int)uap->signum > _SIG_MAXSIG)
|
if ((u_int)signum > _SIG_MAXSIG)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Specification says sigqueue can only send signal to
|
* Specification says sigqueue can only send signal to
|
||||||
* single process.
|
* single process.
|
||||||
*/
|
*/
|
||||||
if (uap->pid <= 0)
|
if (pid <= 0)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
if ((p = pfind(uap->pid)) == NULL) {
|
if ((p = pfind(pid)) == NULL) {
|
||||||
if ((p = zpfind(uap->pid)) == NULL)
|
if ((p = zpfind(pid)) == NULL)
|
||||||
return (ESRCH);
|
return (ESRCH);
|
||||||
}
|
}
|
||||||
error = p_cansignal(td, p, uap->signum);
|
error = p_cansignal(td, p, signum);
|
||||||
if (error == 0 && uap->signum != 0) {
|
if (error == 0 && signum != 0) {
|
||||||
ksiginfo_init(&ksi);
|
ksiginfo_init(&ksi);
|
||||||
ksi.ksi_flags = KSI_SIGQ;
|
ksi.ksi_flags = KSI_SIGQ;
|
||||||
ksi.ksi_signo = uap->signum;
|
ksi.ksi_signo = signum;
|
||||||
ksi.ksi_code = SI_QUEUE;
|
ksi.ksi_code = SI_QUEUE;
|
||||||
ksi.ksi_pid = td->td_proc->p_pid;
|
ksi.ksi_pid = td->td_proc->p_pid;
|
||||||
ksi.ksi_uid = td->td_ucred->cr_ruid;
|
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);
|
error = pksignal(p, ksi.ksi_signo, &ksi);
|
||||||
}
|
}
|
||||||
PROC_UNLOCK(p);
|
PROC_UNLOCK(p);
|
||||||
|
@ -249,6 +249,8 @@ int kern_sigprocmask(struct thread *td, int how,
|
|||||||
int kern_sigsuspend(struct thread *td, sigset_t mask);
|
int kern_sigsuspend(struct thread *td, sigset_t mask);
|
||||||
int kern_sigtimedwait(struct thread *td, sigset_t waitset,
|
int kern_sigtimedwait(struct thread *td, sigset_t waitset,
|
||||||
struct ksiginfo *ksi, struct timespec *timeout);
|
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_socket(struct thread *td, int domain, int type, int protocol);
|
||||||
int kern_statat(struct thread *td, int flag, int fd, char *path,
|
int kern_statat(struct thread *td, int flag, int fd, char *path,
|
||||||
enum uio_seg pathseg, struct stat *sbp,
|
enum uio_seg pathseg, struct stat *sbp,
|
||||||
|
Loading…
Reference in New Issue
Block a user