1 #include <linux/kernel.h>
2 #include <linux/sched.h>
4 #include <linux/file.h>
9 #include <linux/slab.h>
10 #include <linux/ipc.h>
12 #include <asm/types.h>
13 #include <asm/uaccess.h>
14 #include <asm/semaphore.h>
19 extern int sem_ctls[];
22 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
24 * This is really horribly ugly.
36 __kernel_uid_t32 cuid;
37 __kernel_gid_t32 cgid;
44 __kernel_uid32_t32 uid;
45 __kernel_gid32_t32 gid;
46 __kernel_uid32_t32 cuid;
47 __kernel_gid32_t32 cgid;
49 unsigned short __pad1;
51 unsigned short __pad2;
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 */
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;
79 struct ipc_perm32 msg_perm;
82 __kernel_time_t32 msg_stime;
83 __kernel_time_t32 msg_rtime;
84 __kernel_time_t32 msg_ctime;
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;
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;
112 struct ipc_perm32 shm_perm;
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;
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;
138 struct shminfo64_32 {
144 unsigned int __unused1;
145 unsigned int __unused2;
146 unsigned int __unused3;
147 unsigned int __unused4;
152 u32 shm_tot, shm_rss, shm_swp;
153 u32 swap_attempts, swap_successes;
162 #define A(__x) ((unsigned long)(__x))
163 #define AA(__x) ((unsigned long)(__x))
178 #define IPCOP_MASK(__x) (1UL << (__x))
181 ipc_parse_version32 (int *cmd)
191 static int put_semid(void *user_semid, struct semid64_ds *s, int version)
196 struct semid64_ds32 *usp64 = (struct semid64_ds32 *) user_semid;
198 if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) {
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);
215 struct semid_ds32 *usp32 = (struct semid_ds32 *) user_semid;
217 if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) {
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);
238 semctl32 (int first, int second, int third, void *uptr)
245 int version = ipc_parse_version32(&third);
249 if (get_user(pad, (u32 *)uptr))
252 fourth.val = (int)pad;
254 fourth.__pad = (void *)A(pad);
267 err = sys_semctl(first, second, third, fourth);
275 err = sys_semctl(first, second, third|IPC_64, fourth);
279 err = put_semid((void *)A(pad), &s, version);
289 #define MAXBUF (64*1024)
292 do_sys32_msgsnd (int first, int second, int third, void *uptr)
295 struct msgbuf32 *up = (struct msgbuf32 *)uptr;
299 if (second >= MAXBUF-sizeof(struct msgbuf))
301 p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
304 err = get_user(p->mtype, &up->mtype);
305 err |= (copy_from_user(p->mtext, &up->mtext, second) ? -EFAULT : 0);
310 err = sys_msgsnd(first, p, second, third);
318 do_sys32_msgrcv (int first, int second, int msgtyp, int third, int version, void *uptr)
326 struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
327 struct ipc_kludge ipck;
333 if (copy_from_user(&ipck, uipck, sizeof(struct ipc_kludge)))
335 uptr = (void *)A(ipck.msgp);
336 msgtyp = ipck.msgtyp;
338 if (second >= MAXBUF-sizeof(struct msgbuf))
341 p = kmalloc(second + sizeof(struct msgbuf), GFP_USER);
346 err = sys_msgrcv(first, p, second, msgtyp, third);
350 up = (struct msgbuf32 *)uptr;
351 if (put_user(p->mtype, &up->mtype) || copy_to_user(&up->mtext, p->mtext, err))
360 msgctl32 (int first, int second, void *uptr)
362 int err = -EINVAL, err2;
364 struct msqid64_ds m64;
365 struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr;
366 struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr;
368 int version = ipc_parse_version32(&second);
374 err = sys_msgctl(first, second, (struct msqid_ds *)uptr);
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);
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);
393 err = sys_msgctl(first, second, &m);
401 err = sys_msgctl(first, second|IPC_64, (void *) &m64);
404 if (version == IPC_64) {
405 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
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);
427 if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
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);
455 shmat32 (int first, int second, int third, int version, void *uptr)
458 u32 *uaddr = (u32 *)A((u32)third);
462 return -EINVAL; /* iBCS2 emulator entry point: unsupported */
463 err = sys_shmat(first, uptr, second, &raddr);
466 return put_user(raddr, uaddr);
469 static int put_shmid64(struct shmid64_ds *s64p, void *uptr, int version)
473 if (version == IPC_64) {
474 struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
476 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
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);
494 struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
496 if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32)))
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);
515 return err2 ? -EFAULT : 0;
518 shmctl32 (int first, int second, void *uptr)
520 int err = -EFAULT, err2;
522 struct shmid64_ds s64;
524 struct shm_info32 *uip = (struct shm_info32 *)uptr;
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;
535 err = sys_shmctl(first, second|IPC_64, (struct shmid_ds *)&smi);
538 if (version == IPC_64) {
539 if (!access_ok(VERIFY_WRITE, usi64, sizeof(*usi64))) {
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);
549 if (!access_ok(VERIFY_WRITE, usi32, sizeof(*usi32))) {
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);
566 err = sys_shmctl(first, second, (struct shmid_ds *)uptr);
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);
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);
585 err = sys_shmctl(first, second, &s);
593 err = sys_shmctl(first, second|IPC_64, (void *) &s64);
598 err2 = put_shmid64(&s64, uptr, version);
606 err = sys_shmctl(first, second, (void *)&si);
611 if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip))) {
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);
634 sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
638 version = call >> 16; /* hack for backward compatibility */
643 /* struct sembuf is the same on 32 and 64bit :)) */
644 return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, NULL);
647 mm_segment_t oldfs = get_fs();
648 struct timespec32 *ts32 = (struct timespec32 *)AA(fifth);
650 if ((unsigned)second > sem_ctls[2])
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)))
660 err = sys_semtimedop(first, (struct sembuf *)AA(ptr), second,
666 return sys_semget(first, second, third);
668 return semctl32(first, second, third, (void *)AA(ptr));
671 return do_sys32_msgsnd(first, second, third, (void *)AA(ptr));
673 return do_sys32_msgrcv(first, second, fifth, third, version, (void *)AA(ptr));
675 return sys_msgget((key_t) first, second);
677 return msgctl32(first, second, (void *)AA(ptr));
680 return shmat32(first, second, third, version, (void *)AA(ptr));
683 return sys_shmdt((char *)AA(ptr));
685 return sys_shmget(first, second, third);
687 return shmctl32(first, second, (void *)AA(ptr));