diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-07-14 23:40:28 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-07-14 23:40:28 +0000 |
commit | 2936cdf8e0c9bb397150cbee125b4456fee40aab (patch) | |
tree | 4fda94d98d59aeca779113e722431e67b079380e /sys | |
parent | 83ed57ef80de637661b9f6f753f95ef33f816c3d (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.c | 78 | ||||
-rw-r--r-- | sys/kern/sysv_sem.c | 91 | ||||
-rw-r--r-- | sys/kern/sysv_shm.c | 29 | ||||
-rw-r--r-- | sys/sys/msg.h | 11 | ||||
-rw-r--r-- | sys/sys/sem.h | 23 | ||||
-rw-r--r-- | sys/sys/shm.h | 18 |
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 */ |