summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-07-15 11:26:00 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-07-15 11:26:00 +0000
commit9ce377ad798b682ae19e2403ea0bd861b305a164 (patch)
tree4c44a6a80614b2d920c400665ab864a71d258124
parent9a6c53fa6b87af6cc1a546e2a2a956056f711a78 (diff)
Complete rewrite derived from kern_ipc_35.c
-rw-r--r--sys/compat/common/kern_ipc_23.c543
1 files changed, 155 insertions, 388 deletions
diff --git a/sys/compat/common/kern_ipc_23.c b/sys/compat/common/kern_ipc_23.c
index 5b77436bf6b..490362363e0 100644
--- a/sys/compat/common/kern_ipc_23.c
+++ b/sys/compat/common/kern_ipc_23.c
@@ -1,443 +1,210 @@
-/* $OpenBSD: kern_ipc_23.c,v 1.4 2004/06/21 23:50:35 tholo Exp $ */
+/* $OpenBSD: kern_ipc_23.c,v 1.5 2004/07/15 11:25:59 millert Exp $ */
/*
- * Implementation of SVID semaphores
+ * Copyright (c) 2004 Todd C. Miller <Todd.Miller@courtesan.com>
*
- * Author: Daniel Boulet
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * This software is provided ``AS IS'' without any warranties of any kind.
- */
-/*
- * Implementation of SVID messages
- *
- * Author: Daniel Boulet
- *
- * Copyright 1993 Daniel Boulet and RTMX Inc.
- *
- * This system call was implemented by Daniel Boulet under contract from RTMX.
- *
- * Redistribution and use in source forms, with and without modification,
- * are permitted provided that this entire comment appears intact.
- *
- * Redistribution in binary form may occur without any restrictions.
- * Obviously, it would be nice if you gave credit where credit is due
- * but requiring it would be too onerous.
- *
- * This software is provided ``AS IS'' without any warranties of any kind.
- */
-/*
- * Copyright (c) 1994 Adam Glass and Charles M. Hannum. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Adam Glass and Charles M.
- * Hannum.
- * 4. The names of the authors may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
-#include <sys/stat.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
-#include <sys/malloc.h>
-#include <sys/pool.h>
#include <sys/mount.h>
#include <sys/syscallargs.h>
+/*
+ * Convert between new and old struct {msq,sem,shm}id_ds (both ways)
+ */
+#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
+#define cvt_ds(to, from, type, base) do { \
+ (to)->type##_perm.cuid = (from)->type##_perm.cuid; \
+ (to)->type##_perm.cgid = (from)->type##_perm.cgid; \
+ (to)->type##_perm.uid = (from)->type##_perm.uid; \
+ (to)->type##_perm.gid = (from)->type##_perm.gid; \
+ (to)->type##_perm.mode = (from)->type##_perm.mode & 0xffffU; \
+ (to)->type##_perm.seq = (from)->type##_perm.seq; \
+ (to)->type##_perm.key = (from)->type##_perm.key; \
+ bcopy((caddr_t)&(from)->base, (caddr_t)&(to)->base, \
+ sizeof(*(to)) - ((caddr_t)&(to)->base - (caddr_t)to)); \
+} while (0)
+#endif /* SYSVMSG || SYSVSEM || SYSVSHM */
+
#ifdef SYSVMSG
+/*
+ * Copy a struct msqid_ds23 from userland and convert to struct msqid_ds
+ */
+static int
+msqid_copyin(const void *uaddr, void *kaddr, size_t len)
+{
+ struct msqid_ds *msqbuf = kaddr;
+ struct msqid_ds23 omsqbuf;
+ int error;
+
+ if (len != sizeof(struct msqid_ds))
+ return (EFAULT);
+ if ((error = copyin(uaddr, &omsqbuf, sizeof(omsqbuf))) == 0)
+ cvt_ds(msqbuf, &omsqbuf, msg, msg_first);
+ return (error);
+}
+
+/*
+ * Convert a struct msqid_ds to struct msqid_ds23 and copy to userland
+ */
+static int
+msqid_copyout(const void *kaddr, void *uaddr, size_t len)
+{
+ const struct msqid_ds *msqbuf = kaddr;
+ struct msqid_ds23 omsqbuf;
-void msg_freehdr(struct msg *);
+ if (len != sizeof(struct msqid_ds))
+ return (EFAULT);
+ cvt_ds(&omsqbuf, msqbuf, msg, msg_first);
+ return (copyout(&omsqbuf, uaddr, sizeof(omsqbuf)));
+}
+/*
+ * OpenBSD 2.3 msgctl(2) with 16bit values in struct ipcperm.
+ */
int
-compat_23_sys_msgctl(p, v, retval)
- struct proc *p;
- void *v;
- register_t *retval;
+compat_23_sys_msgctl(struct proc *p, void *v, register_t *retval)
{
- register struct compat_23_sys_msgctl_args /* {
+ struct compat_23_sys_msgctl_args /* {
syscallarg(int) msqid;
syscallarg(int) cmd;
- syscallarg(struct msqid_ds *) buf;
+ syscallarg(struct msqid_ds23 *) buf;
} */ *uap = v;
- int msqid = SCARG(uap, msqid);
- int cmd = SCARG(uap, cmd);
- struct omsqid_ds *user_msqptr = SCARG(uap, buf);
- struct ucred *cred = p->p_ucred;
- int rval, error;
- struct omsqid_ds omsqbuf;
- register struct msqid_ds *msqptr;
-
-#ifdef MSG_DEBUG_OK
- printf("call to msgctl(%d, %d, %p)\n", msqid, cmd, user_msqptr);
-#endif
-
- msqid = IPCID_TO_IX(msqid);
-
- if (msqid < 0 || msqid >= msginfo.msgmni) {
-#ifdef MSG_DEBUG_OK
- printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid,
- msginfo.msgmni);
-#endif
- return(EINVAL);
- }
-
- msqptr = &msqids[msqid];
- if (msqptr->msg_qbytes == 0) {
-#ifdef MSG_DEBUG_OK
- printf("no such msqid\n");
-#endif
- return(EINVAL);
- }
- if (msqptr->msg_perm.seq != IPCID_TO_SEQ(SCARG(uap, msqid))) {
-#ifdef MSG_DEBUG_OK
- printf("wrong sequence number\n");
-#endif
- return(EINVAL);
- }
-
- error = rval = 0;
-
- switch (cmd) {
-
- case IPC_RMID:
- {
- struct msg *msghdr;
- if ((error = ipcperm(cred, &msqptr->msg_perm, IPC_M)) != 0)
- return(error);
- /* Free the message headers */
- msghdr = msqptr->msg_first;
- while (msghdr != NULL) {
- struct msg *msghdr_tmp;
-
- /* Free the segments of each message */
- msqptr->msg_cbytes -= msghdr->msg_ts;
- msqptr->msg_qnum--;
- msghdr_tmp = msghdr;
- msghdr = msghdr->msg_next;
- msg_freehdr(msghdr_tmp);
- }
-
-#ifdef DIAGNOSTIC
- if (msqptr->msg_cbytes != 0)
- panic("sys_omsgctl: msg_cbytes is screwed up");
- if (msqptr->msg_qnum != 0)
- panic("sys_omsgctl: msg_qnum is screwed up");
-#endif
-
- msqptr->msg_qbytes = 0; /* Mark it as free */
-
- wakeup((caddr_t)msqptr);
- }
-
- break;
-
- case IPC_SET:
- if ((error = ipcperm(cred, &msqptr->msg_perm, IPC_M)))
- return(error);
- if ((error = copyin(user_msqptr, &omsqbuf, sizeof(omsqbuf))) != 0)
- return(error);
- if (omsqbuf.msg_qbytes > msqptr->msg_qbytes && cred->cr_uid != 0)
- return(EPERM);
- if (omsqbuf.msg_qbytes > msginfo.msgmnb) {
-#ifdef MSG_DEBUG_OK
- printf("can't increase msg_qbytes beyond %d (truncating)\n",
- msginfo.msgmnb);
-#endif
- omsqbuf.msg_qbytes = msginfo.msgmnb; /* silently restrict qbytes to system limit */
- }
- if (omsqbuf.msg_qbytes == 0) {
-#ifdef MSG_DEBUG_OK
- printf("can't reduce msg_qbytes to 0\n");
-#endif
- return(EINVAL); /* non-standard errno! */
- }
- msqptr->msg_perm.uid = omsqbuf.msg_perm.uid; /* change the owner */
- msqptr->msg_perm.gid = omsqbuf.msg_perm.gid; /* change the owner */
- msqptr->msg_perm.mode = (msqptr->msg_perm.mode & ~0777) |
- (omsqbuf.msg_perm.mode & 0777);
- msqptr->msg_qbytes = omsqbuf.msg_qbytes;
- msqptr->msg_ctime = time_second;
- break;
-
- case IPC_STAT:
- if ((error = ipcperm(cred, &msqptr->msg_perm, IPC_R))) {
-#ifdef MSG_DEBUG_OK
- printf("requester doesn't have read access\n");
-#endif
- return(error);
- }
- msqid_n2o(msqptr, &omsqbuf);
- error = copyout((caddr_t)&omsqbuf, user_msqptr, sizeof omsqbuf);
- break;
-
- default:
-#ifdef MSG_DEBUG_OK
- printf("invalid command %d\n", cmd);
-#endif
- return(EINVAL);
- }
-
- if (error == 0)
- *retval = rval;
- return(error);
+ return (msgctl1(p, SCARG(uap, msqid), SCARG(uap, cmd),
+ (caddr_t)SCARG(uap, buf), msqid_copyin, msqid_copyout));
}
#endif /* SYSVMSG */
-#ifdef SYSVSHM
-
-struct shmid_ds *shm_find_segment_by_shmid(int);
-void shm_deallocate_segment(struct shmid_ds *);
-
-#define SHMSEG_REMOVED 0x0400 /* XXX */
-
-int
-compat_23_sys_shmctl(p, v, retval)
- struct proc *p;
- void *v;
- register_t *retval;
+#ifdef SYSVSEM
+/*
+ * Copy a struct semid_ds23 from userland and convert to struct semid_ds
+ */
+static int
+semid_copyin(const void *uaddr, void *kaddr, size_t len)
{
- struct compat_23_sys_shmctl_args /* {
- syscallarg(int) shmid;
- syscallarg(int) cmd;
- syscallarg(struct shmid_ds *) buf;
- } */ *uap = v;
+ struct semid_ds *sembuf = kaddr;
+ struct semid_ds23 osembuf;
int error;
- struct ucred *cred = p->p_ucred;
- struct oshmid_ds oinbuf;
- struct shmid_ds *shmseg;
- extern int shm_last_free;
- shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid));
- if (shmseg == NULL)
- return EINVAL;
- switch (SCARG(uap, cmd)) {
- case IPC_STAT:
- if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_R)) != 0)
- return error;
- shmid_n2o(shmseg, &oinbuf);
- error = copyout((caddr_t)&oinbuf, SCARG(uap, buf),
- sizeof(oinbuf));
- if (error)
- return error;
- break;
- case IPC_SET:
- if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0)
- return error;
- error = copyin(SCARG(uap, buf), (caddr_t)&oinbuf,
- sizeof(oinbuf));
- if (error)
- return error;
- shmseg->shm_perm.uid = oinbuf.shm_perm.uid;
- shmseg->shm_perm.gid = oinbuf.shm_perm.gid;
- shmseg->shm_perm.mode =
- (shmseg->shm_perm.mode & ~ACCESSPERMS) |
- (oinbuf.shm_perm.mode & ACCESSPERMS);
- shmseg->shm_ctime = time_second;
- break;
- case IPC_RMID:
- if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_M)) != 0)
- return error;
- shmseg->shm_perm.key = IPC_PRIVATE;
- shmseg->shm_perm.mode |= SHMSEG_REMOVED;
- if (shmseg->shm_nattch <= 0) {
- shm_deallocate_segment(shmseg);
- shm_last_free = IPCID_TO_IX(SCARG(uap, shmid));
- }
- break;
- case SHM_LOCK:
- case SHM_UNLOCK:
- default:
- return EINVAL;
- }
- return 0;
+ if (len != sizeof(struct semid_ds))
+ return (EFAULT);
+ if ((error = copyin(uaddr, &osembuf, sizeof(osembuf))) == 0)
+ cvt_ds(sembuf, &osembuf, sem, sem_base);
+ return (error);
}
-#endif /* SYSVSHM */
-#ifdef SYSVSEM
+/*
+ * Convert a struct semid_ds to struct semid_ds23 and copy to userland
+ */
+static int
+semid_copyout(const void *kaddr, void *uaddr, size_t len)
+{
+ const struct semid_ds *sembuf = kaddr;
+ struct semid_ds23 osembuf;
-extern struct pool sema_pool;
-void semundo_clear(int, int);
+ if (len != sizeof(struct semid_ds))
+ return (EFAULT);
+ cvt_ds(&osembuf, sembuf, sem, sem_base);
+ return (copyout(&osembuf, uaddr, sizeof(osembuf)));
+}
+/*
+ * OpenBSD 2.3 semctl(2) with 16bit values in struct ipcperm.
+ */
int
-compat_23_sys___semctl(p, v, retval)
- struct proc *p;
- register void *v;
- register_t *retval;
+compat_23_sys___semctl(struct proc *p, void *v, register_t *retval)
{
- register struct compat_23_sys___semctl_args /* {
+ struct compat_23_sys___semctl_args /* {
syscallarg(int) semid;
syscallarg(int) semnum;
syscallarg(int) cmd;
syscallarg(union semun *) arg;
} */ *uap = v;
- int semid = SCARG(uap, semid);
- int semnum = SCARG(uap, semnum);
- int cmd = SCARG(uap, cmd);
- union semun *arg = SCARG(uap, arg);
- union semun real_arg;
- struct ucred *cred = p->p_ucred;
- int i, rval, error;
- struct semid_ds *semaptr;
- struct osemid_ds osbuf;
- extern int semtot;
-
-#ifdef SEM_DEBUG
- printf("call to semctl(%d, %d, %d, %p)\n", semid, semnum, cmd, arg);
-#endif
-
- semid = IPCID_TO_IX(semid);
- if (semid < 0 || semid >= seminfo.semmsl)
- return(EINVAL);
-
- if ((semaptr = sema[semid]) == NULL ||
- semaptr->sem_perm.seq != IPCID_TO_SEQ(SCARG(uap, semid)))
- return(EINVAL);
-
- error = rval = 0;
+ union semun arg;
+ int error = 0, cmd = SCARG(uap, cmd);
switch (cmd) {
- case IPC_RMID:
- if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_M)) != 0)
- return(error);
- semaptr->sem_perm.cuid = cred->cr_uid;
- semaptr->sem_perm.uid = cred->cr_uid;
- semtot -= semaptr->sem_nsems;
- free(semaptr->sem_base, M_SHM);
- pool_put(&sema_pool, semaptr);
- sema[semid] = NULL;
- semundo_clear(semid, -1);
- wakeup((caddr_t)&sema[semid]);
- break;
-
case IPC_SET:
- if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_M)))
- return(error);
- if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
- return(error);
- if ((error = copyin(real_arg.buf, (caddr_t)&osbuf,
- sizeof(osbuf))) != 0)
- return(error);
- semaptr->sem_perm.uid = osbuf.sem_perm.uid;
- semaptr->sem_perm.gid = osbuf.sem_perm.gid;
- semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) |
- (osbuf.sem_perm.mode & 0777);
- semaptr->sem_ctime = time_second;
- break;
-
case IPC_STAT:
- if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
- return(error);
- if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
- return(error);
- semid_n2o(semaptr, &osbuf);
- error = copyout((caddr_t)&osbuf, real_arg.buf, sizeof(osbuf));
- break;
-
- case GETNCNT:
- if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
- return(error);
- if (semnum < 0 || semnum >= semaptr->sem_nsems)
- return(EINVAL);
- rval = semaptr->sem_base[semnum].semncnt;
- break;
-
- case GETPID:
- if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
- return(error);
- if (semnum < 0 || semnum >= semaptr->sem_nsems)
- return(EINVAL);
- rval = semaptr->sem_base[semnum].sempid;
- break;
-
- case GETVAL:
- if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
- return(error);
- if (semnum < 0 || semnum >= semaptr->sem_nsems)
- return(EINVAL);
- rval = semaptr->sem_base[semnum].semval;
- break;
-
case GETALL:
- if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
- return(error);
- if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
- return(error);
- for (i = 0; i < semaptr->sem_nsems; i++) {
- error = copyout((caddr_t)&semaptr->sem_base[i].semval,
- &real_arg.array[i], sizeof(real_arg.array[0]));
- if (error != 0)
- break;
- }
+ case SETVAL:
+ case SETALL:
+ error = copyin(SCARG(uap, arg), &arg, sizeof(arg));
break;
+ }
+ if (error == 0) {
+ error = semctl1(p, SCARG(uap, semid), SCARG(uap, semnum),
+ cmd, &arg, retval, semid_copyin, semid_copyout);
+ }
+ return (error);
+}
+#endif /* SYSVSEM */
- case GETZCNT:
- if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_R)))
- return(error);
- if (semnum < 0 || semnum >= semaptr->sem_nsems)
- return(EINVAL);
- rval = semaptr->sem_base[semnum].semzcnt;
- break;
+#ifdef SYSVSHM
+/*
+ * Copy a struct shmid_ds23 from userland and convert to struct shmid_ds
+ */
+static int
+shmid_copyin(const void *uaddr, void *kaddr, size_t len)
+{
+ struct shmid_ds *shmbuf = kaddr;
+ struct shmid_ds23 oshmbuf;
+ int error;
- case SETVAL:
- if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_W)))
- return(error);
- if (semnum < 0 || semnum >= semaptr->sem_nsems)
- return(EINVAL);
- if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
- return(error);
- semaptr->sem_base[semnum].semval = real_arg.val;
- semundo_clear(semid, semnum);
- wakeup((caddr_t)&sema[semid]);
- break;
+ if (len != sizeof(struct shmid_ds))
+ return (EFAULT);
+ if ((error = copyin(uaddr, &oshmbuf, sizeof(oshmbuf))) == 0)
+ cvt_ds(shmbuf, &oshmbuf, shm, shm_segsz);
+ return (error);
+}
- case SETALL:
- if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_W)))
- return(error);
- if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
- return(error);
- for (i = 0; i < semaptr->sem_nsems; i++) {
- error = copyin(&real_arg.array[i],
- (caddr_t)&semaptr->sem_base[i].semval,
- sizeof(real_arg.array[0]));
- if (error != 0)
- break;
- }
- semundo_clear(semid, -1);
- wakeup((caddr_t)&sema[semid]);
- break;
+/*
+ * Convert a struct shmid_ds to struct shmid_ds23 and copy to userland
+ */
+static int
+shmid_copyout(const void *kaddr, void *uaddr, size_t len)
+{
+ const struct shmid_ds *shmbuf = kaddr;
+ struct shmid_ds23 oshmbuf;
- default:
- return(EINVAL);
- }
+ if (len != sizeof(struct shmid_ds))
+ return (EFAULT);
+ cvt_ds(&oshmbuf, shmbuf, shm, shm_segsz);
+ return (copyout(&oshmbuf, uaddr, sizeof(oshmbuf)));
+}
+
+/*
+ * OpenBSD 2.3 shmctl(2) with 16bit values in struct ipcperm.
+ */
+int
+compat_23_sys_shmctl(struct proc *p, void *v, register_t *retval)
+{
+ struct compat_23_sys_shmctl_args /* {
+ syscallarg(int) shmid;
+ syscallarg(int) cmd;
+ syscallarg(struct shmid_ds23 *) buf;
+ } */ *uap = v;
- if (error == 0)
- *retval = rval;
- return(error);
+ return (shmctl1(p, SCARG(uap, shmid), SCARG(uap, cmd),
+ (caddr_t)SCARG(uap, buf), shmid_copyin, shmid_copyout));
}
-#endif /* SYSVSEM */
+#endif /* SYSVSHM */