1baed7fc9SChristoph Hellwig /* 2baed7fc9SChristoph Hellwig * sys_ipc() is the old de-multiplexer for the SysV IPC calls. 3baed7fc9SChristoph Hellwig * 4baed7fc9SChristoph Hellwig * This is really horribly ugly, and new architectures should just wire up 5baed7fc9SChristoph Hellwig * the individual syscalls instead. 6baed7fc9SChristoph Hellwig */ 7baed7fc9SChristoph Hellwig #include <linux/unistd.h> 8*20bc2a3aSAl Viro #include <linux/syscalls.h> 9baed7fc9SChristoph Hellwig 10baed7fc9SChristoph Hellwig #ifdef __ARCH_WANT_SYS_IPC 11baed7fc9SChristoph Hellwig #include <linux/errno.h> 12baed7fc9SChristoph Hellwig #include <linux/ipc.h> 13baed7fc9SChristoph Hellwig #include <linux/shm.h> 14baed7fc9SChristoph Hellwig #include <linux/uaccess.h> 15baed7fc9SChristoph Hellwig 1645575f5aSAnton Blanchard SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, 17baed7fc9SChristoph Hellwig unsigned long, third, void __user *, ptr, long, fifth) 18baed7fc9SChristoph Hellwig { 19baed7fc9SChristoph Hellwig int version, ret; 20baed7fc9SChristoph Hellwig 21baed7fc9SChristoph Hellwig version = call >> 16; /* hack for backward compatibility */ 22baed7fc9SChristoph Hellwig call &= 0xffff; 23baed7fc9SChristoph Hellwig 24baed7fc9SChristoph Hellwig switch (call) { 25baed7fc9SChristoph Hellwig case SEMOP: 26baed7fc9SChristoph Hellwig return sys_semtimedop(first, (struct sembuf __user *)ptr, 27baed7fc9SChristoph Hellwig second, NULL); 28baed7fc9SChristoph Hellwig case SEMTIMEDOP: 29baed7fc9SChristoph Hellwig return sys_semtimedop(first, (struct sembuf __user *)ptr, 30baed7fc9SChristoph Hellwig second, 31baed7fc9SChristoph Hellwig (const struct timespec __user *)fifth); 32baed7fc9SChristoph Hellwig 33baed7fc9SChristoph Hellwig case SEMGET: 34baed7fc9SChristoph Hellwig return sys_semget(first, second, third); 35baed7fc9SChristoph Hellwig case SEMCTL: { 36e1fd1f49SAl Viro unsigned long arg; 37baed7fc9SChristoph Hellwig if (!ptr) 38baed7fc9SChristoph Hellwig return -EINVAL; 39e1fd1f49SAl Viro if (get_user(arg, (unsigned long __user *) ptr)) 40baed7fc9SChristoph Hellwig return -EFAULT; 41e1fd1f49SAl Viro return sys_semctl(first, second, third, arg); 42baed7fc9SChristoph Hellwig } 43baed7fc9SChristoph Hellwig 44baed7fc9SChristoph Hellwig case MSGSND: 45baed7fc9SChristoph Hellwig return sys_msgsnd(first, (struct msgbuf __user *) ptr, 46baed7fc9SChristoph Hellwig second, third); 47baed7fc9SChristoph Hellwig case MSGRCV: 48baed7fc9SChristoph Hellwig switch (version) { 49baed7fc9SChristoph Hellwig case 0: { 50baed7fc9SChristoph Hellwig struct ipc_kludge tmp; 51baed7fc9SChristoph Hellwig if (!ptr) 52baed7fc9SChristoph Hellwig return -EINVAL; 53baed7fc9SChristoph Hellwig 54baed7fc9SChristoph Hellwig if (copy_from_user(&tmp, 55baed7fc9SChristoph Hellwig (struct ipc_kludge __user *) ptr, 56baed7fc9SChristoph Hellwig sizeof(tmp))) 57baed7fc9SChristoph Hellwig return -EFAULT; 58baed7fc9SChristoph Hellwig return sys_msgrcv(first, tmp.msgp, second, 59baed7fc9SChristoph Hellwig tmp.msgtyp, third); 60baed7fc9SChristoph Hellwig } 61baed7fc9SChristoph Hellwig default: 62baed7fc9SChristoph Hellwig return sys_msgrcv(first, 63baed7fc9SChristoph Hellwig (struct msgbuf __user *) ptr, 64baed7fc9SChristoph Hellwig second, fifth, third); 65baed7fc9SChristoph Hellwig } 66baed7fc9SChristoph Hellwig case MSGGET: 67baed7fc9SChristoph Hellwig return sys_msgget((key_t) first, second); 68baed7fc9SChristoph Hellwig case MSGCTL: 69baed7fc9SChristoph Hellwig return sys_msgctl(first, second, (struct msqid_ds __user *)ptr); 70baed7fc9SChristoph Hellwig 71baed7fc9SChristoph Hellwig case SHMAT: 72baed7fc9SChristoph Hellwig switch (version) { 73baed7fc9SChristoph Hellwig default: { 74baed7fc9SChristoph Hellwig unsigned long raddr; 75baed7fc9SChristoph Hellwig ret = do_shmat(first, (char __user *)ptr, 76079a96aeSWill Deacon second, &raddr, SHMLBA); 77baed7fc9SChristoph Hellwig if (ret) 78baed7fc9SChristoph Hellwig return ret; 79baed7fc9SChristoph Hellwig return put_user(raddr, (unsigned long __user *) third); 80baed7fc9SChristoph Hellwig } 81baed7fc9SChristoph Hellwig case 1: 82baed7fc9SChristoph Hellwig /* 83baed7fc9SChristoph Hellwig * This was the entry point for kernel-originating calls 84baed7fc9SChristoph Hellwig * from iBCS2 in 2.2 days. 85baed7fc9SChristoph Hellwig */ 86baed7fc9SChristoph Hellwig return -EINVAL; 87baed7fc9SChristoph Hellwig } 88baed7fc9SChristoph Hellwig case SHMDT: 89baed7fc9SChristoph Hellwig return sys_shmdt((char __user *)ptr); 90baed7fc9SChristoph Hellwig case SHMGET: 91baed7fc9SChristoph Hellwig return sys_shmget(first, second, third); 92baed7fc9SChristoph Hellwig case SHMCTL: 93baed7fc9SChristoph Hellwig return sys_shmctl(first, second, 94baed7fc9SChristoph Hellwig (struct shmid_ds __user *) ptr); 95baed7fc9SChristoph Hellwig default: 96baed7fc9SChristoph Hellwig return -ENOSYS; 97baed7fc9SChristoph Hellwig } 98baed7fc9SChristoph Hellwig } 99baed7fc9SChristoph Hellwig #endif 100*20bc2a3aSAl Viro 101*20bc2a3aSAl Viro #ifdef CONFIG_COMPAT 102*20bc2a3aSAl Viro #include <linux/compat.h> 103*20bc2a3aSAl Viro 104*20bc2a3aSAl Viro #ifndef COMPAT_SHMLBA 105*20bc2a3aSAl Viro #define COMPAT_SHMLBA SHMLBA 106*20bc2a3aSAl Viro #endif 107*20bc2a3aSAl Viro 108*20bc2a3aSAl Viro struct compat_ipc_kludge { 109*20bc2a3aSAl Viro compat_uptr_t msgp; 110*20bc2a3aSAl Viro compat_long_t msgtyp; 111*20bc2a3aSAl Viro }; 112*20bc2a3aSAl Viro 113*20bc2a3aSAl Viro #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC 114*20bc2a3aSAl Viro COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second, 115*20bc2a3aSAl Viro u32, third, compat_uptr_t, ptr, u32, fifth) 116*20bc2a3aSAl Viro { 117*20bc2a3aSAl Viro int version; 118*20bc2a3aSAl Viro u32 pad; 119*20bc2a3aSAl Viro 120*20bc2a3aSAl Viro version = call >> 16; /* hack for backward compatibility */ 121*20bc2a3aSAl Viro call &= 0xffff; 122*20bc2a3aSAl Viro 123*20bc2a3aSAl Viro switch (call) { 124*20bc2a3aSAl Viro case SEMOP: 125*20bc2a3aSAl Viro /* struct sembuf is the same on 32 and 64bit :)) */ 126*20bc2a3aSAl Viro return sys_semtimedop(first, compat_ptr(ptr), second, NULL); 127*20bc2a3aSAl Viro case SEMTIMEDOP: 128*20bc2a3aSAl Viro return compat_sys_semtimedop(first, compat_ptr(ptr), second, 129*20bc2a3aSAl Viro compat_ptr(fifth)); 130*20bc2a3aSAl Viro case SEMGET: 131*20bc2a3aSAl Viro return sys_semget(first, second, third); 132*20bc2a3aSAl Viro case SEMCTL: 133*20bc2a3aSAl Viro if (!ptr) 134*20bc2a3aSAl Viro return -EINVAL; 135*20bc2a3aSAl Viro if (get_user(pad, (u32 __user *) compat_ptr(ptr))) 136*20bc2a3aSAl Viro return -EFAULT; 137*20bc2a3aSAl Viro return compat_sys_semctl(first, second, third, pad); 138*20bc2a3aSAl Viro 139*20bc2a3aSAl Viro case MSGSND: 140*20bc2a3aSAl Viro return compat_sys_msgsnd(first, ptr, second, third); 141*20bc2a3aSAl Viro 142*20bc2a3aSAl Viro case MSGRCV: { 143*20bc2a3aSAl Viro void __user *uptr = compat_ptr(ptr); 144*20bc2a3aSAl Viro 145*20bc2a3aSAl Viro if (first < 0 || second < 0) 146*20bc2a3aSAl Viro return -EINVAL; 147*20bc2a3aSAl Viro 148*20bc2a3aSAl Viro if (!version) { 149*20bc2a3aSAl Viro struct compat_ipc_kludge ipck; 150*20bc2a3aSAl Viro if (!uptr) 151*20bc2a3aSAl Viro return -EINVAL; 152*20bc2a3aSAl Viro if (copy_from_user(&ipck, uptr, sizeof(ipck))) 153*20bc2a3aSAl Viro return -EFAULT; 154*20bc2a3aSAl Viro return compat_sys_msgrcv(first, ipck.msgp, second, 155*20bc2a3aSAl Viro ipck.msgtyp, third); 156*20bc2a3aSAl Viro } 157*20bc2a3aSAl Viro return compat_sys_msgrcv(first, ptr, second, fifth, third); 158*20bc2a3aSAl Viro } 159*20bc2a3aSAl Viro case MSGGET: 160*20bc2a3aSAl Viro return sys_msgget(first, second); 161*20bc2a3aSAl Viro case MSGCTL: 162*20bc2a3aSAl Viro return compat_sys_msgctl(first, second, compat_ptr(ptr)); 163*20bc2a3aSAl Viro 164*20bc2a3aSAl Viro case SHMAT: { 165*20bc2a3aSAl Viro int err; 166*20bc2a3aSAl Viro unsigned long raddr; 167*20bc2a3aSAl Viro 168*20bc2a3aSAl Viro if (version == 1) 169*20bc2a3aSAl Viro return -EINVAL; 170*20bc2a3aSAl Viro err = do_shmat(first, compat_ptr(ptr), second, &raddr, 171*20bc2a3aSAl Viro COMPAT_SHMLBA); 172*20bc2a3aSAl Viro if (err < 0) 173*20bc2a3aSAl Viro return err; 174*20bc2a3aSAl Viro return put_user(raddr, (compat_ulong_t *)compat_ptr(third)); 175*20bc2a3aSAl Viro } 176*20bc2a3aSAl Viro case SHMDT: 177*20bc2a3aSAl Viro return sys_shmdt(compat_ptr(ptr)); 178*20bc2a3aSAl Viro case SHMGET: 179*20bc2a3aSAl Viro return sys_shmget(first, (unsigned)second, third); 180*20bc2a3aSAl Viro case SHMCTL: 181*20bc2a3aSAl Viro return compat_sys_shmctl(first, second, compat_ptr(ptr)); 182*20bc2a3aSAl Viro } 183*20bc2a3aSAl Viro 184*20bc2a3aSAl Viro return -ENOSYS; 185*20bc2a3aSAl Viro } 186*20bc2a3aSAl Viro #endif 187*20bc2a3aSAl Viro #endif 188