[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® 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