diff options
Diffstat (limited to 'sys/kern')
-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 |
3 files changed, 104 insertions, 94 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; |