summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2010-03-19 11:04:42 +0000
committerkib <kib@FreeBSD.org>2010-03-19 11:04:42 +0000
commitb27fa06f976447590802ac0521932dc2803b4854 (patch)
treec0f64553fae4afa41d4796848ab08f701505e447 /sys/kern
parent610214ed4c4cf8e4c9ec77a65d3b4fee64af5657 (diff)
downloadFreeBSD-src-b27fa06f976447590802ac0521932dc2803b4854.zip
FreeBSD-src-b27fa06f976447590802ac0521932dc2803b4854.tar.gz
Move SysV IPC freebsd32 compat shims from freebsd32_misc.c to corresponding
sysv_{msg,sem,shm}.c files. Mark SysV IPC freebsd32 syscalls as NOSTD and add required SYSCALL_INIT_HELPER/SYSCALL32_INIT_HELPERs to provide auto register/unregister on module load. This makes COMPAT_FREEBSD32 functional with SysV IPC compiled and loaded as modules. Reviewed by: jhb MFC after: 2 weeks
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/sysv_msg.c220
-rw-r--r--sys/kern/sysv_sem.c236
-rw-r--r--sys/kern/sysv_shm.c295
3 files changed, 712 insertions, 39 deletions
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index c7c67d4..01d7f79 100644
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -74,7 +74,7 @@ __FBSDID("$FreeBSD$");
static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues");
-static void msginit(void);
+static int msginit(void);
static int msgunload(void);
static int sysvmsg_modload(struct module *, int, void *);
@@ -152,10 +152,45 @@ static struct msg *msghdrs; /* MSGTQL msg headers */
static struct msqid_kernel *msqids; /* MSGMNI msqid_kernel struct's */
static struct mtx msq_mtx; /* global mutex for message queues. */
-static void
+static struct syscall_helper_data msg_syscalls[] = {
+ SYSCALL_INIT_HELPER(msgctl),
+ SYSCALL_INIT_HELPER(msgget),
+ SYSCALL_INIT_HELPER(msgsnd),
+ SYSCALL_INIT_HELPER(msgrcv),
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+ SYSCALL_INIT_HELPER(msgsys),
+ SYSCALL_INIT_HELPER(freebsd7_msgctl),
+#endif
+ SYSCALL_INIT_LAST
+};
+
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_ipc.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>
+
+static struct syscall_helper_data msg32_syscalls[] = {
+ SYSCALL32_INIT_HELPER(freebsd32_msgctl),
+ SYSCALL32_INIT_HELPER(freebsd32_msgsnd),
+ SYSCALL32_INIT_HELPER(freebsd32_msgrcv),
+ SYSCALL32_INIT_HELPER(msgget),
+ SYSCALL32_INIT_HELPER(freebsd32_msgsys),
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+ SYSCALL32_INIT_HELPER(freebsd7_freebsd32_msgctl),
+#endif
+ SYSCALL_INIT_LAST
+};
+#endif
+
+static int
msginit()
{
- register int i;
+ int i, error;
TUNABLE_INT_FETCH("kern.ipc.msgseg", &msginfo.msgseg);
TUNABLE_INT_FETCH("kern.ipc.msgssz", &msginfo.msgssz);
@@ -235,6 +270,16 @@ msginit()
#endif
}
mtx_init(&msq_mtx, "msq", NULL, MTX_DEF);
+
+ error = syscall_helper_register(msg_syscalls);
+ if (error != 0)
+ return (error);
+#ifdef COMPAT_FREEBSD32
+ error = syscall32_helper_register(msg32_syscalls);
+ if (error != 0)
+ return (error);
+#endif
+ return (0);
}
static int
@@ -246,6 +291,11 @@ msgunload()
int i;
#endif
+ syscall_helper_unregister(msg_syscalls);
+#ifdef COMPAT_FREEBSD32
+ syscall32_helper_unregister(msg32_syscalls);
+#endif
+
for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
/*
* Look for an unallocated and unlocked msqid_ds.
@@ -283,7 +333,9 @@ sysvmsg_modload(struct module *module, int cmd, void *arg)
switch (cmd) {
case MOD_LOAD:
- msginit();
+ error = msginit();
+ if (error != 0)
+ msgunload();
break;
case MOD_UNLOAD:
error = msgunload();
@@ -303,11 +355,6 @@ static moduledata_t sysvmsg_mod = {
NULL
};
-SYSCALL_MODULE_HELPER(msgctl);
-SYSCALL_MODULE_HELPER(msgget);
-SYSCALL_MODULE_HELPER(msgsnd);
-SYSCALL_MODULE_HELPER(msgrcv);
-
DECLARE_MODULE(sysvmsg, sysvmsg_mod, SI_SUB_SYSV_MSG, SI_ORDER_FIRST);
MODULE_VERSION(sysvmsg, 1);
@@ -1257,10 +1304,159 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, msgseg, CTLFLAG_RDTUN, &msginfo.msgseg, 0,
SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids, CTLFLAG_RD,
NULL, 0, sysctl_msqids, "", "Message queue IDs");
+#ifdef COMPAT_FREEBSD32
+int
+freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap)
+{
+
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+ switch (uap->which) {
+ case 0:
+ return (freebsd7_freebsd32_msgctl(td,
+ (struct freebsd7_freebsd32_msgctl_args *)&uap->a2));
+ case 2:
+ return (freebsd32_msgsnd(td,
+ (struct freebsd32_msgsnd_args *)&uap->a2));
+ case 3:
+ return (freebsd32_msgrcv(td,
+ (struct freebsd32_msgrcv_args *)&uap->a2));
+ default:
+ return (msgsys(td, (struct msgsys_args *)uap));
+ }
+#else
+ return (nosys(td, NULL));
+#endif
+}
+
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+int
+freebsd7_freebsd32_msgctl(struct thread *td,
+ struct freebsd7_freebsd32_msgctl_args *uap)
+{
+ struct msqid_ds msqbuf;
+ struct msqid_ds32_old msqbuf32;
+ int error;
+
+ if (uap->cmd == IPC_SET) {
+ error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
+ if (error)
+ return (error);
+ freebsd32_ipcperm_old_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
+ PTRIN_CP(msqbuf32, msqbuf, msg_first);
+ PTRIN_CP(msqbuf32, msqbuf, msg_last);
+ CP(msqbuf32, msqbuf, msg_cbytes);
+ CP(msqbuf32, msqbuf, msg_qnum);
+ CP(msqbuf32, msqbuf, msg_qbytes);
+ CP(msqbuf32, msqbuf, msg_lspid);
+ CP(msqbuf32, msqbuf, msg_lrpid);
+ CP(msqbuf32, msqbuf, msg_stime);
+ CP(msqbuf32, msqbuf, msg_rtime);
+ CP(msqbuf32, msqbuf, msg_ctime);
+ }
+ error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
+ if (error)
+ return (error);
+ if (uap->cmd == IPC_STAT) {
+ bzero(&msqbuf32, sizeof(msqbuf32));
+ freebsd32_ipcperm_old_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
+ PTROUT_CP(msqbuf, msqbuf32, msg_first);
+ PTROUT_CP(msqbuf, msqbuf32, msg_last);
+ CP(msqbuf, msqbuf32, msg_cbytes);
+ CP(msqbuf, msqbuf32, msg_qnum);
+ CP(msqbuf, msqbuf32, msg_qbytes);
+ CP(msqbuf, msqbuf32, msg_lspid);
+ CP(msqbuf, msqbuf32, msg_lrpid);
+ CP(msqbuf, msqbuf32, msg_stime);
+ CP(msqbuf, msqbuf32, msg_rtime);
+ CP(msqbuf, msqbuf32, msg_ctime);
+ error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
+ }
+ return (error);
+}
+#endif
+
+int
+freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap)
+{
+ struct msqid_ds msqbuf;
+ struct msqid_ds32 msqbuf32;
+ int error;
+
+ if (uap->cmd == IPC_SET) {
+ error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32));
+ if (error)
+ return (error);
+ freebsd32_ipcperm_in(&msqbuf32.msg_perm, &msqbuf.msg_perm);
+ PTRIN_CP(msqbuf32, msqbuf, msg_first);
+ PTRIN_CP(msqbuf32, msqbuf, msg_last);
+ CP(msqbuf32, msqbuf, msg_cbytes);
+ CP(msqbuf32, msqbuf, msg_qnum);
+ CP(msqbuf32, msqbuf, msg_qbytes);
+ CP(msqbuf32, msqbuf, msg_lspid);
+ CP(msqbuf32, msqbuf, msg_lrpid);
+ CP(msqbuf32, msqbuf, msg_stime);
+ CP(msqbuf32, msqbuf, msg_rtime);
+ CP(msqbuf32, msqbuf, msg_ctime);
+ }
+ error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf);
+ if (error)
+ return (error);
+ if (uap->cmd == IPC_STAT) {
+ freebsd32_ipcperm_out(&msqbuf.msg_perm, &msqbuf32.msg_perm);
+ PTROUT_CP(msqbuf, msqbuf32, msg_first);
+ PTROUT_CP(msqbuf, msqbuf32, msg_last);
+ CP(msqbuf, msqbuf32, msg_cbytes);
+ CP(msqbuf, msqbuf32, msg_qnum);
+ CP(msqbuf, msqbuf32, msg_qbytes);
+ CP(msqbuf, msqbuf32, msg_lspid);
+ CP(msqbuf, msqbuf32, msg_lrpid);
+ CP(msqbuf, msqbuf32, msg_stime);
+ CP(msqbuf, msqbuf32, msg_rtime);
+ CP(msqbuf, msqbuf32, msg_ctime);
+ error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32));
+ }
+ return (error);
+}
+
+int
+freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap)
+{
+ const void *msgp;
+ long mtype;
+ int32_t mtype32;
+ int error;
+
+ msgp = PTRIN(uap->msgp);
+ if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0)
+ return (error);
+ mtype = mtype32;
+ return (kern_msgsnd(td, uap->msqid,
+ (const char *)msgp + sizeof(mtype32),
+ uap->msgsz, uap->msgflg, mtype));
+}
+
+int
+freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap)
+{
+ void *msgp;
+ long mtype;
+ int32_t mtype32;
+ int error;
+
+ msgp = PTRIN(uap->msgp);
+ if ((error = kern_msgrcv(td, uap->msqid,
+ (char *)msgp + sizeof(mtype32), uap->msgsz,
+ uap->msgtyp, uap->msgflg, &mtype)) != 0)
+ return (error);
+ mtype32 = (int32_t)mtype;
+ return (copyout(&mtype32, msgp, sizeof(mtype32)));
+}
+#endif
+
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
-SYSCALL_MODULE_HELPER(msgsys);
-SYSCALL_MODULE_HELPER(freebsd7_msgctl);
/* XXX casting to (sy_call_t *) is bogus, as usual. */
static sy_call_t *msgcalls[] = {
@@ -1295,7 +1491,9 @@ msgsys(td, uap)
return (error);
}
+#ifndef CP
#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0)
+#endif
#ifndef _SYS_SYSPROTO_H_
struct freebsd7_msgctl_args {
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index 2f2b528..f6d781c7 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -70,7 +70,7 @@ static MALLOC_DEFINE(M_SEM, "sem", "SVID compatible semaphores");
#define DPRINTF(a)
#endif
-static void seminit(void);
+static int seminit(void);
static int sysvsem_modload(struct module *, int, void *);
static int semunload(void);
static void semexit_myhook(void *arg, struct proc *p);
@@ -214,10 +214,43 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, semaem, CTLFLAG_RW, &seminfo.semaem, 0,
SYSCTL_PROC(_kern_ipc, OID_AUTO, sema, CTLFLAG_RD,
NULL, 0, sysctl_sema, "", "");
-static void
+static struct syscall_helper_data sem_syscalls[] = {
+ SYSCALL_INIT_HELPER(__semctl),
+ SYSCALL_INIT_HELPER(semget),
+ SYSCALL_INIT_HELPER(semop),
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+ SYSCALL_INIT_HELPER(semsys),
+ SYSCALL_INIT_HELPER(freebsd7___semctl),
+#endif
+ SYSCALL_INIT_LAST
+};
+
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_ipc.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>
+
+static struct syscall_helper_data sem32_syscalls[] = {
+ SYSCALL32_INIT_HELPER(freebsd32_semctl),
+ SYSCALL32_INIT_HELPER(semget),
+ SYSCALL32_INIT_HELPER(semop),
+ SYSCALL32_INIT_HELPER(freebsd32_semsys),
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+ SYSCALL32_INIT_HELPER(freebsd7_freebsd32_semctl),
+#endif
+ SYSCALL_INIT_LAST
+};
+#endif
+
+static int
seminit(void)
{
- int i;
+ int i, error;
TUNABLE_INT_FETCH("kern.ipc.semmap", &seminfo.semmap);
TUNABLE_INT_FETCH("kern.ipc.semmni", &seminfo.semmni);
@@ -258,6 +291,16 @@ seminit(void)
mtx_init(&sem_undo_mtx, "semu", NULL, MTX_DEF);
semexit_tag = EVENTHANDLER_REGISTER(process_exit, semexit_myhook, NULL,
EVENTHANDLER_PRI_ANY);
+
+ error = syscall_helper_register(sem_syscalls);
+ if (error != 0)
+ return (error);
+#ifdef COMPAT_FREEBSD32
+ error = syscall32_helper_register(sem32_syscalls);
+ if (error != 0)
+ return (error);
+#endif
+ return (0);
}
static int
@@ -269,6 +312,10 @@ semunload(void)
if (semtot != 0)
return (EBUSY);
+#ifdef COMPAT_FREEBSD32
+ syscall32_helper_unregister(sem32_syscalls);
+#endif
+ syscall_helper_unregister(sem_syscalls);
EVENTHANDLER_DEREGISTER(process_exit, semexit_tag);
#ifdef MAC
for (i = 0; i < seminfo.semmni; i++)
@@ -292,7 +339,9 @@ sysvsem_modload(struct module *module, int cmd, void *arg)
switch (cmd) {
case MOD_LOAD:
- seminit();
+ error = seminit();
+ if (error != 0)
+ semunload();
break;
case MOD_UNLOAD:
error = semunload();
@@ -312,10 +361,6 @@ static moduledata_t sysvsem_mod = {
NULL
};
-SYSCALL_MODULE_HELPER(__semctl);
-SYSCALL_MODULE_HELPER(semget);
-SYSCALL_MODULE_HELPER(semop);
-
DECLARE_MODULE(sysvsem, sysvsem_mod, SI_SUB_SYSV_SEM, SI_ORDER_FIRST);
MODULE_VERSION(sysvsem, 1);
@@ -1316,8 +1361,6 @@ sysctl_sema(SYSCTL_HANDLER_ARGS)
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
-SYSCALL_MODULE_HELPER(semsys);
-SYSCALL_MODULE_HELPER(freebsd7___semctl);
/* XXX casting to (sy_call_t *) is bogus, as usual. */
static sy_call_t *semcalls[] = {
@@ -1351,7 +1394,9 @@ semsys(td, uap)
return (error);
}
+#ifndef CP
#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0)
+#endif
#ifndef _SYS_SYSPROTO_H_
struct freebsd7___semctl_args {
@@ -1432,7 +1477,172 @@ freebsd7___semctl(struct thread *td, struct freebsd7___semctl_args *uap)
return (error);
}
-#undef CP
+#endif /* COMPAT_FREEBSD{4,5,6,7} */
+
+#ifdef COMPAT_FREEBSD32
+
+int
+freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap)
+{
+
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+ switch (uap->which) {
+ case 0:
+ return (freebsd7_freebsd32_semctl(td,
+ (struct freebsd7_freebsd32_semctl_args *)&uap->a2));
+ default:
+ return (semsys(td, (struct semsys_args *)uap));
+ }
+#else
+ return (nosys(td, NULL));
+#endif
+}
+
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+int
+freebsd7_freebsd32_semctl(struct thread *td,
+ struct freebsd7_freebsd32_semctl_args *uap)
+{
+ struct semid_ds32_old dsbuf32;
+ struct semid_ds dsbuf;
+ union semun semun;
+ union semun32 arg;
+ register_t rval;
+ int error;
+
+ switch (uap->cmd) {
+ case SEM_STAT:
+ case IPC_SET:
+ case IPC_STAT:
+ case GETALL:
+ case SETVAL:
+ case SETALL:
+ error = copyin(uap->arg, &arg, sizeof(arg));
+ if (error)
+ return (error);
+ break;
+ }
+
+ switch (uap->cmd) {
+ case SEM_STAT:
+ case IPC_STAT:
+ semun.buf = &dsbuf;
+ break;
+ case IPC_SET:
+ error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
+ if (error)
+ return (error);
+ freebsd32_ipcperm_old_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
+ PTRIN_CP(dsbuf32, dsbuf, sem_base);
+ CP(dsbuf32, dsbuf, sem_nsems);
+ CP(dsbuf32, dsbuf, sem_otime);
+ CP(dsbuf32, dsbuf, sem_ctime);
+ semun.buf = &dsbuf;
+ break;
+ case GETALL:
+ case SETALL:
+ semun.array = PTRIN(arg.array);
+ break;
+ case SETVAL:
+ semun.val = arg.val;
+ break;
+ }
+
+ error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
+ &rval);
+ if (error)
+ return (error);
+
+ switch (uap->cmd) {
+ case SEM_STAT:
+ case IPC_STAT:
+ bzero(&dsbuf32, sizeof(dsbuf32));
+ freebsd32_ipcperm_old_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
+ PTROUT_CP(dsbuf, dsbuf32, sem_base);
+ CP(dsbuf, dsbuf32, sem_nsems);
+ CP(dsbuf, dsbuf32, sem_otime);
+ CP(dsbuf, dsbuf32, sem_ctime);
+ error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
+ break;
+ }
+
+ if (error == 0)
+ td->td_retval[0] = rval;
+ return (error);
+}
+#endif
+
+int
+freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap)
+{
+ struct semid_ds32 dsbuf32;
+ struct semid_ds dsbuf;
+ union semun semun;
+ union semun32 arg;
+ register_t rval;
+ int error;
+
+ switch (uap->cmd) {
+ case SEM_STAT:
+ case IPC_SET:
+ case IPC_STAT:
+ case GETALL:
+ case SETVAL:
+ case SETALL:
+ error = copyin(uap->arg, &arg, sizeof(arg));
+ if (error)
+ return (error);
+ break;
+ }
+
+ switch (uap->cmd) {
+ case SEM_STAT:
+ case IPC_STAT:
+ semun.buf = &dsbuf;
+ break;
+ case IPC_SET:
+ error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32));
+ if (error)
+ return (error);
+ freebsd32_ipcperm_in(&dsbuf32.sem_perm, &dsbuf.sem_perm);
+ PTRIN_CP(dsbuf32, dsbuf, sem_base);
+ CP(dsbuf32, dsbuf, sem_nsems);
+ CP(dsbuf32, dsbuf, sem_otime);
+ CP(dsbuf32, dsbuf, sem_ctime);
+ semun.buf = &dsbuf;
+ break;
+ case GETALL:
+ case SETALL:
+ semun.array = PTRIN(arg.array);
+ break;
+ case SETVAL:
+ semun.val = arg.val;
+ break;
+ }
+
+ error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun,
+ &rval);
+ if (error)
+ return (error);
+
+ switch (uap->cmd) {
+ case SEM_STAT:
+ case IPC_STAT:
+ bzero(&dsbuf32, sizeof(dsbuf32));
+ freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm);
+ PTROUT_CP(dsbuf, dsbuf32, sem_base);
+ CP(dsbuf, dsbuf32, sem_nsems);
+ CP(dsbuf, dsbuf32, sem_otime);
+ CP(dsbuf, dsbuf32, sem_ctime);
+ error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32));
+ break;
+ }
+
+ if (error == 0)
+ td->td_retval[0] = rval;
+ return (error);
+}
-#endif /* COMPAT_FREEBSD4 || COMPAT_FREEBSD5 || COMPAT_FREEBSD6 ||
- COMPAT_FREEBSD7 */
+#endif /* COMPAT_FREEBSD32 */
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index a16c8af..ddf4ce1 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -122,7 +122,7 @@ static struct shmid_kernel *shm_find_segment_by_shmid(int);
static struct shmid_kernel *shm_find_segment_by_shmidx(int);
static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *);
static void shmrealloc(void);
-static void shminit(void);
+static int shminit(void);
static int sysvshm_modload(struct module *, int, void *);
static int shmunload(void);
static void shmexit_myhook(struct vmspace *vm);
@@ -816,10 +816,47 @@ shmrealloc(void)
shmalloced = shminfo.shmmni;
}
-static void
+static struct syscall_helper_data shm_syscalls[] = {
+ SYSCALL_INIT_HELPER(shmat),
+ SYSCALL_INIT_HELPER(shmctl),
+ SYSCALL_INIT_HELPER(shmdt),
+ SYSCALL_INIT_HELPER(shmget),
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+ SYSCALL_INIT_HELPER(freebsd7_shmctl),
+#endif
+#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43))
+ SYSCALL_INIT_HELPER(shmsys),
+#endif
+ SYSCALL_INIT_LAST
+};
+
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_ipc.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>
+
+static struct syscall_helper_data shm32_syscalls[] = {
+ SYSCALL32_INIT_HELPER(shmat),
+ SYSCALL32_INIT_HELPER(shmdt),
+ SYSCALL32_INIT_HELPER(shmget),
+ SYSCALL32_INIT_HELPER(freebsd32_shmsys),
+ SYSCALL32_INIT_HELPER(freebsd32_shmctl),
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+ SYSCALL32_INIT_HELPER(freebsd7_freebsd32_shmctl),
+#endif
+ SYSCALL_INIT_LAST
+};
+#endif
+
+static int
shminit()
{
- int i;
+ int i, error;
#ifndef BURN_BRIDGES
if (TUNABLE_ULONG_FETCH("kern.ipc.shmmaxpgs", &shminfo.shmall) != 0)
@@ -855,6 +892,16 @@ shminit()
shm_committed = 0;
shmexit_hook = &shmexit_myhook;
shmfork_hook = &shmfork_myhook;
+
+ error = syscall_helper_register(shm_syscalls);
+ if (error != 0)
+ return (error);
+#ifdef COMPAT_FREEBSD32
+ error = syscall32_helper_register(shm32_syscalls);
+ if (error != 0)
+ return (error);
+#endif
+ return (0);
}
static int
@@ -867,6 +914,11 @@ shmunload()
if (shm_nused > 0)
return (EBUSY);
+#ifdef COMPAT_FREEBSD32
+ syscall32_helper_unregister(shm32_syscalls);
+#endif
+ syscall_helper_unregister(shm_syscalls);
+
#ifdef MAC
for (i = 0; i < shmalloced; i++)
mac_sysvshm_destroy(&shmsegs[i]);
@@ -985,14 +1037,234 @@ shmsys(td, uap)
return (error);
}
-SYSCALL_MODULE_HELPER(shmsys);
#endif /* i386 && (COMPAT_FREEBSD4 || COMPAT_43) */
+#ifdef COMPAT_FREEBSD32
+
+int
+freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap)
+{
+
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+ switch (uap->which) {
+ case 0: { /* shmat */
+ struct shmat_args ap;
+
+ ap.shmid = uap->a2;
+ ap.shmaddr = PTRIN(uap->a3);
+ ap.shmflg = uap->a4;
+ return (sysent[SYS_shmat].sy_call(td, &ap));
+ }
+ case 2: { /* shmdt */
+ struct shmdt_args ap;
-#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0)
+ ap.shmaddr = PTRIN(uap->a2);
+ return (sysent[SYS_shmdt].sy_call(td, &ap));
+ }
+ case 3: { /* shmget */
+ struct shmget_args ap;
+ ap.key = uap->a2;
+ ap.size = uap->a3;
+ ap.shmflg = uap->a4;
+ return (sysent[SYS_shmget].sy_call(td, &ap));
+ }
+ case 4: { /* shmctl */
+ struct freebsd7_freebsd32_shmctl_args ap;
+
+ ap.shmid = uap->a2;
+ ap.cmd = uap->a3;
+ ap.buf = PTRIN(uap->a4);
+ return (freebsd7_freebsd32_shmctl(td, &ap));
+ }
+ case 1: /* oshmctl */
+ default:
+ return (EINVAL);
+ }
+#else
+ return (nosys(td, NULL));
+#endif
+}
+
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+int
+freebsd7_freebsd32_shmctl(struct thread *td,
+ struct freebsd7_freebsd32_shmctl_args *uap)
+{
+ int error = 0;
+ union {
+ struct shmid_ds shmid_ds;
+ struct shm_info shm_info;
+ struct shminfo shminfo;
+ } u;
+ union {
+ struct shmid_ds32_old shmid_ds32;
+ struct shm_info32 shm_info32;
+ struct shminfo32 shminfo32;
+ } u32;
+ size_t sz;
+
+ if (uap->cmd == IPC_SET) {
+ if ((error = copyin(uap->buf, &u32.shmid_ds32,
+ sizeof(u32.shmid_ds32))))
+ goto done;
+ freebsd32_ipcperm_old_in(&u32.shmid_ds32.shm_perm,
+ &u.shmid_ds.shm_perm);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
+ }
+
+ error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
+ if (error)
+ goto done;
+
+ /* Cases in which we need to copyout */
+ switch (uap->cmd) {
+ case IPC_INFO:
+ CP(u.shminfo, u32.shminfo32, shmmax);
+ CP(u.shminfo, u32.shminfo32, shmmin);
+ CP(u.shminfo, u32.shminfo32, shmmni);
+ CP(u.shminfo, u32.shminfo32, shmseg);
+ CP(u.shminfo, u32.shminfo32, shmall);
+ error = copyout(&u32.shminfo32, uap->buf,
+ sizeof(u32.shminfo32));
+ break;
+ case SHM_INFO:
+ CP(u.shm_info, u32.shm_info32, used_ids);
+ CP(u.shm_info, u32.shm_info32, shm_rss);
+ CP(u.shm_info, u32.shm_info32, shm_tot);
+ CP(u.shm_info, u32.shm_info32, shm_swp);
+ CP(u.shm_info, u32.shm_info32, swap_attempts);
+ CP(u.shm_info, u32.shm_info32, swap_successes);
+ error = copyout(&u32.shm_info32, uap->buf,
+ sizeof(u32.shm_info32));
+ break;
+ case SHM_STAT:
+ case IPC_STAT:
+ freebsd32_ipcperm_old_out(&u.shmid_ds.shm_perm,
+ &u32.shmid_ds32.shm_perm);
+ if (u.shmid_ds.shm_segsz > INT32_MAX)
+ u32.shmid_ds32.shm_segsz = INT32_MAX;
+ else
+ CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
+ u32.shmid_ds32.shm_internal = 0;
+ error = copyout(&u32.shmid_ds32, uap->buf,
+ sizeof(u32.shmid_ds32));
+ break;
+ }
+
+done:
+ if (error) {
+ /* Invalidate the return value */
+ td->td_retval[0] = -1;
+ }
+ return (error);
+}
+#endif
+
+int
+freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap)
+{
+ int error = 0;
+ union {
+ struct shmid_ds shmid_ds;
+ struct shm_info shm_info;
+ struct shminfo shminfo;
+ } u;
+ union {
+ struct shmid_ds32 shmid_ds32;
+ struct shm_info32 shm_info32;
+ struct shminfo32 shminfo32;
+ } u32;
+ size_t sz;
+
+ if (uap->cmd == IPC_SET) {
+ if ((error = copyin(uap->buf, &u32.shmid_ds32,
+ sizeof(u32.shmid_ds32))))
+ goto done;
+ freebsd32_ipcperm_in(&u32.shmid_ds32.shm_perm,
+ &u.shmid_ds.shm_perm);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_segsz);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_lpid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_cpid);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_nattch);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_atime);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_dtime);
+ CP(u32.shmid_ds32, u.shmid_ds, shm_ctime);
+ }
+
+ error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz);
+ if (error)
+ goto done;
+
+ /* Cases in which we need to copyout */
+ switch (uap->cmd) {
+ case IPC_INFO:
+ CP(u.shminfo, u32.shminfo32, shmmax);
+ CP(u.shminfo, u32.shminfo32, shmmin);
+ CP(u.shminfo, u32.shminfo32, shmmni);
+ CP(u.shminfo, u32.shminfo32, shmseg);
+ CP(u.shminfo, u32.shminfo32, shmall);
+ error = copyout(&u32.shminfo32, uap->buf,
+ sizeof(u32.shminfo32));
+ break;
+ case SHM_INFO:
+ CP(u.shm_info, u32.shm_info32, used_ids);
+ CP(u.shm_info, u32.shm_info32, shm_rss);
+ CP(u.shm_info, u32.shm_info32, shm_tot);
+ CP(u.shm_info, u32.shm_info32, shm_swp);
+ CP(u.shm_info, u32.shm_info32, swap_attempts);
+ CP(u.shm_info, u32.shm_info32, swap_successes);
+ error = copyout(&u32.shm_info32, uap->buf,
+ sizeof(u32.shm_info32));
+ break;
+ case SHM_STAT:
+ case IPC_STAT:
+ freebsd32_ipcperm_out(&u.shmid_ds.shm_perm,
+ &u32.shmid_ds32.shm_perm);
+ if (u.shmid_ds.shm_segsz > INT32_MAX)
+ u32.shmid_ds32.shm_segsz = INT32_MAX;
+ else
+ CP(u.shmid_ds, u32.shmid_ds32, shm_segsz);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_lpid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_cpid);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_nattch);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_atime);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_dtime);
+ CP(u.shmid_ds, u32.shmid_ds32, shm_ctime);
+ error = copyout(&u32.shmid_ds32, uap->buf,
+ sizeof(u32.shmid_ds32));
+ break;
+ }
+
+done:
+ if (error) {
+ /* Invalidate the return value */
+ td->td_retval[0] = -1;
+ }
+ return (error);
+}
+#endif
+
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
+
+#ifndef CP
+#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0)
+#endif
#ifndef _SYS_SYSPROTO_H_
struct freebsd7_shmctl_args {
@@ -1068,10 +1340,6 @@ done:
return (error);
}
-SYSCALL_MODULE_HELPER(freebsd7_shmctl);
-
-#undef CP
-
#endif /* COMPAT_FREEBSD4 || COMPAT_FREEBSD5 || COMPAT_FREEBSD6 ||
COMPAT_FREEBSD7 */
@@ -1082,7 +1350,9 @@ sysvshm_modload(struct module *module, int cmd, void *arg)
switch (cmd) {
case MOD_LOAD:
- shminit();
+ error = shminit();
+ if (error != 0)
+ shmunload();
break;
case MOD_UNLOAD:
error = shmunload();
@@ -1102,10 +1372,5 @@ static moduledata_t sysvshm_mod = {
NULL
};
-SYSCALL_MODULE_HELPER(shmat);
-SYSCALL_MODULE_HELPER(shmctl);
-SYSCALL_MODULE_HELPER(shmdt);
-SYSCALL_MODULE_HELPER(shmget);
-
DECLARE_MODULE(sysvshm, sysvshm_mod, SI_SUB_SYSV_SHM, SI_ORDER_FIRST);
MODULE_VERSION(sysvshm, 1);
OpenPOWER on IntegriCloud