Giant Pushdown: sysv shm, sem, and msg calls.

This commit is contained in:
Matthew Dillon 2001-08-31 00:02:18 +00:00
parent f99a696093
commit b6a4b4f9ae
5 changed files with 510 additions and 283 deletions

View File

@ -3,7 +3,7 @@
* *
* DO NOT EDIT-- this file is automatically generated. * DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$ * $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" #include "opt_compat.h"
@ -191,9 +191,9 @@ struct sysent sysent[] = {
{ AS(rtprio_args), (sy_call_t *)rtprio }, /* 166 = rtprio */ { AS(rtprio_args), (sy_call_t *)rtprio }, /* 166 = rtprio */
{ 0, (sy_call_t *)nosys }, /* 167 = nosys */ { 0, (sy_call_t *)nosys }, /* 167 = nosys */
{ 0, (sy_call_t *)nosys }, /* 168 = nosys */ { 0, (sy_call_t *)nosys }, /* 168 = nosys */
{ AS(semsys_args), (sy_call_t *)lkmressys }, /* 169 = semsys */ { SYF_MPSAFE | AS(semsys_args), (sy_call_t *)lkmressys }, /* 169 = semsys */
{ AS(msgsys_args), (sy_call_t *)lkmressys }, /* 170 = msgsys */ { SYF_MPSAFE | AS(msgsys_args), (sy_call_t *)lkmressys }, /* 170 = msgsys */
{ AS(shmsys_args), (sy_call_t *)lkmressys }, /* 171 = shmsys */ { SYF_MPSAFE | AS(shmsys_args), (sy_call_t *)lkmressys }, /* 171 = shmsys */
{ 0, (sy_call_t *)nosys }, /* 172 = nosys */ { 0, (sy_call_t *)nosys }, /* 172 = nosys */
{ AS(pread_args), (sy_call_t *)pread }, /* 173 = pread */ { AS(pread_args), (sy_call_t *)pread }, /* 173 = pread */
{ AS(pwrite_args), (sy_call_t *)pwrite }, /* 174 = pwrite */ { 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 }, /* 217 = lkmnosys */
{ 0, (sy_call_t *)lkmnosys }, /* 218 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 218 = lkmnosys */
{ 0, (sy_call_t *)lkmnosys }, /* 219 = lkmnosys */ { 0, (sy_call_t *)lkmnosys }, /* 219 = lkmnosys */
{ AS(__semctl_args), (sy_call_t *)lkmressys }, /* 220 = __semctl */ { SYF_MPSAFE | AS(__semctl_args), (sy_call_t *)lkmressys }, /* 220 = __semctl */
{ AS(semget_args), (sy_call_t *)lkmressys }, /* 221 = semget */ { SYF_MPSAFE | AS(semget_args), (sy_call_t *)lkmressys }, /* 221 = semget */
{ AS(semop_args), (sy_call_t *)lkmressys }, /* 222 = semop */ { SYF_MPSAFE | AS(semop_args), (sy_call_t *)lkmressys }, /* 222 = semop */
{ 0, (sy_call_t *)nosys }, /* 223 = semconfig */ { 0, (sy_call_t *)nosys }, /* 223 = semconfig */
{ AS(msgctl_args), (sy_call_t *)lkmressys }, /* 224 = msgctl */ { SYF_MPSAFE | AS(msgctl_args), (sy_call_t *)lkmressys }, /* 224 = msgctl */
{ AS(msgget_args), (sy_call_t *)lkmressys }, /* 225 = msgget */ { SYF_MPSAFE | AS(msgget_args), (sy_call_t *)lkmressys }, /* 225 = msgget */
{ AS(msgsnd_args), (sy_call_t *)lkmressys }, /* 226 = msgsnd */ { SYF_MPSAFE | AS(msgsnd_args), (sy_call_t *)lkmressys }, /* 226 = msgsnd */
{ AS(msgrcv_args), (sy_call_t *)lkmressys }, /* 227 = msgrcv */ { SYF_MPSAFE | AS(msgrcv_args), (sy_call_t *)lkmressys }, /* 227 = msgrcv */
{ AS(shmat_args), (sy_call_t *)lkmressys }, /* 228 = shmat */ { SYF_MPSAFE | AS(shmat_args), (sy_call_t *)lkmressys }, /* 228 = shmat */
{ AS(shmctl_args), (sy_call_t *)lkmressys }, /* 229 = shmctl */ { SYF_MPSAFE | AS(shmctl_args), (sy_call_t *)lkmressys }, /* 229 = shmctl */
{ AS(shmdt_args), (sy_call_t *)lkmressys }, /* 230 = shmdt */ { SYF_MPSAFE | AS(shmdt_args), (sy_call_t *)lkmressys }, /* 230 = shmdt */
{ AS(shmget_args), (sy_call_t *)lkmressys }, /* 231 = shmget */ { 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_gettime_args), (sy_call_t *)clock_gettime }, /* 232 = clock_gettime */
{ AS(clock_settime_args), (sy_call_t *)clock_settime }, /* 233 = clock_settime */ { AS(clock_settime_args), (sy_call_t *)clock_settime }, /* 233 = clock_settime */
{ AS(clock_getres_args), (sy_call_t *)clock_getres }, /* 234 = clock_getres */ { AS(clock_getres_args), (sy_call_t *)clock_getres }, /* 234 = clock_getres */

View File

@ -263,15 +263,15 @@
167 UNIMPL NOHIDE nosys 167 UNIMPL NOHIDE nosys
168 UNIMPL NOHIDE nosys 168 UNIMPL NOHIDE nosys
; 169 is initialized by the SYSVSEM code if present or loaded ; 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); } int a5); }
; 169 is initialized by the SYSVMSG code if present or loaded ; 169 is initialized by the SYSVMSG code if present or loaded
; XXX should be { int semsys(int which, ...); } ; 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); } int a5, int a6); }
; 169 is initialized by the SYSVSHM code if present or loaded ; 169 is initialized by the SYSVSHM code if present or loaded
; XXX should be { int msgsys(int which, ...); } ; 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, ...); } ; XXX should be { int shmsys(int which, ...); }
172 UNIMPL NOHIDE nosys 172 UNIMPL NOHIDE nosys
173 STD POSIX { ssize_t pread(int fd, void *buf, size_t nbyte, \ 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 ; The following were introduced with NetBSD/4.4Lite-2
; They are initialized by thier respective modules/sysinits ; 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); } union semun *arg); }
221 NOSTD BSD { int semget(key_t key, int nsems, int semflg); } 221 MNOSTD BSD { int semget(key_t key, int nsems, int semflg); }
222 NOSTD BSD { int semop(int semid, struct sembuf *sops, \ 222 MNOSTD BSD { int semop(int semid, struct sembuf *sops, \
u_int nsops); } u_int nsops); }
223 UNIMPL NOHIDE semconfig 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); } struct msqid_ds *buf); }
225 NOSTD BSD { int msgget(key_t key, int msgflg); } 225 MNOSTD BSD { int msgget(key_t key, int msgflg); }
226 NOSTD BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \ 226 MNOSTD BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \
int msgflg); } 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); } long msgtyp, int msgflg); }
228 NOSTD BSD { int shmat(int shmid, void *shmaddr, int shmflg); } 228 MNOSTD BSD { int shmat(int shmid, void *shmaddr, int shmflg); }
229 NOSTD BSD { int shmctl(int shmid, int cmd, \ 229 MNOSTD BSD { int shmctl(int shmid, int cmd, \
struct shmid_ds *buf); } struct shmid_ds *buf); }
230 NOSTD BSD { int shmdt(void *shmaddr); } 230 MNOSTD BSD { int shmdt(void *shmaddr); }
231 NOSTD BSD { int shmget(key_t key, int size, int shmflg); } 231 MNOSTD BSD { int shmget(key_t key, int size, int shmflg); }
; ;
232 STD POSIX { int clock_gettime(clockid_t clock_id, \ 232 STD POSIX { int clock_gettime(clockid_t clock_id, \
struct timespec *tp); } struct timespec *tp); }

View File

@ -26,6 +26,8 @@
#include <sys/sysproto.h> #include <sys/sysproto.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/msg.h> #include <sys/msg.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/sysent.h> #include <sys/sysent.h>
@ -263,6 +265,8 @@ MODULE_VERSION(sysvmsg, 1);
/* /*
* Entry point for all MSG calls * Entry point for all MSG calls
*
* MPSAFE
*/ */
int int
msgsys(p, uap) msgsys(p, uap)
@ -277,13 +281,22 @@ msgsys(p, uap)
int a6; int a6;
} */ *uap; } */ *uap;
{ {
int error;
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) mtx_lock(&Giant);
return (ENOSYS);
if (uap->which >= sizeof(msgcalls)/sizeof(msgcalls[0])) if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
return (EINVAL); error = ENOSYS;
return ((*msgcalls[uap->which])(p, &uap->a2)); 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 static void
@ -318,6 +331,9 @@ struct msgctl_args {
}; };
#endif #endif
/*
* MPSAFE
*/
int int
msgctl(p, uap) msgctl(p, uap)
struct proc *p; struct proc *p;
@ -326,16 +342,19 @@ msgctl(p, uap)
int msqid = uap->msqid; int msqid = uap->msqid;
int cmd = uap->cmd; int cmd = uap->cmd;
struct msqid_ds *user_msqptr = uap->buf; struct msqid_ds *user_msqptr = uap->buf;
int rval, eval; int rval, error;
struct msqid_ds msqbuf; struct msqid_ds msqbuf;
register struct msqid_ds *msqptr; register struct msqid_ds *msqptr;
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr); printf("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr);
#endif #endif
mtx_lock(&Giant);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
return (ENOSYS); error = ENOSYS;
goto done2;
}
msqid = IPCID_TO_IX(msqid); msqid = IPCID_TO_IX(msqid);
@ -344,7 +363,8 @@ msgctl(p, uap)
printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid,
msginfo.msgmni); msginfo.msgmni);
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
msqptr = &msqids[msqid]; msqptr = &msqids[msqid];
@ -353,16 +373,18 @@ msgctl(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("no such msqid\n"); printf("no such msqid\n");
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("wrong sequence number\n"); printf("wrong sequence number\n");
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
eval = 0; error = 0;
rval = 0; rval = 0;
switch (cmd) { switch (cmd) {
@ -370,8 +392,8 @@ msgctl(p, uap)
case IPC_RMID: case IPC_RMID:
{ {
struct msg *msghdr; struct msg *msghdr;
if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_M))) if ((error = ipcperm(p, &msqptr->msg_perm, IPC_M)))
return(eval); goto done2;
/* Free the message headers */ /* Free the message headers */
msghdr = msqptr->msg_first; msghdr = msqptr->msg_first;
while (msghdr != NULL) { while (msghdr != NULL) {
@ -398,14 +420,14 @@ msgctl(p, uap)
break; break;
case IPC_SET: case IPC_SET:
if ((eval = ipcperm(p, &msqptr->msg_perm, IPC_M))) if ((error = ipcperm(p, &msqptr->msg_perm, IPC_M)))
return(eval); goto done2;
if ((eval = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0) if ((error = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0)
return(eval); goto done2;
if (msqbuf.msg_qbytes > msqptr->msg_qbytes) { if (msqbuf.msg_qbytes > msqptr->msg_qbytes) {
eval = suser(p); error = suser(p);
if (eval) if (error)
return(eval); goto done2;
} }
if (msqbuf.msg_qbytes > msginfo.msgmnb) { if (msqbuf.msg_qbytes > msginfo.msgmnb) {
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
@ -418,7 +440,8 @@ msgctl(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("can't reduce msg_qbytes to 0\n"); printf("can't reduce msg_qbytes to 0\n");
#endif #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.uid = msqbuf.msg_perm.uid; /* change the owner */
msqptr->msg_perm.gid = msqbuf.msg_perm.gid; /* change the owner */ msqptr->msg_perm.gid = msqbuf.msg_perm.gid; /* change the owner */
@ -429,13 +452,13 @@ msgctl(p, uap)
break; break;
case IPC_STAT: 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 #ifdef MSG_DEBUG_OK
printf("requester doesn't have read access\n"); printf("requester doesn't have read access\n");
#endif #endif
return(eval); goto done2;
} }
eval = copyout((caddr_t)msqptr, user_msqptr, error = copyout((caddr_t)msqptr, user_msqptr,
sizeof(struct msqid_ds)); sizeof(struct msqid_ds));
break; break;
@ -443,12 +466,15 @@ msgctl(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("invalid command %d\n", cmd); printf("invalid command %d\n", cmd);
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
if (eval == 0) if (error == 0)
p->p_retval[0] = rval; p->p_retval[0] = rval;
return(eval); done2:
mtx_unlock(&Giant);
return(error);
} }
#ifndef _SYS_SYSPROTO_H_ #ifndef _SYS_SYSPROTO_H_
@ -458,12 +484,15 @@ struct msgget_args {
}; };
#endif #endif
/*
* MPSAFE
*/
int int
msgget(p, uap) msgget(p, uap)
struct proc *p; struct proc *p;
register struct msgget_args *uap; register struct msgget_args *uap;
{ {
int msqid, eval; int msqid, error = 0;
int key = uap->key; int key = uap->key;
int msgflg = uap->msgflg; int msgflg = uap->msgflg;
struct ucred *cred = p->p_ucred; struct ucred *cred = p->p_ucred;
@ -473,8 +502,12 @@ msgget(p, uap)
printf("msgget(0x%x, 0%o)\n", key, msgflg); printf("msgget(0x%x, 0%o)\n", key, msgflg);
#endif #endif
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) mtx_lock(&Giant);
return (ENOSYS);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
error = ENOSYS;
goto done2;
}
if (key != IPC_PRIVATE) { if (key != IPC_PRIVATE) {
for (msqid = 0; msqid < msginfo.msgmni; msqid++) { for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
@ -491,14 +524,15 @@ msgget(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("not exclusive\n"); printf("not exclusive\n");
#endif #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 #ifdef MSG_DEBUG_OK
printf("requester doesn't have 0%o access\n", printf("requester doesn't have 0%o access\n",
msgflg & 0700); msgflg & 0700);
#endif #endif
return(eval); goto done2;
} }
goto found; goto found;
} }
@ -524,7 +558,8 @@ msgget(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("no more msqid_ds's available\n"); printf("no more msqid_ds's available\n");
#endif #endif
return(ENOSPC); error = ENOSPC;
goto done2;
} }
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("msqid %d is available\n", msqid); printf("msqid %d is available\n", msqid);
@ -551,13 +586,16 @@ msgget(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("didn't find it and wasn't asked to create it\n"); printf("didn't find it and wasn't asked to create it\n");
#endif #endif
return(ENOENT); error = ENOENT;
goto done2;
} }
found: found:
/* Construct the unique msqid */ /* Construct the unique msqid */
p->p_retval[0] = IXSEQ_TO_IPCID(msqid, msqptr->msg_perm); p->p_retval[0] = IXSEQ_TO_IPCID(msqid, msqptr->msg_perm);
return(0); done2:
mtx_unlock(&Giant);
return (error);
} }
#ifndef _SYS_SYSPROTO_H_ #ifndef _SYS_SYSPROTO_H_
@ -569,6 +607,9 @@ struct msgsnd_args {
}; };
#endif #endif
/*
* MPSAFE
*/
int int
msgsnd(p, uap) msgsnd(p, uap)
struct proc *p; struct proc *p;
@ -578,7 +619,7 @@ msgsnd(p, uap)
void *user_msgp = uap->msgp; void *user_msgp = uap->msgp;
size_t msgsz = uap->msgsz; size_t msgsz = uap->msgsz;
int msgflg = uap->msgflg; int msgflg = uap->msgflg;
int segs_needed, eval; int segs_needed, error = 0;
register struct msqid_ds *msqptr; register struct msqid_ds *msqptr;
register struct msg *msghdr; register struct msg *msghdr;
short next; short next;
@ -587,9 +628,12 @@ msgsnd(p, uap)
printf("call to msgsnd(%d, 0x%x, %d, %d)\n", msqid, user_msgp, msgsz, printf("call to msgsnd(%d, 0x%x, %d, %d)\n", msqid, user_msgp, msgsz,
msgflg); msgflg);
#endif #endif
mtx_lock(&Giant);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
return (ENOSYS); error = ENOSYS;
goto done2;
}
msqid = IPCID_TO_IX(msqid); msqid = IPCID_TO_IX(msqid);
@ -598,7 +642,8 @@ msgsnd(p, uap)
printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid,
msginfo.msgmni); msginfo.msgmni);
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
msqptr = &msqids[msqid]; msqptr = &msqids[msqid];
@ -606,20 +651,22 @@ msgsnd(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("no such message queue id\n"); printf("no such message queue id\n");
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("wrong sequence number\n"); printf("wrong sequence number\n");
#endif #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 #ifdef MSG_DEBUG_OK
printf("requester doesn't have write access\n"); printf("requester doesn't have write access\n");
#endif #endif
return(eval); goto done2;
} }
segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz; segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz;
@ -639,7 +686,8 @@ msgsnd(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("msgsz > msqptr->msg_qbytes\n"); printf("msgsz > msqptr->msg_qbytes\n");
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
if (msqptr->msg_perm.mode & MSG_LOCKED) { if (msqptr->msg_perm.mode & MSG_LOCKED) {
@ -674,7 +722,8 @@ msgsnd(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("need more resources but caller doesn't want to wait\n"); printf("need more resources but caller doesn't want to wait\n");
#endif #endif
return(EAGAIN); error = EAGAIN;
goto done2;
} }
if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0) { if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0) {
@ -694,18 +743,19 @@ msgsnd(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("goodnight\n"); printf("goodnight\n");
#endif #endif
eval = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH, error = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH,
"msgwait", 0); "msgwait", 0);
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("good morning, eval=%d\n", eval); printf("good morning, error=%d\n", error);
#endif #endif
if (we_own_it) if (we_own_it)
msqptr->msg_perm.mode &= ~MSG_LOCKED; msqptr->msg_perm.mode &= ~MSG_LOCKED;
if (eval != 0) { if (error != 0) {
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("msgsnd: interrupted system call\n"); printf("msgsnd: interrupted system call\n");
#endif #endif
return(EINTR); error = EINTR;
goto done2;
} }
/* /*
@ -716,7 +766,8 @@ msgsnd(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("msqid deleted\n"); printf("msqid deleted\n");
#endif #endif
return(EIDRM); error = EIDRM;
goto done2;
} }
} else { } else {
@ -787,15 +838,15 @@ msgsnd(p, uap)
* Copy in the message type * 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) { sizeof(msghdr->msg_type))) != 0) {
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("error %d copying the message type\n", eval); printf("error %d copying the message type\n", error);
#endif #endif
msg_freehdr(msghdr); msg_freehdr(msghdr);
msqptr->msg_perm.mode &= ~MSG_LOCKED; msqptr->msg_perm.mode &= ~MSG_LOCKED;
wakeup((caddr_t)msqptr); wakeup((caddr_t)msqptr);
return(eval); goto done2;
} }
user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type); user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type);
@ -810,7 +861,8 @@ msgsnd(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("mtype (%d) < 1\n", msghdr->msg_type); printf("mtype (%d) < 1\n", msghdr->msg_type);
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
/* /*
@ -828,15 +880,15 @@ msgsnd(p, uap)
panic("next too low #2"); panic("next too low #2");
if (next >= msginfo.msgseg) if (next >= msginfo.msgseg)
panic("next out of range #2"); 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) { tlen)) != 0) {
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("error %d copying in message segment\n", eval); printf("error %d copying in message segment\n", error);
#endif #endif
msg_freehdr(msghdr); msg_freehdr(msghdr);
msqptr->msg_perm.mode &= ~MSG_LOCKED; msqptr->msg_perm.mode &= ~MSG_LOCKED;
wakeup((caddr_t)msqptr); wakeup((caddr_t)msqptr);
return(eval); goto done2;
} }
msgsz -= tlen; msgsz -= tlen;
user_msgp = (char *)user_msgp + tlen; user_msgp = (char *)user_msgp + tlen;
@ -858,7 +910,8 @@ msgsnd(p, uap)
if (msqptr->msg_qbytes == 0) { if (msqptr->msg_qbytes == 0) {
msg_freehdr(msghdr); msg_freehdr(msghdr);
wakeup((caddr_t)msqptr); wakeup((caddr_t)msqptr);
return(EIDRM); error = EIDRM;
goto done2;
} }
/* /*
@ -881,7 +934,9 @@ msgsnd(p, uap)
wakeup((caddr_t)msqptr); wakeup((caddr_t)msqptr);
p->p_retval[0] = 0; p->p_retval[0] = 0;
return(0); done2:
mtx_unlock(&Giant);
return (error);
} }
#ifndef _SYS_SYSPROTO_H_ #ifndef _SYS_SYSPROTO_H_
@ -894,6 +949,9 @@ struct msgrcv_args {
}; };
#endif #endif
/*
* MPSAFE
*/
int int
msgrcv(p, uap) msgrcv(p, uap)
struct proc *p; struct proc *p;
@ -907,7 +965,7 @@ msgrcv(p, uap)
size_t len; size_t len;
register struct msqid_ds *msqptr; register struct msqid_ds *msqptr;
register struct msg *msghdr; register struct msg *msghdr;
int eval; int error = 0;
short next; short next;
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
@ -915,8 +973,12 @@ msgrcv(p, uap)
msgsz, msgtyp, msgflg); msgsz, msgtyp, msgflg);
#endif #endif
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) mtx_lock(&Giant);
return (ENOSYS);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
error = ENOSYS;
goto done2;
}
msqid = IPCID_TO_IX(msqid); msqid = IPCID_TO_IX(msqid);
@ -925,7 +987,8 @@ msgrcv(p, uap)
printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid,
msginfo.msgmni); msginfo.msgmni);
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
msqptr = &msqids[msqid]; msqptr = &msqids[msqid];
@ -933,20 +996,22 @@ msgrcv(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("no such message queue id\n"); printf("no such message queue id\n");
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("wrong sequence number\n"); printf("wrong sequence number\n");
#endif #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 #ifdef MSG_DEBUG_OK
printf("requester doesn't have read access\n"); printf("requester doesn't have read access\n");
#endif #endif
return(eval); goto done2;
} }
msghdr = NULL; msghdr = NULL;
@ -960,7 +1025,8 @@ msgrcv(p, uap)
printf("first message on the queue is too big (want %d, got %d)\n", printf("first message on the queue is too big (want %d, got %d)\n",
msgsz, msghdr->msg_ts); msgsz, msghdr->msg_ts);
#endif #endif
return(E2BIG); error = E2BIG;
goto done2;
} }
if (msqptr->msg_first == msqptr->msg_last) { if (msqptr->msg_first == msqptr->msg_last) {
msqptr->msg_first = NULL; 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", printf("requested message on the queue is too big (want %d, got %d)\n",
msgsz, msghdr->msg_ts); msgsz, msghdr->msg_ts);
#endif #endif
return(E2BIG); error = E2BIG;
goto done2;
} }
*prev = msghdr->msg_next; *prev = msghdr->msg_next;
if (msghdr == msqptr->msg_last) { if (msghdr == msqptr->msg_last) {
@ -1045,7 +1112,8 @@ msgrcv(p, uap)
msgtyp); msgtyp);
#endif #endif
/* The SVID says to return ENOMSG. */ /* The SVID says to return ENOMSG. */
return(ENOMSG); error = ENOMSG;
goto done2;
} }
/* /*
@ -1055,17 +1123,18 @@ msgrcv(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("msgrcv: goodnight\n"); printf("msgrcv: goodnight\n");
#endif #endif
eval = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH, "msgwait", error = tsleep((caddr_t)msqptr, (PZERO - 4) | PCATCH, "msgwait",
0); 0);
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("msgrcv: good morning (eval=%d)\n", eval); printf("msgrcv: good morning (error=%d)\n", error);
#endif #endif
if (eval != 0) { if (error != 0) {
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("msgsnd: interrupted system call\n"); printf("msgsnd: interrupted system call\n");
#endif #endif
return(EINTR); error = EINTR;
goto done2;
} }
/* /*
@ -1077,7 +1146,8 @@ msgrcv(p, uap)
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("msqid deleted\n"); printf("msqid deleted\n");
#endif #endif
return(EIDRM); error = EIDRM;
goto done2;
} }
} }
@ -1109,15 +1179,15 @@ msgrcv(p, uap)
* Return the type to the user. * 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)); sizeof(msghdr->msg_type));
if (eval != 0) { if (error != 0) {
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("error (%d) copying out message type\n", eval); printf("error (%d) copying out message type\n", error);
#endif #endif
msg_freehdr(msghdr); msg_freehdr(msghdr);
wakeup((caddr_t)msqptr); wakeup((caddr_t)msqptr);
return(eval); goto done2;
} }
user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type); user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type);
@ -1137,16 +1207,16 @@ msgrcv(p, uap)
panic("next too low #3"); panic("next too low #3");
if (next >= msginfo.msgseg) if (next >= msginfo.msgseg)
panic("next out of range #3"); 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); user_msgp, tlen);
if (eval != 0) { if (error != 0) {
#ifdef MSG_DEBUG_OK #ifdef MSG_DEBUG_OK
printf("error (%d) copying out message segment\n", printf("error (%d) copying out message segment\n",
eval); error);
#endif #endif
msg_freehdr(msghdr); msg_freehdr(msghdr);
wakeup((caddr_t)msqptr); wakeup((caddr_t)msqptr);
return(eval); goto done2;
} }
user_msgp = (char *)user_msgp + tlen; user_msgp = (char *)user_msgp + tlen;
next = msgmaps[next].next; next = msgmaps[next].next;
@ -1159,7 +1229,9 @@ msgrcv(p, uap)
msg_freehdr(msghdr); msg_freehdr(msghdr);
wakeup((caddr_t)msqptr); wakeup((caddr_t)msqptr);
p->p_retval[0] = msgsz; p->p_retval[0] = msgsz;
return(0); done2:
mtx_unlock(&Giant);
return (error);
} }
static int static int

View File

@ -15,6 +15,8 @@
#include <sys/sysproto.h> #include <sys/sysproto.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/proc.h> #include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sem.h> #include <sys/sem.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/sysent.h> #include <sys/sysent.h>
@ -244,6 +246,8 @@ MODULE_VERSION(sysvsem, 1);
/* /*
* Entry point for all SEM calls * Entry point for all SEM calls
*
* MPSAFE
*/ */
int int
semsys(p, uap) semsys(p, uap)
@ -257,13 +261,23 @@ semsys(p, uap)
int a5; int a5;
} */ *uap; } */ *uap;
{ {
int error;
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) mtx_lock(&Giant);
return (ENOSYS);
if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0])) if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
return (EINVAL); error = ENOSYS;
return ((*semcalls[uap->which])(p, &uap->a2)); goto done2;
}
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 #endif
/*
* MPSAFE
*/
int int
__semctl(p, uap) __semctl(p, uap)
struct proc *p; struct proc *p;
@ -459,33 +476,40 @@ __semctl(p, uap)
union semun *arg = uap->arg; union semun *arg = uap->arg;
union semun real_arg; union semun real_arg;
struct ucred *cred = p->p_ucred; struct ucred *cred = p->p_ucred;
int i, rval, eval; int i, rval, error;
struct semid_ds sbuf; struct semid_ds sbuf;
register struct semid_ds *semaptr; register struct semid_ds *semaptr;
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("call to semctl(%d, %d, %d, 0x%x)\n", semid, semnum, cmd, arg); printf("call to semctl(%d, %d, %d, 0x%x)\n", semid, semnum, cmd, arg);
#endif #endif
mtx_lock(&Giant);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
return (ENOSYS); error = ENOSYS;
goto done2;
}
semid = IPCID_TO_IX(semid); semid = IPCID_TO_IX(semid);
if (semid < 0 || semid >= seminfo.semmsl) if (semid < 0 || semid >= seminfo.semmsl) {
return(EINVAL); error = EINVAL;
goto done2;
}
semaptr = &sema[semid]; semaptr = &sema[semid];
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 || if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
return(EINVAL); error = EINVAL;
goto done2;
}
eval = 0; error = 0;
rval = 0; rval = 0;
switch (cmd) { switch (cmd) {
case IPC_RMID: case IPC_RMID:
if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_M))) if ((error = ipcperm(p, &semaptr->sem_perm, IPC_M)))
return(eval); goto done2;
semaptr->sem_perm.cuid = cred->cr_uid; semaptr->sem_perm.cuid = cred->cr_uid;
semaptr->sem_perm.uid = cred->cr_uid; semaptr->sem_perm.uid = cred->cr_uid;
semtot -= semaptr->sem_nsems; semtot -= semaptr->sem_nsems;
@ -502,13 +526,14 @@ __semctl(p, uap)
break; break;
case IPC_SET: case IPC_SET:
if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_M))) if ((error = ipcperm(p, &semaptr->sem_perm, IPC_M)))
return(eval); goto done2;
if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
return(eval); goto done2;
if ((eval = copyin(real_arg.buf, (caddr_t)&sbuf, if ((error = copyin(real_arg.buf, (caddr_t)&sbuf,
sizeof(sbuf))) != 0) sizeof(sbuf))) != 0) {
return(eval); goto done2;
}
semaptr->sem_perm.uid = sbuf.sem_perm.uid; semaptr->sem_perm.uid = sbuf.sem_perm.uid;
semaptr->sem_perm.gid = sbuf.sem_perm.gid; semaptr->sem_perm.gid = sbuf.sem_perm.gid;
semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) | semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) |
@ -517,81 +542,91 @@ __semctl(p, uap)
break; break;
case IPC_STAT: case IPC_STAT:
if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
return(eval); goto done2;
if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
return(eval); goto done2;
eval = copyout((caddr_t)semaptr, real_arg.buf, error = copyout((caddr_t)semaptr, real_arg.buf,
sizeof(struct semid_ds)); sizeof(struct semid_ds));
break; break;
case GETNCNT: case GETNCNT:
if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
return(eval); goto done2;
if (semnum < 0 || semnum >= semaptr->sem_nsems) if (semnum < 0 || semnum >= semaptr->sem_nsems) {
return(EINVAL); error = EINVAL;
goto done2;
}
rval = semaptr->sem_base[semnum].semncnt; rval = semaptr->sem_base[semnum].semncnt;
break; break;
case GETPID: case GETPID:
if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
return(eval); goto done2;
if (semnum < 0 || semnum >= semaptr->sem_nsems) if (semnum < 0 || semnum >= semaptr->sem_nsems) {
return(EINVAL); error = EINVAL;
goto done2;
}
rval = semaptr->sem_base[semnum].sempid; rval = semaptr->sem_base[semnum].sempid;
break; break;
case GETVAL: case GETVAL:
if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
return(eval); goto done2;
if (semnum < 0 || semnum >= semaptr->sem_nsems) if (semnum < 0 || semnum >= semaptr->sem_nsems) {
return(EINVAL); error = EINVAL;
goto done2;
}
rval = semaptr->sem_base[semnum].semval; rval = semaptr->sem_base[semnum].semval;
break; break;
case GETALL: case GETALL:
if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
return(eval); goto done2;
if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
return(eval); goto done2;
for (i = 0; i < semaptr->sem_nsems; i++) { 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])); &real_arg.array[i], sizeof(real_arg.array[0]));
if (eval != 0) if (error != 0)
break; break;
} }
break; break;
case GETZCNT: case GETZCNT:
if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_R))) if ((error = ipcperm(p, &semaptr->sem_perm, IPC_R)))
return(eval); goto done2;
if (semnum < 0 || semnum >= semaptr->sem_nsems) if (semnum < 0 || semnum >= semaptr->sem_nsems) {
return(EINVAL); error = EINVAL;
goto done2;
}
rval = semaptr->sem_base[semnum].semzcnt; rval = semaptr->sem_base[semnum].semzcnt;
break; break;
case SETVAL: case SETVAL:
if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_W))) if ((error = ipcperm(p, &semaptr->sem_perm, IPC_W)))
return(eval); goto done2;
if (semnum < 0 || semnum >= semaptr->sem_nsems) if (semnum < 0 || semnum >= semaptr->sem_nsems) {
return(EINVAL); error = EINVAL;
if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) goto done2;
return(eval); }
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
goto done2;
semaptr->sem_base[semnum].semval = real_arg.val; semaptr->sem_base[semnum].semval = real_arg.val;
semundo_clear(semid, semnum); semundo_clear(semid, semnum);
wakeup((caddr_t)semaptr); wakeup((caddr_t)semaptr);
break; break;
case SETALL: case SETALL:
if ((eval = ipcperm(p, &semaptr->sem_perm, IPC_W))) if ((error = ipcperm(p, &semaptr->sem_perm, IPC_W)))
return(eval); goto done2;
if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
return(eval); goto done2;
for (i = 0; i < semaptr->sem_nsems; i++) { 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, (caddr_t)&semaptr->sem_base[i].semval,
sizeof(real_arg.array[0])); sizeof(real_arg.array[0]));
if (eval != 0) if (error != 0)
break; break;
} }
semundo_clear(semid, -1); semundo_clear(semid, -1);
@ -599,12 +634,15 @@ __semctl(p, uap)
break; break;
default: default:
return(EINVAL); error = EINVAL;
break;
} }
if (eval == 0) if (error == 0)
p->p_retval[0] = rval; p->p_retval[0] = rval;
return(eval); done2:
mtx_unlock(&Giant);
return(error);
} }
#ifndef _SYS_SYSPROTO_H_ #ifndef _SYS_SYSPROTO_H_
@ -615,12 +653,15 @@ struct semget_args {
}; };
#endif #endif
/*
* MPSAFE
*/
int int
semget(p, uap) semget(p, uap)
struct proc *p; struct proc *p;
register struct semget_args *uap; register struct semget_args *uap;
{ {
int semid, eval; int semid, error = 0;
int key = uap->key; int key = uap->key;
int nsems = uap->nsems; int nsems = uap->nsems;
int semflg = uap->semflg; int semflg = uap->semflg;
@ -629,9 +670,12 @@ semget(p, uap)
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("semget(0x%x, %d, 0%o)\n", key, nsems, semflg); printf("semget(0x%x, %d, 0%o)\n", key, nsems, semflg);
#endif #endif
mtx_lock(&Giant);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
return (ENOSYS); error = ENOSYS;
goto done2;
}
if (key != IPC_PRIVATE) { if (key != IPC_PRIVATE) {
for (semid = 0; semid < seminfo.semmni; semid++) { for (semid = 0; semid < seminfo.semmni; semid++) {
@ -643,20 +687,23 @@ semget(p, uap)
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("found public key\n"); printf("found public key\n");
#endif #endif
if ((eval = ipcperm(p, &sema[semid].sem_perm, if ((error = ipcperm(p, &sema[semid].sem_perm,
semflg & 0700))) semflg & 0700))) {
return(eval); goto done2;
}
if (nsems > 0 && sema[semid].sem_nsems < nsems) { if (nsems > 0 && sema[semid].sem_nsems < nsems) {
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("too small\n"); printf("too small\n");
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) { if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("not exclusive\n"); printf("not exclusive\n");
#endif #endif
return(EEXIST); error = EEXIST;
goto done2;
} }
goto found; goto found;
} }
@ -671,14 +718,16 @@ semget(p, uap)
printf("nsems out of range (0<%d<=%d)\n", nsems, printf("nsems out of range (0<%d<=%d)\n", nsems,
seminfo.semmsl); seminfo.semmsl);
#endif #endif
return(EINVAL); error = EINVAL;
goto done2;
} }
if (nsems > seminfo.semmns - semtot) { if (nsems > seminfo.semmns - semtot) {
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("not enough semaphores left (need %d, got %d)\n", printf("not enough semaphores left (need %d, got %d)\n",
nsems, seminfo.semmns - semtot); nsems, seminfo.semmns - semtot);
#endif #endif
return(ENOSPC); error = ENOSPC;
goto done2;
} }
for (semid = 0; semid < seminfo.semmni; semid++) { for (semid = 0; semid < seminfo.semmni; semid++) {
if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0) if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0)
@ -688,7 +737,8 @@ semget(p, uap)
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("no more semid_ds's available\n"); printf("no more semid_ds's available\n");
#endif #endif
return(ENOSPC); error = ENOSPC;
goto done2;
} }
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("semid %d is available\n", semid); printf("semid %d is available\n", semid);
@ -716,12 +766,15 @@ semget(p, uap)
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("didn't find it and wasn't asked to create it\n"); printf("didn't find it and wasn't asked to create it\n");
#endif #endif
return(ENOENT); error = ENOENT;
goto done2;
} }
found: found:
p->p_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm); p->p_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm);
return(0); done2:
mtx_unlock(&Giant);
return (error);
} }
#ifndef _SYS_SYSPROTO_H_ #ifndef _SYS_SYSPROTO_H_
@ -732,6 +785,9 @@ struct semop_args {
}; };
#endif #endif
/*
* MPSAFE
*/
int int
semop(p, uap) semop(p, uap)
struct proc *p; struct proc *p;
@ -744,47 +800,58 @@ semop(p, uap)
register struct sembuf *sopptr; register struct sembuf *sopptr;
register struct sem *semptr; register struct sem *semptr;
struct sem_undo *suptr = NULL; struct sem_undo *suptr = NULL;
int i, j, eval; int i, j, error = 0;
int do_wakeup, do_undos; int do_wakeup, do_undos;
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("call to semop(%d, 0x%x, %d)\n", semid, sops, nsops); printf("call to semop(%d, 0x%x, %d)\n", semid, sops, nsops);
#endif #endif
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) mtx_lock(&Giant);
return (ENOSYS);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
error = ENOSYS;
goto done2;
}
semid = IPCID_TO_IX(semid); /* Convert back to zero origin */ semid = IPCID_TO_IX(semid); /* Convert back to zero origin */
if (semid < 0 || semid >= seminfo.semmsl) if (semid < 0 || semid >= seminfo.semmsl) {
return(EINVAL); error = EINVAL;
goto done2;
}
semaptr = &sema[semid]; semaptr = &sema[semid];
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) {
return(EINVAL); error = EINVAL;
if (semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) goto done2;
return(EINVAL); }
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 #ifdef SEM_DEBUG
printf("eval = %d from ipaccess\n", eval); printf("error = %d from ipaccess\n", error);
#endif #endif
return(eval); goto done2;
} }
if (nsops > MAX_SOPS) { if (nsops > MAX_SOPS) {
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("too many sops (max=%d, nsops=%d)\n", MAX_SOPS, nsops); printf("too many sops (max=%d, nsops=%d)\n", MAX_SOPS, nsops);
#endif #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 #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])); uap->sops, &sops, nsops * sizeof(sops[0]));
#endif #endif
return(eval); goto done2;
} }
/* /*
@ -804,8 +871,10 @@ semop(p, uap)
for (i = 0; i < nsops; i++) { for (i = 0; i < nsops; i++) {
sopptr = &sops[i]; sopptr = &sops[i];
if (sopptr->sem_num >= semaptr->sem_nsems) if (sopptr->sem_num >= semaptr->sem_nsems) {
return(EFBIG); error = EFBIG;
goto done2;
}
semptr = &semaptr->sem_base[sopptr->sem_num]; semptr = &semaptr->sem_base[sopptr->sem_num];
@ -866,8 +935,10 @@ semop(p, uap)
* If the request that we couldn't satisfy has the * If the request that we couldn't satisfy has the
* NOWAIT flag set then return with EAGAIN. * NOWAIT flag set then return with EAGAIN.
*/ */
if (sopptr->sem_flg & IPC_NOWAIT) if (sopptr->sem_flg & IPC_NOWAIT) {
return(EAGAIN); error = EAGAIN;
goto done2;
}
if (sopptr->sem_op == 0) if (sopptr->sem_op == 0)
semptr->semzcnt++; semptr->semzcnt++;
@ -877,16 +948,18 @@ semop(p, uap)
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("semop: good night!\n"); printf("semop: good night!\n");
#endif #endif
eval = tsleep((caddr_t)semaptr, (PZERO - 4) | PCATCH, error = tsleep((caddr_t)semaptr, (PZERO - 4) | PCATCH,
"semwait", 0); "semwait", 0);
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("semop: good morning (eval=%d)!\n", eval); printf("semop: good morning (error=%d)!\n", error);
#endif #endif
suptr = NULL; /* sem_undo may have been reallocated */ suptr = NULL; /* sem_undo may have been reallocated */
if (eval != 0) if (error != 0) {
return(EINTR); error = EINTR;
goto done2;
}
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("semop: good morning!\n"); printf("semop: good morning!\n");
#endif #endif
@ -895,8 +968,10 @@ semop(p, uap)
* Make sure that the semaphore still exists * Make sure that the semaphore still exists
*/ */
if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 || if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ||
semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) {
return(EIDRM); error = EIDRM;
goto done2;
}
/* /*
* The semaphore is still alive. Readjust the count of * The semaphore is still alive. Readjust the count of
@ -925,9 +1000,9 @@ done:
adjval = sops[i].sem_op; adjval = sops[i].sem_op;
if (adjval == 0) if (adjval == 0)
continue; continue;
eval = semundo_adjust(p, &suptr, semid, error = semundo_adjust(p, &suptr, semid,
sops[i].sem_num, -adjval); sops[i].sem_num, -adjval);
if (eval == 0) if (error == 0)
continue; continue;
/* /*
@ -955,9 +1030,9 @@ done:
sops[j].sem_op; sops[j].sem_op;
#ifdef SEM_DEBUG #ifdef SEM_DEBUG
printf("eval = %d from semundo_adjust\n", eval); printf("error = %d from semundo_adjust\n", error);
#endif #endif
return(eval); goto done2;
} /* loop through the sops */ } /* loop through the sops */
} /* if (do_undos) */ } /* if (do_undos) */
@ -982,7 +1057,9 @@ done:
printf("semop: done\n"); printf("semop: done\n");
#endif #endif
p->p_retval[0] = 0; p->p_retval[0] = 0;
return(0); done2:
mtx_unlock(&Giant);
return (error);
} }
/* /*

View File

@ -233,6 +233,9 @@ struct shmdt_args {
}; };
#endif #endif
/*
* MPSAFE
*/
int int
shmdt(p, uap) shmdt(p, uap)
struct proc *p; struct proc *p;
@ -240,22 +243,34 @@ shmdt(p, uap)
{ {
struct shmmap_state *shmmap_s; struct shmmap_state *shmmap_s;
int i; int i;
int error; int error = 0;
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) mtx_lock(&Giant);
return (ENOSYS);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
error = ENOSYS;
goto done2;
}
shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm;
if (shmmap_s == NULL) if (shmmap_s == NULL) {
return EINVAL; error = EINVAL;
for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) goto done2;
}
for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) {
if (shmmap_s->shmid != -1 && if (shmmap_s->shmid != -1 &&
shmmap_s->va == (vm_offset_t)uap->shmaddr) shmmap_s->va == (vm_offset_t)uap->shmaddr) {
break; break;
if (i == shminfo.shmseg) }
return EINVAL; }
if (i == shminfo.shmseg) {
error = EINVAL;
goto done2;
}
error = shm_delete_mapping(p, shmmap_s); error = shm_delete_mapping(p, shmmap_s);
return error; done2:
mtx_unlock(&Giant);
return (error);
} }
#ifndef _SYS_SYSPROTO_H_ #ifndef _SYS_SYSPROTO_H_
@ -266,12 +281,15 @@ struct shmat_args {
}; };
#endif #endif
/*
* MPSAFE
*/
int int
shmat(p, uap) shmat(p, uap)
struct proc *p; struct proc *p;
struct shmat_args *uap; struct shmat_args *uap;
{ {
int error, i, flags; int i, flags;
struct shmid_ds *shmseg; struct shmid_ds *shmseg;
struct shmmap_state *shmmap_s = NULL; struct shmmap_state *shmmap_s = NULL;
struct shm_handle *shm_handle; struct shm_handle *shm_handle;
@ -279,11 +297,14 @@ shmat(p, uap)
vm_prot_t prot; vm_prot_t prot;
vm_size_t size; vm_size_t size;
int rv; int rv;
int error = 0;
GIANT_REQUIRED; mtx_lock(&Giant);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
return (ENOSYS); error = ENOSYS;
goto done2;
}
shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm;
if (shmmap_s == NULL) { if (shmmap_s == NULL) {
@ -294,19 +315,23 @@ shmat(p, uap)
p->p_vmspace->vm_shm = (caddr_t)shmmap_s; p->p_vmspace->vm_shm = (caddr_t)shmmap_s;
} }
shmseg = shm_find_segment_by_shmid(uap->shmid); shmseg = shm_find_segment_by_shmid(uap->shmid);
if (shmseg == NULL) if (shmseg == NULL) {
return EINVAL; error = EINVAL;
goto done2;
}
error = ipcperm(p, &shmseg->shm_perm, error = ipcperm(p, &shmseg->shm_perm,
(uap->shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); (uap->shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
if (error) if (error)
return error; goto done2;
for (i = 0; i < shminfo.shmseg; i++) { for (i = 0; i < shminfo.shmseg; i++) {
if (shmmap_s->shmid == -1) if (shmmap_s->shmid == -1)
break; break;
shmmap_s++; shmmap_s++;
} }
if (i >= shminfo.shmseg) if (i >= shminfo.shmseg) {
return EMFILE; error = EMFILE;
goto done2;
}
size = round_page(shmseg->shm_segsz); size = round_page(shmseg->shm_segsz);
#ifdef VM_PROT_READ_IS_EXEC #ifdef VM_PROT_READ_IS_EXEC
prot = VM_PROT_READ | VM_PROT_EXECUTE; prot = VM_PROT_READ | VM_PROT_EXECUTE;
@ -318,12 +343,14 @@ shmat(p, uap)
flags = MAP_ANON | MAP_SHARED; flags = MAP_ANON | MAP_SHARED;
if (uap->shmaddr) { if (uap->shmaddr) {
flags |= MAP_FIXED; flags |= MAP_FIXED;
if (uap->shmflg & SHM_RND) if (uap->shmflg & SHM_RND) {
attach_va = (vm_offset_t)uap->shmaddr & ~(SHMLBA-1); 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; attach_va = (vm_offset_t)uap->shmaddr;
else } else {
return EINVAL; error = EINVAL;
goto done2;
}
} else { } else {
/* /*
* This is just a hint to vm_map_find() about where to * 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, 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); 0, &attach_va, size, (flags & MAP_FIXED)?0:1, prot, prot, 0);
if (rv != KERN_SUCCESS) { if (rv != KERN_SUCCESS) {
return ENOMEM; error = ENOMEM;
goto done2;
} }
vm_map_inherit(&p->p_vmspace->vm_map, vm_map_inherit(&p->p_vmspace->vm_map,
attach_va, attach_va + size, VM_INHERIT_SHARE); attach_va, attach_va + size, VM_INHERIT_SHARE);
@ -349,7 +377,9 @@ shmat(p, uap)
shmseg->shm_atime = time_second; shmseg->shm_atime = time_second;
shmseg->shm_nattch++; shmseg->shm_nattch++;
p->p_retval[0] = attach_va; p->p_retval[0] = attach_va;
return 0; done2:
mtx_unlock(&Giant);
return (error);
} }
struct oshmid_ds { struct oshmid_ds {
@ -370,27 +400,36 @@ struct oshmctl_args {
struct oshmid_ds *ubuf; struct oshmid_ds *ubuf;
}; };
/*
* MPSAFE
*/
static int static int
oshmctl(p, uap) oshmctl(p, uap)
struct proc *p; struct proc *p;
struct oshmctl_args *uap; struct oshmctl_args *uap;
{ {
#ifdef COMPAT_43 #ifdef COMPAT_43
int error; int error = 0;
struct shmid_ds *shmseg; struct shmid_ds *shmseg;
struct oshmid_ds outbuf; struct oshmid_ds outbuf;
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) mtx_lock(&Giant);
return (ENOSYS);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
error = ENOSYS;
goto done2;
}
shmseg = shm_find_segment_by_shmid(uap->shmid); shmseg = shm_find_segment_by_shmid(uap->shmid);
if (shmseg == NULL) if (shmseg == NULL) {
return EINVAL; error = EINVAL;
goto done2;
}
switch (uap->cmd) { switch (uap->cmd) {
case IPC_STAT: case IPC_STAT:
error = ipcperm(p, &shmseg->shm_perm, IPC_R); error = ipcperm(p, &shmseg->shm_perm, IPC_R);
if (error) if (error)
return error; goto done2;
outbuf.shm_perm = shmseg->shm_perm; outbuf.shm_perm = shmseg->shm_perm;
outbuf.shm_segsz = shmseg->shm_segsz; outbuf.shm_segsz = shmseg->shm_segsz;
outbuf.shm_cpid = shmseg->shm_cpid; outbuf.shm_cpid = shmseg->shm_cpid;
@ -402,13 +441,16 @@ oshmctl(p, uap)
outbuf.shm_handle = shmseg->shm_internal; outbuf.shm_handle = shmseg->shm_internal;
error = copyout((caddr_t)&outbuf, uap->ubuf, sizeof(outbuf)); error = copyout((caddr_t)&outbuf, uap->ubuf, sizeof(outbuf));
if (error) if (error)
return error; goto done2;
break; break;
default: default:
/* XXX casting to (sy_call_t *) is bogus, as usual. */ /* 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 #else
return EINVAL; return EINVAL;
#endif #endif
@ -422,39 +464,46 @@ struct shmctl_args {
}; };
#endif #endif
/*
* MPSAFE
*/
int int
shmctl(p, uap) shmctl(p, uap)
struct proc *p; struct proc *p;
struct shmctl_args *uap; struct shmctl_args *uap;
{ {
int error; int error = 0;
struct shmid_ds inbuf; struct shmid_ds inbuf;
struct shmid_ds *shmseg; struct shmid_ds *shmseg;
GIANT_REQUIRED; mtx_lock(&Giant);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
return (ENOSYS); error = ENOSYS;
goto done2;
}
shmseg = shm_find_segment_by_shmid(uap->shmid); shmseg = shm_find_segment_by_shmid(uap->shmid);
if (shmseg == NULL) if (shmseg == NULL) {
return EINVAL; error = EINVAL;
goto done2;
}
switch (uap->cmd) { switch (uap->cmd) {
case IPC_STAT: case IPC_STAT:
error = ipcperm(p, &shmseg->shm_perm, IPC_R); error = ipcperm(p, &shmseg->shm_perm, IPC_R);
if (error) if (error)
return error; goto done2;
error = copyout((caddr_t)shmseg, uap->buf, sizeof(inbuf)); error = copyout((caddr_t)shmseg, uap->buf, sizeof(inbuf));
if (error) if (error)
return error; goto done2;
break; break;
case IPC_SET: case IPC_SET:
error = ipcperm(p, &shmseg->shm_perm, IPC_M); error = ipcperm(p, &shmseg->shm_perm, IPC_M);
if (error) if (error)
return error; goto done2;
error = copyin(uap->buf, (caddr_t)&inbuf, sizeof(inbuf)); error = copyin(uap->buf, (caddr_t)&inbuf, sizeof(inbuf));
if (error) if (error)
return error; goto done2;
shmseg->shm_perm.uid = inbuf.shm_perm.uid; shmseg->shm_perm.uid = inbuf.shm_perm.uid;
shmseg->shm_perm.gid = inbuf.shm_perm.gid; shmseg->shm_perm.gid = inbuf.shm_perm.gid;
shmseg->shm_perm.mode = shmseg->shm_perm.mode =
@ -465,7 +514,7 @@ shmctl(p, uap)
case IPC_RMID: case IPC_RMID:
error = ipcperm(p, &shmseg->shm_perm, IPC_M); error = ipcperm(p, &shmseg->shm_perm, IPC_M);
if (error) if (error)
return error; goto done2;
shmseg->shm_perm.key = IPC_PRIVATE; shmseg->shm_perm.key = IPC_PRIVATE;
shmseg->shm_perm.mode |= SHMSEG_REMOVED; shmseg->shm_perm.mode |= SHMSEG_REMOVED;
if (shmseg->shm_nattch <= 0) { if (shmseg->shm_nattch <= 0) {
@ -478,9 +527,12 @@ shmctl(p, uap)
case SHM_UNLOCK: case SHM_UNLOCK:
#endif #endif
default: default:
return EINVAL; error = EINVAL;
break;
} }
return 0; done2:
mtx_unlock(&Giant);
return (error);
} }
#ifndef _SYS_SYSPROTO_H_ #ifndef _SYS_SYSPROTO_H_
@ -607,15 +659,23 @@ shmget_allocate_segment(p, uap, mode)
return 0; return 0;
} }
/*
* MPSAFE
*/
int int
shmget(p, uap) shmget(p, uap)
struct proc *p; struct proc *p;
struct shmget_args *uap; struct shmget_args *uap;
{ {
int segnum, mode, error; int segnum, mode;
int error;
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) mtx_lock(&Giant);
return (ENOSYS);
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
error = ENOSYS;
goto done2;
}
mode = uap->shmflg & ACCESSPERMS; mode = uap->shmflg & ACCESSPERMS;
if (uap->key != IPC_PRIVATE) { if (uap->key != IPC_PRIVATE) {
@ -625,14 +685,22 @@ shmget(p, uap)
error = shmget_existing(p, uap, mode, segnum); error = shmget_existing(p, uap, mode, segnum);
if (error == EAGAIN) if (error == EAGAIN)
goto again; 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 int
shmsys(p, uap) shmsys(p, uap)
struct proc *p; struct proc *p;
@ -644,13 +712,23 @@ shmsys(p, uap)
int a4; int a4;
} */ *uap; } */ *uap;
{ {
int error;
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) mtx_lock(&Giant);
return (ENOSYS);
if (uap->which >= sizeof(shmcalls)/sizeof(shmcalls[0])) if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
return EINVAL; error = ENOSYS;
return ((*shmcalls[uap->which])(p, &uap->a2)); 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 static void