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
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=82607
5 changed files with 510 additions and 283 deletions

View File

@ -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 */

View File

@ -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); }

View File

@ -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

View File

@ -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;
if (!jail_sysvipc_allowed && jailed(p->p_ucred))
return (ENOSYS);
mtx_lock(&Giant);
if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0]))
return (EINVAL);
return ((*semcalls[uap->which])(p, &uap->a2));
if (!jail_sysvipc_allowed && jailed(p->p_ucred)) {
error = ENOSYS;
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
/*
* 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 @@ semop(p, uap)
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 @@ semop(p, uap)
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 @@ semop(p, uap)
printf("semop: done\n");
#endif
p->p_retval[0] = 0;
return(0);
done2:
mtx_unlock(&Giant);
return (error);
}
/*

View File

@ -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;
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;
}
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