[SSI] openssi/kernel/ipc msg.c,1.19,1.20

Roger Tsang <[email protected]> Mon, 05 Apr 2010 05:10:52 +0000
Newsgroups gmane.linux.cluster.ssic.cvs
Message-ID <[email protected]>
Update of /cvsroot/ssic-linux/openssi/kernel/ipc
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv7945/kernel/ipc

Modified Files:
      Tag: OPENSSI-FC
	msg.c 
Log Message:
- Fix memory corruption in sys_msgsnd() due to double kfree of msg_msgseg structures after sending to remote message queue. ssi_msgpack() already freed msg_msgseg. The second kfree is done in free_msg() prior returning to user space.
- Eliminate unnecessary struct msgbuf de-serialization in sys_msgsnd() at remote clients. The existing implementation de-serializes the user's buffer into msg_msg structure for the local message queue first. Then if it determines the queue is remote the msg_msg structure is re-serialized for transport. The new implementation skips all that and instead sends a copy of the user's buffer to the server.
- Remove ssi_msgpack() it is no longer used.
- Create ssi_load_msg() based on ipc/msgutil.c:load_msg() to load kernel space buffer.
- ssi_remote_msgrcv() to skip zero'ing of kernel space receive buffer. There is no security issue since the contents of buffer is not copied to user space unless the remote operation is successful.

 cluster/ssi/ipc/ipcmsg_svr.c |   80 +++++----------------
 include/cluster/gen/ipc.svc  |    4 -
 ipc/msg.c                    |  133 +++++++++++++++++++++--------------
 3 files changed, 102 insertions(+), 115 deletions(-)


Index: msg.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/ipc/msg.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- msg.c	3 Apr 2010 22:00:37 -0000	1.19
+++ msg.c	5 Apr 2010 05:10:50 -0000	1.20
@@ -901,60 +901,85 @@
 	return 0;
 }
 
