1#include <linux/kernel.h> 2#include <linux/sched.h> 3#include <linux/fs.h> 4#include <linux/file.h> 5#include <linux/sem.h> 6#include <linux/msg.h> 7#include <linux/mm.h> 8#include <linux/shm.h> 9#include <linux/slab.h> 10#include <linux/ipc.h> 11#include <asm/mman.h> 12#include <asm/types.h> 13#include <asm/uaccess.h> 14#include <asm/semaphore.h> 15#include <asm/ipc.h> 16 17#include <asm/ia32.h> 18 19/* 20 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. 21 * 22 * This is really horribly ugly. 23 */ 24 25struct msgbuf32 { 26 s32 mtype; 27 char mtext[1]; 28}; 29 30struct ipc_perm32 { 31 int key; 32 __kernel_uid_t32 uid; 33 __kernel_gid_t32 gid; 34 __kernel_uid_t32 cuid; 35 __kernel_gid_t32 cgid; 36 unsigned short mode; 37 unsigned short seq; 38}; 39 40struct ipc64_perm32 { 41 unsigned key; 42 __kernel_uid32_t32 uid; 43 __kernel_gid32_t32 gid; 44 __kernel_uid32_t32 cuid; 45 __kernel_gid32_t32 cgid; 46 unsigned short mode; 47 unsigned short __pad1; 48 unsigned short seq; 49 unsigned short __pad2; 50 unsigned int unused1; 51 unsigned int unused2; 52}; 53 54struct semid_ds32 { 55 struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */ 56 __kernel_time_t32 sem_otime; /* last semop time */ 57 __kernel_time_t32 sem_ctime; /* last change time */ 58 u32 sem_base; /* ptr to first semaphore in array */ 59 u32 sem_pending; /* pending operations to be processed */ 60 u32 sem_pending_last; /* last pending operation */ 61 u32 undo; /* undo requests on this array */ 62 unsigned short sem_nsems; /* no. of semaphores in array */ 63}; 64 65struct semid64_ds32 { 66 struct ipc64_perm32 sem_perm; 67 __kernel_time_t32 sem_otime; 68 unsigned int __unused1; 69 __kernel_time_t32 sem_ctime; 70 unsigned int __unused2; 71 unsigned int sem_nsems; 72 unsigned int __unused3; 73 unsigned int __unused4; 74}; 75 76struct msqid_ds32 { 77 struct ipc_perm32 msg_perm; 78 u32 msg_first; 79 u32 msg_last; 80 __kernel_time_t32 msg_stime; 81 __kernel_time_t32 msg_rtime; 82 __kernel_time_t32 msg_ctime; 83 u32 wwait; 84 u32 rwait; 85 unsigned short msg_cbytes; 86 unsigned short msg_qnum; 87 unsigned short msg_qbytes; 88 __kernel_ipc_pid_t32 msg_lspid; 89 __kernel_ipc_pid_t32 msg_lrpid; 90}; 91 92struct msqid64_ds32 { 93 struct ipc64_perm32 msg_perm; 94 __kernel_time_t32 msg_stime; 95 unsigned int __unused1; 96 __kernel_time_t32 msg_rtime; 97 unsigned int __unused2; 98 __kernel_time_t32 msg_ctime; 99 unsigned int __unused3; 100 unsigned int msg_cbytes; 101 unsigned int msg_qnum; 102 unsigned int msg_qbytes; 103 __kernel_pid_t32 msg_lspid; 104 __kernel_pid_t32 msg_lrpid; 105 unsigned int __unused4; 106 unsigned int __unused5; 107}; 108 109struct shmid_ds32 { 110 struct ipc_perm32 shm_perm; 111 int shm_segsz; 112 __kernel_time_t32 shm_atime; 113 __kernel_time_t32 shm_dtime; 114 __kernel_time_t32 shm_ctime; 115 __kernel_ipc_pid_t32 shm_cpid; 116 __kernel_ipc_pid_t32 shm_lpid; 117 unsigned short shm_nattch; 118}; 119 120struct shmid64_ds32 { 121 struct ipc64_perm32 shm_perm; 122 __kernel_size_t32 shm_segsz; 123 __kernel_time_t32 shm_atime; 124 unsigned int __unused1; 125 __kernel_time_t32 shm_dtime; 126 unsigned int __unused2; 127 __kernel_time_t32 shm_ctime; 128 unsigned int __unused3; 129 __kernel_pid_t32 shm_cpid; 130 __kernel_pid_t32 shm_lpid; 131 unsigned int shm_nattch; 132 unsigned int __unused4; 133 unsigned int __unused5; 134}; 135 136struct shminfo64_32 { 137 unsigned int shmmax; 138 unsigned int shmmin; 139 unsigned int shmmni; 140 unsigned int shmseg; 141 unsigned int shmall; 142 unsigned int __unused1; 143 unsigned int __unused2; 144 unsigned int __unused3; 145 unsigned int __unused4; 146}; 147 148struct shm_info32 { 149 int used_ids; 150 u32 shm_tot, shm_rss, shm_swp; 151 u32 swap_attempts, swap_successes; 152}; 153 154struct ipc_kludge { 155 u32 msgp; 156 s32 msgtyp; 157}; 158 159 160#define A(__x) ((unsigned long)(__x)) 161#define AA(__x) ((unsigned long)(__x)) 162 163#define SEMOP 1 164#define SEMGET 2 165#define SEMCTL 3 166#define MSGSND 11 167#define MSGRCV 12 168#define MSGGET 13 169#define MSGCTL 14 170#define SHMAT 21 171#define SHMDT 22 172#define SHMGET 23 173#define SHMCTL 24 174 175#define IPCOP_MASK(__x) (1UL << (__x)) 176 177static int 178ipc_parse_version32 (int *cmd) 179{ 180 if (*cmd & IPC_64) { 181 *cmd ^= IPC_64; 182 return IPC_64; 183 } else { 184 return IPC_OLD; 185 } 186} 187 188static int 189semctl32 (int first, int second, int third, void *uptr) 190{ 191 union semun fourth; 192 u32 pad; 193 int err = 0, err2; 194 struct semid64_ds s; 195 mm_segment_t old_fs; 196 int version = ipc_parse_version32(&third); 197 198 if (!uptr) 199 return -EINVAL; 200 if (get_user(pad, (u32 *)uptr)) 201 return -EFAULT; 202 if (third == SETVAL) 203 fourth.val = (int)pad; 204 else 205 fourth.__pad = (void *)A(pad); 206 switch (third) { 207 case IPC_INFO: 208 case IPC_RMID: 209 case IPC_SET: 210 case SEM_INFO: 211 case GETVAL: 212 case GETPID: 213 case GETNCNT: 214 case GETZCNT: 215 case GETALL: 216 case SETVAL: 217 case SETALL: 218 err = sys_semctl(first, second, third, fourth); 219 break; 220 221 case IPC_STAT: 222 case SEM_STAT: 223 fourth.__pad = &s; 224 old_fs = get_fs(); 225 set_fs(KERNEL_DS); 226 err = sys_semctl(first, second|IPC_64, third, fourth); 227 set_fs(old_fs); 228 229 if (version == IPC_64) { 230 struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad); 231 232 if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) { 233 err = -EFAULT; 234 break; 235 } 236 err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key); 237 err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid); 238 err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid); 239 err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid); 240 err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid); 241 err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode); 242 err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq); 243 err2 |= __put_user(s.sem_otime, &usp64->sem_otime); 244 err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime); 245 err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems); 246 } else { 247 struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad); 248 249 if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) { 250 err = -EFAULT; 251 break; 252 } 253 err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key); 254 err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid); 255 err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid); 256 err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid); 257 err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid); 258 err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode); 259 err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq); 260 err2 |= __put_user(s.sem_otime, &usp32->sem_otime); 261 err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime); 262 err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems); 263 } 264 if (err2) 265 err = -EFAULT; 266 break; 267 } 268 return err; 269} 270 271#define MAXBUF (64*1024) 272 273static int 274do_sys32_msgsnd (int first, int second, int third, void *uptr) 275{ 276 struct msgbuf *p; 277 struct msgbuf32 *up = (struct msgbuf32 *)uptr; 278 mm_segment_t old_fs; 279 int err; 280 281 if (second >= MAXBUF-sizeof(struct msgbuf)) 282 return -EINVAL; 283 p = kmalloc(second + sizeof(struct msgbuf), GFP_USER); 284 if (!p) 285 return -ENOMEM; 286 err = get_user(p->mtype, &up->mtype); 287 err |= copy_from_user(p->mtext, &up->mtext, second); 288 if (err) 289 goto out; 290 old_fs = get_fs(); 291 set_fs(KERNEL_DS); 292 err = sys_msgsnd(first, p, second, third); 293 set_fs(old_fs); 294 out: 295 kfree(p); 296 return err; 297} 298 299static int 300do_sys32_msgrcv (int first, int second, int msgtyp, int third, int version, void *uptr) 301{ 302 struct msgbuf32 *up; 303 struct msgbuf *p; 304 mm_segment_t old_fs; 305 int err; 306 307 if (!version) { 308 struct ipc_kludge *uipck = (struct ipc_kludge *)uptr; 309 struct ipc_kludge ipck; 310 311 err = -EINVAL; 312 if (!uptr) 313 goto out; 314 err = -EFAULT; 315 if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge))) 316 goto out; 317 uptr = (void *)A(ipck.msgp); 318 msgtyp = ipck.msgtyp; 319 } 320 if (second >= MAXBUF-sizeof(struct msgbuf)) 321 return -EINVAL; 322 err = -ENOMEM; 323 p = kmalloc(second + sizeof(struct msgbuf), GFP_USER); 324 if (!p) 325 goto out; 326 old_fs = get_fs(); 327 set_fs(KERNEL_DS); 328 err = sys_msgrcv(first, p, second, msgtyp, third); 329 set_fs(old_fs); 330 if (err < 0) 331 goto free_then_out; 332 up = (struct msgbuf32 *)uptr; 333 if (put_user(p->mtype, &up->mtype) || copy_to_user(&up->mtext, p->mtext, err)) 334 err = -EFAULT; 335free_then_out: 336 kfree(p); 337out: 338 return err; 339} 340 341static int 342msgctl32 (int first, int second, void *uptr) 343{ 344 int err = -EINVAL, err2; 345 struct msqid_ds m; 346 struct msqid64_ds m64; 347 struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr; 348 struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr; 349 mm_segment_t old_fs; 350 int version = ipc_parse_version32(&second); 351 352 switch (second) { 353 case IPC_INFO: 354 case IPC_RMID: 355 case MSG_INFO: 356 err = sys_msgctl(first, second, (struct msqid_ds *)uptr); 357 break; 358 359 case IPC_SET: 360 if (version == IPC_64) { 361 err = get_user(m.msg_perm.uid, &up64->msg_perm.uid); 362 err |= get_user(m.msg_perm.gid, &up64->msg_perm.gid); 363 err |= get_user(m.msg_perm.mode, &up64->msg_perm.mode); 364 err |= get_user(m.msg_qbytes, &up64->msg_qbytes); 365 } else { 366 err = get_user(m.msg_perm.uid, &up32->msg_perm.uid); 367 err |= get_user(m.msg_perm.gid, &up32->msg_perm.gid); 368 err |= get_user(m.msg_perm.mode, &up32->msg_perm.mode); 369 err |= get_user(m.msg_qbytes, &up32->msg_qbytes); 370 } 371 if (err) 372 break; 373 old_fs = get_fs(); 374 set_fs(KERNEL_DS); 375 err = sys_msgctl(first, second, &m); 376 set_fs(old_fs); 377 break; 378 379 case IPC_STAT: 380 case MSG_STAT: 381 old_fs = get_fs(); 382 set_fs(KERNEL_DS); 383 err = sys_msgctl(first, second|IPC_64, (void *) &m64); 384 set_fs(old_fs); 385 386 if (version == IPC_64) { 387 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { 388 err = -EFAULT; 389 break; 390 } 391 err2 = __put_user(m64.msg_perm.key, &up64->msg_perm.key); 392 err2 |= __put_user(m64.msg_perm.uid, &up64->msg_perm.uid); 393 err2 |= __put_user(m64.msg_perm.gid, &up64->msg_perm.gid); 394 err2 |= __put_user(m64.msg_perm.cuid, &up64->msg_perm.cuid); 395 err2 |= __put_user(m64.msg_perm.cgid, &up64->msg_perm.cgid); 396 err2 |= __put_user(m64.msg_perm.mode, &up64->msg_perm.mode); 397 err2 |= __put_user(m64.msg_perm.seq, &up64->msg_perm.seq); 398 err2 |= __put_user(m64.msg_stime, &up64->msg_stime); 399 err2 |= __put_user(m64.msg_rtime, &up64->msg_rtime); 400 err2 |= __put_user(m64.msg_ctime, &up64->msg_ctime); 401 err2 |= __put_user(m64.msg_cbytes, &up64->msg_cbytes); 402 err2 |= __put_user(m64.msg_qnum, &up64->msg_qnum); 403 err2 |= __put_user(m64.msg_qbytes, &up64->msg_qbytes); 404 err2 |= __put_user(m64.msg_lspid, &up64->msg_lspid); 405 err2 |= __put_user(m64.msg_lrpid, &up64->msg_lrpid); 406 if (err2) 407 err = -EFAULT; 408 } else { 409 if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) { 410 err = -EFAULT; 411 break; 412 } 413 err2 = __put_user(m64.msg_perm.key, &up32->msg_perm.key); 414 err2 |= __put_user(m64.msg_perm.uid, &up32->msg_perm.uid); 415 err2 |= __put_user(m64.msg_perm.gid, &up32->msg_perm.gid); 416 err2 |= __put_user(m64.msg_perm.cuid, &up32->msg_perm.cuid); 417 err2 |= __put_user(m64.msg_perm.cgid, &up32->msg_perm.cgid); 418 err2 |= __put_user(m64.msg_perm.mode, &up32->msg_perm.mode); 419 err2 |= __put_user(m64.msg_perm.seq, &up32->msg_perm.seq); 420 err2 |= __put_user(m64.msg_stime, &up32->msg_stime); 421 err2 |= __put_user(m64.msg_rtime, &up32->msg_rtime); 422 err2 |= __put_user(m64.msg_ctime, &up32->msg_ctime); 423 err2 |= __put_user(m64.msg_cbytes, &up32->msg_cbytes); 424 err2 |= __put_user(m64.msg_qnum, &up32->msg_qnum); 425 err2 |= __put_user(m64.msg_qbytes, &up32->msg_qbytes); 426 err2 |= __put_user(m64.msg_lspid, &up32->msg_lspid); 427 err2 |= __put_user(m64.msg_lrpid, &up32->msg_lrpid); 428 if (err2) 429 err = -EFAULT; 430 } 431 break; 432 } 433 return err; 434} 435 436static int 437shmat32 (int first, int second, int third, int version, void *uptr) 438{ 439 unsigned long raddr; 440 u32 *uaddr = (u32 *)A((u32)third); 441 int err; 442 443 if (version == 1) 444 return -EINVAL; /* iBCS2 emulator entry point: unsupported */ 445 err = sys_shmat(first, uptr, second, &raddr); 446 if (err) 447 return err; 448 return put_user(raddr, uaddr); 449} 450 451static int put_shmid64(struct shmid64_ds *s64p, void *uptr, int version) 452{ 453 int err2; 454#define s64 (*s64p) 455 if (version == IPC_64) { 456 struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr; 457 458 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) 459 return -EFAULT; 460 461 err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key); 462 err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid); 463 err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid); 464 err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid); 465 err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid); 466 err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode); 467 err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq); 468 err2 |= __put_user(s64.shm_atime, &up64->shm_atime); 469 err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime); 470 err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime); 471 err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz); 472 err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch); 473 err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid); 474 err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid); 475 } else { 476 struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr; 477 478 if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) 479 return -EFAULT; 480 481 err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key); 482 err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid); 483 err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid); 484 err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid); 485 err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid); 486 err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode); 487 err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq); 488 err2 |= __put_user(s64.shm_atime, &up32->shm_atime); 489 err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime); 490 err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime); 491 err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz); 492 err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch); 493 err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid); 494 err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid); 495 } 496#undef s64 497 return err2 ? -EFAULT : 0; 498} 499static int 500shmctl32 (int first, int second, void *uptr) 501{ 502 int err = -EFAULT, err2; 503 struct shmid_ds s; 504 struct shmid64_ds s64; 505 mm_segment_t old_fs; 506 struct shm_info32 *uip = (struct shm_info32 *)uptr; 507 struct shm_info si; 508 int version = ipc_parse_version32(&second); 509 struct shminfo64 smi; 510 struct shminfo *usi32 = (struct shminfo *) uptr; 511 struct shminfo64_32 *usi64 = (struct shminfo64_32 *) uptr; 512 513 switch (second) { 514 case IPC_INFO: 515 old_fs = get_fs(); 516 set_fs(KERNEL_DS); 517 err = sys_shmctl(first, second|IPC_64, (struct shmid_ds *)&smi); 518 set_fs(old_fs); 519 520 if (version == IPC_64) { 521 if (!access_ok(VERIFY_WRITE, usi64, sizeof(*usi64))) { 522 err = -EFAULT; 523 break; 524 } 525 err2 = __put_user(smi.shmmax, &usi64->shmmax); 526 err2 |= __put_user(smi.shmmin, &usi64->shmmin); 527 err2 |= __put_user(smi.shmmni, &usi64->shmmni); 528 err2 |= __put_user(smi.shmseg, &usi64->shmseg); 529 err2 |= __put_user(smi.shmall, &usi64->shmall); 530 } else { 531 if (!access_ok(VERIFY_WRITE, usi32, sizeof(*usi32))) { 532 err = -EFAULT; 533 break; 534 } 535 err2 = __put_user(smi.shmmax, &usi32->shmmax); 536 err2 |= __put_user(smi.shmmin, &usi32->shmmin); 537 err2 |= __put_user(smi.shmmni, &usi32->shmmni); 538 err2 |= __put_user(smi.shmseg, &usi32->shmseg); 539 err2 |= __put_user(smi.shmall, &usi32->shmall); 540 } 541 if (err2) 542 err = -EFAULT; 543 break; 544 545 case IPC_RMID: 546 case SHM_LOCK: 547 case SHM_UNLOCK: 548 err = sys_shmctl(first, second, (struct shmid_ds *)uptr); 549 break; 550 551 case IPC_SET: 552 if (version == IPC_64) { 553 struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr; 554 err = get_user(s.shm_perm.uid, &up64->shm_perm.uid); 555 err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid); 556 err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode); 557 } else { 558 struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr; 559 err = get_user(s.shm_perm.uid, &up32->shm_perm.uid); 560 err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid); 561 err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode); 562 } 563 if (err) 564 break; 565 old_fs = get_fs(); 566 set_fs(KERNEL_DS); 567 err = sys_shmctl(first, second, &s); 568 set_fs(old_fs); 569 break; 570 571 case IPC_STAT: 572 case SHM_STAT: 573 old_fs = get_fs(); 574 set_fs(KERNEL_DS); 575 err = sys_shmctl(first, second|IPC_64, (void *) &s64); 576 set_fs(old_fs); 577 578 if (err < 0) 579 break; 580 err2 = put_shmid64(&s64, uptr, version); 581 if (err2) 582 err = err2; 583 break; 584 585 case SHM_INFO: 586 old_fs = get_fs(); 587 set_fs(KERNEL_DS); 588 err = sys_shmctl(first, second, (void *)&si); 589 set_fs(old_fs); 590 if (err < 0) 591 break; 592 593 if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip))) { 594 err = -EFAULT; 595 break; 596 } 597 err2 = __put_user(si.used_ids, &uip->used_ids); 598 err2 |= __put_user(si.shm_tot, &uip->shm_tot); 599 err2 |= __put_user(si.shm_rss, &uip->shm_rss); 600 err2 |= __put_user(si.shm_swp, &uip->shm_swp); 601 err2 |= __put_user(si.swap_attempts, &uip->swap_attempts); 602 err2 |= __put_user(si.swap_successes, &uip->swap_successes); 603 if (err2) 604 err = -EFAULT; 605 break; 606 607 } 608 return err; 609} 610 611asmlinkage long 612sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) 613{ 614 int version; 615 616 version = call >> 16; /* hack for backward compatibility */ 617 call &= 0xffff; 618 619 switch (call) { 620 case SEMOP: 621 /* struct sembuf is the same on 32 and 64bit :)) */ 622 return sys_semop(first, (struct sembuf *)AA(ptr), second); 623 case SEMGET: 624 return sys_semget(first, second, third); 625 case SEMCTL: 626 return semctl32(first, second, third, (void *)AA(ptr)); 627 628 case MSGSND: 629 return do_sys32_msgsnd(first, second, third, (void *)AA(ptr)); 630 case MSGRCV: 631 return do_sys32_msgrcv(first, second, fifth, third, version, (void *)AA(ptr)); 632 case MSGGET: 633 return sys_msgget((key_t) first, second); 634 case MSGCTL: 635 return msgctl32(first, second, (void *)AA(ptr)); 636 637 case SHMAT: 638 return shmat32(first, second, third, version, (void *)AA(ptr)); 639 break; 640 case SHMDT: 641 return sys_shmdt((char *)AA(ptr)); 642 case SHMGET: 643 return sys_shmget(first, second, third); 644 case SHMCTL: 645 return shmctl32(first, second, (void *)AA(ptr)); 646 647 default: 648 return -EINVAL; 649 } 650 return -EINVAL; 651} 652 653