diff options
author | dillon <dillon@FreeBSD.org> | 2001-08-31 00:02:18 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 2001-08-31 00:02:18 +0000 |
commit | 3f46dfb9c029a45e072dc37f3993ad34b0c049ae (patch) | |
tree | c572df73674734906e6a9b3b8daf10e73b61f8aa | |
parent | a12a09cb3fead9dd44d529b10167fc746211181c (diff) | |
download | FreeBSD-src-3f46dfb9c029a45e072dc37f3993ad34b0c049ae.zip FreeBSD-src-3f46dfb9c029a45e072dc37f3993ad34b0c049ae.tar.gz |
Giant Pushdown: sysv shm, sem, and msg calls.
-rw-r--r-- | sys/kern/init_sysent.c | 30 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 28 | ||||
-rw-r--r-- | sys/kern/sysv_msg.c | 244 | ||||
-rw-r--r-- | sys/kern/sysv_sem.c | 295 | ||||
-rw-r--r-- | sys/kern/sysv_shm.c | 196 |
5 files changed, 510 insertions, 283 deletions
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 1f63bb0..2e5034e 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -3,7 +3,7 @@ * * DO NOT EDIT-- this file is automatically generated. * $FreeBSD$ - * created from FreeBSD: src/sys/kern/syscalls.master,v 1.91 2001/05/29 09:22:22 phk Exp + * created from FreeBSD: src/sys/kern/syscalls.master,v 1.92 2001/08/30 18:50:56 dillon Exp */ #include "opt_compat.h" @@ -191,9 +191,9 @@ struct sysent sysent[] = { { AS(rtprio_args), (sy_call_t *)rtprio }, /* 166 = rtprio */ { 0, (sy_call_t *)nosys }, /* 167 = nosys */ { 0, (sy_call_t *)nosys }, /* 168 = nosys */ - { AS(semsys_args), (sy_call_t *)lkmressys }, /* 169 = semsys */ - { AS(msgsys_args), (sy_call_t *)lkmressys }, /* 170 = msgsys */ - { AS(shmsys_args), (sy_call_t *)lkmressys }, /* 171 = shmsys */ + { SYF_MPSAFE | AS(semsys_args), (sy_call_t *)lkmressys }, /* 169 = semsys */ + { SYF_MPSAFE | AS(msgsys_args), (sy_call_t *)lkmressys }, /* 170 = msgsys */ + { SYF_MPSAFE | AS(shmsys_args), (sy_call_t *)lkmressys }, /* 171 = shmsys */ { 0, (sy_call_t *)nosys }, /* 172 = nosys */ { AS(pread_args), (sy_call_t *)pread }, /* 173 = pread */ { AS(pwrite_args), (sy_call_t *)pwrite }, /* 174 = pwrite */ @@ -242,18 +242,18 @@ struct sysent sysent[] = { { 0, (sy_call_t *)lkmnosys }, /* 217 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 218 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 219 = lkmnosys */ - { AS(__semctl_args), (sy_call_t *)lkmressys }, /* 220 = __semctl */ - { AS(semget_args), (sy_call_t *)lkmressys }, /* 221 = semget */ - { AS(semop_args), (sy_call_t *)lkmressys }, /* 222 = semop */ + { SYF_MPSAFE | AS(__semctl_args), (sy_call_t *)lkmressys }, /* 220 = __semctl */ + { SYF_MPSAFE | AS(semget_args), (sy_call_t *)lkmressys }, /* 221 = semget */ + { SYF_MPSAFE | AS(semop_args), (sy_call_t *)lkmressys }, /* 222 = semop */ { 0, (sy_call_t *)nosys }, /* 223 = semconfig */ - { AS(msgctl_args), (sy_call_t *)lkmressys }, /* 224 = msgctl */ - { AS(msgget_args), (sy_call_t *)lkmressys }, /* 225 = msgget */ - { AS(msgsnd_args), (sy_call_t *)lkmressys }, /* 226 = msgsnd */ - { AS(msgrcv_args), (sy_call_t *)lkmressys }, /* 227 = msgrcv */ - { AS(shmat_args), (sy_call_t *)lkmressys }, /* 228 = shmat */ - { AS(shmctl_args), (sy_call_t *)lkmressys }, /* 229 = shmctl */ - { AS(shmdt_args), (sy_call_t *)lkmressys }, /* 230 = shmdt */ - { AS(shmget_args), (sy_call_t *)lkmressys }, /* 231 = shmget */ + { SYF_MPSAFE | AS(msgctl_args), (sy_call_t *)lkmressys }, /* 224 = msgctl */ + { SYF_MPSAFE | AS(msgget_args), (sy_call_t *)lkmressys }, /* 225 = msgget */ + { SYF_MPSAFE | AS(msgsnd_args), (sy_call_t *)lkmressys }, /* 226 = msgsnd */ + { SYF_MPSAFE | AS(msgrcv_args), (sy_call_t *)lkmressys }, /* 227 = msgrcv */ + { SYF_MPSAFE | AS(shmat_args), (sy_call_t *)lkmressys }, /* 228 = shmat */ + { SYF_MPSAFE | AS(shmctl_args), (sy_call_t *)lkmressys }, /* 229 = shmctl */ + { SYF_MPSAFE | AS(shmdt_args), (sy_call_t *)lkmressys }, /* 230 = shmdt */ + { SYF_MPSAFE | AS(shmget_args), (sy_call_t *)lkmressys }, /* 231 = shmget */ { AS(clock_gettime_args), (sy_call_t *)clock_gettime }, /* 232 = clock_gettime */ { AS(clock_settime_args), (sy_call_t *)clock_settime }, /* 233 = clock_settime */ { AS(clock_getres_args), (sy_call_t *)clock_getres }, /* 234 = clock_getres */ diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index b8ff694..1eb0918 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -263,15 +263,15 @@ 167 UNIMPL NOHIDE nosys 168 UNIMPL NOHIDE nosys ; 169 is initialized by the SYSVSEM code if present or loaded -169 NOSTD BSD { int semsys(int which, int a2, int a3, int a4, \ +169 MNOSTD BSD { int semsys(int which, int a2, int a3, int a4, \ int a5); } ; 169 is initialized by the SYSVMSG code if present or loaded ; XXX should be { int semsys(int which, ...); } -170 NOSTD BSD { int msgsys(int which, int a2, int a3, int a4, \ +170 MNOSTD BSD { int msgsys(int which, int a2, int a3, int a4, \ int a5, int a6); } ; 169 is initialized by the SYSVSHM code if present or loaded ; XXX should be { int msgsys(int which, ...); } -171 NOSTD BSD { int shmsys(int which, int a2, int a3, int a4); } +171 MNOSTD BSD { int shmsys(int which, int a2, int a3, int a4); } ; XXX should be { int shmsys(int which, ...); } 172 UNIMPL NOHIDE nosys 173 STD POSIX { ssize_t pread(int fd, void *buf, size_t nbyte, \ @@ -345,24 +345,24 @@ ; ; The following were introduced with NetBSD/4.4Lite-2 ; They are initialized by thier respective modules/sysinits -220 NOSTD BSD { int __semctl(int semid, int semnum, int cmd, \ +220 MNOSTD BSD { int __semctl(int semid, int semnum, int cmd, \ union semun *arg); } -221 NOSTD BSD { int semget(key_t key, int nsems, int semflg); } -222 NOSTD BSD { int semop(int semid, struct sembuf *sops, \ +221 MNOSTD BSD { int semget(key_t key, int nsems, int semflg); } +222 MNOSTD BSD { int semop(int semid, struct sembuf *sops, \ u_int nsops); } 223 UNIMPL NOHIDE semconfig -224 NOSTD BSD { int msgctl(int msqid, int cmd, \ +224 MNOSTD BSD { int msgctl(int msqid, int cmd, \ struct msqid_ds *buf); } -225 NOSTD BSD { int msgget(key_t key, int msgflg); } -226 NOSTD BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \ +225 MNOSTD BSD { int msgget(key_t key, int msgflg); } +226 MNOSTD BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \ int msgflg); } -227 NOSTD BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \ +227 MNOSTD BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \ long msgtyp, int msgflg); } -228 NOSTD BSD { int shmat(int shmid, void *shmaddr, int shmflg); } -229 NOSTD BSD { int shmctl(int shmid, int cmd, \ +228 MNOSTD BSD { int shmat(int shmid, void *shmaddr, int shmflg); } +229 MNOSTD BSD { int shmctl(int shmid, int cmd, \ struct shmid_ds *buf); } -230 NOSTD BSD { int shmdt(void *shmaddr); } -231 NOSTD BSD { int shmget(key_t key, int size, int shmflg); } +230 MNOSTD BSD { int shmdt(void *shmaddr); } +231 MNOSTD BSD { int shmget(key_t key, int size, int shmflg); } ; 232 STD POSIX { int clock_gettime(clockid_t clock_id, \ struct timespec *tp); } diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c index 97c06c8..d6badbe 100644 --- a/sys/kern/sysv_msg.c +++ b/sys/kern/sysv_msg.c @@ -26,6 +26,8 @@ #include <sys/sysproto.h> #include <sys/kernel.h> #include <sys/proc.h> +#include <sys/lock.h> +#include <sys/mutex.h> #include <sys/msg.h> #include <sys/syscall.h> #include <sys/sysent.h> @@ -263,6 +265,8 @@ MODULE_VERSION(sysvmsg, 1); /* * Entry point for all MSG calls + * + * MPSAFE */ int msgsys(p, uap) @@ -277,13 +281,22 @@ msgsys(p, uap) int a6; } */ *uap; { + int error; - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + mtx_lock(&Giant); - if (uap->which >= sizeof(msgcalls)/sizeof(msgcalls[0])) - return (EINVAL); - return ((*msgcalls[uap->which])(p, &uap->a2)); + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } + if (uap->which >= sizeof(msgcalls)/sizeof(msgcalls[0])) { + error = EINVAL; + goto done2; + } + error = (*msgcalls[uap->which])(p, &uap->a2); +done2: + mtx_unlock(&Giant); + return (error); } static void @@ -318,6 +331,9 @@ struct msgctl_args { }; #endif +/* + * MPSAFE + */ int msgctl(p, uap) struct proc *p; @@ -326,16 +342,19 @@ msgctl(p, uap) int msqid = uap->msqid; int cmd = uap->cmd; struct msqid_ds *user_msqptr = uap->buf; - int rval, eval; + int rval, error; struct msqid_ds msqbuf; register struct msqid_ds *msqptr; #ifdef MSG_DEBUG_OK printf("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr); #endif + mtx_lock(&Giant); - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } msqid = IPCID_TO_IX(msqid); @@ -344,7 +363,8 @@ msgctl(p, uap) printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, msginfo.msgmni); #endif - return(EINVAL); + error = EINVAL; + goto done2; } msqptr = &msqids[msqid]; @@ -353,16 +373,18 @@ msgctl(p, uap) #ifdef MSG_DEBUG_OK printf("no such msqid\n"); #endif - return(EINVAL); + error = EINVAL; + goto done2; } if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { #ifdef MSG_DEBUG_OK printf("wrong sequence number\n"); #endif - return(EINVAL); + error = EINVAL; + goto done2; } - eval = 0; + error = 0; rval = 0; switch (cmd) { @@ -370,8 +392,8 @@ msgctl(p, uap) case IPC_RMID: { struct msg *msghdr; - if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_M))) - return(eval); + if ((error = ipcperm(p, &msqptr->msg_perm, IPC_M))) + goto done2; /* Free the message headers */ msghdr = msqptr->msg_first; while (msghdr != NULL) { @@ -398,14 +420,14 @@ msgctl(p, uap) break; case IPC_SET: - if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_M))) - return(eval); - if ((eval = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0) - return(eval); + if ((error = ipcperm(p, &msqptr->msg_perm, IPC_M))) + goto done2; + if ((error = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0) + goto done2; if (msqbuf.msg_qbytes > msqptr->msg_qbytes) { - eval = suser(p); - if (eval) - return(eval); + error = suser(p); + if (error) + goto done2; } if (msqbuf.msg_qbytes > msginfo.msgmnb) { #ifdef MSG_DEBUG_OK @@ -418,7 +440,8 @@ msgctl(p, uap) #ifdef MSG_DEBUG_OK printf("can't reduce msg_qbytes to 0\n"); #endif - return(EINVAL); /* non-standard errno! */ + error = EINVAL; /* non-standard errno! */ + goto done2; } msqptr->msg_perm.uid = msqbuf.msg_perm.uid; /* change the owner */ msqptr->msg_perm.gid = msqbuf.msg_perm.gid; /* change the owner */ @@ -429,13 +452,13 @@ msgctl(p, uap) break; case IPC_STAT: - if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_R))) { + if ((error = ipcperm(p, &msqptr->msg_perm, IPC_R))) { #ifdef MSG_DEBUG_OK printf("requester doesn't have read access\n"); #endif - return(eval); + goto done2; } - eval = copyout((caddr_t)msqptr, user_msqptr, + error = copyout((caddr_t)msqptr, user_msqptr, sizeof(struct msqid_ds)); break; @@ -443,12 +466,15 @@ msgctl(p, uap) #ifdef MSG_DEBUG_OK printf("invalid command %d\n", cmd); #endif - return(EINVAL); + error = EINVAL; + goto done2; } - if (eval == 0) + if (error == 0) p->p_retval[0] = rval; - return(eval); +done2: + mtx_unlock(&Giant); + return(error); } #ifndef _SYS_SYSPROTO_H_ @@ -458,12 +484,15 @@ struct msgget_args { }; #endif +/* + * MPSAFE + */ int msgget(p, uap) struct proc *p; register struct msgget_args *uap; { - int msqid, eval; + int msqid, error = 0; int key = uap->key; int msgflg = uap->msgflg; struct ucred *cred = p->p_ucred; @@ -473,8 +502,12 @@ msgget(p, uap) printf("msgget(0x%x, 0%o)\n", key, msgflg); #endif - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + mtx_lock(&Giant); + + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } if (key != IPC_PRIVATE) { for (msqid = 0; msqid < msginfo.msgmni; msqid++) { @@ -491,14 +524,15 @@ msgget(p, uap) #ifdef MSG_DEBUG_OK printf("not exclusive\n"); #endif - return(EEXIST); + error = EEXIST; + goto done2; } - if ((eval = ipcperm(p, &msqptr->msg_perm, msgflg & 0700 ))) { + if ((error = ipcperm(p, &msqptr->msg_perm, msgflg & 0700 ))) { #ifdef MSG_DEBUG_OK printf("requester doesn't have 0%o access\n", msgflg & 0700); #endif - return(eval); + goto done2; } goto found; } @@ -524,7 +558,8 @@ msgget(p, uap) #ifdef MSG_DEBUG_OK printf("no more msqid_ds's available\n"); #endif - return(ENOSPC); + error = ENOSPC; + goto done2; } #ifdef MSG_DEBUG_OK printf("msqid %d is available\n", msqid); @@ -551,13 +586,16 @@ msgget(p, uap) #ifdef MSG_DEBUG_OK printf("didn't find it and wasn't asked to create it\n"); #endif - return(ENOENT); + error = ENOENT; + goto done2; } found: /* Construct the unique msqid */ p->p_retval[0] = IXSEQ_TO_IPCID(msqid, msqptr->msg_perm); - return(0); +done2: + mtx_unlock(&Giant); + return (error); } #ifndef _SYS_SYSPROTO_H_ @@ -569,6 +607,9 @@ struct msgsnd_args { }; #endif +/* + * MPSAFE + */ int msgsnd(p, uap) struct proc *p; @@ -578,7 +619,7 @@ msgsnd(p, uap) void *user_msgp = uap->msgp; size_t msgsz = uap->msgsz; int msgflg = uap->msgflg; - int segs_needed, eval; + int segs_needed, error = 0; register struct msqid_ds *msqptr; register struct msg *msghdr; short next; @@ -587,9 +628,12 @@ msgsnd(p, uap) printf("call to msgsnd(%d, 0x%x, %d, %d)\n", msqid, user_msgp, msgsz, msgflg); #endif + mtx_lock(&Giant); - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } msqid = IPCID_TO_IX(msqid); @@ -598,7 +642,8 @@ msgsnd(p, uap) printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, msginfo.msgmni); #endif - return(EINVAL); + error = EINVAL; + goto done2; } msqptr = &msqids[msqid]; @@ -606,20 +651,22 @@ msgsnd(p, uap) #ifdef MSG_DEBUG_OK printf("no such message queue id\n"); #endif - return(EINVAL); + error = EINVAL; + goto done2; } if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { #ifdef MSG_DEBUG_OK printf("wrong sequence number\n"); #endif - return(EINVAL); + error = EINVAL; + goto done2; } - if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_W))) { + if ((error = ipcperm(p, &msqptr->msg_perm, IPC_W))) { #ifdef MSG_DEBUG_OK printf("requester doesn't have write access\n"); #endif - return(eval); + goto done2; } segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz; @@ -639,7 +686,8 @@ msgsnd(p, uap) #ifdef MSG_DEBUG_OK printf("msgsz > msqptr->msg_qbytes\n"); #endif - return(EINVAL); + error = EINVAL; + goto done2; } if (msqptr->msg_perm.mode & MSG_LOCKED) { @@ -674,7 +722,8 @@ msgsnd(p, uap) #ifdef MSG_DEBUG_OK printf("need more resources but caller doesn't want to wait\n"); #endif - return(EAGAIN); + error = EAGAIN; + goto done2; } if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0) { @@ -694,18 +743,19 @@ msgsnd(p, uap) #ifdef MSG_DEBUG_OK printf("goodnight\n"); #endif - eval = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH, + error = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH, "msgwait", 0); #ifdef MSG_DEBUG_OK - printf("good morning, eval=%d\n", eval); + printf("good morning, error=%d\n", error); #endif if (we_own_it) msqptr->msg_perm.mode &= ~MSG_LOCKED; - if (eval != 0) { + if (error != 0) { #ifdef MSG_DEBUG_OK printf("msgsnd: interrupted system call\n"); #endif - return(EINTR); + error = EINTR; + goto done2; } /* @@ -716,7 +766,8 @@ msgsnd(p, uap) #ifdef MSG_DEBUG_OK printf("msqid deleted\n"); #endif - return(EIDRM); + error = EIDRM; + goto done2; } } else { @@ -787,15 +838,15 @@ msgsnd(p, uap) * Copy in the message type */ - if ((eval = copyin(user_msgp, &msghdr->msg_type, + if ((error = copyin(user_msgp, &msghdr->msg_type, sizeof(msghdr->msg_type))) != 0) { #ifdef MSG_DEBUG_OK - printf("error %d copying the message type\n", eval); + printf("error %d copying the message type\n", error); #endif msg_freehdr(msghdr); msqptr->msg_perm.mode &= ~MSG_LOCKED; wakeup((caddr_t)msqptr); - return(eval); + goto done2; } user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type); @@ -810,7 +861,8 @@ msgsnd(p, uap) #ifdef MSG_DEBUG_OK printf("mtype (%d) < 1\n", msghdr->msg_type); #endif - return(EINVAL); + error = EINVAL; + goto done2; } /* @@ -828,15 +880,15 @@ msgsnd(p, uap) panic("next too low #2"); if (next >= msginfo.msgseg) panic("next out of range #2"); - if ((eval = copyin(user_msgp, &msgpool[next * msginfo.msgssz], + if ((error = copyin(user_msgp, &msgpool[next * msginfo.msgssz], tlen)) != 0) { #ifdef MSG_DEBUG_OK - printf("error %d copying in message segment\n", eval); + printf("error %d copying in message segment\n", error); #endif msg_freehdr(msghdr); msqptr->msg_perm.mode &= ~MSG_LOCKED; wakeup((caddr_t)msqptr); - return(eval); + goto done2; } msgsz -= tlen; user_msgp = (char *)user_msgp + tlen; @@ -858,7 +910,8 @@ msgsnd(p, uap) if (msqptr->msg_qbytes == 0) { msg_freehdr(msghdr); wakeup((caddr_t)msqptr); - return(EIDRM); + error = EIDRM; + goto done2; } /* @@ -881,7 +934,9 @@ msgsnd(p, uap) wakeup((caddr_t)msqptr); p->p_retval[0] = 0; - return(0); +done2: + mtx_unlock(&Giant); + return (error); } #ifndef _SYS_SYSPROTO_H_ @@ -894,6 +949,9 @@ struct msgrcv_args { }; #endif +/* + * MPSAFE + */ int msgrcv(p, uap) struct proc *p; @@ -907,7 +965,7 @@ msgrcv(p, uap) size_t len; register struct msqid_ds *msqptr; register struct msg *msghdr; - int eval; + int error = 0; short next; #ifdef MSG_DEBUG_OK @@ -915,8 +973,12 @@ msgrcv(p, uap) msgsz, msgtyp, msgflg); #endif - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + mtx_lock(&Giant); + + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } msqid = IPCID_TO_IX(msqid); @@ -925,7 +987,8 @@ msgrcv(p, uap) printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, msginfo.msgmni); #endif - return(EINVAL); + error = EINVAL; + goto done2; } msqptr = &msqids[msqid]; @@ -933,20 +996,22 @@ msgrcv(p, uap) #ifdef MSG_DEBUG_OK printf("no such message queue id\n"); #endif - return(EINVAL); + error = EINVAL; + goto done2; } if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { #ifdef MSG_DEBUG_OK printf("wrong sequence number\n"); #endif - return(EINVAL); + error = EINVAL; + goto done2; } - if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_R))) { + if ((error = ipcperm(p, &msqptr->msg_perm, IPC_R))) { #ifdef MSG_DEBUG_OK printf("requester doesn't have read access\n"); #endif - return(eval); + goto done2; } msghdr = NULL; @@ -960,7 +1025,8 @@ msgrcv(p, uap) printf("first message on the queue is too big (want %d, got %d)\n", msgsz, msghdr->msg_ts); #endif - return(E2BIG); + error = E2BIG; + goto done2; } if (msqptr->msg_first == msqptr->msg_last) { msqptr->msg_first = NULL; @@ -999,7 +1065,8 @@ msgrcv(p, uap) printf("requested message on the queue is too big (want %d, got %d)\n", msgsz, msghdr->msg_ts); #endif - return(E2BIG); + error = E2BIG; + goto done2; } *prev = msghdr->msg_next; if (msghdr == msqptr->msg_last) { @@ -1045,7 +1112,8 @@ msgrcv(p, uap) msgtyp); #endif /* The SVID says to return ENOMSG. */ - return(ENOMSG); + error = ENOMSG; + goto done2; } /* @@ -1055,17 +1123,18 @@ msgrcv(p, uap) #ifdef MSG_DEBUG_OK printf("msgrcv: goodnight\n"); #endif - eval = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH, "msgwait", + error = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH, "msgwait", 0); #ifdef MSG_DEBUG_OK - printf("msgrcv: good morning (eval=%d)\n", eval); + printf("msgrcv: good morning (error=%d)\n", error); #endif - if (eval != 0) { + if (error != 0) { #ifdef MSG_DEBUG_OK printf("msgsnd: interrupted system call\n"); #endif - return(EINTR); + error = EINTR; + goto done2; } /* @@ -1077,7 +1146,8 @@ msgrcv(p, uap) #ifdef MSG_DEBUG_OK printf("msqid deleted\n"); #endif - return(EIDRM); + error = EIDRM; + goto done2; } } @@ -1109,15 +1179,15 @@ msgrcv(p, uap) * Return the type to the user. */ - eval = copyout((caddr_t)&(msghdr->msg_type), user_msgp, + error = copyout((caddr_t)&(msghdr->msg_type), user_msgp, sizeof(msghdr->msg_type)); - if (eval != 0) { + if (error != 0) { #ifdef MSG_DEBUG_OK - printf("error (%d) copying out message type\n", eval); + printf("error (%d) copying out message type\n", error); #endif msg_freehdr(msghdr); wakeup((caddr_t)msqptr); - return(eval); + goto done2; } user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type); @@ -1137,16 +1207,16 @@ msgrcv(p, uap) panic("next too low #3"); if (next >= msginfo.msgseg) panic("next out of range #3"); - eval = copyout((caddr_t)&msgpool[next * msginfo.msgssz], + error = copyout((caddr_t)&msgpool[next * msginfo.msgssz], user_msgp, tlen); - if (eval != 0) { + if (error != 0) { #ifdef MSG_DEBUG_OK printf("error (%d) copying out message segment\n", - eval); + error); #endif msg_freehdr(msghdr); wakeup((caddr_t)msqptr); - return(eval); + goto done2; } user_msgp = (char *)user_msgp + tlen; next = msgmaps[next].next; @@ -1159,7 +1229,9 @@ msgrcv(p, uap) msg_freehdr(msghdr); wakeup((caddr_t)msqptr); p->p_retval[0] = msgsz; - return(0); +done2: + mtx_unlock(&Giant); + return (error); } static int diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index 6cd80f3..ac32395 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -15,6 +15,8 @@ #include <sys/sysproto.h> #include <sys/kernel.h> #include <sys/proc.h> +#include <sys/lock.h> +#include <sys/mutex.h> #include <sys/sem.h> #include <sys/syscall.h> #include <sys/sysent.h> @@ -244,6 +246,8 @@ MODULE_VERSION(sysvsem, 1); /* * Entry point for all SEM calls + * + * MPSAFE */ int semsys(p, uap) @@ -257,13 +261,23 @@ semsys(p, uap) int a5; } */ *uap; { + int error; + + mtx_lock(&Giant); - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } - if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0])) - return (EINVAL); - return ((*semcalls[uap->which])(p, &uap->a2)); + if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0])) { + error = EINVAL; + goto done2; + } + error = (*semcalls[uap->which])(p, &uap->a2); +done2: + mtx_unlock(&Giant); + return (error); } /* @@ -448,6 +462,9 @@ struct __semctl_args { }; #endif +/* + * MPSAFE + */ int __semctl(p, uap) struct proc *p; @@ -459,33 +476,40 @@ __semctl(p, uap) union semun *arg = uap->arg; union semun real_arg; struct ucred *cred = p->p_ucred; - int i, rval, eval; + int i, rval, error; struct semid_ds sbuf; register struct semid_ds *semaptr; #ifdef SEM_DEBUG printf("call to semctl(%d, %d, %d, 0x%x)\n", semid, semnum, cmd, arg); #endif + mtx_lock(&Giant); - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } semid = IPCID_TO_IX(semid); - if (semid < 0 || semid >= seminfo.semmsl) - return(EINVAL); + if (semid < 0 || semid >= seminfo.semmsl) { + error = EINVAL; + goto done2; + } semaptr = &sema[semid]; if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 || - semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) - return(EINVAL); + semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) { + error = EINVAL; + goto done2; + } - eval = 0; + error = 0; rval = 0; switch (cmd) { case IPC_RMID: - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_M))) - return(eval); + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_M))) + goto done2; semaptr->sem_perm.cuid = cred->cr_uid; semaptr->sem_perm.uid = cred->cr_uid; semtot -= semaptr->sem_nsems; @@ -502,13 +526,14 @@ __semctl(p, uap) break; case IPC_SET: - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_M))) - return(eval); - if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) - return(eval); - if ((eval = copyin(real_arg.buf, (caddr_t)&sbuf, - sizeof(sbuf))) != 0) - return(eval); + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_M))) + goto done2; + if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0) + goto done2; + if ((error = copyin(real_arg.buf, (caddr_t)&sbuf, + sizeof(sbuf))) != 0) { + goto done2; + } semaptr->sem_perm.uid = sbuf.sem_perm.uid; semaptr->sem_perm.gid = sbuf.sem_perm.gid; semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) | @@ -517,81 +542,91 @@ __semctl(p, uap) break; case IPC_STAT: - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) - return(eval); - if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) - return(eval); - eval = copyout((caddr_t)semaptr, real_arg.buf, - sizeof(struct semid_ds)); + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R))) + goto done2; + if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0) + goto done2; + error = copyout((caddr_t)semaptr, real_arg.buf, + sizeof(struct semid_ds)); break; case GETNCNT: - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) - return(eval); - if (semnum < 0 || semnum >= semaptr->sem_nsems) - return(EINVAL); + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R))) + goto done2; + if (semnum < 0 || semnum >= semaptr->sem_nsems) { + error = EINVAL; + goto done2; + } rval = semaptr->sem_base[semnum].semncnt; break; case GETPID: - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) - return(eval); - if (semnum < 0 || semnum >= semaptr->sem_nsems) - return(EINVAL); + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R))) + goto done2; + if (semnum < 0 || semnum >= semaptr->sem_nsems) { + error = EINVAL; + goto done2; + } rval = semaptr->sem_base[semnum].sempid; break; case GETVAL: - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) - return(eval); - if (semnum < 0 || semnum >= semaptr->sem_nsems) - return(EINVAL); + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R))) + goto done2; + if (semnum < 0 || semnum >= semaptr->sem_nsems) { + error = EINVAL; + goto done2; + } rval = semaptr->sem_base[semnum].semval; break; case GETALL: - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) - return(eval); - if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) - return(eval); + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R))) + goto done2; + if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0) + goto done2; for (i = 0; i < semaptr->sem_nsems; i++) { - eval = copyout((caddr_t)&semaptr->sem_base[i].semval, + error = copyout((caddr_t)&semaptr->sem_base[i].semval, &real_arg.array[i], sizeof(real_arg.array[0])); - if (eval != 0) + if (error != 0) break; } break; case GETZCNT: - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) - return(eval); - if (semnum < 0 || semnum >= semaptr->sem_nsems) - return(EINVAL); + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R))) + goto done2; + if (semnum < 0 || semnum >= semaptr->sem_nsems) { + error = EINVAL; + goto done2; + } rval = semaptr->sem_base[semnum].semzcnt; break; case SETVAL: - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_W))) - return(eval); - if (semnum < 0 || semnum >= semaptr->sem_nsems) - return(EINVAL); - if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) - return(eval); + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_W))) + goto done2; + if (semnum < 0 || semnum >= semaptr->sem_nsems) { + error = EINVAL; + goto done2; + } + if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0) + goto done2; semaptr->sem_base[semnum].semval = real_arg.val; semundo_clear(semid, semnum); wakeup((caddr_t)semaptr); break; case SETALL: - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_W))) - return(eval); - if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) - return(eval); + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_W))) + goto done2; + if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0) + goto done2; for (i = 0; i < semaptr->sem_nsems; i++) { - eval = copyin(&real_arg.array[i], + error = copyin(&real_arg.array[i], (caddr_t)&semaptr->sem_base[i].semval, sizeof(real_arg.array[0])); - if (eval != 0) + if (error != 0) break; } semundo_clear(semid, -1); @@ -599,12 +634,15 @@ __semctl(p, uap) break; default: - return(EINVAL); + error = EINVAL; + break; } - if (eval == 0) + if (error == 0) p->p_retval[0] = rval; - return(eval); +done2: + mtx_unlock(&Giant); + return(error); } #ifndef _SYS_SYSPROTO_H_ @@ -615,12 +653,15 @@ struct semget_args { }; #endif +/* + * MPSAFE + */ int semget(p, uap) struct proc *p; register struct semget_args *uap; { - int semid, eval; + int semid, error = 0; int key = uap->key; int nsems = uap->nsems; int semflg = uap->semflg; @@ -629,9 +670,12 @@ semget(p, uap) #ifdef SEM_DEBUG printf("semget(0x%x, %d, 0%o)\n", key, nsems, semflg); #endif + mtx_lock(&Giant); - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } if (key != IPC_PRIVATE) { for (semid = 0; semid < seminfo.semmni; semid++) { @@ -643,20 +687,23 @@ semget(p, uap) #ifdef SEM_DEBUG printf("found public key\n"); #endif - if ((eval = ipcperm(p, &sema[semid].sem_perm, - semflg & 0700))) - return(eval); + if ((error = ipcperm(p, &sema[semid].sem_perm, + semflg & 0700))) { + goto done2; + } if (nsems > 0 && sema[semid].sem_nsems < nsems) { #ifdef SEM_DEBUG printf("too small\n"); #endif - return(EINVAL); + error = EINVAL; + goto done2; } if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) { #ifdef SEM_DEBUG printf("not exclusive\n"); #endif - return(EEXIST); + error = EEXIST; + goto done2; } goto found; } @@ -671,14 +718,16 @@ semget(p, uap) printf("nsems out of range (0<%d<=%d)\n", nsems, seminfo.semmsl); #endif - return(EINVAL); + error = EINVAL; + goto done2; } if (nsems > seminfo.semmns - semtot) { #ifdef SEM_DEBUG printf("not enough semaphores left (need %d, got %d)\n", nsems, seminfo.semmns - semtot); #endif - return(ENOSPC); + error = ENOSPC; + goto done2; } for (semid = 0; semid < seminfo.semmni; semid++) { if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0) @@ -688,7 +737,8 @@ semget(p, uap) #ifdef SEM_DEBUG printf("no more semid_ds's available\n"); #endif - return(ENOSPC); + error = ENOSPC; + goto done2; } #ifdef SEM_DEBUG printf("semid %d is available\n", semid); @@ -716,12 +766,15 @@ semget(p, uap) #ifdef SEM_DEBUG printf("didn't find it and wasn't asked to create it\n"); #endif - return(ENOENT); + error = ENOENT; + goto done2; } found: p->p_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm); - return(0); +done2: + mtx_unlock(&Giant); + return (error); } #ifndef _SYS_SYSPROTO_H_ @@ -732,6 +785,9 @@ struct semop_args { }; #endif +/* + * MPSAFE + */ int semop(p, uap) struct proc *p; @@ -744,47 +800,58 @@ semop(p, uap) register struct sembuf *sopptr; register struct sem *semptr; struct sem_undo *suptr = NULL; - int i, j, eval; + int i, j, error = 0; int do_wakeup, do_undos; #ifdef SEM_DEBUG printf("call to semop(%d, 0x%x, %d)\n", semid, sops, nsops); #endif - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + mtx_lock(&Giant); + + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } semid = IPCID_TO_IX(semid); /* Convert back to zero origin */ - if (semid < 0 || semid >= seminfo.semmsl) - return(EINVAL); + if (semid < 0 || semid >= seminfo.semmsl) { + error = EINVAL; + goto done2; + } semaptr = &sema[semid]; - if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) - return(EINVAL); - if (semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) - return(EINVAL); + if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) { + error = EINVAL; + goto done2; + } + if (semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) { + error = EINVAL; + goto done2; + } - if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_W))) { + if ((error = ipcperm(p, &semaptr->sem_perm, IPC_W))) { #ifdef SEM_DEBUG - printf("eval = %d from ipaccess\n", eval); + printf("error = %d from ipaccess\n", error); #endif - return(eval); + goto done2; } if (nsops > MAX_SOPS) { #ifdef SEM_DEBUG printf("too many sops (max=%d, nsops=%d)\n", MAX_SOPS, nsops); #endif - return(E2BIG); + error = E2BIG; + goto done2; } - if ((eval = copyin(uap->sops, &sops, nsops * sizeof(sops[0]))) != 0) { + if ((error = copyin(uap->sops, &sops, nsops * sizeof(sops[0]))) != 0) { #ifdef SEM_DEBUG - printf("eval = %d from copyin(%08x, %08x, %d)\n", eval, + printf("error = %d from copyin(%08x, %08x, %d)\n", error, uap->sops, &sops, nsops * sizeof(sops[0])); #endif - return(eval); + goto done2; } /* @@ -804,8 +871,10 @@ semop(p, uap) for (i = 0; i < nsops; i++) { sopptr = &sops[i]; - if (sopptr->sem_num >= semaptr->sem_nsems) - return(EFBIG); + if (sopptr->sem_num >= semaptr->sem_nsems) { + error = EFBIG; + goto done2; + } semptr = &semaptr->sem_base[sopptr->sem_num]; @@ -866,8 +935,10 @@ semop(p, uap) * If the request that we couldn't satisfy has the * NOWAIT flag set then return with EAGAIN. */ - if (sopptr->sem_flg & IPC_NOWAIT) - return(EAGAIN); + if (sopptr->sem_flg & IPC_NOWAIT) { + error = EAGAIN; + goto done2; + } if (sopptr->sem_op == 0) semptr->semzcnt++; @@ -877,16 +948,18 @@ semop(p, uap) #ifdef SEM_DEBUG printf("semop: good night!\n"); #endif - eval = tsleep((caddr_t)semaptr, (PZERO - 4) | PCATCH, + error = tsleep((caddr_t)semaptr, (PZERO - 4) | PCATCH, "semwait", 0); #ifdef SEM_DEBUG - printf("semop: good morning (eval=%d)!\n", eval); + printf("semop: good morning (error=%d)!\n", error); #endif suptr = NULL; /* sem_undo may have been reallocated */ - if (eval != 0) - return(EINTR); + if (error != 0) { + error = EINTR; + goto done2; + } #ifdef SEM_DEBUG printf("semop: good morning!\n"); #endif @@ -895,8 +968,10 @@ semop(p, uap) * Make sure that the semaphore still exists */ if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 || - semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) - return(EIDRM); + semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) { + error = EIDRM; + goto done2; + } /* * The semaphore is still alive. Readjust the count of @@ -925,9 +1000,9 @@ done: adjval = sops[i].sem_op; if (adjval == 0) continue; - eval = semundo_adjust(p, &suptr, semid, + error = semundo_adjust(p, &suptr, semid, sops[i].sem_num, -adjval); - if (eval == 0) + if (error == 0) continue; /* @@ -955,9 +1030,9 @@ done: sops[j].sem_op; #ifdef SEM_DEBUG - printf("eval = %d from semundo_adjust\n", eval); + printf("error = %d from semundo_adjust\n", error); #endif - return(eval); + goto done2; } /* loop through the sops */ } /* if (do_undos) */ @@ -982,7 +1057,9 @@ done: printf("semop: done\n"); #endif p->p_retval[0] = 0; - return(0); +done2: + mtx_unlock(&Giant); + return (error); } /* diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 96a4541..ce9574c 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -233,6 +233,9 @@ struct shmdt_args { }; #endif +/* + * MPSAFE + */ int shmdt(p, uap) struct proc *p; @@ -240,22 +243,34 @@ shmdt(p, uap) { struct shmmap_state *shmmap_s; int i; - int error; + int error = 0; + + mtx_lock(&Giant); - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; - if (shmmap_s == NULL) - return EINVAL; - for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) + if (shmmap_s == NULL) { + error = EINVAL; + goto done2; + } + for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) { if (shmmap_s->shmid != -1 && - shmmap_s->va == (vm_offset_t)uap->shmaddr) + shmmap_s->va == (vm_offset_t)uap->shmaddr) { break; - if (i == shminfo.shmseg) - return EINVAL; + } + } + if (i == shminfo.shmseg) { + error = EINVAL; + goto done2; + } error = shm_delete_mapping(p, shmmap_s); - return error; +done2: + mtx_unlock(&Giant); + return (error); } #ifndef _SYS_SYSPROTO_H_ @@ -266,12 +281,15 @@ struct shmat_args { }; #endif +/* + * MPSAFE + */ int shmat(p, uap) struct proc *p; struct shmat_args *uap; { - int error, i, flags; + int i, flags; struct shmid_ds *shmseg; struct shmmap_state *shmmap_s = NULL; struct shm_handle *shm_handle; @@ -279,11 +297,14 @@ shmat(p, uap) vm_prot_t prot; vm_size_t size; int rv; + int error = 0; - GIANT_REQUIRED; + mtx_lock(&Giant); - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; if (shmmap_s == NULL) { @@ -294,19 +315,23 @@ shmat(p, uap) p->p_vmspace->vm_shm = (caddr_t)shmmap_s; } shmseg = shm_find_segment_by_shmid(uap->shmid); - if (shmseg == NULL) - return EINVAL; + if (shmseg == NULL) { + error = EINVAL; + goto done2; + } error = ipcperm(p, &shmseg->shm_perm, (uap->shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); if (error) - return error; + goto done2; for (i = 0; i < shminfo.shmseg; i++) { if (shmmap_s->shmid == -1) break; shmmap_s++; } - if (i >= shminfo.shmseg) - return EMFILE; + if (i >= shminfo.shmseg) { + error = EMFILE; + goto done2; + } size = round_page(shmseg->shm_segsz); #ifdef VM_PROT_READ_IS_EXEC prot = VM_PROT_READ | VM_PROT_EXECUTE; @@ -318,12 +343,14 @@ shmat(p, uap) flags = MAP_ANON | MAP_SHARED; if (uap->shmaddr) { flags |= MAP_FIXED; - if (uap->shmflg & SHM_RND) + if (uap->shmflg & SHM_RND) { attach_va = (vm_offset_t)uap->shmaddr & ~(SHMLBA-1); - else if (((vm_offset_t)uap->shmaddr & (SHMLBA-1)) == 0) + } else if (((vm_offset_t)uap->shmaddr & (SHMLBA-1)) == 0) { attach_va = (vm_offset_t)uap->shmaddr; - else - return EINVAL; + } else { + error = EINVAL; + goto done2; + } } else { /* * This is just a hint to vm_map_find() about where to @@ -338,7 +365,8 @@ shmat(p, uap) rv = vm_map_find(&p->p_vmspace->vm_map, shm_handle->shm_object, 0, &attach_va, size, (flags & MAP_FIXED)?0:1, prot, prot, 0); if (rv != KERN_SUCCESS) { - return ENOMEM; + error = ENOMEM; + goto done2; } vm_map_inherit(&p->p_vmspace->vm_map, attach_va, attach_va + size, VM_INHERIT_SHARE); @@ -349,7 +377,9 @@ shmat(p, uap) shmseg->shm_atime = time_second; shmseg->shm_nattch++; p->p_retval[0] = attach_va; - return 0; +done2: + mtx_unlock(&Giant); + return (error); } struct oshmid_ds { @@ -370,27 +400,36 @@ struct oshmctl_args { struct oshmid_ds *ubuf; }; +/* + * MPSAFE + */ static int oshmctl(p, uap) struct proc *p; struct oshmctl_args *uap; { #ifdef COMPAT_43 - int error; + int error = 0; struct shmid_ds *shmseg; struct oshmid_ds outbuf; - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + mtx_lock(&Giant); + + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } shmseg = shm_find_segment_by_shmid(uap->shmid); - if (shmseg == NULL) - return EINVAL; + if (shmseg == NULL) { + error = EINVAL; + goto done2; + } switch (uap->cmd) { case IPC_STAT: error = ipcperm(p, &shmseg->shm_perm, IPC_R); if (error) - return error; + goto done2; outbuf.shm_perm = shmseg->shm_perm; outbuf.shm_segsz = shmseg->shm_segsz; outbuf.shm_cpid = shmseg->shm_cpid; @@ -402,13 +441,16 @@ oshmctl(p, uap) outbuf.shm_handle = shmseg->shm_internal; error = copyout((caddr_t)&outbuf, uap->ubuf, sizeof(outbuf)); if (error) - return error; + goto done2; break; default: /* XXX casting to (sy_call_t *) is bogus, as usual. */ - return ((sy_call_t *)shmctl)(p, uap); + error = ((sy_call_t *)shmctl)(p, uap); + break; } - return 0; +done2: + mtx_unlock(&Giant); + return (error); #else return EINVAL; #endif @@ -422,39 +464,46 @@ struct shmctl_args { }; #endif +/* + * MPSAFE + */ int shmctl(p, uap) struct proc *p; struct shmctl_args *uap; { - int error; + int error = 0; struct shmid_ds inbuf; struct shmid_ds *shmseg; - GIANT_REQUIRED; + mtx_lock(&Giant); - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } shmseg = shm_find_segment_by_shmid(uap->shmid); - if (shmseg == NULL) - return EINVAL; + if (shmseg == NULL) { + error = EINVAL; + goto done2; + } switch (uap->cmd) { case IPC_STAT: error = ipcperm(p, &shmseg->shm_perm, IPC_R); if (error) - return error; + goto done2; error = copyout((caddr_t)shmseg, uap->buf, sizeof(inbuf)); if (error) - return error; + goto done2; break; case IPC_SET: error = ipcperm(p, &shmseg->shm_perm, IPC_M); if (error) - return error; + goto done2; error = copyin(uap->buf, (caddr_t)&inbuf, sizeof(inbuf)); if (error) - return error; + goto done2; shmseg->shm_perm.uid = inbuf.shm_perm.uid; shmseg->shm_perm.gid = inbuf.shm_perm.gid; shmseg->shm_perm.mode = @@ -465,7 +514,7 @@ shmctl(p, uap) case IPC_RMID: error = ipcperm(p, &shmseg->shm_perm, IPC_M); if (error) - return error; + goto done2; shmseg->shm_perm.key = IPC_PRIVATE; shmseg->shm_perm.mode |= SHMSEG_REMOVED; if (shmseg->shm_nattch <= 0) { @@ -478,9 +527,12 @@ shmctl(p, uap) case SHM_UNLOCK: #endif default: - return EINVAL; + error = EINVAL; + break; } - return 0; +done2: + mtx_unlock(&Giant); + return (error); } #ifndef _SYS_SYSPROTO_H_ @@ -607,15 +659,23 @@ shmget_allocate_segment(p, uap, mode) return 0; } +/* + * MPSAFE + */ int shmget(p, uap) struct proc *p; struct shmget_args *uap; { - int segnum, mode, error; + int segnum, mode; + int error; - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + mtx_lock(&Giant); + + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } mode = uap->shmflg & ACCESSPERMS; if (uap->key != IPC_PRIVATE) { @@ -625,14 +685,22 @@ shmget(p, uap) error = shmget_existing(p, uap, mode, segnum); if (error == EAGAIN) goto again; - return error; + goto done2; + } + if ((uap->shmflg & IPC_CREAT) == 0) { + error = ENOENT; + goto done2; } - if ((uap->shmflg & IPC_CREAT) == 0) - return ENOENT; } - return shmget_allocate_segment(p, uap, mode); + error = shmget_allocate_segment(p, uap, mode); +done2: + mtx_unlock(&Giant); + return (error); } +/* + * MPSAFE + */ int shmsys(p, uap) struct proc *p; @@ -644,13 +712,23 @@ shmsys(p, uap) int a4; } */ *uap; { + int error; - if (!jail_sysvipc_allowed && jailed(p->p_ucred)) - return (ENOSYS); + mtx_lock(&Giant); - if (uap->which >= sizeof(shmcalls)/sizeof(shmcalls[0])) - return EINVAL; - return ((*shmcalls[uap->which])(p, &uap->a2)); + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { + error = ENOSYS; + goto done2; + } + + if (uap->which >= sizeof(shmcalls)/sizeof(shmcalls[0])) { + error = EINVAL; + goto done2; + } + error = (*shmcalls[uap->which])(p, &uap->a2); +done2: + mtx_unlock(&Giant); + return (error); } static void |