[IRDA]: Fix rfcomm use-after-free
[pandora-kernel.git] / ipc / msg.c
index 5b213d9..a03fcb5 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -52,7 +52,7 @@ struct msg_receiver {
        long                    r_msgtype;
        long                    r_maxsize;
 
-       volatile struct msg_msg *r_msg;
+       struct msg_msg          *volatile r_msg;
 };
 
 /* one msg_sender for each sleeping sender */
@@ -87,7 +87,7 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg);
 static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
 #endif
 
-static void __ipc_init __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
+static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
 {
        ns->ids[IPC_MSG_IDS] = ids;
        ns->msg_ctlmax = MSGMAX;
@@ -96,7 +96,6 @@ static void __ipc_init __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *i
        ipc_init_ids(ids, ns->msg_ctlmni);
 }
 
-#ifdef CONFIG_IPC_NS
 int msg_init_ns(struct ipc_namespace *ns)
 {
        struct ipc_ids *ids;
@@ -124,10 +123,10 @@ void msg_exit_ns(struct ipc_namespace *ns)
        }
        mutex_unlock(&msg_ids(ns).mutex);
 
+       ipc_fini_ids(ns->ids[IPC_MSG_IDS]);
        kfree(ns->ids[IPC_MSG_IDS]);
        ns->ids[IPC_MSG_IDS] = NULL;
 }
-#endif
 
 void __init msg_init(void)
 {
@@ -386,7 +385,7 @@ copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version)
 asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
 {
        struct kern_ipc_perm *ipcp;
-       struct msq_setbuf setbuf;
+       struct msq_setbuf uninitialized_var(setbuf);
        struct msg_queue *msq;
        int err, version;
        struct ipc_namespace *ns;
@@ -510,7 +509,7 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
        err = audit_ipc_obj(ipcp);
        if (err)
                goto out_unlock_up;
-       if (cmd==IPC_SET) {
+       if (cmd == IPC_SET) {
                err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid,
                                         setbuf.mode);
                if (err)
@@ -625,12 +624,11 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
        return 0;
 }
 
-asmlinkage long
-sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
+long do_msgsnd(int msqid, long mtype, void __user *mtext,
+               size_t msgsz, int msgflg)
 {
        struct msg_queue *msq;
        struct msg_msg *msg;
-       long mtype;
        int err;
        struct ipc_namespace *ns;
 
@@ -638,12 +636,10 @@ sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
 
        if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
                return -EINVAL;
-       if (get_user(mtype, &msgp->mtype))
-               return -EFAULT;
        if (mtype < 1)
                return -EINVAL;
 
-       msg = load_msg(msgp->mtext, msgsz);
+       msg = load_msg(mtext, msgsz);
        if (IS_ERR(msg))
                return PTR_ERR(msg);
 
@@ -722,6 +718,16 @@ out_free:
        return err;
 }
 
+asmlinkage long
+sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
+{
+       long mtype;
+
+       if (get_user(mtype, &msgp->mtype))
+               return -EFAULT;
+       return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
+}
+
 static inline int convert_mode(long *msgtyp, int msgflg)
 {
        /*
@@ -741,8 +747,8 @@ static inline int convert_mode(long *msgtyp, int msgflg)
        return SEARCH_EQUAL;
 }
 
-asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
-                          long msgtyp, int msgflg)
+long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
+               size_t msgsz, long msgtyp, int msgflg)
 {
        struct msg_queue *msq;
        struct msg_msg *msg;
@@ -888,15 +894,30 @@ out_unlock:
                return PTR_ERR(msg);
 
        msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
-       if (put_user (msg->m_type, &msgp->mtype) ||
-           store_msg(msgp->mtext, msg, msgsz)) {
+       *pmtype = msg->m_type;
+       if (store_msg(mtext, msg, msgsz))
                msgsz = -EFAULT;
-       }
+
        free_msg(msg);
 
        return msgsz;
 }
 
+asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
+                          long msgtyp, int msgflg)
+{
+       long err, mtype;
+
+       err =  do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
+       if (err < 0)
+               goto out;
+
+       if (put_user(mtype, &msgp->mtype))
+               err = -EFAULT;
+out:
+       return err;
+}
+
 #ifdef CONFIG_PROC_FS
 static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
 {