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