ARM: OMAP2/3: CM: fix cm_split_idlest functionality
[sfrench/cifs-2.6.git] / ipc / syscall.c
index 52429489cde0070ab9398648ca326592e824a2a7..667022746ca56914e77fcb0b9a1c23ff4b02d3d6 100644 (file)
@@ -5,12 +5,12 @@
  * the individual syscalls instead.
  */
 #include <linux/unistd.h>
+#include <linux/syscalls.h>
 
 #ifdef __ARCH_WANT_SYS_IPC
 #include <linux/errno.h>
 #include <linux/ipc.h>
 #include <linux/shm.h>
-#include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
 SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
@@ -97,3 +97,91 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
        }
 }
 #endif
+
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+
+#ifndef COMPAT_SHMLBA
+#define COMPAT_SHMLBA  SHMLBA
+#endif
+
+struct compat_ipc_kludge {
+       compat_uptr_t msgp;
+       compat_long_t msgtyp;
+};
+
+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
+COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
+       u32, third, compat_uptr_t, ptr, u32, fifth)
+{
+       int version;
+       u32 pad;
+
+       version = call >> 16; /* hack for backward compatibility */
+       call &= 0xffff;
+
+       switch (call) {
+       case SEMOP:
+               /* struct sembuf is the same on 32 and 64bit :)) */
+               return sys_semtimedop(first, compat_ptr(ptr), second, NULL);
+       case SEMTIMEDOP:
+               return compat_sys_semtimedop(first, compat_ptr(ptr), second,
+                                               compat_ptr(fifth));
+       case SEMGET:
+               return sys_semget(first, second, third);
+       case SEMCTL:
+               if (!ptr)
+                       return -EINVAL;
+               if (get_user(pad, (u32 __user *) compat_ptr(ptr)))
+                       return -EFAULT;
+               return compat_sys_semctl(first, second, third, pad);
+
+       case MSGSND:
+               return compat_sys_msgsnd(first, ptr, second, third);
+
+       case MSGRCV: {
+               void __user *uptr = compat_ptr(ptr);
+
+               if (first < 0 || second < 0)
+                       return -EINVAL;
+
+               if (!version) {
+                       struct compat_ipc_kludge ipck;
+                       if (!uptr)
+                               return -EINVAL;
+                       if (copy_from_user(&ipck, uptr, sizeof(ipck)))
+                               return -EFAULT;
+                       return compat_sys_msgrcv(first, ipck.msgp, second,
+                                                ipck.msgtyp, third);
+               }
+               return compat_sys_msgrcv(first, ptr, second, fifth, third);
+       }
+       case MSGGET:
+               return sys_msgget(first, second);
+       case MSGCTL:
+               return compat_sys_msgctl(first, second, compat_ptr(ptr));
+
+       case SHMAT: {
+               int err;
+               unsigned long raddr;
+
+               if (version == 1)
+                       return -EINVAL;
+               err = do_shmat(first, compat_ptr(ptr), second, &raddr,
+                              COMPAT_SHMLBA);
+               if (err < 0)
+                       return err;
+               return put_user(raddr, (compat_ulong_t *)compat_ptr(third));
+       }
+       case SHMDT:
+               return sys_shmdt(compat_ptr(ptr));
+       case SHMGET:
+               return sys_shmget(first, (unsigned)second, third);
+       case SHMCTL:
+               return compat_sys_shmctl(first, second, compat_ptr(ptr));
+       }
+
+       return -ENOSYS;
+}
+#endif
+#endif