summaryrefslogtreecommitdiffstats
path: root/ipc/msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/msg.c')
-rw-r--r--ipc/msg.c81
1 files changed, 34 insertions, 47 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index e505bcc01..bcc58a4c5 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -1,6 +1,13 @@
/*
* linux/ipc/msg.c
* Copyright (C) 1992 Krishna Balasubramanian
+ *
+ * Removed all the remaining kerneld mess
+ * Catch the -EFAULT stuff properly
+ * Use GFP_KERNEL for messages as in 1.2
+ * Fixed up the unchecked user space derefs
+ * Copyright (C) 1998 Alan Cox & Andi Kleen
+ *
*/
#include <linux/errno.h>
@@ -29,7 +36,7 @@ static int used_queues = 0;
static int max_msqid = 0;
static struct wait_queue *msg_lock = NULL;
-__initfunc(void msg_init (void))
+void __init msg_init (void)
{
int id;
@@ -42,21 +49,16 @@ __initfunc(void msg_init (void))
static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
{
- int id, err;
+ int id;
struct msqid_ds *msq;
struct ipc_perm *ipcp;
struct msg *msgh;
long mtype;
- unsigned long flags;
if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0)
return -EINVAL;
- if (!msgp)
- return -EFAULT;
- err = verify_area (VERIFY_READ, msgp->mtext, msgsz);
- if (err)
- return err;
- get_user(mtype, &msgp->mtype);
+ if (get_user(mtype, &msgp->mtype))
+ return -EFAULT;
if (mtype < 1)
return -EINVAL;
id = (unsigned int) msqid % MSGMNI;
@@ -85,12 +87,16 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg
}
/* allocate message header and text space*/
- msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_ATOMIC);
+ msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_KERNEL);
if (!msgh)
return -ENOMEM;
msgh->msg_spot = (char *) (msgh + 1);
- copy_from_user (msgh->msg_spot, msgp->mtext, msgsz);
+ if (copy_from_user(msgh->msg_spot, msgp->mtext, msgsz))
+ {
+ kfree(msgh);
+ return -EFAULT;
+ }
if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID
|| msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) {
@@ -103,8 +109,6 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg
msgh->msg_type = mtype;
msgh->msg_stime = CURRENT_TIME;
- save_flags(flags);
- cli();
if (!msq->msg_first)
msq->msg_first = msq->msg_last = msgh;
else {
@@ -117,7 +121,6 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg
msq->msg_qnum++;
msq->msg_lspid = current->pid;
msq->msg_stime = CURRENT_TIME;
- restore_flags(flags);
wake_up (&msq->rwait);
return 0;
}
@@ -128,17 +131,10 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
struct ipc_perm *ipcp;
struct msg *tmsg, *leastp = NULL;
struct msg *nmsg = NULL;
- int id, err;
- unsigned long flags;
+ int id;
if (msqid < 0 || (long) msgsz < 0)
return -EINVAL;
- if (!msgp || !msgp->mtext)
- return -EFAULT;
-
- err = verify_area (VERIFY_WRITE, msgp->mtext, msgsz);
- if (err)
- return err;
id = (unsigned int) msqid % MSGMNI;
msq = msgque [id];
@@ -160,8 +156,6 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
return -EACCES;
}
- save_flags(flags);
- cli();
if (msgtyp == 0)
nmsg = msq->msg_first;
else if (msgtyp > 0) {
@@ -186,15 +180,12 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
if (leastp && leastp->msg_type <= - msgtyp)
nmsg = leastp;
}
- restore_flags(flags);
if (nmsg) { /* done finding a message */
if ((msgsz < nmsg->msg_ts) && !(msgflg & MSG_NOERROR)) {
return -E2BIG;
}
msgsz = (msgsz > nmsg->msg_ts)? nmsg->msg_ts : msgsz;
- save_flags(flags);
- cli();
if (nmsg == msq->msg_first)
msq->msg_first = nmsg->msg_next;
else {
@@ -214,10 +205,10 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
msgbytes -= nmsg->msg_ts;
msghdrs--;
msq->msg_cbytes -= nmsg->msg_ts;
- restore_flags(flags);
wake_up (&msq->wwait);
- put_user (nmsg->msg_type, &msgp->mtype);
- copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz);
+ if (put_user (nmsg->msg_type, &msgp->mtype) ||
+ copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz))
+ msgsz = -EFAULT;
kfree(nmsg);
return msgsz;
} else { /* did not find a message */
@@ -395,19 +386,16 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
msginfo.msgmap = msghdrs;
msginfo.msgtql = msgbytes;
}
- err = verify_area (VERIFY_WRITE, buf, sizeof (struct msginfo));
- if (err)
- goto out;
- copy_to_user (buf, &msginfo, sizeof(struct msginfo));
+
+ err = -EFAULT;
+ if (copy_to_user (buf, &msginfo, sizeof(struct msginfo)))
+ goto out;
err = max_msqid;
goto out;
}
case MSG_STAT:
if (!buf)
goto out;
- err = verify_area (VERIFY_WRITE, buf, sizeof (*buf));
- if (err)
- goto out;
err = -EINVAL;
if (msqid > max_msqid)
goto out;
@@ -427,23 +415,21 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
tbuf.msg_qbytes = msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
- copy_to_user (buf, &tbuf, sizeof(*buf));
+ err = -EFAULT;
+ if (copy_to_user (buf, &tbuf, sizeof(*buf)))
+ goto out;
err = id;
goto out;
case IPC_SET:
if (!buf)
goto out;
- err = verify_area (VERIFY_READ, buf, sizeof (*buf));
- if (err)
- goto out;
- copy_from_user (&tbuf, buf, sizeof (*buf));
+ err = -EFAULT;
+ if (!copy_from_user (&tbuf, buf, sizeof (*buf)))
+ err = 0;
break;
case IPC_STAT:
if (!buf)
goto out;
- err = verify_area (VERIFY_WRITE, buf, sizeof(*buf));
- if (err)
- goto out;
break;
}
@@ -471,8 +457,9 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
tbuf.msg_qbytes = msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
- copy_to_user (buf, &tbuf, sizeof (*buf));
- err = 0;
+ err = -EFAULT;
+ if (!copy_to_user (buf, &tbuf, sizeof (*buf)))
+ err = 0;
goto out;
case IPC_SET:
err = -EPERM;