1*542f82ceSmaxv /* $NetBSD: linux_ipc.c,v 1.57 2019/08/23 10:22:15 maxv Exp $ */
2d4649701Serh
3d4649701Serh /*-
48096c25aSfvdl * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
5d4649701Serh * All rights reserved.
6d4649701Serh *
7d4649701Serh * This code is derived from software contributed to The NetBSD Foundation
88096c25aSfvdl * by Frank van der Linden and Eric Haszlakiewicz.
9d4649701Serh *
10d4649701Serh * Redistribution and use in source and binary forms, with or without
11d4649701Serh * modification, are permitted provided that the following conditions
12d4649701Serh * are met:
13d4649701Serh * 1. Redistributions of source code must retain the above copyright
14d4649701Serh * notice, this list of conditions and the following disclaimer.
15d4649701Serh * 2. Redistributions in binary form must reproduce the above copyright
16d4649701Serh * notice, this list of conditions and the following disclaimer in the
17d4649701Serh * documentation and/or other materials provided with the distribution.
18d4649701Serh *
19d4649701Serh * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20d4649701Serh * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21d4649701Serh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22d4649701Serh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23d4649701Serh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24d4649701Serh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25d4649701Serh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26d4649701Serh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27d4649701Serh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28d4649701Serh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29d4649701Serh * POSSIBILITY OF SUCH DAMAGE.
30d4649701Serh */
313bf459f3Sfvdl
32dab6ef8bSlukem #include <sys/cdefs.h>
33*542f82ceSmaxv __KERNEL_RCSID(0, "$NetBSD: linux_ipc.c,v 1.57 2019/08/23 10:22:15 maxv Exp $");
34dab6ef8bSlukem
356a89288aSmrg #if defined(_KERNEL_OPT)
36d9a22c58Serh #include "opt_sysv.h"
37011229ffSjdolecek #endif
38d9a22c58Serh
393bf459f3Sfvdl #include <sys/param.h>
403bf459f3Sfvdl #include <sys/shm.h>
4102b3c95bSfvdl #include <sys/sem.h>
423bf459f3Sfvdl #include <sys/msg.h>
433bf459f3Sfvdl #include <sys/proc.h>
443bf459f3Sfvdl #include <sys/systm.h>
4529158b16Snjoly #include <sys/vnode.h>
463bf459f3Sfvdl
473bf459f3Sfvdl #include <sys/mount.h>
483bf459f3Sfvdl #include <sys/syscallargs.h>
493bf459f3Sfvdl
50908291d2Schristos #include <compat/linux/common/linux_types.h>
51908291d2Schristos #include <compat/linux/common/linux_signal.h>
52908291d2Schristos #include <compat/linux/common/linux_util.h>
53908291d2Schristos #include <compat/linux/common/linux_ipc.h>
54908291d2Schristos #include <compat/linux/common/linux_msg.h>
55908291d2Schristos #include <compat/linux/common/linux_shm.h>
56908291d2Schristos #include <compat/linux/common/linux_sem.h>
573bf459f3Sfvdl
58ee0c5b44Smanu #include <compat/linux/linux_syscallargs.h>
59ee0c5b44Smanu #include <compat/linux/linux_syscall.h>
60ee0c5b44Smanu
61663b29bbSdogcow #include <compat/linux/common/linux_ipccall.h>
624eecf433Snjoly #include <compat/linux/common/linux_machdep.h>
63663b29bbSdogcow
643bf459f3Sfvdl /*
65d4649701Serh * Note: Not all linux architechtures have explicit versions
66d4649701Serh * of the SYSV* syscalls. On the ones that don't
67d4649701Serh * we pretend that they are defined anyway. *_args and
68d4649701Serh * prototypes are defined in individual headers;
69d4649701Serh * syscalls.master lists those syscalls as NOARGS.
703bf459f3Sfvdl *
71d4649701Serh * The functions in multiarch are the ones that just need
72d4649701Serh * the arguments shuffled around and then use the
73d4649701Serh * normal NetBSD syscall.
74d4649701Serh *
75d4649701Serh * Function in multiarch:
76d4649701Serh * linux_sys_ipc : linux_ipccall.c
771ff2a8d0Salnsn * linux_semop : linux_ipccall.c
78d4649701Serh * linux_semget : linux_ipccall.c
79d4649701Serh * linux_msgsnd : linux_ipccall.c
80d4649701Serh * linux_msgrcv : linux_ipccall.c
81d4649701Serh * linux_msgget : linux_ipccall.c
82d4649701Serh * linux_shmdt : linux_ipccall.c
83d4649701Serh * linux_shmget : linux_ipccall.c
843bf459f3Sfvdl */
853bf459f3Sfvdl
862452eadcSfvdl #if defined (SYSVSEM) || defined(SYSVSHM) || defined(SYSVMSG)
873bf459f3Sfvdl /*
883bf459f3Sfvdl * Convert between Linux and NetBSD ipc_perm structures. Only the
893bf459f3Sfvdl * order of the fields is different.
903bf459f3Sfvdl */
91d4649701Serh void
linux_to_bsd_ipc_perm(struct linux_ipc_perm * lpp,struct ipc_perm * bpp)9228bae79bSdsl linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
933bf459f3Sfvdl {
94245f292fSmycroft
952c358fcaSthorpej bpp->_key = lpp->l_key;
963bf459f3Sfvdl bpp->uid = lpp->l_uid;
973bf459f3Sfvdl bpp->gid = lpp->l_gid;
983bf459f3Sfvdl bpp->cuid = lpp->l_cuid;
993bf459f3Sfvdl bpp->cgid = lpp->l_cgid;
1003bf459f3Sfvdl bpp->mode = lpp->l_mode;
1012c358fcaSthorpej bpp->_seq = lpp->l_seq;
1023bf459f3Sfvdl }
1033bf459f3Sfvdl
104d4649701Serh void
linux_to_bsd_ipc64_perm(struct linux_ipc64_perm * lpp,struct ipc_perm * bpp)10528bae79bSdsl linux_to_bsd_ipc64_perm(struct linux_ipc64_perm *lpp, struct ipc_perm *bpp)
10665de380aSchristos {
10765de380aSchristos bpp->_key = lpp->l_key;
10865de380aSchristos bpp->uid = lpp->l_uid;
10965de380aSchristos bpp->gid = lpp->l_gid;
11065de380aSchristos bpp->cuid = lpp->l_cuid;
11165de380aSchristos bpp->cgid = lpp->l_cgid;
11265de380aSchristos bpp->mode = lpp->l_mode;
11365de380aSchristos bpp->_seq = lpp->l_seq;
11465de380aSchristos }
11565de380aSchristos
11665de380aSchristos void
bsd_to_linux_ipc_perm(struct ipc_perm * bpp,struct linux_ipc_perm * lpp)11728bae79bSdsl bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
1183bf459f3Sfvdl {
119245f292fSmycroft
12039e3203eSmrg memset(lpp, 0, sizeof *lpp);
1212c358fcaSthorpej lpp->l_key = bpp->_key;
1223bf459f3Sfvdl lpp->l_uid = bpp->uid;
1233bf459f3Sfvdl lpp->l_gid = bpp->gid;
1243bf459f3Sfvdl lpp->l_cuid = bpp->cuid;
1253bf459f3Sfvdl lpp->l_cgid = bpp->cgid;
1263bf459f3Sfvdl lpp->l_mode = bpp->mode;
1272c358fcaSthorpej lpp->l_seq = bpp->_seq;
1283bf459f3Sfvdl }
12965de380aSchristos
13065de380aSchristos void
bsd_to_linux_ipc64_perm(struct ipc_perm * bpp,struct linux_ipc64_perm * lpp)13128bae79bSdsl bsd_to_linux_ipc64_perm(struct ipc_perm *bpp, struct linux_ipc64_perm *lpp)
13265de380aSchristos {
13339e3203eSmrg
13439e3203eSmrg memset(lpp, 0, sizeof *lpp);
13565de380aSchristos lpp->l_key = bpp->_key;
13665de380aSchristos lpp->l_uid = bpp->uid;
13765de380aSchristos lpp->l_gid = bpp->gid;
13865de380aSchristos lpp->l_cuid = bpp->cuid;
13965de380aSchristos lpp->l_cgid = bpp->cgid;
14065de380aSchristos lpp->l_mode = bpp->mode;
14165de380aSchristos lpp->l_seq = bpp->_seq;
14265de380aSchristos }
14365de380aSchristos
1442452eadcSfvdl #endif
1453bf459f3Sfvdl
1463bf459f3Sfvdl #ifdef SYSVSEM
1473bf459f3Sfvdl /*
14802b3c95bSfvdl * Semaphore operations. Most constants and structures are the same on
14902b3c95bSfvdl * both systems. Only semctl() needs some extra work.
1503bf459f3Sfvdl */
15102b3c95bSfvdl
15202b3c95bSfvdl /*
15302b3c95bSfvdl * Convert between Linux and NetBSD semid_ds structures.
15402b3c95bSfvdl */
155d4649701Serh void
bsd_to_linux_semid_ds(struct semid_ds * bs,struct linux_semid_ds * ls)15628bae79bSdsl bsd_to_linux_semid_ds(struct semid_ds *bs, struct linux_semid_ds *ls)
15702b3c95bSfvdl {
15839e3203eSmrg
15939e3203eSmrg memset(ls, 0, sizeof *ls);
16002b3c95bSfvdl bsd_to_linux_ipc_perm(&bs->sem_perm, &ls->l_sem_perm);
16102b3c95bSfvdl ls->l_sem_otime = bs->sem_otime;
16202b3c95bSfvdl ls->l_sem_ctime = bs->sem_ctime;
16302b3c95bSfvdl ls->l_sem_nsems = bs->sem_nsems;
16402b3c95bSfvdl }
16502b3c95bSfvdl
166d4649701Serh void
bsd_to_linux_semid64_ds(struct semid_ds * bs,struct linux_semid64_ds * ls)167436fa0efSnjoly bsd_to_linux_semid64_ds(struct semid_ds *bs, struct linux_semid64_ds *ls)
168436fa0efSnjoly {
16939e3203eSmrg
17039e3203eSmrg memset(ls, 0, sizeof *ls);
171436fa0efSnjoly bsd_to_linux_ipc64_perm(&bs->sem_perm, &ls->l_sem_perm);
172436fa0efSnjoly ls->l_sem_otime = bs->sem_otime;
173436fa0efSnjoly ls->l_sem_ctime = bs->sem_ctime;
174436fa0efSnjoly ls->l_sem_nsems = bs->sem_nsems;
175436fa0efSnjoly }
176436fa0efSnjoly
177436fa0efSnjoly void
linux_to_bsd_semid_ds(struct linux_semid_ds * ls,struct semid_ds * bs)17828bae79bSdsl linux_to_bsd_semid_ds(struct linux_semid_ds *ls, struct semid_ds *bs)
17902b3c95bSfvdl {
18039e3203eSmrg
18102b3c95bSfvdl linux_to_bsd_ipc_perm(&ls->l_sem_perm, &bs->sem_perm);
18202b3c95bSfvdl bs->sem_otime = ls->l_sem_otime;
18302b3c95bSfvdl bs->sem_ctime = ls->l_sem_ctime;
18402b3c95bSfvdl bs->sem_nsems = ls->l_sem_nsems;
18502b3c95bSfvdl }
18602b3c95bSfvdl
187436fa0efSnjoly void
linux_to_bsd_semid64_ds(struct linux_semid64_ds * ls,struct semid_ds * bs)188436fa0efSnjoly linux_to_bsd_semid64_ds(struct linux_semid64_ds *ls, struct semid_ds *bs)
189436fa0efSnjoly {
19039e3203eSmrg
191436fa0efSnjoly linux_to_bsd_ipc64_perm(&ls->l_sem_perm, &bs->sem_perm);
192436fa0efSnjoly bs->sem_otime = ls->l_sem_otime;
193436fa0efSnjoly bs->sem_ctime = ls->l_sem_ctime;
194436fa0efSnjoly bs->sem_nsems = ls->l_sem_nsems;
195436fa0efSnjoly }
196436fa0efSnjoly
19702b3c95bSfvdl /*
1982c358fcaSthorpej * Most of this can be handled by directly passing the arguments on; we
1992c358fcaSthorpej * just need to frob the `cmd' and convert the semid_ds and semun.
20002b3c95bSfvdl */
2013bf459f3Sfvdl int
linux_sys_semctl(struct lwp * l,const struct linux_sys_semctl_args * uap,register_t * retval)2027e2790cfSdsl linux_sys_semctl(struct lwp *l, const struct linux_sys_semctl_args *uap, register_t *retval)
2033bf459f3Sfvdl {
2047e2790cfSdsl /* {
205d4649701Serh syscallarg(int) semid;
206d4649701Serh syscallarg(int) semnum;
207d4649701Serh syscallarg(int) cmd;
208d4649701Serh syscallarg(union linux_semun) arg;
2097e2790cfSdsl } */
2102c358fcaSthorpej struct semid_ds sembuf;
2112c358fcaSthorpej struct linux_semid_ds lsembuf;
212436fa0efSnjoly struct linux_semid64_ds lsembuf64;
2132c358fcaSthorpej union __semun semun;
214436fa0efSnjoly int cmd, lcmd, error;
2152c358fcaSthorpej void *pass_arg = NULL;
21602b3c95bSfvdl
217436fa0efSnjoly lcmd = SCARG(uap, cmd);
218436fa0efSnjoly #ifdef LINUX_IPC_FORCE64
219436fa0efSnjoly lcmd |= LINUX_IPC_64;
220436fa0efSnjoly #endif
2212c358fcaSthorpej
222d3dabe12Snjoly switch (lcmd & ~LINUX_IPC_64) {
223769c9d47Smycroft case LINUX_IPC_SET:
224d3dabe12Snjoly if (lcmd & LINUX_IPC_64) {
225436fa0efSnjoly error = copyin(SCARG(uap, arg).l_buf, &lsembuf64,
226436fa0efSnjoly sizeof(lsembuf64));
227d3dabe12Snjoly linux_to_bsd_semid64_ds(&lsembuf64, &sembuf);
228d3dabe12Snjoly } else {
229d3dabe12Snjoly error = copyin(SCARG(uap, arg).l_buf, &lsembuf,
230d3dabe12Snjoly sizeof(lsembuf));
231d3dabe12Snjoly linux_to_bsd_semid_ds(&lsembuf, &sembuf);
232d3dabe12Snjoly }
233436fa0efSnjoly if (error)
234436fa0efSnjoly return (error);
2352c358fcaSthorpej pass_arg = &sembuf;
2362c358fcaSthorpej cmd = IPC_SET;
237d4649701Serh break;
2382c358fcaSthorpej
2392c358fcaSthorpej case LINUX_IPC_STAT:
2402c358fcaSthorpej pass_arg = &sembuf;
2412c358fcaSthorpej cmd = IPC_STAT;
2422c358fcaSthorpej break;
2432c358fcaSthorpej
244769c9d47Smycroft case LINUX_IPC_RMID:
2452c358fcaSthorpej cmd = IPC_RMID;
246769c9d47Smycroft break;
2472c358fcaSthorpej
248769c9d47Smycroft case LINUX_GETVAL:
2492c358fcaSthorpej cmd = GETVAL;
250769c9d47Smycroft break;
2512c358fcaSthorpej
252769c9d47Smycroft case LINUX_GETPID:
2532c358fcaSthorpej cmd = GETPID;
254769c9d47Smycroft break;
2552c358fcaSthorpej
256769c9d47Smycroft case LINUX_GETNCNT:
2572c358fcaSthorpej cmd = GETNCNT;
258769c9d47Smycroft break;
2592c358fcaSthorpej
260769c9d47Smycroft case LINUX_GETZCNT:
2612c358fcaSthorpej cmd = GETZCNT;
262769c9d47Smycroft break;
2632c358fcaSthorpej
264c0567a6bStron case LINUX_GETALL:
2652c358fcaSthorpej pass_arg = &semun;
2662c358fcaSthorpej semun.array = SCARG(uap, arg).l_array;
2672c358fcaSthorpej cmd = GETALL;
268c0567a6bStron break;
2692c358fcaSthorpej
2702c358fcaSthorpej case LINUX_SETVAL:
2712c358fcaSthorpej pass_arg = &semun;
2722c358fcaSthorpej semun.val = SCARG(uap, arg).l_val;
2732c358fcaSthorpej cmd = SETVAL;
2742c358fcaSthorpej break;
2752c358fcaSthorpej
276c0567a6bStron case LINUX_SETALL:
2772c358fcaSthorpej pass_arg = &semun;
2782c358fcaSthorpej semun.array = SCARG(uap, arg).l_array;
2792c358fcaSthorpej cmd = SETALL;
280769c9d47Smycroft break;
2812c358fcaSthorpej
28202b3c95bSfvdl default:
2832c358fcaSthorpej return (EINVAL);
28402b3c95bSfvdl }
2852c358fcaSthorpej
286f474dcebSad error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd,
2872c358fcaSthorpej pass_arg, retval);
288436fa0efSnjoly if (error)
289436fa0efSnjoly return error;
2902c358fcaSthorpej
291436fa0efSnjoly switch (lcmd) {
292436fa0efSnjoly case LINUX_IPC_STAT:
2932c358fcaSthorpej bsd_to_linux_semid_ds(&sembuf, &lsembuf);
2942c358fcaSthorpej error = copyout(&lsembuf, SCARG(uap, arg).l_buf,
2952c358fcaSthorpej sizeof(lsembuf));
296436fa0efSnjoly break;
297436fa0efSnjoly case LINUX_IPC_STAT | LINUX_IPC_64:
298436fa0efSnjoly bsd_to_linux_semid64_ds(&sembuf, &lsembuf64);
299436fa0efSnjoly error = copyout(&lsembuf64, SCARG(uap, arg).l_buf,
300436fa0efSnjoly sizeof(lsembuf64));
301436fa0efSnjoly break;
302436fa0efSnjoly default:
303436fa0efSnjoly break;
3042c358fcaSthorpej }
3052c358fcaSthorpej
3062c358fcaSthorpej return (error);
3073bf459f3Sfvdl }
3083bf459f3Sfvdl #endif /* SYSVSEM */
3093bf459f3Sfvdl
3103bf459f3Sfvdl #ifdef SYSVMSG
31102b3c95bSfvdl
312d4649701Serh void
linux_to_bsd_msqid_ds(struct linux_msqid_ds * lmp,struct msqid_ds * bmp)31328bae79bSdsl linux_to_bsd_msqid_ds(struct linux_msqid_ds *lmp, struct msqid_ds *bmp)
31402b3c95bSfvdl {
315245f292fSmycroft
316bf54b26cSjoerg memset(bmp, 0, sizeof(*bmp));
31702b3c95bSfvdl linux_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm);
3182c358fcaSthorpej bmp->_msg_cbytes = lmp->l_msg_cbytes;
31902b3c95bSfvdl bmp->msg_qnum = lmp->l_msg_qnum;
32002b3c95bSfvdl bmp->msg_qbytes = lmp->l_msg_qbytes;
32102b3c95bSfvdl bmp->msg_lspid = lmp->l_msg_lspid;
32202b3c95bSfvdl bmp->msg_lrpid = lmp->l_msg_lrpid;
32302b3c95bSfvdl bmp->msg_stime = lmp->l_msg_stime;
32402b3c95bSfvdl bmp->msg_rtime = lmp->l_msg_rtime;
32502b3c95bSfvdl bmp->msg_ctime = lmp->l_msg_ctime;
32602b3c95bSfvdl }
32702b3c95bSfvdl
328d4649701Serh void
linux_to_bsd_msqid64_ds(struct linux_msqid64_ds * lmp,struct msqid_ds * bmp)329e82000b5Snjoly linux_to_bsd_msqid64_ds(struct linux_msqid64_ds *lmp, struct msqid_ds *bmp)
330e82000b5Snjoly {
331bf54b26cSjoerg
332bf54b26cSjoerg memset(bmp, 0, sizeof(*bmp));
333e82000b5Snjoly linux_to_bsd_ipc64_perm(&lmp->l_msg_perm, &bmp->msg_perm);
33439e3203eSmrg bmp->_msg_cbytes = lmp->l_msg_cbytes;
335e82000b5Snjoly bmp->msg_stime = lmp->l_msg_stime;
336e82000b5Snjoly bmp->msg_rtime = lmp->l_msg_rtime;
337e82000b5Snjoly bmp->msg_ctime = lmp->l_msg_ctime;
338e82000b5Snjoly bmp->msg_qnum = lmp->l_msg_qnum;
339e82000b5Snjoly bmp->msg_qbytes = lmp->l_msg_qbytes;
340e82000b5Snjoly bmp->msg_lspid = lmp->l_msg_lspid;
341e82000b5Snjoly bmp->msg_lrpid = lmp->l_msg_lrpid;
342e82000b5Snjoly }
343e82000b5Snjoly
344e82000b5Snjoly void
bsd_to_linux_msqid_ds(struct msqid_ds * bmp,struct linux_msqid_ds * lmp)34528bae79bSdsl bsd_to_linux_msqid_ds(struct msqid_ds *bmp, struct linux_msqid_ds *lmp)
34602b3c95bSfvdl {
347245f292fSmycroft
348bf54b26cSjoerg memset(lmp, 0, sizeof(*lmp));
34902b3c95bSfvdl bsd_to_linux_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm);
3502c358fcaSthorpej lmp->l_msg_cbytes = bmp->_msg_cbytes;
35102b3c95bSfvdl lmp->l_msg_qnum = bmp->msg_qnum;
35202b3c95bSfvdl lmp->l_msg_qbytes = bmp->msg_qbytes;
35302b3c95bSfvdl lmp->l_msg_lspid = bmp->msg_lspid;
35402b3c95bSfvdl lmp->l_msg_lrpid = bmp->msg_lrpid;
35502b3c95bSfvdl lmp->l_msg_stime = bmp->msg_stime;
35602b3c95bSfvdl lmp->l_msg_rtime = bmp->msg_rtime;
35702b3c95bSfvdl lmp->l_msg_ctime = bmp->msg_ctime;
35802b3c95bSfvdl }
35902b3c95bSfvdl
360e82000b5Snjoly void
bsd_to_linux_msqid64_ds(struct msqid_ds * bmp,struct linux_msqid64_ds * lmp)361e82000b5Snjoly bsd_to_linux_msqid64_ds(struct msqid_ds *bmp, struct linux_msqid64_ds *lmp)
362e82000b5Snjoly {
363bf54b26cSjoerg
364bf54b26cSjoerg memset(lmp, 0, sizeof(*lmp));
365e82000b5Snjoly bsd_to_linux_ipc64_perm(&bmp->msg_perm, &lmp->l_msg_perm);
36639e3203eSmrg lmp->l_msg_cbytes = bmp->_msg_cbytes;
367e82000b5Snjoly lmp->l_msg_stime = bmp->msg_stime;
368e82000b5Snjoly lmp->l_msg_rtime = bmp->msg_rtime;
369e82000b5Snjoly lmp->l_msg_ctime = bmp->msg_ctime;
370e82000b5Snjoly lmp->l_msg_cbytes = bmp->_msg_cbytes;
371e82000b5Snjoly lmp->l_msg_qnum = bmp->msg_qnum;
372e82000b5Snjoly lmp->l_msg_qbytes = bmp->msg_qbytes;
373e82000b5Snjoly lmp->l_msg_lspid = bmp->msg_lspid;
374e82000b5Snjoly lmp->l_msg_lrpid = bmp->msg_lrpid;
375e82000b5Snjoly }
376e82000b5Snjoly
377d4649701Serh int
linux_sys_msgctl(struct lwp * l,const struct linux_sys_msgctl_args * uap,register_t * retval)3787e2790cfSdsl linux_sys_msgctl(struct lwp *l, const struct linux_sys_msgctl_args *uap, register_t *retval)
3793bf459f3Sfvdl {
3807e2790cfSdsl /* {
381d4649701Serh syscallarg(int) msqid;
382d4649701Serh syscallarg(int) cmd;
383d4649701Serh syscallarg(struct linux_msqid_ds *) buf;
3847e2790cfSdsl } */
385e82000b5Snjoly struct msqid_ds bm, *bmp = NULL;
38602b3c95bSfvdl struct linux_msqid_ds lm;
387e82000b5Snjoly struct linux_msqid64_ds lm64;
388e82000b5Snjoly int cmd, lcmd, error;
38902b3c95bSfvdl
390e82000b5Snjoly lcmd = SCARG(uap, cmd);
391e82000b5Snjoly #ifdef LINUX_IPC_FORCE64
392e82000b5Snjoly lcmd |= LINUX_IPC_64;
393e82000b5Snjoly #endif
394e82000b5Snjoly
395d3dabe12Snjoly switch (lcmd & ~LINUX_IPC_64) {
396769c9d47Smycroft case LINUX_IPC_STAT:
397e82000b5Snjoly cmd = IPC_STAT;
398e82000b5Snjoly bmp = &bm;
399e82000b5Snjoly break;
40002b3c95bSfvdl case LINUX_IPC_SET:
401d3dabe12Snjoly if (lcmd & LINUX_IPC_64) {
402d3dabe12Snjoly error = copyin(SCARG(uap, buf), &lm64, sizeof lm64);
403e82000b5Snjoly linux_to_bsd_msqid64_ds(&lm64, &bm);
404d3dabe12Snjoly } else {
405d3dabe12Snjoly error = copyin(SCARG(uap, buf), &lm, sizeof lm);
406d3dabe12Snjoly linux_to_bsd_msqid_ds(&lm, &bm);
407d3dabe12Snjoly }
408d3dabe12Snjoly if (error)
409d3dabe12Snjoly return error;
410e82000b5Snjoly cmd = IPC_SET;
411e82000b5Snjoly bmp = &bm;
412e82000b5Snjoly break;
413769c9d47Smycroft case LINUX_IPC_RMID:
414e82000b5Snjoly cmd = IPC_RMID;
415769c9d47Smycroft break;
416769c9d47Smycroft default:
41702b3c95bSfvdl return EINVAL;
4183bf459f3Sfvdl }
419e82000b5Snjoly
420e82000b5Snjoly if ((error = msgctl1(l, SCARG(uap, msqid), cmd, bmp)))
421e82000b5Snjoly return error;
422e82000b5Snjoly
423e82000b5Snjoly switch (lcmd) {
424e82000b5Snjoly case LINUX_IPC_STAT:
425e82000b5Snjoly bsd_to_linux_msqid_ds(&bm, &lm);
426e82000b5Snjoly error = copyout(&lm, SCARG(uap, buf), sizeof lm);
427e82000b5Snjoly break;
428e82000b5Snjoly case LINUX_IPC_STAT|LINUX_IPC_64:
429e82000b5Snjoly bsd_to_linux_msqid64_ds(&bm, &lm64);
430e82000b5Snjoly error = copyout(&lm64, SCARG(uap, buf), sizeof lm64);
431e82000b5Snjoly break;
432e82000b5Snjoly default:
433e82000b5Snjoly break;
434e82000b5Snjoly }
435e82000b5Snjoly
436e82000b5Snjoly return error;
437769c9d47Smycroft }
4383bf459f3Sfvdl #endif /* SYSVMSG */
4393bf459f3Sfvdl
4403bf459f3Sfvdl #ifdef SYSVSHM
4413bf459f3Sfvdl /*
442f64366a2Sjdolecek * shmget(2). Just make sure the Linux-compatible shmat() semantics
443f64366a2Sjdolecek * is enabled for the segment, so that shmat() succeeds even when
444f64366a2Sjdolecek * the segment would be removed.
445f64366a2Sjdolecek */
446f64366a2Sjdolecek int
linux_sys_shmget(struct lwp * l,const struct linux_sys_shmget_args * uap,register_t * retval)4477e2790cfSdsl linux_sys_shmget(struct lwp *l, const struct linux_sys_shmget_args *uap, register_t *retval)
448f64366a2Sjdolecek {
4497e2790cfSdsl /* {
450f64366a2Sjdolecek syscallarg(key_t) key;
451f64366a2Sjdolecek syscallarg(size_t) size;
452f64366a2Sjdolecek syscallarg(int) shmflg;
4537e2790cfSdsl } */
4547e2790cfSdsl struct sys_shmget_args bsd_ua;
455f64366a2Sjdolecek
4567e2790cfSdsl SCARG(&bsd_ua, key) = SCARG(uap, key);
4577e2790cfSdsl SCARG(&bsd_ua, size) = SCARG(uap, size);
4587e2790cfSdsl SCARG(&bsd_ua, shmflg) = SCARG(uap, shmflg) | _SHM_RMLINGER;
4597e2790cfSdsl
4607e2790cfSdsl return sys_shmget(l, &bsd_ua, retval);
461f64366a2Sjdolecek }
462f64366a2Sjdolecek
463f64366a2Sjdolecek /*
4643bf459f3Sfvdl * shmat(2). Very straightforward, except that Linux passes a pointer
4653bf459f3Sfvdl * in which the return value is to be passed. This is subsequently
4663bf459f3Sfvdl * handled by libc, apparently.
4673bf459f3Sfvdl */
468432f035fSmanu #ifndef __amd64__
469d4649701Serh int
linux_sys_shmat(struct lwp * l,const struct linux_sys_shmat_args * uap,register_t * retval)4707e2790cfSdsl linux_sys_shmat(struct lwp *l, const struct linux_sys_shmat_args *uap, register_t *retval)
4713bf459f3Sfvdl {
4727e2790cfSdsl /* {
473d4649701Serh syscallarg(int) shmid;
474d4649701Serh syscallarg(void *) shmaddr;
475d4649701Serh syscallarg(int) shmflg;
476d4649701Serh syscallarg(u_long *) raddr;
4777e2790cfSdsl } */
4783bf459f3Sfvdl int error;
4793bf459f3Sfvdl
4807e2790cfSdsl if ((error = sys_shmat(l, (const void *)uap, retval)))
4813bf459f3Sfvdl return error;
4823bf459f3Sfvdl
4837e2790cfSdsl if ((error = copyout(&retval[0], SCARG(uap, raddr), sizeof retval[0])))
4843bf459f3Sfvdl return error;
4853bf459f3Sfvdl
4863bf459f3Sfvdl retval[0] = 0;
4873bf459f3Sfvdl return 0;
4883bf459f3Sfvdl }
489432f035fSmanu #endif /* __amd64__ */
4903bf459f3Sfvdl
4913bf459f3Sfvdl /*
4923bf459f3Sfvdl * Convert between Linux and NetBSD shmid_ds structures.
4933bf459f3Sfvdl * The order of the fields is once again the difference, and
4943bf459f3Sfvdl * we also need a place to store the internal data pointer
4953bf459f3Sfvdl * in, which is unfortunately stored in this structure.
4963bf459f3Sfvdl *
4973bf459f3Sfvdl * We abuse a Linux internal field for that.
4983bf459f3Sfvdl */
499d4649701Serh void
linux_to_bsd_shmid_ds(struct linux_shmid_ds * lsp,struct shmid_ds * bsp)50028bae79bSdsl linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
5013bf459f3Sfvdl {
502245f292fSmycroft
5033bf459f3Sfvdl linux_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm);
5043bf459f3Sfvdl bsp->shm_segsz = lsp->l_shm_segsz;
5053bf459f3Sfvdl bsp->shm_lpid = lsp->l_shm_lpid;
5063bf459f3Sfvdl bsp->shm_cpid = lsp->l_shm_cpid;
5073bf459f3Sfvdl bsp->shm_nattch = lsp->l_shm_nattch;
5083bf459f3Sfvdl bsp->shm_atime = lsp->l_shm_atime;
5093bf459f3Sfvdl bsp->shm_dtime = lsp->l_shm_dtime;
5103bf459f3Sfvdl bsp->shm_ctime = lsp->l_shm_ctime;
5113bf459f3Sfvdl }
5123bf459f3Sfvdl
513d4649701Serh void
linux_to_bsd_shmid64_ds(struct linux_shmid64_ds * lsp,struct shmid_ds * bsp)51428bae79bSdsl linux_to_bsd_shmid64_ds(struct linux_shmid64_ds *lsp, struct shmid_ds *bsp)
51565de380aSchristos {
51665de380aSchristos
51765de380aSchristos linux_to_bsd_ipc64_perm(&lsp->l_shm_perm, &bsp->shm_perm);
51865de380aSchristos bsp->shm_segsz = lsp->l_shm_segsz;
51965de380aSchristos bsp->shm_lpid = lsp->l_shm_lpid;
52065de380aSchristos bsp->shm_cpid = lsp->l_shm_cpid;
52165de380aSchristos bsp->shm_nattch = lsp->l_shm_nattch;
52265de380aSchristos bsp->shm_atime = lsp->l_shm_atime;
52365de380aSchristos bsp->shm_dtime = lsp->l_shm_dtime;
52465de380aSchristos bsp->shm_ctime = lsp->l_shm_ctime;
52565de380aSchristos }
52665de380aSchristos
52765de380aSchristos void
bsd_to_linux_shmid_ds(struct shmid_ds * bsp,struct linux_shmid_ds * lsp)52828bae79bSdsl bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
5293bf459f3Sfvdl {
530245f292fSmycroft
53139e3203eSmrg memset(lsp, 0, sizeof *lsp);
5323bf459f3Sfvdl bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm);
5333bf459f3Sfvdl lsp->l_shm_segsz = bsp->shm_segsz;
5343bf459f3Sfvdl lsp->l_shm_lpid = bsp->shm_lpid;
5353bf459f3Sfvdl lsp->l_shm_cpid = bsp->shm_cpid;
5363bf459f3Sfvdl lsp->l_shm_nattch = bsp->shm_nattch;
5373bf459f3Sfvdl lsp->l_shm_atime = bsp->shm_atime;
5383bf459f3Sfvdl lsp->l_shm_dtime = bsp->shm_dtime;
5393bf459f3Sfvdl lsp->l_shm_ctime = bsp->shm_ctime;
5403bf459f3Sfvdl }
5413bf459f3Sfvdl
54265de380aSchristos void
bsd_to_linux_shmid64_ds(struct shmid_ds * bsp,struct linux_shmid64_ds * lsp)54328bae79bSdsl bsd_to_linux_shmid64_ds(struct shmid_ds *bsp, struct linux_shmid64_ds *lsp)
54465de380aSchristos {
54539e3203eSmrg
54639e3203eSmrg memset(lsp, 0, sizeof *lsp);
54765de380aSchristos bsd_to_linux_ipc64_perm(&bsp->shm_perm, &lsp->l_shm_perm);
54865de380aSchristos lsp->l_shm_segsz = bsp->shm_segsz;
54965de380aSchristos lsp->l_shm_lpid = bsp->shm_lpid;
55065de380aSchristos lsp->l_shm_cpid = bsp->shm_cpid;
55165de380aSchristos lsp->l_shm_nattch = bsp->shm_nattch;
55265de380aSchristos lsp->l_shm_atime = bsp->shm_atime;
55365de380aSchristos lsp->l_shm_dtime = bsp->shm_dtime;
55465de380aSchristos lsp->l_shm_ctime = bsp->shm_ctime;
55565de380aSchristos }
55665de380aSchristos
5573bf459f3Sfvdl /*
55869614dfeSnjoly * shmctl.
5593bf459f3Sfvdl *
5603bf459f3Sfvdl * The usual structure conversion and massaging is done.
5613bf459f3Sfvdl */
562d4649701Serh int
linux_sys_shmctl(struct lwp * l,const struct linux_sys_shmctl_args * uap,register_t * retval)5637e2790cfSdsl linux_sys_shmctl(struct lwp *l, const struct linux_sys_shmctl_args *uap, register_t *retval)
5643bf459f3Sfvdl {
5657e2790cfSdsl /* {
566d4649701Serh syscallarg(int) shmid;
567d4649701Serh syscallarg(int) cmd;
568d4649701Serh syscallarg(struct linux_shmid_ds *) buf;
5697e2790cfSdsl } */
570c271f319Sdsl struct shmid_ds bs;
571*542f82ceSmaxv struct ipc_perm perm;
572769c9d47Smycroft struct linux_shmid_ds ls;
57365de380aSchristos struct linux_shmid64_ds ls64;
57465de380aSchristos struct linux_shminfo64 lsi64;
57565de380aSchristos struct linux_shm_info lsi;
57629158b16Snjoly int error, i, cmd, shmid;
5773bf459f3Sfvdl
57829158b16Snjoly shmid = SCARG(uap, shmid);
57965de380aSchristos cmd = SCARG(uap, cmd);
580f1bd64daSnjoly #ifdef LINUX_IPC_FORCE64
5814eecf433Snjoly cmd |= LINUX_IPC_64;
5824eecf433Snjoly #endif
58329158b16Snjoly
584a1cf1f2eSnjoly switch (cmd & ~LINUX_IPC_64) {
58565de380aSchristos case LINUX_SHM_STAT:
586*542f82ceSmaxv error = shm_find_segment_perm_by_index(shmid, &perm);
587*542f82ceSmaxv if (error)
588*542f82ceSmaxv return error;
589*542f82ceSmaxv shmid = IXSEQ_TO_IPCID(shmid, perm);
59029158b16Snjoly retval[0] = shmid;
591a1cf1f2eSnjoly /*FALLTHROUGH*/
59265de380aSchristos
593a1cf1f2eSnjoly case LINUX_IPC_STAT:
59429158b16Snjoly error = shmctl1(l, shmid, IPC_STAT, &bs);
595c271f319Sdsl if (error != 0)
59665de380aSchristos return error;
597a1cf1f2eSnjoly if (cmd & LINUX_IPC_64) {
59865de380aSchristos bsd_to_linux_shmid64_ds(&bs, &ls64);
599a1cf1f2eSnjoly error = copyout(&ls64, SCARG(uap, buf), sizeof ls64);
600a1cf1f2eSnjoly } else {
601a1cf1f2eSnjoly bsd_to_linux_shmid_ds(&bs, &ls);
602a1cf1f2eSnjoly error = copyout(&ls, SCARG(uap, buf), sizeof ls);
603a1cf1f2eSnjoly }
604a1cf1f2eSnjoly return error;
60565de380aSchristos
6063bf459f3Sfvdl case LINUX_IPC_SET:
607a1cf1f2eSnjoly if (cmd & LINUX_IPC_64) {
608a1cf1f2eSnjoly error = copyin(SCARG(uap, buf), &ls64, sizeof ls64);
609d8f89665Snjoly linux_to_bsd_shmid64_ds(&ls64, &bs);
610a1cf1f2eSnjoly } else {
611a1cf1f2eSnjoly error = copyin(SCARG(uap, buf), &ls, sizeof ls);
612a1cf1f2eSnjoly linux_to_bsd_shmid_ds(&ls, &bs);
613a1cf1f2eSnjoly }
614a1cf1f2eSnjoly if (error != 0)
615a1cf1f2eSnjoly return error;
616d8f89665Snjoly return shmctl1(l, shmid, IPC_SET, &bs);
617d8f89665Snjoly
6183bf459f3Sfvdl case LINUX_IPC_RMID:
61929158b16Snjoly return shmctl1(l, shmid, IPC_RMID, NULL);
62065de380aSchristos
6213bf459f3Sfvdl case LINUX_SHM_LOCK:
62229158b16Snjoly return shmctl1(l, shmid, SHM_LOCK, NULL);
62365de380aSchristos
6243bf459f3Sfvdl case LINUX_SHM_UNLOCK:
62529158b16Snjoly return shmctl1(l, shmid, SHM_UNLOCK, NULL);
62665de380aSchristos
6273bf459f3Sfvdl case LINUX_IPC_INFO:
62865de380aSchristos memset(&lsi64, 0, sizeof lsi64);
62965de380aSchristos lsi64.l_shmmax = shminfo.shmmax;
63065de380aSchristos lsi64.l_shmmin = shminfo.shmmin;
63165de380aSchristos lsi64.l_shmmni = shminfo.shmmni;
63265de380aSchristos lsi64.l_shmseg = shminfo.shmseg;
63365de380aSchristos lsi64.l_shmall = shminfo.shmall;
63429158b16Snjoly for (i = shminfo.shmmni - 1; i > 0; i--)
63529158b16Snjoly if (shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED)
63629158b16Snjoly break;
63729158b16Snjoly retval[0] = i;
63865de380aSchristos return copyout(&lsi64, SCARG(uap, buf), sizeof lsi64);
63965de380aSchristos
6403bf459f3Sfvdl case LINUX_SHM_INFO:
64165de380aSchristos (void)memset(&lsi, 0, sizeof lsi);
64265de380aSchristos lsi.l_used_ids = shm_nused;
64365de380aSchristos for (i = 0; i < shminfo.shmmni; i++)
64465de380aSchristos if (shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED)
64529158b16Snjoly lsi.l_shm_tot +=
64629158b16Snjoly round_page(shmsegs[i].shm_segsz) /
64729158b16Snjoly uvmexp.pagesize;
64865de380aSchristos lsi.l_shm_rss = 0;
64965de380aSchristos lsi.l_shm_swp = 0;
65065de380aSchristos lsi.l_swap_attempts = 0;
65165de380aSchristos lsi.l_swap_successes = 0;
65229158b16Snjoly for (i = shminfo.shmmni - 1; i > 0; i--)
65329158b16Snjoly if (shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED)
65429158b16Snjoly break;
65529158b16Snjoly retval[0] = i;
65665de380aSchristos return copyout(&lsi, SCARG(uap, buf), sizeof lsi);
65765de380aSchristos
6583bf459f3Sfvdl default:
65965de380aSchristos #ifdef DEBUG
66065de380aSchristos printf("linux_sys_shmctl cmd %d\n", SCARG(uap, cmd));
66165de380aSchristos #endif
6623bf459f3Sfvdl return EINVAL;
6633bf459f3Sfvdl }
6643bf459f3Sfvdl }
6653bf459f3Sfvdl #endif /* SYSVSHM */
666