summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-07-14 23:40:28 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-07-14 23:40:28 +0000
commit2936cdf8e0c9bb397150cbee125b4456fee40aab (patch)
tree4fda94d98d59aeca779113e722431e67b079380e /sys
parent83ed57ef80de637661b9f6f753f95ef33f816c3d (diff)
Move the guts of the {sem,msg,shm}ctl system calls into a new function
which also takes two function pointers for copyin/copyout. For the real syscalls these are just the normal copyin/copyout functions. For the compat routines, these are funtions that convert between the new and old foo_ds structs automagically. OK deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/sysv_msg.c78
-rw-r--r--sys/kern/sysv_sem.c91
-rw-r--r--sys/kern/sysv_shm.c29
-rw-r--r--sys/sys/msg.h11
-rw-r--r--sys/sys/sem.h23
-rw-r--r--sys/sys/shm.h18
6 files changed, 136 insertions, 114 deletions
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index bf7cf0fbd27..071d839fab7 100644
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysv_msg.c,v 1.16 2004/06/21 23:50:36 tholo Exp $ */
+/* $OpenBSD: sysv_msg.c,v 1.17 2004/07/14 23:40:27 millert Exp $ */
/* $NetBSD: sysv_msg.c,v 1.19 1996/02/09 19:00:18 christos Exp $ */
/*
@@ -167,45 +167,50 @@ sys_msgctl(p, v, retval)
syscallarg(int) cmd;
syscallarg(struct msqid_ds *) buf;
} */ *uap = v;
- int msqid = SCARG(uap, msqid);
- int cmd = SCARG(uap, cmd);
- struct msqid_ds *user_msqptr = SCARG(uap, buf);
+
+ return (msgctl1(p, SCARG(uap, msqid), SCARG(uap, cmd),
+ (caddr_t)SCARG(uap, buf), copyin, copyout));
+}
+
+int
+msgctl1(p, msqid, cmd, buf, ds_copyin, ds_copyout)
+ struct proc *p;
+ int msqid;
+ int cmd;
+ caddr_t buf;
+ int (*ds_copyin)(const void *, void *, size_t);
+ int (*ds_copyout)(const void *, void *, size_t);
+{
struct ucred *cred = p->p_ucred;
- int rval, eval;
- struct msqid_ds msqbuf;
- register struct msqid_ds *msqptr;
+ struct msqid_ds msqbuf, *msqptr;
+ struct msg *msghdr;
+ int ix, error = 0;
- DPRINTF(("call to msgctl(%d, %d, %p)\n", msqid, cmd, user_msqptr));
+ DPRINTF(("call to msgctl(%d, %d, %p)\n", msqid, cmd, buf));
- msqid = IPCID_TO_IX(msqid);
+ ix = IPCID_TO_IX(msqid);
- if (msqid < 0 || msqid >= msginfo.msgmni) {
- DPRINTF(("msqid (%d) out of range (0<=msqid<%d)\n", msqid,
+ if (ix < 0 || ix >= msginfo.msgmni) {
+ DPRINTF(("msqid (%d) out of range (0<=msqid<%d)\n", ix,
msginfo.msgmni));
return (EINVAL);
}
- msqptr = &msqids[msqid];
+ msqptr = &msqids[ix];
if (msqptr->msg_qbytes == 0) {
DPRINTF(("no such msqid\n"));
return (EINVAL);
}
- if (msqptr->msg_perm.seq != IPCID_TO_SEQ(SCARG(uap, msqid))) {
+ if (msqptr->msg_perm.seq != IPCID_TO_SEQ(msqid)) {
DPRINTF(("wrong sequence number\n"));
return (EINVAL);
}
- eval = 0;
- rval = 0;
-
switch (cmd) {
-
case IPC_RMID:
- {
- struct msg *msghdr;
- if ((eval = ipcperm(cred, &msqptr->msg_perm, IPC_M)) != 0)
- return (eval);
+ if ((error = ipcperm(cred, &msqptr->msg_perm, IPC_M)) != 0)
+ return (error);
/* Free the message headers */
msghdr = msqptr->msg_first;
while (msghdr != NULL) {
@@ -225,20 +230,17 @@ sys_msgctl(p, v, retval)
if (msqptr->msg_qnum != 0)
panic("sys_msgctl: msg_qnum is screwed up");
#endif
-
msqptr->msg_qbytes = 0; /* Mark it as free */
-
wakeup(msqptr);
- }
-
break;
case IPC_SET:
- if ((eval = ipcperm(cred, &msqptr->msg_perm, IPC_M)))
- return (eval);
- if ((eval = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0)
- return (eval);
- if (msqbuf.msg_qbytes > msqptr->msg_qbytes && cred->cr_uid != 0)
+ if ((error = ipcperm(cred, &msqptr->msg_perm, IPC_M)))
+ return (error);
+ if ((error = ds_copyin(buf, &msqbuf, sizeof(msqbuf))) != 0)
+ return (error);
+ if (msqbuf.msg_qbytes > msqptr->msg_qbytes &&
+ cred->cr_uid != 0)
return (EPERM);
if (msqbuf.msg_qbytes > msginfo.msgmnb) {
DPRINTF(("can't increase msg_qbytes beyond %d "
@@ -250,8 +252,8 @@ sys_msgctl(p, v, retval)
DPRINTF(("can't reduce msg_qbytes to 0\n"));
return (EINVAL); /* non-standard errno! */
}
- msqptr->msg_perm.uid = msqbuf.msg_perm.uid; /* change owner */
- msqptr->msg_perm.gid = msqbuf.msg_perm.gid; /* change owner */
+ msqptr->msg_perm.uid = msqbuf.msg_perm.uid;
+ msqptr->msg_perm.gid = msqbuf.msg_perm.gid;
msqptr->msg_perm.mode = (msqptr->msg_perm.mode & ~0777) |
(msqbuf.msg_perm.mode & 0777);
msqptr->msg_qbytes = msqbuf.msg_qbytes;
@@ -259,22 +261,18 @@ sys_msgctl(p, v, retval)
break;
case IPC_STAT:
- if ((eval = ipcperm(cred, &msqptr->msg_perm, IPC_R))) {
+ if ((error = ipcperm(cred, &msqptr->msg_perm, IPC_R))) {
DPRINTF(("requester doesn't have read access\n"));
- return (eval);
+ return (error);
}
- eval = copyout(msqptr, user_msqptr,
- sizeof(struct msqid_ds));
+ error = ds_copyout(msqptr, buf, sizeof(struct msqid_ds));
break;
default:
DPRINTF(("invalid command %d\n", cmd));
return (EINVAL);
}
-
- if (eval == 0)
- *retval = rval;
- return (eval);
+ return (error);
}
int
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index d868dbd7ced..5e86bf14461 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysv_sem.c,v 1.30 2004/06/21 23:50:36 tholo Exp $ */
+/* $OpenBSD: sysv_sem.c,v 1.31 2004/07/14 23:40:27 millert Exp $ */
/* $NetBSD: sysv_sem.c,v 1.26 1996/02/09 19:00:25 christos Exp $ */
/*
@@ -249,28 +249,45 @@ sys___semctl(struct proc *p, void *v, register_t *retval)
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;
+ union semun arg;
+ int error = 0, cmd = SCARG(uap, cmd);
+
+ switch (cmd) {
+ case IPC_SET:
+ case IPC_STAT:
+ case GETALL:
+ 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, copyin, copyout);
+ }
+ return (error);
+}
+
+int
+semctl1(struct proc *p, int semid, int semnum, int cmd, union semun *arg,
+ register_t *retval, int (*ds_copyin)(const void *, void *, size_t),
+ int (*ds_copyout)(const void *, void *, size_t))
+{
struct ucred *cred = p->p_ucred;
- int i, rval, error;
+ int i, ix, error = 0;
struct semid_ds sbuf;
struct semid_ds *semaptr;
DPRINTF(("call to semctl(%d, %d, %d, %p)\n", semid, semnum, cmd, arg));
- semid = IPCID_TO_IX(semid);
- if (semid < 0 || semid >= seminfo.semmni)
+ ix = IPCID_TO_IX(semid);
+ if (ix < 0 || ix >= seminfo.semmni)
return (EINVAL);
- if ((semaptr = sema[semid]) == NULL ||
- semaptr->sem_perm.seq != IPCID_TO_SEQ(SCARG(uap, semid)))
+ if ((semaptr = sema[ix]) == NULL ||
+ semaptr->sem_perm.seq != IPCID_TO_SEQ(semid))
return (EINVAL);
- error = rval = 0;
-
switch (cmd) {
case IPC_RMID:
if ((error = ipcperm(cred, &semaptr->sem_perm, IPC_M)) != 0)
@@ -280,17 +297,15 @@ sys___semctl(struct proc *p, void *v, register_t *retval)
semtot -= semaptr->sem_nsems;
free(semaptr->sem_base, M_SEM);
pool_put(&sema_pool, semaptr);
- sema[semid] = NULL;
- semundo_clear(semid, -1);
- wakeup(&sema[semid]);
+ sema[ix] = NULL;
+ semundo_clear(ix, -1);
+ wakeup(&sema[ix]);
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, &sbuf, sizeof(sbuf))) != 0)
+ if ((error = ds_copyin(arg->buf, &sbuf, sizeof(sbuf))) != 0)
return (error);
semaptr->sem_perm.uid = sbuf.sem_perm.uid;
semaptr->sem_perm.gid = sbuf.sem_perm.gid;
@@ -302,9 +317,7 @@ sys___semctl(struct proc *p, void *v, register_t *retval)
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);
- error = copyout(semaptr, real_arg.buf, sizeof(struct semid_ds));
+ error = ds_copyout(semaptr, arg->buf, sizeof(struct semid_ds));
break;
case GETNCNT:
@@ -312,7 +325,7 @@ sys___semctl(struct proc *p, void *v, register_t *retval)
return (error);
if (semnum < 0 || semnum >= semaptr->sem_nsems)
return (EINVAL);
- rval = semaptr->sem_base[semnum].semncnt;
+ *retval = semaptr->sem_base[semnum].semncnt;
break;
case GETPID:
@@ -320,7 +333,7 @@ sys___semctl(struct proc *p, void *v, register_t *retval)
return (error);
if (semnum < 0 || semnum >= semaptr->sem_nsems)
return (EINVAL);
- rval = semaptr->sem_base[semnum].sempid;
+ *retval = semaptr->sem_base[semnum].sempid;
break;
case GETVAL:
@@ -328,17 +341,15 @@ sys___semctl(struct proc *p, void *v, register_t *retval)
return (error);
if (semnum < 0 || semnum >= semaptr->sem_nsems)
return (EINVAL);
- rval = semaptr->sem_base[semnum].semval;
+ *retval = 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(&semaptr->sem_base[i].semval,
- &real_arg.array[i], sizeof(real_arg.array[0]));
+ error = ds_copyout(&semaptr->sem_base[i].semval,
+ &arg->array[i], sizeof(arg->array[0]));
if (error != 0)
break;
}
@@ -349,7 +360,7 @@ sys___semctl(struct proc *p, void *v, register_t *retval)
return (error);
if (semnum < 0 || semnum >= semaptr->sem_nsems)
return (EINVAL);
- rval = semaptr->sem_base[semnum].semzcnt;
+ *retval = semaptr->sem_base[semnum].semzcnt;
break;
case SETVAL:
@@ -357,35 +368,29 @@ sys___semctl(struct proc *p, void *v, register_t *retval)
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(&sema[semid]);
+ semaptr->sem_base[semnum].semval = arg->val;
+ semundo_clear(ix, semnum);
+ wakeup(&sema[ix]);
break;
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],
+ error = ds_copyin(&arg->array[i],
&semaptr->sem_base[i].semval,
- sizeof(real_arg.array[0]));
+ sizeof(arg->array[0]));
if (error != 0)
break;
}
- semundo_clear(semid, -1);
- wakeup(&sema[semid]);
+ semundo_clear(ix, -1);
+ wakeup(&sema[ix]);
break;
default:
return (EINVAL);
}
- if (error == 0)
- *retval = rval;
return (error);
}
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index 3be8c1a1523..df588682aea 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysv_shm.c,v 1.44 2004/06/21 23:50:36 tholo Exp $ */
+/* $OpenBSD: sysv_shm.c,v 1.45 2004/07/14 23:40:27 millert Exp $ */
/* $NetBSD: sysv_shm.c,v 1.50 1998/10/21 22:24:29 tron Exp $ */
/*
@@ -300,28 +300,35 @@ sys_shmctl(struct proc *p, void *v, register_t *retval)
syscallarg(int) cmd;
syscallarg(struct shmid_ds *) buf;
} */ *uap = v;
- int error;
+
+ return (shmctl1(p, SCARG(uap, shmid), SCARG(uap, cmd),
+ (caddr_t)SCARG(uap, buf), copyin, copyout));
+}
+
+int
+shmctl1(struct proc *p, int shmid, int cmd, caddr_t buf,
+ int (*ds_copyin)(const void *, void *, size_t),
+ int (*ds_copyout)(const void *, void *, size_t))
+{
struct ucred *cred = p->p_ucred;
- struct shmid_ds inbuf;
- struct shmid_ds *shmseg;
+ struct shmid_ds inbuf, *shmseg;
+ int error;
- shmseg = shm_find_segment_by_shmid(SCARG(uap, shmid), 1);
+ shmseg = shm_find_segment_by_shmid(shmid, 1);
if (shmseg == NULL)
return (EINVAL);
- switch (SCARG(uap, cmd)) {
+ switch (cmd) {
case IPC_STAT:
if ((error = ipcperm(cred, &shmseg->shm_perm, IPC_R)) != 0)
return (error);
- error = copyout((caddr_t)shmseg, SCARG(uap, buf),
- sizeof(inbuf));
+ error = ds_copyout(shmseg, buf, sizeof(inbuf));
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)&inbuf,
- sizeof(inbuf));
+ error = ds_copyin(buf, &inbuf, sizeof(inbuf));
if (error)
return (error);
shmseg->shm_perm.uid = inbuf.shm_perm.uid;
@@ -338,7 +345,7 @@ sys_shmctl(struct proc *p, void *v, register_t *retval)
shmseg->shm_perm.mode |= SHMSEG_REMOVED;
if (shmseg->shm_nattch <= 0) {
shm_deallocate_segment(shmseg);
- shm_last_free = IPCID_TO_IX(SCARG(uap, shmid));
+ shm_last_free = IPCID_TO_IX(shmid);
shmsegs[shm_last_free] = NULL;
}
break;
diff --git a/sys/sys/msg.h b/sys/sys/msg.h
index 21e56ed8cbc..ade0d67acb4 100644
--- a/sys/sys/msg.h
+++ b/sys/sys/msg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: msg.h,v 1.10 2002/12/10 21:30:09 pvalchev Exp $ */
+/* $OpenBSD: msg.h,v 1.11 2004/07/14 23:40:27 millert Exp $ */
/* $NetBSD: msg.h,v 1.9 1996/02/09 18:25:18 christos Exp $ */
/*
@@ -184,8 +184,13 @@ int msgsnd(int, const void *, size_t, int);
int msgrcv(int, void *, size_t, long, int);
__END_DECLS
#else
-void msginit(void);
-void msqid_n2o(struct msqid_ds *, struct omsqid_ds *);
+struct proc;
+
+void msginit(void);
+void msqid_n2o(struct msqid_ds *, struct omsqid_ds *);
+int msgctl1(struct proc *, int, int, caddr_t,
+ int (*)(const void *, void *, size_t),
+ int (*)(const void *, void *, size_t));
#endif /* !_KERNEL */
#endif /* !_SYS_MSG_H_ */
diff --git a/sys/sys/sem.h b/sys/sys/sem.h
index 809eb676ec1..c5cea91e629 100644
--- a/sys/sys/sem.h
+++ b/sys/sys/sem.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sem.h,v 1.15 2004/05/03 17:38:47 millert Exp $ */
+/* $OpenBSD: sem.h,v 1.16 2004/07/14 23:40:27 millert Exp $ */
/* $NetBSD: sem.h,v 1.8 1996/02/09 18:25:29 christos Exp $ */
/*
@@ -195,17 +195,20 @@ extern struct semid_ds **sema; /* semaphore id list */
#include <sys/cdefs.h>
__BEGIN_DECLS
-int semctl(int, int, int, ...);
-int __semctl(int, int, int, union semun *);
-int semget(key_t, int, int);
-int semop(int, struct sembuf *, size_t);
-int semconfig(int);
+int semctl(int, int, int, ...);
+int __semctl(int, int, int, union semun *);
+int semget(key_t, int, int);
+int semop(int, struct sembuf *, size_t);
+int semconfig(int);
__END_DECLS
#else
-void seminit(void);
-void semexit(struct proc *);
-void semid_n2o(struct semid_ds *, struct osemid_ds *);
-int sysctl_sysvsem(int *, u_int, void *, size_t *, void *, size_t);
+void seminit(void);
+void semexit(struct proc *);
+void semid_n2o(struct semid_ds *, struct osemid_ds *);
+int sysctl_sysvsem(int *, u_int, void *, size_t *, void *, size_t);
+int semctl1(struct proc *, int, int, int, union semun *, register_t *,
+ int (*)(const void *, void *, size_t),
+ int (*)(const void *, void *, size_t));
#endif /* !_KERNEL */
#endif /* !_SEM_H_ */
diff --git a/sys/sys/shm.h b/sys/sys/shm.h
index b02075d3950..43a6c8bc44f 100644
--- a/sys/sys/shm.h
+++ b/sys/sys/shm.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: shm.h,v 1.16 2004/05/03 17:38:47 millert Exp $ */
+/* $OpenBSD: shm.h,v 1.17 2004/07/14 23:40:27 millert Exp $ */
/* $NetBSD: shm.h,v 1.20 1996/04/09 20:55:35 cgd Exp $ */
/*
@@ -149,14 +149,18 @@ extern struct shmid_ds **shmsegs;
extern int shmseg;
extern int shmmaxpgs;
+struct proc;
struct vmspace;
-void shminit(void);
-void shmfork(struct vmspace *, struct vmspace *);
-void shmexit(struct vmspace *);
-void shmid_n2o(struct shmid_ds *, struct oshmid_ds *);
-int sysctl_sysvshm(int *, u_int, void *, size_t *, void *, size_t);
-int sys_shmat1(struct proc *, void *, register_t *, int);
+void shminit(void);
+void shmfork(struct vmspace *, struct vmspace *);
+void shmexit(struct vmspace *);
+void shmid_n2o(struct shmid_ds *, struct oshmid_ds *);
+int sysctl_sysvshm(int *, u_int, void *, size_t *, void *, size_t);
+int sys_shmat1(struct proc *, void *, register_t *, int);
+int shmctl1(struct proc *, int, int, caddr_t,
+ int (*)(const void *, void *, size_t),
+ int (*)(const void *, void *, size_t));
#else /* !_KERNEL */