-#ifdef CONFIG_SSI  
-/* Taken from ipc/msgutil.c:load_msg() */
-int ssi_msgpack (struct msg_msgseg *seg, size_t msgsz, char *packedsegs)
+#ifdef CONFIG_SSI
+/* Adaptation of ipc/msgutil.c:load_msg() for kernel space */
+struct msg_msg *ssi_load_msg(const void *src, int len)
 {
-	struct msg_msgseg *newseg, *last;
-	int len, alen;
-	char *msgsegs, *dest;
+	struct msg_msg *msg;
+	struct msg_msgseg **pseg;
+	int err;
+	int alen;
 
-	len = msgsz - DATALEN_MSG;
-	msgsegs = (char *) kmalloc (len, GFP_KERNEL);
-	if (msgsegs == NULL)
-		return -ENOMEM;
-	dest = msgsegs;
-	newseg = seg;
+	alen = len;
+	if (alen > DATALEN_MSG)
+		alen = DATALEN_MSG;
+
+	msg = (struct msg_msg *)kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
+	if (msg == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	msg->next = NULL;
+	msg->security = NULL;
+
+	memcpy(msg + 1, src, alen);
+
+	len -= alen;
+	src = ((char *)src) + alen;
+	pseg = &msg->next;
 	while (len > 0) {
+		struct msg_msgseg *seg;
 		alen = len;
-		last = newseg;
 		if (alen > DATALEN_SEG)
 			alen = DATALEN_SEG;
-		memcpy (dest, newseg + 1, alen);
+		seg = (struct msg_msgseg *)kmalloc(sizeof(*seg) + alen,
+						 GFP_KERNEL);
+		if (seg == NULL) {
+			err = -ENOMEM;
+			goto out_err;
+		}
+		*pseg = seg;
+		seg->next = NULL;
+		memcpy(seg + 1, src, alen);
+
+		pseg = &seg->next;
 		len -= alen;
-		dest = ((char*)dest) + alen;
-		newseg = seg->next;
-		kfree(last);
+		src = ((char __user *)src) + alen;
 	}
-	packedsegs = msgsegs;
-	return len;
+
+	return msg;
+
+out_err:
+	free_msg(msg);
+	return ERR_PTR(err);
 }
 
+
 int
 ssi_remote_msgsnd(
 	clusternode_t svr_node,
 	int msqid,
-	struct msg_msg *msg,
+	long mtype,
+	struct msgbuf __user *msgp,
 	size_t msgsz,
 	int msgflg)
 {
 	int rval, err;
-	int msize, bufsize = 0;
-	char *packedsegs = NULL;
+	char *msgtxt;
 
-	if (msg->next != NULL) {
-		bufsize = ssi_msgpack(msg->next, msgsz, packedsegs);
-		if (bufsize < 0)
-			return -ENOMEM;
-	}
-	if (msgsz < DATALEN_MSG)
-		msize = msgsz + sizeof(struct msg_msg);
-	else
-		msize = DATALEN_MSG;
+#ifdef DEBUG
+	BUG_ON(msgsz > MAX_INT);
+#endif
+	msgtxt = (char *) kmalloc(msgsz, GFP_KERNEL);
+	if (msgtxt == NULL)
+		return -ENOMEM;
 
+	if (copy_from_user(msgtxt, msgp->mtext, msgsz)) {
+		kfree(msgtxt);
+		return -EFAULT;
+	}
 retry:
-	err = cli_ripc_msgsnd(svr_node, &rval, msqid, msg, msize, packedsegs,
-		       	bufsize, msgflg);
+	err = cli_ripc_msgsnd(svr_node, &rval, msqid, mtype,
+					msgtxt, (int)msgsz, msgflg);
 	if (err) {
 		if (err != -EREMOTE) {
 			idelay(HZ/10);
@@ -962,9 +987,7 @@
 		}
 		rval = -EINVAL;
 	}
-	if (packedsegs)
-		kfree(packedsegs);
-
+	kfree(msgtxt);
 	return rval;
 }
 #endif  /*  CONFIG_SSI  */
@@ -985,14 +1008,9 @@
 	if (mtype < 1)
 		return -EINVAL;
 
-	msg = load_msg(msgp->mtext, msgsz);
-	if(IS_ERR(msg))
-		return PTR_ERR(msg);
-
-	msg->m_type = mtype;
-	msg->m_ts = msgsz;
-
 #ifdef CONFIG_SSI
+	msg = NULL;
+
 	svr_node = msg_get_svr_node(msqid);
 	if (!svr_node) {
 namesvr_snd_go:
@@ -1002,10 +1020,23 @@
 			goto out_free;
 		}
 	}
-	if (svr_node != this_node)
-		err = ssi_remote_msgsnd(svr_node, msqid, msg, msgsz, msgflg);
-	else
-		err = ssi_msgsnd(msqid, &msg, msgsz, msgflg);
+	if (svr_node != this_node) {
+		err = ssi_remote_msgsnd(svr_node, msqid, mtype,
+						msgp, msgsz, msgflg);
+		goto out;
+	}
+
+	if (!msg) {
+		msg = load_msg(msgp->mtext, msgsz);
+		if(IS_ERR(msg))
+			return PTR_ERR(msg);
+
+		msg->m_type = mtype;
+		msg->m_ts = msgsz;
+	}
+
+	err = ssi_msgsnd(msqid, &msg, msgsz, msgflg);
+out:
 	if (err == -EINVAL) {
 		msg_set_svr_node(msqid, 0);
 		goto namesvr_snd_go;
@@ -1158,12 +1189,10 @@
 	int msgflg)
 {
 	long rettyp;
-	int rval, txtsz;
-	int status;
+	int status, rval, txtsz = (int)msgsz;
 	char *msgtxt;
 
-	txtsz = (int)msgsz;
-	msgtxt = (char *) kzmalloc(txtsz, GFP_KERNEL);
+	msgtxt = (char *) kmalloc(txtsz, GFP_KERNEL);
 	if (msgtxt == NULL)
 		 return -ENOMEM;
 


------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev