inet_diag: fix inet_diag_bc_audit(), CVE-2011-2213
[linux-flexiantxendom0-natty.git] / ipc / compat.c
index 1fe95f6..845a287 100644 (file)
  *
  */
 #include <linux/compat.h>
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/highuid.h>
 #include <linux/init.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
-#include <linux/slab.h>
 #include <linux/syscalls.h>
 
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
 #include "util.h"
@@ -116,7 +114,6 @@ struct compat_shm_info {
 
 extern int sem_ctls[];
 #define sc_semopm      (sem_ctls[2])
-#define MAXBUF (64*1024)
 
 static inline int compat_ipc_parse_version(int *cmd)
 {
@@ -227,7 +224,7 @@ static inline int put_compat_semid_ds(struct semid64_ds *s,
        int err;
 
        if (!access_ok (VERIFY_WRITE, up, sizeof(*up)))
-               err = -EFAULT;
+               return -EFAULT;
        err  = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
        err |= __put_user(s->sem_otime, &up->sem_otime);
        err |= __put_user(s->sem_ctime, &up->sem_ctime);
@@ -244,6 +241,8 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr)
        struct semid64_ds __user *up64;
        int version = compat_ipc_parse_version(&third);
 
+       memset(&s64, 0, sizeof(s64));
+
        if (!uptr)
                return -EINVAL;
        if (get_user(pad, (u32 __user *) uptr))
@@ -308,35 +307,30 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr)
 
 long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
 {
-       struct msgbuf __user *p;
        struct compat_msgbuf __user *up = uptr;
        long type;
 
        if (first < 0)
                return -EINVAL;
-       if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf)))
+       if (second < 0)
                return -EINVAL;
 
-       p = compat_alloc_user_space(second + sizeof(struct msgbuf));
-       if (get_user(type, &up->mtype) ||
-           put_user(type, &p->mtype) ||
-           copy_in_user(p->mtext, up->mtext, second))
+       if (get_user(type, &up->mtype))
                return -EFAULT;
 
-       return sys_msgsnd(first, p, second, third);
+       return do_msgsnd(first, type, up->mtext, second, third);
 }
 
 long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
                           int version, void __user *uptr)
 {
-       struct msgbuf __user *p;
        struct compat_msgbuf __user *up;
        long type;
        int err;
 
        if (first < 0)
                return -EINVAL;
-       if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf)))
+       if (second < 0)
                return -EINVAL;
 
        if (!version) {
@@ -350,14 +344,11 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
                uptr = compat_ptr(ipck.msgp);
                msgtyp = ipck.msgtyp;
        }
-       p = compat_alloc_user_space(second + sizeof(struct msgbuf));
-       err = sys_msgrcv(first, p, second, msgtyp, third);
+       up = uptr;
+       err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third);
        if (err < 0)
                goto out;
-       up = uptr;
-       if (get_user(type, &p->mtype) ||
-           put_user(type, &up->mtype) ||
-           copy_in_user(up->mtext, p->mtext, err))
+       if (put_user(type, &up->mtype))
                err = -EFAULT;
 out:
        return err;
@@ -432,6 +423,8 @@ long compat_sys_msgctl(int first, int second, void __user *uptr)
        int version = compat_ipc_parse_version(&second);
        void __user *p;
 
+       memset(&m64, 0, sizeof(m64));
+
        switch (second & (~IPC_64)) {
        case IPC_INFO:
        case IPC_RMID:
@@ -552,6 +545,8 @@ static inline int put_compat_shminfo64(struct shminfo64 *smi,
 
        if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
                return -EFAULT;
+       if (smi->shmmax > INT_MAX)
+               smi->shmmax = INT_MAX;
        err  = __put_user(smi->shmmax, &up64->shmmax);
        err |= __put_user(smi->shmmin, &up64->shmmin);
        err |= __put_user(smi->shmmni, &up64->shmmni);
@@ -567,6 +562,8 @@ static inline int put_compat_shminfo(struct shminfo64 *smi,
 
        if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
                return -EFAULT;
+       if (smi->shmmax > INT_MAX)
+               smi->shmmax = INT_MAX;
        err  = __put_user(smi->shmmax, &up->shmmax);
        err |= __put_user(smi->shmmin, &up->shmmin);
        err |= __put_user(smi->shmmni, &up->shmmni);
@@ -601,6 +598,8 @@ long compat_sys_shmctl(int first, int second, void __user *uptr)
        int err, err2;
        int version = compat_ipc_parse_version(&second);
 
+       memset(&s64, 0, sizeof(s64));
+
        switch (second & (~IPC_64)) {
        case IPC_RMID:
        case SHM_LOCK: