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