Wrap kmq_notify(2) for compat32 to properly consume struct sigevent32

argument.

Reviewed and tested by:	Petr Salinger <Petr.Salinger@seznam.cz>
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2013-07-21 19:40:30 +00:00
parent ab751a525b
commit 058262c69a
2 changed files with 61 additions and 26 deletions

View File

@ -825,8 +825,8 @@
const char *msg_ptr, size_t msg_len,\
unsigned msg_prio, \
const struct timespec32 *abs_timeout);}
461 AUE_NULL NOPROTO|NOSTD { int kmq_notify(int mqd, \
const struct sigevent *sigev); }
461 AUE_NULL NOSTD { int freebsd32_kmq_notify(int mqd, \
const struct sigevent32 *sigev); }
462 AUE_NULL NOPROTO|NOSTD { int kmq_unlink(const char *path); }
463 AUE_NULL NOPROTO { int abort2(const char *why, int nargs, void **args); }
464 AUE_NULL NOPROTO { int thr_set_name(long id, const char *name); }

View File

@ -2235,10 +2235,9 @@ sys_kmq_timedsend(struct thread *td, struct kmq_timedsend_args *uap)
return (error);
}
int
sys_kmq_notify(struct thread *td, struct kmq_notify_args *uap)
static int
kern_kmq_notify(struct thread *td, int mqd, struct sigevent *sigev)
{
struct sigevent ev;
struct filedesc *fdp;
struct proc *p;
struct mqueue *mq;
@ -2246,34 +2245,31 @@ sys_kmq_notify(struct thread *td, struct kmq_notify_args *uap)
struct mqueue_notifier *nt, *newnt = NULL;
int error;
p = td->td_proc;
fdp = td->td_proc->p_fd;
if (uap->sigev) {
error = copyin(uap->sigev, &ev, sizeof(ev));
if (error)
return (error);
if (ev.sigev_notify != SIGEV_SIGNAL &&
ev.sigev_notify != SIGEV_THREAD_ID &&
ev.sigev_notify != SIGEV_NONE)
if (sigev != NULL) {
if (sigev->sigev_notify != SIGEV_SIGNAL &&
sigev->sigev_notify != SIGEV_THREAD_ID &&
sigev->sigev_notify != SIGEV_NONE)
return (EINVAL);
if ((ev.sigev_notify == SIGEV_SIGNAL ||
ev.sigev_notify == SIGEV_THREAD_ID) &&
!_SIG_VALID(ev.sigev_signo))
if ((sigev->sigev_notify == SIGEV_SIGNAL ||
sigev->sigev_notify == SIGEV_THREAD_ID) &&
!_SIG_VALID(sigev->sigev_signo))
return (EINVAL);
}
error = getmq(td, uap->mqd, &fp, NULL, &mq);
p = td->td_proc;
fdp = td->td_proc->p_fd;
error = getmq(td, mqd, &fp, NULL, &mq);
if (error)
return (error);
again:
FILEDESC_SLOCK(fdp);
fp2 = fget_locked(fdp, uap->mqd);
fp2 = fget_locked(fdp, mqd);
if (fp2 == NULL) {
FILEDESC_SUNLOCK(fdp);
error = EBADF;
goto out;
}
#ifdef CAPABILITIES
error = cap_check(cap_rights(fdp, uap->mqd), CAP_POLL_EVENT);
error = cap_check(cap_rights(fdp, mqd), CAP_POLL_EVENT);
if (error) {
FILEDESC_SUNLOCK(fdp);
goto out;
@ -2286,12 +2282,12 @@ sys_kmq_notify(struct thread *td, struct kmq_notify_args *uap)
}
mtx_lock(&mq->mq_mutex);
FILEDESC_SUNLOCK(fdp);
if (uap->sigev != NULL) {
if (sigev != NULL) {
if (mq->mq_notifier != NULL) {
error = EBUSY;
} else {
PROC_LOCK(p);
nt = notifier_search(p, uap->mqd);
nt = notifier_search(p, mqd);
if (nt == NULL) {
if (newnt == NULL) {
PROC_UNLOCK(p);
@ -2314,10 +2310,10 @@ sys_kmq_notify(struct thread *td, struct kmq_notify_args *uap)
nt->nt_ksi.ksi_flags |= KSI_INS | KSI_EXT;
nt->nt_ksi.ksi_code = SI_MESGQ;
nt->nt_proc = p;
nt->nt_ksi.ksi_mqd = uap->mqd;
nt->nt_ksi.ksi_mqd = mqd;
notifier_insert(p, nt);
}
nt->nt_sigev = ev;
nt->nt_sigev = *sigev;
mq->mq_notifier = nt;
PROC_UNLOCK(p);
/*
@ -2330,7 +2326,7 @@ sys_kmq_notify(struct thread *td, struct kmq_notify_args *uap)
mqueue_send_notification(mq);
}
} else {
notifier_remove(p, mq, uap->mqd);
notifier_remove(p, mq, mqd);
}
mtx_unlock(&mq->mq_mutex);
@ -2341,6 +2337,23 @@ sys_kmq_notify(struct thread *td, struct kmq_notify_args *uap)
return (error);
}
int
sys_kmq_notify(struct thread *td, struct kmq_notify_args *uap)
{
struct sigevent ev, *evp;
int error;
if (uap->sigev == NULL) {
evp = NULL;
} else {
error = copyin(uap->sigev, &ev, sizeof(ev));
if (error != 0)
return (error);
evp = &ev;
}
return (kern_kmq_notify(td, uap->mqd, evp));
}
static void
mqueue_fdclose(struct thread *td, int fd, struct file *fp)
{
@ -2637,6 +2650,7 @@ static struct syscall_helper_data mq_syscalls[] = {
#ifdef COMPAT_FREEBSD32
#include <compat/freebsd32/freebsd32.h>
#include <compat/freebsd32/freebsd32_proto.h>
#include <compat/freebsd32/freebsd32_signal.h>
#include <compat/freebsd32/freebsd32_syscall.h>
#include <compat/freebsd32/freebsd32_util.h>
@ -2763,12 +2777,33 @@ freebsd32_kmq_timedreceive(struct thread *td,
return (error);
}
int
freebsd32_kmq_notify(struct thread *td, struct freebsd32_kmq_notify_args *uap)
{
struct sigevent ev, *evp;
struct sigevent32 ev32;
int error;
if (uap->sigev == NULL) {
evp = NULL;
} else {
error = copyin(uap->sigev, &ev32, sizeof(ev32));
if (error != 0)
return (error);
error = convert_sigevent32(&ev32, &ev);
if (error != 0)
return (error);
evp = &ev;
}
return (kern_kmq_notify(td, uap->mqd, evp));
}
static struct syscall_helper_data mq32_syscalls[] = {
SYSCALL32_INIT_HELPER(freebsd32_kmq_open),
SYSCALL32_INIT_HELPER(freebsd32_kmq_setattr),
SYSCALL32_INIT_HELPER(freebsd32_kmq_timedsend),
SYSCALL32_INIT_HELPER(freebsd32_kmq_timedreceive),
SYSCALL32_INIT_HELPER_COMPAT(kmq_notify),
SYSCALL32_INIT_HELPER(freebsd32_kmq_notify),
SYSCALL32_INIT_HELPER_COMPAT(kmq_unlink),
SYSCALL_INIT_LAST
};