patch-2.1.116 linux/ipc/msg.c

Next file: linux/kernel/capability.c
Previous file: linux/include/linux/videodev.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.115/linux/ipc/msg.c linux/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 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 @@
 
 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 @@
 	}
 	
 	/* 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 @@
 	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 @@
 	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 @@
 	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 @@
 			return -EACCES;
 		}
 
-		save_flags(flags);
-		cli();
 		if (msgtyp == 0) 
 			nmsg = msq->msg_first;
 		else if (msgtyp > 0) {
@@ -186,15 +180,12 @@
 			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 @@
 			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 @@
 			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 @@
 		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 @@
 		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;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov