summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-07-21 19:40:30 +0000
committerkib <kib@FreeBSD.org>2013-07-21 19:40:30 +0000
commite9d8b81db78ac44bc32831cd4227161dafd886bd (patch)
treeae074afa3525eade06df30b42bc1ee81439856fd
parent5dee91b64aae9fff70d72aa914ef0f8dd482c8cd (diff)
downloadFreeBSD-src-e9d8b81db78ac44bc32831cd4227161dafd886bd.zip
FreeBSD-src-e9d8b81db78ac44bc32831cd4227161dafd886bd.tar.gz
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
-rw-r--r--sys/compat/freebsd32/syscalls.master4
-rw-r--r--sys/kern/uipc_mqueue.c83
2 files changed, 61 insertions, 26 deletions
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index d9a73d9..e058f6a 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -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); }
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index 73579d3..11acedb 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -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 @@ again:
}
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 @@ again:
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 @@ again:
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 @@ out:
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
};
OpenPOWER on IntegriCloud