summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2001-08-31 00:02:18 +0000
committerdillon <dillon@FreeBSD.org>2001-08-31 00:02:18 +0000
commit3f46dfb9c029a45e072dc37f3993ad34b0c049ae (patch)
treec572df73674734906e6a9b3b8daf10e73b61f8aa
parenta12a09cb3fead9dd44d529b10167fc746211181c (diff)
downloadFreeBSD-src-3f46dfb9c029a45e072dc37f3993ad34b0c049ae.zip
FreeBSD-src-3f46dfb9c029a45e072dc37f3993ad34b0c049ae.tar.gz
Giant Pushdown: sysv shm, sem, and msg calls.
-rw-r--r--sys/kern/init_sysent.c30
-rw-r--r--sys/kern/syscalls.master28
-rw-r--r--sys/kern/sysv_msg.c244
-rw-r--r--sys/kern/sysv_sem.c295
-rw-r--r--sys/kern/sysv_shm.c196
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
OpenPOWER on IntegriCloud