patch-2.1.23 linux/ipc/msg.c
Next file: linux/ipc/sem.c
Previous file: linux/init/main.c
Back to the patch index
Back to the overall index
- Lines: 276
- Date:
Sun Jan 26 12:07:48 1997
- Orig file:
v2.1.22/linux/ipc/msg.c
- Orig date:
Tue Oct 29 19:58:47 1996
diff -u --recursive --new-file v2.1.22/linux/ipc/msg.c linux/ipc/msg.c
@@ -15,6 +15,8 @@
#include <linux/malloc.h>
#include <linux/kerneld.h>
#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
@@ -393,15 +395,25 @@
asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
{
+ int ret;
+
/* IPC_KERNELD is used as a marker for kernel level calls */
- return real_msgsnd(msqid, msgp, msgsz, msgflg & ~IPC_KERNELD);
+ lock_kernel();
+ ret = real_msgsnd(msqid, msgp, msgsz, msgflg & ~IPC_KERNELD);
+ unlock_kernel();
+ return ret;
}
asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,
long msgtyp, int msgflg)
{
+ int ret;
+
/* IPC_KERNELD is used as a marker for kernel level calls */
- return real_msgrcv (msqid, msgp, msgsz, msgtyp, msgflg & ~IPC_KERNELD);
+ lock_kernel();
+ ret = real_msgrcv (msqid, msgp, msgsz, msgtyp, msgflg & ~IPC_KERNELD);
+ unlock_kernel();
+ return ret;
}
static int findkey (key_t key)
@@ -463,51 +475,60 @@
asmlinkage int sys_msgget (key_t key, int msgflg)
{
- int id;
+ int id, ret = -EPERM;
struct msqid_ds *msq;
/*
* If the IPC_KERNELD flag is set, the key is forced to IPC_PRIVATE,
* and a designated kerneld message queue is created/referred to
*/
+ lock_kernel();
if ((msgflg & IPC_KERNELD)) {
int i;
if (!suser())
- return -EPERM;
+ goto out;
#ifdef NEW_KERNELD_PROTOCOL
if ((msgflg & IPC_KERNELD) == OLDIPC_KERNELD) {
printk(KERN_ALERT "Please recompile your kerneld daemons!\n");
- return -EPERM;
+ goto out;
}
#endif
+ ret = -ENOSPC;
if ((kerneld_msqid == -1) && (kerneld_msqid =
newque(IPC_PRIVATE, msgflg & S_IRWXU)) < 0)
- return -ENOSPC;
+ goto out;
for (i = 0; i < MAX_KERNELDS; ++i) {
if (kerneld_arr[i] == 0) {
kerneld_arr[i] = current->pid;
++n_kernelds;
- return kerneld_msqid;
+ ret = kerneld_msqid;
+ goto out;
}
}
- return -ENOSPC;
+ goto out;
}
/* else it is a "normal" request */
if (key == IPC_PRIVATE)
- return newque(key, msgflg);
- if ((id = findkey (key)) == -1) { /* key not used */
+ ret = newque(key, msgflg);
+ else if ((id = findkey (key)) == -1) { /* key not used */
if (!(msgflg & IPC_CREAT))
- return -ENOENT;
- return newque(key, msgflg);
- }
- if (msgflg & IPC_CREAT && msgflg & IPC_EXCL)
- return -EEXIST;
- msq = msgque[id];
- if (msq == IPC_UNUSED || msq == IPC_NOID)
- return -EIDRM;
- if (ipcperms(&msq->msg_perm, msgflg))
- return -EACCES;
- return (unsigned int) msq->msg_perm.seq * MSGMNI + id;
+ ret = -ENOENT;
+ else
+ ret = newque(key, msgflg);
+ } else if (msgflg & IPC_CREAT && msgflg & IPC_EXCL) {
+ ret = -EEXIST;
+ } else {
+ msq = msgque[id];
+ if (msq == IPC_UNUSED || msq == IPC_NOID)
+ ret = -EIDRM;
+ else if (ipcperms(&msq->msg_perm, msgflg))
+ ret = -EACCES;
+ else
+ ret = (unsigned int) msq->msg_perm.seq * MSGMNI + id;
+ }
+out:
+ unlock_kernel();
+ return ret;
}
static void freeque (int id)
@@ -537,18 +558,20 @@
asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
{
- int id, err;
+ int id, err = -EINVAL;
struct msqid_ds *msq;
struct msqid_ds tbuf;
struct ipc_perm *ipcp;
+ lock_kernel();
if (msqid < 0 || cmd < 0)
- return -EINVAL;
+ goto out;
+ err = -EFAULT;
switch (cmd) {
case IPC_INFO:
case MSG_INFO:
if (!buf)
- return -EFAULT;
+ goto out;
{
struct msginfo msginfo;
msginfo.msgmni = MSGMNI;
@@ -566,23 +589,26 @@
}
err = verify_area (VERIFY_WRITE, buf, sizeof (struct msginfo));
if (err)
- return err;
+ goto out;
copy_to_user (buf, &msginfo, sizeof(struct msginfo));
- return max_msqid;
+ err = max_msqid;
+ goto out;
}
case MSG_STAT:
if (!buf)
- return -EFAULT;
+ goto out;
err = verify_area (VERIFY_WRITE, buf, sizeof (*buf));
if (err)
- return err;
+ goto out;
+ err = -EINVAL;
if (msqid > max_msqid)
- return -EINVAL;
+ goto out;
msq = msgque[msqid];
if (msq == IPC_UNUSED || msq == IPC_NOID)
- return -EINVAL;
+ goto out;
+ err = -EACCES;
if (ipcperms (&msq->msg_perm, S_IRUGO))
- return -EACCES;
+ goto out;
id = (unsigned int) msq->msg_perm.seq * MSGMNI + msqid;
tbuf.msg_perm = msq->msg_perm;
tbuf.msg_stime = msq->msg_stime;
@@ -594,36 +620,40 @@
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
copy_to_user (buf, &tbuf, sizeof(*buf));
- return id;
+ err = id;
+ goto out;
case IPC_SET:
if (!buf)
- return -EFAULT;
+ goto out;
err = verify_area (VERIFY_READ, buf, sizeof (*buf));
if (err)
- return err;
+ goto out;
copy_from_user (&tbuf, buf, sizeof (*buf));
break;
case IPC_STAT:
if (!buf)
- return -EFAULT;
+ goto out;
err = verify_area (VERIFY_WRITE, buf, sizeof(*buf));
if (err)
- return err;
+ goto out;
break;
}
id = (unsigned int) msqid % MSGMNI;
msq = msgque [id];
+ err = -EINVAL;
if (msq == IPC_UNUSED || msq == IPC_NOID)
- return -EINVAL;
+ goto out;
+ err = -EIDRM;
if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI)
- return -EIDRM;
+ goto out;
ipcp = &msq->msg_perm;
switch (cmd) {
case IPC_STAT:
+ err = -EACCES;
if (ipcperms (ipcp, S_IRUGO))
- return -EACCES;
+ goto out;
tbuf.msg_perm = msq->msg_perm;
tbuf.msg_stime = msq->msg_stime;
tbuf.msg_rtime = msq->msg_rtime;
@@ -634,24 +664,28 @@
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
copy_to_user (buf, &tbuf, sizeof (*buf));
- return 0;
+ err = 0;
+ goto out;
case IPC_SET:
+ err = -EPERM;
if (!suser() && current->euid != ipcp->cuid &&
current->euid != ipcp->uid)
- return -EPERM;
+ goto out;
if (tbuf.msg_qbytes > MSGMNB && !suser())
- return -EPERM;
+ goto out;
msq->msg_qbytes = tbuf.msg_qbytes;
ipcp->uid = tbuf.msg_perm.uid;
ipcp->gid = tbuf.msg_perm.gid;
ipcp->mode = (ipcp->mode & ~S_IRWXUGO) |
(S_IRWXUGO & tbuf.msg_perm.mode);
msq->msg_ctime = CURRENT_TIME;
- return 0;
+ err = 0;
+ goto out;
case IPC_RMID:
+ err = -EPERM;
if (!suser() && current->euid != ipcp->cuid &&
current->euid != ipcp->uid)
- return -EPERM;
+ goto out;
/*
* There is only one kerneld message queue,
* mark it as non-existent
@@ -659,10 +693,15 @@
if ((kerneld_msqid >= 0) && (msqid == kerneld_msqid))
kerneld_msqid = -1;
freeque (id);
- return 0;
+ err = 0;
+ goto out;
default:
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
+out:
+ unlock_kernel();
+ return err;
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov