xref: /freebsd-src/sys/compat/linux/linux_ipc.c (revision 3460fab5fced39c7ea597cc7de0ebc3e4c88989a)
1c21dee17SSøren Schmidt /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
37f2d13d6SPedro F. Giffuni  *
49a14aa01SUlrich Spörlein  * Copyright (c) 1994-1995 Søren Schmidt
5c21dee17SSøren Schmidt  * All rights reserved.
6c21dee17SSøren Schmidt  *
7c21dee17SSøren Schmidt  * Redistribution and use in source and binary forms, with or without
8c21dee17SSøren Schmidt  * modification, are permitted provided that the following conditions
9c21dee17SSøren Schmidt  * are met:
10c21dee17SSøren Schmidt  * 1. Redistributions of source code must retain the above copyright
110ba1b365SEd Maste  *    notice, this list of conditions and the following disclaimer.
12c21dee17SSøren Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
13c21dee17SSøren Schmidt  *    notice, this list of conditions and the following disclaimer in the
14c21dee17SSøren Schmidt  *    documentation and/or other materials provided with the distribution.
15c21dee17SSøren Schmidt  *
160ba1b365SEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
170ba1b365SEd Maste  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
180ba1b365SEd Maste  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
190ba1b365SEd Maste  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
200ba1b365SEd Maste  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210ba1b365SEd Maste  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
220ba1b365SEd Maste  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
230ba1b365SEd Maste  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
240ba1b365SEd Maste  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
250ba1b365SEd Maste  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
260ba1b365SEd Maste  * SUCH DAMAGE.
27c21dee17SSøren Schmidt  */
28c21dee17SSøren Schmidt 
29c21dee17SSøren Schmidt #include <sys/param.h>
30104a9b7eSAlexander Kabaev #include <sys/limits.h>
313ad9c842SMaxim Sobolev #include <sys/msg.h>
32d8e53d94SDmitry Chagin #include <sys/proc.h>
339b86a416SKATO Takenori #include <sys/sem.h>
34c21dee17SSøren Schmidt #include <sys/shm.h>
35c10e04f5SDmitry Chagin #include <sys/stat.h>
36d8e53d94SDmitry Chagin #include <sys/syscallsubr.h>
37513eb69eSDmitry Chagin #include <sys/sysent.h>
38d8e53d94SDmitry Chagin #include <sys/sysproto.h>
39c21dee17SSøren Schmidt 
401997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32
414af27623STim J. Robbins #include <machine/../linux32/linux.h>
424af27623STim J. Robbins #include <machine/../linux32/linux32_proto.h>
431997c537SDavid E. O'Brien #else
441997c537SDavid E. O'Brien #include <machine/../linux/linux.h>
451997c537SDavid E. O'Brien #include <machine/../linux/linux_proto.h>
464af27623STim J. Robbins #endif
47afa66fa8SMarcel Moolenaar #include <compat/linux/linux_ipc.h>
48ab60bc84SDmitry Chagin #include <compat/linux/linux_ipc64.h>
49c8a79231SDmitry Chagin #include <compat/linux/linux_time.h>
50afa66fa8SMarcel Moolenaar #include <compat/linux/linux_util.h>
51c21dee17SSøren Schmidt 
52ab60bc84SDmitry Chagin /*
53ab60bc84SDmitry Chagin  * old, pre 2.4 kernel
54ab60bc84SDmitry Chagin  */
55ab60bc84SDmitry Chagin struct l_ipc_perm {
56ab60bc84SDmitry Chagin 	l_key_t		key;
57ab60bc84SDmitry Chagin 	l_uid16_t	uid;
58ab60bc84SDmitry Chagin 	l_gid16_t	gid;
59ab60bc84SDmitry Chagin 	l_uid16_t	cuid;
60ab60bc84SDmitry Chagin 	l_gid16_t	cgid;
61ab60bc84SDmitry Chagin 	l_ushort	mode;
62ab60bc84SDmitry Chagin 	l_ushort	seq;
63ab60bc84SDmitry Chagin };
64ab60bc84SDmitry Chagin 
65a6e5348eSMichael Reifenberger struct l_seminfo {
66a6e5348eSMichael Reifenberger 	l_int semmap;
67a6e5348eSMichael Reifenberger 	l_int semmni;
68a6e5348eSMichael Reifenberger 	l_int semmns;
69a6e5348eSMichael Reifenberger 	l_int semmnu;
70a6e5348eSMichael Reifenberger 	l_int semmsl;
71a6e5348eSMichael Reifenberger 	l_int semopm;
72a6e5348eSMichael Reifenberger 	l_int semume;
73a6e5348eSMichael Reifenberger 	l_int semusz;
74a6e5348eSMichael Reifenberger 	l_int semvmx;
75a6e5348eSMichael Reifenberger 	l_int semaem;
76a6e5348eSMichael Reifenberger };
77a6e5348eSMichael Reifenberger 
78a6e5348eSMichael Reifenberger struct l_shminfo {
79a6e5348eSMichael Reifenberger 	l_int shmmax;
80a6e5348eSMichael Reifenberger 	l_int shmmin;
81a6e5348eSMichael Reifenberger 	l_int shmmni;
82a6e5348eSMichael Reifenberger 	l_int shmseg;
83a6e5348eSMichael Reifenberger 	l_int shmall;
84a6e5348eSMichael Reifenberger };
85a6e5348eSMichael Reifenberger 
86a6e5348eSMichael Reifenberger struct l_shm_info {
87a6e5348eSMichael Reifenberger 	l_int used_ids;
88a6e5348eSMichael Reifenberger 	l_ulong shm_tot;  /* total allocated shm */
89a6e5348eSMichael Reifenberger 	l_ulong shm_rss;  /* total resident shm */
90a6e5348eSMichael Reifenberger 	l_ulong shm_swp;  /* total swapped shm */
91a6e5348eSMichael Reifenberger 	l_ulong swap_attempts;
92a6e5348eSMichael Reifenberger 	l_ulong swap_successes;
93a6e5348eSMichael Reifenberger };
94a6e5348eSMichael Reifenberger 
9534ec45feSJung-uk Kim struct l_msginfo {
9634ec45feSJung-uk Kim 	l_int msgpool;
9734ec45feSJung-uk Kim 	l_int msgmap;
9834ec45feSJung-uk Kim 	l_int msgmax;
9934ec45feSJung-uk Kim 	l_int msgmnb;
10034ec45feSJung-uk Kim 	l_int msgmni;
10134ec45feSJung-uk Kim 	l_int msgssz;
10234ec45feSJung-uk Kim 	l_int msgtql;
10334ec45feSJung-uk Kim 	l_ushort msgseg;
10434ec45feSJung-uk Kim };
10534ec45feSJung-uk Kim 
106491dec93SMichael Reifenberger static void
bsd_to_linux_shminfo(struct shminfo * bpp,struct l_shminfo64 * lpp)107ab60bc84SDmitry Chagin bsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo64 *lpp)
108491dec93SMichael Reifenberger {
10931f7ad15SDmitry Chagin 
110491dec93SMichael Reifenberger 	lpp->shmmax = bpp->shmmax;
111491dec93SMichael Reifenberger 	lpp->shmmin = bpp->shmmin;
112491dec93SMichael Reifenberger 	lpp->shmmni = bpp->shmmni;
113491dec93SMichael Reifenberger 	lpp->shmseg = bpp->shmseg;
114491dec93SMichael Reifenberger 	lpp->shmall = bpp->shmall;
115491dec93SMichael Reifenberger }
116491dec93SMichael Reifenberger 
117491dec93SMichael Reifenberger static void
bsd_to_linux_shm_info(struct shm_info * bpp,struct l_shm_info * lpp)118491dec93SMichael Reifenberger bsd_to_linux_shm_info( struct shm_info *bpp, struct l_shm_info *lpp)
119491dec93SMichael Reifenberger {
12031f7ad15SDmitry Chagin 
121491dec93SMichael Reifenberger 	lpp->used_ids = bpp->used_ids;
122491dec93SMichael Reifenberger 	lpp->shm_tot = bpp->shm_tot;
123491dec93SMichael Reifenberger 	lpp->shm_rss = bpp->shm_rss;
124491dec93SMichael Reifenberger 	lpp->shm_swp = bpp->shm_swp;
125491dec93SMichael Reifenberger 	lpp->swap_attempts = bpp->swap_attempts;
126491dec93SMichael Reifenberger 	lpp->swap_successes = bpp->swap_successes;
127491dec93SMichael Reifenberger }
128491dec93SMichael Reifenberger 
129c21dee17SSøren Schmidt static void
linux_to_bsd_ipc_perm(struct l_ipc64_perm * lpp,struct ipc_perm * bpp)130ab60bc84SDmitry Chagin linux_to_bsd_ipc_perm(struct l_ipc64_perm *lpp, struct ipc_perm *bpp)
131c21dee17SSøren Schmidt {
13231f7ad15SDmitry Chagin 
133c21dee17SSøren Schmidt 	bpp->key = lpp->key;
134c21dee17SSøren Schmidt 	bpp->uid = lpp->uid;
135c21dee17SSøren Schmidt 	bpp->gid = lpp->gid;
136c21dee17SSøren Schmidt 	bpp->cuid = lpp->cuid;
137c21dee17SSøren Schmidt 	bpp->cgid = lpp->cgid;
138c21dee17SSøren Schmidt 	bpp->mode = lpp->mode;
139c21dee17SSøren Schmidt 	bpp->seq = lpp->seq;
140c21dee17SSøren Schmidt }
141c21dee17SSøren Schmidt 
142c21dee17SSøren Schmidt static void
bsd_to_linux_ipc_perm(struct ipc_perm * bpp,struct l_ipc64_perm * lpp)143ab60bc84SDmitry Chagin bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc64_perm *lpp)
144c21dee17SSøren Schmidt {
14531f7ad15SDmitry Chagin 
146c21dee17SSøren Schmidt 	lpp->key = bpp->key;
147c21dee17SSøren Schmidt 	lpp->uid = bpp->uid;
148c21dee17SSøren Schmidt 	lpp->gid = bpp->gid;
149c21dee17SSøren Schmidt 	lpp->cuid = bpp->cuid;
150c21dee17SSøren Schmidt 	lpp->cgid = bpp->cgid;
151c10e04f5SDmitry Chagin 	lpp->mode = bpp->mode & (S_IRWXU|S_IRWXG|S_IRWXO);
152c21dee17SSøren Schmidt 	lpp->seq = bpp->seq;
153c21dee17SSøren Schmidt }
154c21dee17SSøren Schmidt 
1553ad9c842SMaxim Sobolev struct l_msqid_ds {
1563ad9c842SMaxim Sobolev 	struct l_ipc_perm	msg_perm;
1574af27623STim J. Robbins 	l_uintptr_t		msg_first;	/* first message on queue,unused */
1584af27623STim J. Robbins 	l_uintptr_t		msg_last;	/* last message in queue,unused */
1593ad9c842SMaxim Sobolev 	l_time_t		msg_stime;	/* last msgsnd time */
1603ad9c842SMaxim Sobolev 	l_time_t		msg_rtime;	/* last msgrcv time */
1613ad9c842SMaxim Sobolev 	l_time_t		msg_ctime;	/* last change time */
1623ad9c842SMaxim Sobolev 	l_ulong			msg_lcbytes;	/* Reuse junk fields for 32 bit */
1633ad9c842SMaxim Sobolev 	l_ulong			msg_lqbytes;	/* ditto */
1643ad9c842SMaxim Sobolev 	l_ushort		msg_cbytes;	/* current number of bytes on queue */
1653ad9c842SMaxim Sobolev 	l_ushort		msg_qnum;	/* number of messages in queue */
1663ad9c842SMaxim Sobolev 	l_ushort		msg_qbytes;	/* max number of bytes on queue */
1673ad9c842SMaxim Sobolev 	l_pid_t			msg_lspid;	/* pid of last msgsnd */
1683ad9c842SMaxim Sobolev 	l_pid_t			msg_lrpid;	/* last receive pid */
169e45e3698SDmitry Chagin };
1703ad9c842SMaxim Sobolev 
1715002a60fSMarcel Moolenaar struct l_semid_ds {
1725002a60fSMarcel Moolenaar 	struct l_ipc_perm	sem_perm;
1735002a60fSMarcel Moolenaar 	l_time_t		sem_otime;
1745002a60fSMarcel Moolenaar 	l_time_t		sem_ctime;
1754af27623STim J. Robbins 	l_uintptr_t		sem_base;
1764af27623STim J. Robbins 	l_uintptr_t		sem_pending;
1774af27623STim J. Robbins 	l_uintptr_t		sem_pending_last;
1784af27623STim J. Robbins 	l_uintptr_t		undo;
1795002a60fSMarcel Moolenaar 	l_ushort		sem_nsems;
180e45e3698SDmitry Chagin };
1819b86a416SKATO Takenori 
1825002a60fSMarcel Moolenaar struct l_shmid_ds {
1835002a60fSMarcel Moolenaar 	struct l_ipc_perm	shm_perm;
1845002a60fSMarcel Moolenaar 	l_int			shm_segsz;
1855002a60fSMarcel Moolenaar 	l_time_t		shm_atime;
1865002a60fSMarcel Moolenaar 	l_time_t		shm_dtime;
1875002a60fSMarcel Moolenaar 	l_time_t		shm_ctime;
1885002a60fSMarcel Moolenaar 	l_ushort		shm_cpid;
1895002a60fSMarcel Moolenaar 	l_ushort		shm_lpid;
1905002a60fSMarcel Moolenaar 	l_short			shm_nattch;
1915002a60fSMarcel Moolenaar 	l_ushort		private1;
1924af27623STim J. Robbins 	l_uintptr_t		private2;
1934af27623STim J. Robbins 	l_uintptr_t		private3;
194c21dee17SSøren Schmidt };
195c21dee17SSøren Schmidt 
196c21dee17SSøren Schmidt static void
linux_to_bsd_semid_ds(struct l_semid64_ds * lsp,struct semid_ds * bsp)197ab60bc84SDmitry Chagin linux_to_bsd_semid_ds(struct l_semid64_ds *lsp, struct semid_ds *bsp)
1989b86a416SKATO Takenori {
19931f7ad15SDmitry Chagin 
2009b86a416SKATO Takenori 	linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm);
2019b86a416SKATO Takenori 	bsp->sem_otime = lsp->sem_otime;
2029b86a416SKATO Takenori 	bsp->sem_ctime = lsp->sem_ctime;
2039b86a416SKATO Takenori 	bsp->sem_nsems = lsp->sem_nsems;
2049b86a416SKATO Takenori }
2059b86a416SKATO Takenori 
2069b86a416SKATO Takenori static void
bsd_to_linux_semid_ds(struct semid_ds * bsp,struct l_semid64_ds * lsp)207ab60bc84SDmitry Chagin bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid64_ds *lsp)
2089b86a416SKATO Takenori {
20931f7ad15SDmitry Chagin 
2109b86a416SKATO Takenori 	bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm);
2119b86a416SKATO Takenori 	lsp->sem_otime = bsp->sem_otime;
2129b86a416SKATO Takenori 	lsp->sem_ctime = bsp->sem_ctime;
2139b86a416SKATO Takenori 	lsp->sem_nsems = bsp->sem_nsems;
2149b86a416SKATO Takenori }
2159b86a416SKATO Takenori 
2169b86a416SKATO Takenori static void
linux_to_bsd_shmid_ds(struct l_shmid64_ds * lsp,struct shmid_ds * bsp)217ab60bc84SDmitry Chagin linux_to_bsd_shmid_ds(struct l_shmid64_ds *lsp, struct shmid_ds *bsp)
218c21dee17SSøren Schmidt {
21931f7ad15SDmitry Chagin 
220c21dee17SSøren Schmidt 	linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
221c21dee17SSøren Schmidt 	bsp->shm_segsz = lsp->shm_segsz;
222c21dee17SSøren Schmidt 	bsp->shm_lpid = lsp->shm_lpid;
223c21dee17SSøren Schmidt 	bsp->shm_cpid = lsp->shm_cpid;
224c21dee17SSøren Schmidt 	bsp->shm_nattch = lsp->shm_nattch;
225c21dee17SSøren Schmidt 	bsp->shm_atime = lsp->shm_atime;
226c21dee17SSøren Schmidt 	bsp->shm_dtime = lsp->shm_dtime;
227c21dee17SSøren Schmidt 	bsp->shm_ctime = lsp->shm_ctime;
228c21dee17SSøren Schmidt }
229c21dee17SSøren Schmidt 
230c21dee17SSøren Schmidt static void
bsd_to_linux_shmid_ds(struct shmid_ds * bsp,struct l_shmid64_ds * lsp)231ab60bc84SDmitry Chagin bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid64_ds *lsp)
232c21dee17SSøren Schmidt {
23331f7ad15SDmitry Chagin 
234c21dee17SSøren Schmidt 	bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
235c21dee17SSøren Schmidt 	lsp->shm_segsz = bsp->shm_segsz;
236c21dee17SSøren Schmidt 	lsp->shm_lpid = bsp->shm_lpid;
237c21dee17SSøren Schmidt 	lsp->shm_cpid = bsp->shm_cpid;
238c21dee17SSøren Schmidt 	lsp->shm_nattch = bsp->shm_nattch;
239c21dee17SSøren Schmidt 	lsp->shm_atime = bsp->shm_atime;
240c21dee17SSøren Schmidt 	lsp->shm_dtime = bsp->shm_dtime;
241c21dee17SSøren Schmidt 	lsp->shm_ctime = bsp->shm_ctime;
242c21dee17SSøren Schmidt }
243c21dee17SSøren Schmidt 
2443ad9c842SMaxim Sobolev static void
linux_to_bsd_msqid_ds(struct l_msqid64_ds * lsp,struct msqid_ds * bsp)245ab60bc84SDmitry Chagin linux_to_bsd_msqid_ds(struct l_msqid64_ds *lsp, struct msqid_ds *bsp)
2463ad9c842SMaxim Sobolev {
24731f7ad15SDmitry Chagin 
2483ad9c842SMaxim Sobolev 	linux_to_bsd_ipc_perm(&lsp->msg_perm, &bsp->msg_perm);
2493ad9c842SMaxim Sobolev 	bsp->msg_cbytes = lsp->msg_cbytes;
2503ad9c842SMaxim Sobolev 	bsp->msg_qnum = lsp->msg_qnum;
2513ad9c842SMaxim Sobolev 	bsp->msg_qbytes = lsp->msg_qbytes;
2523ad9c842SMaxim Sobolev 	bsp->msg_lspid = lsp->msg_lspid;
2533ad9c842SMaxim Sobolev 	bsp->msg_lrpid = lsp->msg_lrpid;
2543ad9c842SMaxim Sobolev 	bsp->msg_stime = lsp->msg_stime;
2553ad9c842SMaxim Sobolev 	bsp->msg_rtime = lsp->msg_rtime;
2563ad9c842SMaxim Sobolev 	bsp->msg_ctime = lsp->msg_ctime;
2573ad9c842SMaxim Sobolev }
2583ad9c842SMaxim Sobolev 
2593ad9c842SMaxim Sobolev static void
bsd_to_linux_msqid_ds(struct msqid_ds * bsp,struct l_msqid64_ds * lsp)260ab60bc84SDmitry Chagin bsd_to_linux_msqid_ds(struct msqid_ds *bsp, struct l_msqid64_ds *lsp)
2613ad9c842SMaxim Sobolev {
26231f7ad15SDmitry Chagin 
2633ad9c842SMaxim Sobolev 	bsd_to_linux_ipc_perm(&bsp->msg_perm, &lsp->msg_perm);
2643ad9c842SMaxim Sobolev 	lsp->msg_cbytes = bsp->msg_cbytes;
2653ad9c842SMaxim Sobolev 	lsp->msg_qnum = bsp->msg_qnum;
2663ad9c842SMaxim Sobolev 	lsp->msg_qbytes = bsp->msg_qbytes;
2673ad9c842SMaxim Sobolev 	lsp->msg_lspid = bsp->msg_lspid;
2683ad9c842SMaxim Sobolev 	lsp->msg_lrpid = bsp->msg_lrpid;
2693ad9c842SMaxim Sobolev 	lsp->msg_stime = bsp->msg_stime;
2703ad9c842SMaxim Sobolev 	lsp->msg_rtime = bsp->msg_rtime;
2713ad9c842SMaxim Sobolev 	lsp->msg_ctime = bsp->msg_ctime;
2723ad9c842SMaxim Sobolev }
2733ad9c842SMaxim Sobolev 
274ab60bc84SDmitry Chagin static int
linux_ipc64_perm_to_ipc_perm(struct l_ipc64_perm * in,struct l_ipc_perm * out)275ab60bc84SDmitry Chagin linux_ipc64_perm_to_ipc_perm(struct l_ipc64_perm *in, struct l_ipc_perm *out)
2763ad9c842SMaxim Sobolev {
2773ad9c842SMaxim Sobolev 
2783ad9c842SMaxim Sobolev 	out->key = in->key;
2793ad9c842SMaxim Sobolev 	out->uid = in->uid;
2803ad9c842SMaxim Sobolev 	out->gid = in->gid;
2813ad9c842SMaxim Sobolev 	out->cuid = in->cuid;
2823ad9c842SMaxim Sobolev 	out->cgid = in->cgid;
2833ad9c842SMaxim Sobolev 	out->mode = in->mode;
2843ad9c842SMaxim Sobolev 	out->seq = in->seq;
285ab60bc84SDmitry Chagin 
286ab60bc84SDmitry Chagin 	/* Linux does not check overflow */
287ab60bc84SDmitry Chagin 	if (out->uid != in->uid || out->gid != in->gid ||
288ab60bc84SDmitry Chagin 	    out->cuid != in->cuid || out->cgid != in->cgid ||
289ab60bc84SDmitry Chagin 	    out->mode != in->mode)
290ab60bc84SDmitry Chagin 		return (EOVERFLOW);
291ab60bc84SDmitry Chagin 	else
292ab60bc84SDmitry Chagin 		return (0);
2933ad9c842SMaxim Sobolev }
2943ad9c842SMaxim Sobolev 
2953ad9c842SMaxim Sobolev static int
linux_msqid_pullup(l_int ver,struct l_msqid64_ds * linux_msqid64,caddr_t uaddr)296ab60bc84SDmitry Chagin linux_msqid_pullup(l_int ver, struct l_msqid64_ds *linux_msqid64, caddr_t uaddr)
2973ad9c842SMaxim Sobolev {
298ab60bc84SDmitry Chagin 	struct l_msqid_ds linux_msqid;
2993ad9c842SMaxim Sobolev 	int error;
3003ad9c842SMaxim Sobolev 
301ab60bc84SDmitry Chagin 	if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64))
302ab60bc84SDmitry Chagin 		return (copyin(uaddr, linux_msqid64, sizeof(*linux_msqid64)));
303eb089321SDmitry Chagin 
304ab60bc84SDmitry Chagin 	error = copyin(uaddr, &linux_msqid, sizeof(linux_msqid));
3053ad9c842SMaxim Sobolev 	if (error != 0)
3063ad9c842SMaxim Sobolev 		return (error);
3073ad9c842SMaxim Sobolev 
308ab60bc84SDmitry Chagin 	bzero(linux_msqid64, sizeof(*linux_msqid64));
309ab60bc84SDmitry Chagin 	linux_msqid64->msg_perm.uid = linux_msqid.msg_perm.uid;
310ab60bc84SDmitry Chagin 	linux_msqid64->msg_perm.gid = linux_msqid.msg_perm.gid;
311ab60bc84SDmitry Chagin 	linux_msqid64->msg_perm.mode = linux_msqid.msg_perm.mode;
312ab60bc84SDmitry Chagin 	if (linux_msqid.msg_qbytes == 0)
313ab60bc84SDmitry Chagin 		linux_msqid64->msg_qbytes = linux_msqid.msg_lqbytes;
3143ad9c842SMaxim Sobolev 	else
315ab60bc84SDmitry Chagin 		linux_msqid64->msg_qbytes = linux_msqid.msg_qbytes;
316ab60bc84SDmitry Chagin 	return (0);
317ab60bc84SDmitry Chagin }
3183ad9c842SMaxim Sobolev 
3193ad9c842SMaxim Sobolev static int
linux_msqid_pushdown(l_int ver,struct l_msqid64_ds * linux_msqid64,caddr_t uaddr)320ab60bc84SDmitry Chagin linux_msqid_pushdown(l_int ver, struct l_msqid64_ds *linux_msqid64, caddr_t uaddr)
3213ad9c842SMaxim Sobolev {
322ab60bc84SDmitry Chagin 	struct l_msqid_ds linux_msqid;
3233ad9c842SMaxim Sobolev 	int error;
3243ad9c842SMaxim Sobolev 
325ab60bc84SDmitry Chagin 	if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64))
326ab60bc84SDmitry Chagin 		return (copyout(linux_msqid64, uaddr, sizeof(*linux_msqid64)));
327ab60bc84SDmitry Chagin 
328eb089321SDmitry Chagin 	bzero(&linux_msqid, sizeof(linux_msqid));
329ab60bc84SDmitry Chagin 	error = linux_ipc64_perm_to_ipc_perm(&linux_msqid64->msg_perm,
330ab60bc84SDmitry Chagin 	    &linux_msqid.msg_perm);
3313ad9c842SMaxim Sobolev 	if (error != 0)
3323ad9c842SMaxim Sobolev 		return (error);
3333ad9c842SMaxim Sobolev 
334ab60bc84SDmitry Chagin 	linux_msqid.msg_stime = linux_msqid64->msg_stime;
335ab60bc84SDmitry Chagin 	linux_msqid.msg_rtime = linux_msqid64->msg_rtime;
336ab60bc84SDmitry Chagin 	linux_msqid.msg_ctime = linux_msqid64->msg_ctime;
3373ad9c842SMaxim Sobolev 
338ab60bc84SDmitry Chagin 	if (linux_msqid64->msg_cbytes > USHRT_MAX)
339ab60bc84SDmitry Chagin 		linux_msqid.msg_cbytes = USHRT_MAX;
340ab60bc84SDmitry Chagin 	else
341ab60bc84SDmitry Chagin 		linux_msqid.msg_cbytes = linux_msqid64->msg_cbytes;
342ab60bc84SDmitry Chagin 	linux_msqid.msg_lcbytes = linux_msqid64->msg_cbytes;
343ab60bc84SDmitry Chagin 	if (linux_msqid64->msg_qnum > USHRT_MAX)
344c6950243SDmitry Chagin 		linux_msqid.msg_qnum = USHRT_MAX;
345ab60bc84SDmitry Chagin 	else
346ab60bc84SDmitry Chagin 		linux_msqid.msg_qnum = linux_msqid64->msg_qnum;
347ab60bc84SDmitry Chagin 	if (linux_msqid64->msg_qbytes > USHRT_MAX)
348c6950243SDmitry Chagin 		linux_msqid.msg_qbytes = USHRT_MAX;
349ab60bc84SDmitry Chagin 	else
350ab60bc84SDmitry Chagin 		linux_msqid.msg_qbytes = linux_msqid64->msg_qbytes;
351ab60bc84SDmitry Chagin 	linux_msqid.msg_lqbytes = linux_msqid64->msg_qbytes;
352ab60bc84SDmitry Chagin 	linux_msqid.msg_lspid = linux_msqid64->msg_lspid;
353ab60bc84SDmitry Chagin 	linux_msqid.msg_lrpid = linux_msqid64->msg_lrpid;
35431f7ad15SDmitry Chagin 
355ab60bc84SDmitry Chagin 	/* Linux does not check overflow */
356ab60bc84SDmitry Chagin 	if (linux_msqid.msg_stime != linux_msqid64->msg_stime ||
357ab60bc84SDmitry Chagin 	    linux_msqid.msg_rtime != linux_msqid64->msg_rtime ||
358ab60bc84SDmitry Chagin 	    linux_msqid.msg_ctime != linux_msqid64->msg_ctime)
359ab60bc84SDmitry Chagin 		return (EOVERFLOW);
360ab60bc84SDmitry Chagin 	return (copyout(&linux_msqid, uaddr, sizeof(linux_msqid)));
361ab60bc84SDmitry Chagin }
3623ad9c842SMaxim Sobolev 
3633ad9c842SMaxim Sobolev static int
linux_semid_pullup(l_int ver,struct l_semid64_ds * linux_semid64,caddr_t uaddr)364ab60bc84SDmitry Chagin linux_semid_pullup(l_int ver, struct l_semid64_ds *linux_semid64, caddr_t uaddr)
3653ad9c842SMaxim Sobolev {
366ab60bc84SDmitry Chagin 	struct l_semid_ds linux_semid;
3673ad9c842SMaxim Sobolev 	int error;
3683ad9c842SMaxim Sobolev 
369ab60bc84SDmitry Chagin 	if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64))
370ab60bc84SDmitry Chagin 		return (copyin(uaddr, linux_semid64, sizeof(*linux_semid64)));
371ab60bc84SDmitry Chagin 	error = copyin(uaddr, &linux_semid, sizeof(linux_semid));
3723ad9c842SMaxim Sobolev 	if (error != 0)
3733ad9c842SMaxim Sobolev 		return (error);
3743ad9c842SMaxim Sobolev 
375ab60bc84SDmitry Chagin 	bzero(linux_semid64, sizeof(*linux_semid64));
376ab60bc84SDmitry Chagin 	linux_semid64->sem_perm.uid = linux_semid.sem_perm.uid;
377ab60bc84SDmitry Chagin 	linux_semid64->sem_perm.gid = linux_semid.sem_perm.gid;
378ab60bc84SDmitry Chagin 	linux_semid64->sem_perm.mode = linux_semid.sem_perm.mode;
379ab60bc84SDmitry Chagin 	return (0);
380ab60bc84SDmitry Chagin }
3813ad9c842SMaxim Sobolev 
3823ad9c842SMaxim Sobolev static int
linux_semid_pushdown(l_int ver,struct l_semid64_ds * linux_semid64,caddr_t uaddr)383ab60bc84SDmitry Chagin linux_semid_pushdown(l_int ver, struct l_semid64_ds *linux_semid64, caddr_t uaddr)
3843ad9c842SMaxim Sobolev {
385ab60bc84SDmitry Chagin 	struct l_semid_ds linux_semid;
386ab60bc84SDmitry Chagin 	int error;
3873ad9c842SMaxim Sobolev 
388ab60bc84SDmitry Chagin 	if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64))
389ab60bc84SDmitry Chagin 		return (copyout(linux_semid64, uaddr, sizeof(*linux_semid64)));
3903ad9c842SMaxim Sobolev 
391eb089321SDmitry Chagin 	bzero(&linux_semid, sizeof(linux_semid));
392ab60bc84SDmitry Chagin 		error = linux_ipc64_perm_to_ipc_perm(&linux_semid64->sem_perm,
393ab60bc84SDmitry Chagin 	    &linux_semid.sem_perm);
394ab60bc84SDmitry Chagin 	if (error != 0)
395ab60bc84SDmitry Chagin 		return (error);
3963ad9c842SMaxim Sobolev 
397ab60bc84SDmitry Chagin 	linux_semid.sem_otime = linux_semid64->sem_otime;
398ab60bc84SDmitry Chagin 	linux_semid.sem_ctime = linux_semid64->sem_ctime;
399ab60bc84SDmitry Chagin 	linux_semid.sem_nsems = linux_semid64->sem_nsems;
4003ad9c842SMaxim Sobolev 
401ab60bc84SDmitry Chagin 	/* Linux does not check overflow */
402ab60bc84SDmitry Chagin 	if (linux_semid.sem_otime != linux_semid64->sem_otime ||
403ab60bc84SDmitry Chagin 	    linux_semid.sem_ctime != linux_semid64->sem_ctime ||
404ab60bc84SDmitry Chagin 	    linux_semid.sem_nsems != linux_semid64->sem_nsems)
405ab60bc84SDmitry Chagin 		return (EOVERFLOW);
406ab60bc84SDmitry Chagin 	return (copyout(&linux_semid, uaddr, sizeof(linux_semid)));
407ab60bc84SDmitry Chagin }
4083ad9c842SMaxim Sobolev 
4093ad9c842SMaxim Sobolev static int
linux_shmid_pullup(l_int ver,struct l_shmid64_ds * linux_shmid64,caddr_t uaddr)410ab60bc84SDmitry Chagin linux_shmid_pullup(l_int ver, struct l_shmid64_ds *linux_shmid64, caddr_t uaddr)
411ab60bc84SDmitry Chagin {
412ab60bc84SDmitry Chagin 	struct l_shmid_ds linux_shmid;
413ab60bc84SDmitry Chagin 	int error;
414ab60bc84SDmitry Chagin 
415ab60bc84SDmitry Chagin 	if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64))
416ab60bc84SDmitry Chagin 		return (copyin(uaddr, linux_shmid64, sizeof(*linux_shmid64)));
417eb089321SDmitry Chagin 
418ab60bc84SDmitry Chagin 	error = copyin(uaddr, &linux_shmid, sizeof(linux_shmid));
419ab60bc84SDmitry Chagin 	if (error != 0)
420ab60bc84SDmitry Chagin 		return (error);
421ab60bc84SDmitry Chagin 
422ab60bc84SDmitry Chagin 	bzero(linux_shmid64, sizeof(*linux_shmid64));
423ab60bc84SDmitry Chagin 	linux_shmid64->shm_perm.uid = linux_shmid.shm_perm.uid;
424ab60bc84SDmitry Chagin 	linux_shmid64->shm_perm.gid = linux_shmid.shm_perm.gid;
425ab60bc84SDmitry Chagin 	linux_shmid64->shm_perm.mode = linux_shmid.shm_perm.mode;
426ab60bc84SDmitry Chagin 	return (0);
427ab60bc84SDmitry Chagin }
428ab60bc84SDmitry Chagin 
429ab60bc84SDmitry Chagin static int
linux_shmid_pushdown(l_int ver,struct l_shmid64_ds * linux_shmid64,caddr_t uaddr)430ab60bc84SDmitry Chagin linux_shmid_pushdown(l_int ver, struct l_shmid64_ds *linux_shmid64, caddr_t uaddr)
431ab60bc84SDmitry Chagin {
432ab60bc84SDmitry Chagin 	struct l_shmid_ds linux_shmid;
433ab60bc84SDmitry Chagin 	int error;
434ab60bc84SDmitry Chagin 
435ab60bc84SDmitry Chagin 	if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64))
436ab60bc84SDmitry Chagin 		return (copyout(linux_shmid64, uaddr, sizeof(*linux_shmid64)));
437ab60bc84SDmitry Chagin 
438eb089321SDmitry Chagin 	bzero(&linux_shmid, sizeof(linux_shmid));
439ab60bc84SDmitry Chagin 	error = linux_ipc64_perm_to_ipc_perm(&linux_shmid64->shm_perm,
440ab60bc84SDmitry Chagin 	    &linux_shmid.shm_perm);
441ab60bc84SDmitry Chagin 	if (error != 0)
442ab60bc84SDmitry Chagin 		return (error);
443ab60bc84SDmitry Chagin 
444ab60bc84SDmitry Chagin 	linux_shmid.shm_segsz = linux_shmid64->shm_segsz;
445ab60bc84SDmitry Chagin 	linux_shmid.shm_atime = linux_shmid64->shm_atime;
446ab60bc84SDmitry Chagin 	linux_shmid.shm_dtime = linux_shmid64->shm_dtime;
447ab60bc84SDmitry Chagin 	linux_shmid.shm_ctime = linux_shmid64->shm_ctime;
448ab60bc84SDmitry Chagin 	linux_shmid.shm_cpid = linux_shmid64->shm_cpid;
449ab60bc84SDmitry Chagin 	linux_shmid.shm_lpid = linux_shmid64->shm_lpid;
450ab60bc84SDmitry Chagin 	linux_shmid.shm_nattch = linux_shmid64->shm_nattch;
451ab60bc84SDmitry Chagin 
452ab60bc84SDmitry Chagin 	/* Linux does not check overflow */
453ab60bc84SDmitry Chagin 	if (linux_shmid.shm_segsz != linux_shmid64->shm_segsz ||
454ab60bc84SDmitry Chagin 	    linux_shmid.shm_atime != linux_shmid64->shm_atime ||
455ab60bc84SDmitry Chagin 	    linux_shmid.shm_dtime != linux_shmid64->shm_dtime ||
456ab60bc84SDmitry Chagin 	    linux_shmid.shm_ctime != linux_shmid64->shm_ctime ||
457ab60bc84SDmitry Chagin 	    linux_shmid.shm_cpid != linux_shmid64->shm_cpid ||
458ab60bc84SDmitry Chagin 	    linux_shmid.shm_lpid != linux_shmid64->shm_lpid ||
459ab60bc84SDmitry Chagin 	    linux_shmid.shm_nattch != linux_shmid64->shm_nattch)
460ab60bc84SDmitry Chagin 		return (EOVERFLOW);
461ab60bc84SDmitry Chagin 	return (copyout(&linux_shmid, uaddr, sizeof(linux_shmid)));
462ab60bc84SDmitry Chagin }
463ab60bc84SDmitry Chagin 
464ab60bc84SDmitry Chagin static int
linux_shminfo_pushdown(l_int ver,struct l_shminfo64 * linux_shminfo64,caddr_t uaddr)465ab60bc84SDmitry Chagin linux_shminfo_pushdown(l_int ver, struct l_shminfo64 *linux_shminfo64,
4663ad9c842SMaxim Sobolev     caddr_t uaddr)
4673ad9c842SMaxim Sobolev {
468ab60bc84SDmitry Chagin 	struct l_shminfo linux_shminfo;
4693ad9c842SMaxim Sobolev 
470ab60bc84SDmitry Chagin 	if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64))
471ab60bc84SDmitry Chagin 		return (copyout(linux_shminfo64, uaddr,
472ab60bc84SDmitry Chagin 		    sizeof(*linux_shminfo64)));
4733ad9c842SMaxim Sobolev 
474eb089321SDmitry Chagin 	bzero(&linux_shminfo, sizeof(linux_shminfo));
475ab60bc84SDmitry Chagin 	linux_shminfo.shmmax = linux_shminfo64->shmmax;
476ab60bc84SDmitry Chagin 	linux_shminfo.shmmin = linux_shminfo64->shmmin;
477ab60bc84SDmitry Chagin 	linux_shminfo.shmmni = linux_shminfo64->shmmni;
478ab60bc84SDmitry Chagin 	linux_shminfo.shmseg = linux_shminfo64->shmseg;
479ab60bc84SDmitry Chagin 	linux_shminfo.shmall = linux_shminfo64->shmall;
480eb089321SDmitry Chagin 	return (copyout(&linux_shminfo, uaddr, sizeof(linux_shminfo)));
4813ad9c842SMaxim Sobolev }
4823ad9c842SMaxim Sobolev 
4833245a2ecSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
4843245a2ecSDmitry Chagin int
linux_semtimedop_time64(struct thread * td,struct linux_semtimedop_time64_args * args)4853245a2ecSDmitry Chagin linux_semtimedop_time64(struct thread *td, struct linux_semtimedop_time64_args *args)
4863245a2ecSDmitry Chagin {
4873245a2ecSDmitry Chagin 	struct timespec ts, *tsa;
4883245a2ecSDmitry Chagin 	int error;
4893245a2ecSDmitry Chagin 
4903245a2ecSDmitry Chagin 	if (args->timeout) {
491707e567aSDmitry Chagin 		error = linux_get_timespec64(&ts, args->timeout);
4923245a2ecSDmitry Chagin 		if (error != 0)
4933245a2ecSDmitry Chagin 			return (error);
4943245a2ecSDmitry Chagin 		tsa = &ts;
4953245a2ecSDmitry Chagin 	} else
4963245a2ecSDmitry Chagin 		tsa = NULL;
4973245a2ecSDmitry Chagin 
4983245a2ecSDmitry Chagin 	return (kern_semop(td, args->semid, PTRIN(args->tsops),
4993245a2ecSDmitry Chagin 	    args->nsops, tsa));
5003245a2ecSDmitry Chagin }
5013245a2ecSDmitry Chagin #endif /* __i386__) || (__amd64__ && COMPAT_LINUX32) */
5023245a2ecSDmitry Chagin 
5033245a2ecSDmitry Chagin int
linux_semtimedop(struct thread * td,struct linux_semtimedop_args * args)5043245a2ecSDmitry Chagin linux_semtimedop(struct thread *td, struct linux_semtimedop_args *args)
5053245a2ecSDmitry Chagin {
5063245a2ecSDmitry Chagin 	struct timespec ts, *tsa;
5073245a2ecSDmitry Chagin 	int error;
5083245a2ecSDmitry Chagin 
5093245a2ecSDmitry Chagin 	if (args->timeout) {
510707e567aSDmitry Chagin 		error = linux_get_timespec(&ts, args->timeout);
5113245a2ecSDmitry Chagin 		if (error != 0)
5123245a2ecSDmitry Chagin 			return (error);
5133245a2ecSDmitry Chagin 		tsa = &ts;
5143245a2ecSDmitry Chagin 	} else
5153245a2ecSDmitry Chagin 		tsa = NULL;
5163245a2ecSDmitry Chagin 
5173245a2ecSDmitry Chagin 	return (kern_semop(td, args->semid, PTRIN(args->tsops),
5183245a2ecSDmitry Chagin 	    args->nsops, tsa));
5193245a2ecSDmitry Chagin }
5203245a2ecSDmitry Chagin 
521afa66fa8SMarcel Moolenaar int
linux_semget(struct thread * td,struct linux_semget_args * args)522b40ce416SJulian Elischer linux_semget(struct thread *td, struct linux_semget_args *args)
523c21dee17SSøren Schmidt {
5243e0c56a7SDmitry Chagin 	struct semget_args bsd_args = {
5253e0c56a7SDmitry Chagin 		.key = args->key,
5263e0c56a7SDmitry Chagin 		.nsems = args->nsems,
5273e0c56a7SDmitry Chagin 		.semflg = args->semflg
5283e0c56a7SDmitry Chagin 	};
5299b86a416SKATO Takenori 
5303ad9c842SMaxim Sobolev 	if (args->nsems < 0)
5313ad9c842SMaxim Sobolev 		return (EINVAL);
5328451d0ddSKip Macy 	return (sys_semget(td, &bsd_args));
533c21dee17SSøren Schmidt }
534c21dee17SSøren Schmidt 
535afa66fa8SMarcel Moolenaar int
linux_semctl(struct thread * td,struct linux_semctl_args * args)536b40ce416SJulian Elischer linux_semctl(struct thread *td, struct linux_semctl_args *args)
537c21dee17SSøren Schmidt {
538ab60bc84SDmitry Chagin 	struct l_semid64_ds linux_semid64;
539a6e5348eSMichael Reifenberger 	struct l_seminfo linux_seminfo;
54049d409a1SJohn Baldwin 	struct semid_ds semid;
54149d409a1SJohn Baldwin 	union semun semun;
542b1ee5b65SJohn Baldwin 	register_t rval;
54349d409a1SJohn Baldwin 	int cmd, error;
5449b86a416SKATO Takenori 
5456eee883aSEitan Adler 	memset(&linux_seminfo, 0, sizeof(linux_seminfo));
5466eee883aSEitan Adler 	memset(&linux_semid64, 0, sizeof(linux_semid64));
5476eee883aSEitan Adler 
5483ad9c842SMaxim Sobolev 	switch (args->cmd & ~LINUX_IPC_64) {
5499b86a416SKATO Takenori 	case LINUX_IPC_RMID:
55049d409a1SJohn Baldwin 		cmd = IPC_RMID;
5519b86a416SKATO Takenori 		break;
5529b86a416SKATO Takenori 	case LINUX_GETNCNT:
55349d409a1SJohn Baldwin 		cmd = GETNCNT;
5549b86a416SKATO Takenori 		break;
5559b86a416SKATO Takenori 	case LINUX_GETPID:
55649d409a1SJohn Baldwin 		cmd = GETPID;
5579b86a416SKATO Takenori 		break;
5589b86a416SKATO Takenori 	case LINUX_GETVAL:
55949d409a1SJohn Baldwin 		cmd = GETVAL;
5609b86a416SKATO Takenori 		break;
5619b86a416SKATO Takenori 	case LINUX_GETZCNT:
56249d409a1SJohn Baldwin 		cmd = GETZCNT;
5639b86a416SKATO Takenori 		break;
5649b86a416SKATO Takenori 	case LINUX_SETVAL:
56549d409a1SJohn Baldwin 		cmd = SETVAL;
56649d409a1SJohn Baldwin 		semun.val = args->arg.val;
5679b86a416SKATO Takenori 		break;
5689b86a416SKATO Takenori 	case LINUX_IPC_SET:
56949d409a1SJohn Baldwin 		cmd = IPC_SET;
5703ad9c842SMaxim Sobolev 		error = linux_semid_pullup(args->cmd & LINUX_IPC_64,
571ab60bc84SDmitry Chagin 		    &linux_semid64, PTRIN(args->arg.buf));
5728042c504SDmitry Chagin 		if (error != 0)
5735002a60fSMarcel Moolenaar 			return (error);
574ab60bc84SDmitry Chagin 		linux_to_bsd_semid_ds(&linux_semid64, &semid);
57549d409a1SJohn Baldwin 		semun.buf = &semid;
576b1ee5b65SJohn Baldwin 		return (kern_semctl(td, args->semid, args->semnum, cmd, &semun,
577b1ee5b65SJohn Baldwin 		    td->td_retval));
5789b86a416SKATO Takenori 	case LINUX_IPC_STAT:
57949d409a1SJohn Baldwin 		cmd = IPC_STAT;
580ab60bc84SDmitry Chagin 		semun.buf = &semid;
581ab60bc84SDmitry Chagin 		error = kern_semctl(td, args->semid, args->semnum, cmd, &semun,
582ab60bc84SDmitry Chagin 		    &rval);
583ab60bc84SDmitry Chagin 		if (error != 0)
584ab60bc84SDmitry Chagin 			return (error);
585ab60bc84SDmitry Chagin 		bsd_to_linux_semid_ds(&semid, &linux_semid64);
586ab60bc84SDmitry Chagin 		return (linux_semid_pushdown(args->cmd & LINUX_IPC_64,
587ab60bc84SDmitry Chagin 		    &linux_semid64, PTRIN(args->arg.buf)));
588ab60bc84SDmitry Chagin 	case LINUX_SEM_STAT:
58949d409a1SJohn Baldwin 		cmd = SEM_STAT;
59049d409a1SJohn Baldwin 		semun.buf = &semid;
59149d409a1SJohn Baldwin 		error = kern_semctl(td, args->semid, args->semnum, cmd, &semun,
592b1ee5b65SJohn Baldwin 		    &rval);
5938042c504SDmitry Chagin 		if (error != 0)
59449d409a1SJohn Baldwin 			return (error);
595ab60bc84SDmitry Chagin 		bsd_to_linux_semid_ds(&semid, &linux_semid64);
596b1ee5b65SJohn Baldwin 		error = linux_semid_pushdown(args->cmd & LINUX_IPC_64,
597ab60bc84SDmitry Chagin 		    &linux_semid64, PTRIN(args->arg.buf));
598b1ee5b65SJohn Baldwin 		if (error == 0)
599ab60bc84SDmitry Chagin 			td->td_retval[0] = rval;
600b1ee5b65SJohn Baldwin 		return (error);
601a6e5348eSMichael Reifenberger 	case LINUX_IPC_INFO:
602a6e5348eSMichael Reifenberger 	case LINUX_SEM_INFO:
6031080a2c8SBjoern A. Zeeb 		bcopy(&seminfo, &linux_seminfo.semmni, sizeof(linux_seminfo) -
6041080a2c8SBjoern A. Zeeb 		    sizeof(linux_seminfo.semmap) );
6051080a2c8SBjoern A. Zeeb 		/*
60674d7a253SBjoern A. Zeeb 		 * Linux does not use the semmap field but populates it with
60774d7a253SBjoern A. Zeeb 		 * the defined value from SEMMAP, which really is redefined to
60874d7a253SBjoern A. Zeeb 		 * SEMMNS, which they define as SEMMNI * SEMMSL.  Try to
60974d7a253SBjoern A. Zeeb 		 * simulate this returning our dynamic semmns value.
6101080a2c8SBjoern A. Zeeb 		 */
6111080a2c8SBjoern A. Zeeb 		linux_seminfo.semmap = linux_seminfo.semmns;
612a6e5348eSMichael Reifenberger /* XXX BSD equivalent?
613a6e5348eSMichael Reifenberger #define used_semids 10
614a6e5348eSMichael Reifenberger #define used_sems 10
615a6e5348eSMichael Reifenberger 		linux_seminfo.semusz = used_semids;
616a6e5348eSMichael Reifenberger 		linux_seminfo.semaem = used_sems;
617a6e5348eSMichael Reifenberger */
6184af27623STim J. Robbins 		error = copyout(&linux_seminfo,
6194af27623STim J. Robbins 		    PTRIN(args->arg.buf), sizeof(linux_seminfo));
6208042c504SDmitry Chagin 		if (error != 0)
62131f7ad15SDmitry Chagin 			return (error);
622ab60bc84SDmitry Chagin 		/*
623ab60bc84SDmitry Chagin 		 * TODO: Linux return the last assigned id, not the semmni.
624ab60bc84SDmitry Chagin 		 */
625a6e5348eSMichael Reifenberger 		td->td_retval[0] = seminfo.semmni;
626ab60bc84SDmitry Chagin 		return (0);
6279b86a416SKATO Takenori 	case LINUX_GETALL:
62817011df1SAlexander Leidinger 		cmd = GETALL;
629ab60bc84SDmitry Chagin 		semun.array = PTRIN(args->arg.array);
63017011df1SAlexander Leidinger 		break;
6319b86a416SKATO Takenori 	case LINUX_SETALL:
63217011df1SAlexander Leidinger 		cmd = SETALL;
633ab60bc84SDmitry Chagin 		semun.array = PTRIN(args->arg.array);
63417011df1SAlexander Leidinger 		break;
6359b86a416SKATO Takenori 	default:
636e15583ceSAlfred Perlstein 		linux_msg(td, "ipc type %d is not implemented",
6373ad9c842SMaxim Sobolev 		  args->cmd & ~LINUX_IPC_64);
63831f7ad15SDmitry Chagin 		return (EINVAL);
6399b86a416SKATO Takenori 	}
640b1ee5b65SJohn Baldwin 	return (kern_semctl(td, args->semid, args->semnum, cmd, &semun,
641b1ee5b65SJohn Baldwin 	    td->td_retval));
642c21dee17SSøren Schmidt }
643c21dee17SSøren Schmidt 
644afa66fa8SMarcel Moolenaar int
linux_msgsnd(struct thread * td,struct linux_msgsnd_args * args)645b40ce416SJulian Elischer linux_msgsnd(struct thread *td, struct linux_msgsnd_args *args)
646c21dee17SSøren Schmidt {
647f61480ecSJung-uk Kim 	const void *msgp;
648f61480ecSJung-uk Kim 	long mtype;
649f61480ecSJung-uk Kim 	l_long lmtype;
650f61480ecSJung-uk Kim 	int error;
651bb5889bdSSøren Schmidt 
65234ec45feSJung-uk Kim 	if ((l_long)args->msgsz < 0 || args->msgsz > (l_long)msginfo.msgmax)
653f61480ecSJung-uk Kim 		return (EINVAL);
654f61480ecSJung-uk Kim 	msgp = PTRIN(args->msgp);
655f61480ecSJung-uk Kim 	if ((error = copyin(msgp, &lmtype, sizeof(lmtype))) != 0)
656f61480ecSJung-uk Kim 		return (error);
657f61480ecSJung-uk Kim 	mtype = (long)lmtype;
658f61480ecSJung-uk Kim 	return (kern_msgsnd(td, args->msqid,
659f61480ecSJung-uk Kim 	    (const char *)msgp + sizeof(lmtype),
660f61480ecSJung-uk Kim 	    args->msgsz, args->msgflg, mtype));
661c21dee17SSøren Schmidt }
662c21dee17SSøren Schmidt 
663afa66fa8SMarcel Moolenaar int
linux_msgrcv(struct thread * td,struct linux_msgrcv_args * args)664b40ce416SJulian Elischer linux_msgrcv(struct thread *td, struct linux_msgrcv_args *args)
665c21dee17SSøren Schmidt {
666bb5889bdSSøren Schmidt 	void *msgp;
667f61480ecSJung-uk Kim 	long mtype;
668f61480ecSJung-uk Kim 	l_long lmtype;
669f61480ecSJung-uk Kim 	int error;
670bb5889bdSSøren Schmidt 
67134ec45feSJung-uk Kim 	if ((l_long)args->msgsz < 0 || args->msgsz > (l_long)msginfo.msgmax)
672f61480ecSJung-uk Kim 		return (EINVAL);
673f61480ecSJung-uk Kim 	msgp = PTRIN(args->msgp);
674f61480ecSJung-uk Kim 	if ((error = kern_msgrcv(td, args->msqid,
675f61480ecSJung-uk Kim 	    (char *)msgp + sizeof(lmtype), args->msgsz,
676f61480ecSJung-uk Kim 	    args->msgtyp, args->msgflg, &mtype)) != 0)
677f61480ecSJung-uk Kim 		return (error);
678f61480ecSJung-uk Kim 	lmtype = (l_long)mtype;
679f61480ecSJung-uk Kim 	return (copyout(&lmtype, msgp, sizeof(lmtype)));
680c21dee17SSøren Schmidt }
681c21dee17SSøren Schmidt 
682afa66fa8SMarcel Moolenaar int
linux_msgget(struct thread * td,struct linux_msgget_args * args)683b40ce416SJulian Elischer linux_msgget(struct thread *td, struct linux_msgget_args *args)
684c21dee17SSøren Schmidt {
6853e0c56a7SDmitry Chagin 	struct msgget_args bsd_args = {
6863e0c56a7SDmitry Chagin 		.key = args->key,
6873e0c56a7SDmitry Chagin 		.msgflg = args->msgflg
6883e0c56a7SDmitry Chagin 	};
689bb5889bdSSøren Schmidt 
6908451d0ddSKip Macy 	return (sys_msgget(td, &bsd_args));
691c21dee17SSøren Schmidt }
692c21dee17SSøren Schmidt 
693afa66fa8SMarcel Moolenaar int
linux_msgctl(struct thread * td,struct linux_msgctl_args * args)694b40ce416SJulian Elischer linux_msgctl(struct thread *td, struct linux_msgctl_args *args)
695c21dee17SSøren Schmidt {
696f4b6eb04SMaxim Sobolev 	int error, bsd_cmd;
697ab60bc84SDmitry Chagin 	struct l_msqid64_ds linux_msqid64;
698f4b6eb04SMaxim Sobolev 	struct msqid_ds bsd_msqid;
699bb5889bdSSøren Schmidt 
7006eee883aSEitan Adler 	memset(&linux_msqid64, 0, sizeof(linux_msqid64));
7016eee883aSEitan Adler 
702f3ea244eSJohn Baldwin 	bsd_cmd = args->cmd & ~LINUX_IPC_64;
70334ec45feSJung-uk Kim 	switch (bsd_cmd) {
70434ec45feSJung-uk Kim 	case LINUX_IPC_INFO:
70534ec45feSJung-uk Kim 	case LINUX_MSG_INFO: {
70634ec45feSJung-uk Kim 		struct l_msginfo linux_msginfo;
70734ec45feSJung-uk Kim 
7086eee883aSEitan Adler 		memset(&linux_msginfo, 0, sizeof(linux_msginfo));
70934ec45feSJung-uk Kim 		/*
71034ec45feSJung-uk Kim 		 * XXX MSG_INFO uses the same data structure but returns different
71134ec45feSJung-uk Kim 		 * dynamic counters in msgpool, msgmap, and msgtql fields.
71234ec45feSJung-uk Kim 		 */
71334ec45feSJung-uk Kim 		linux_msginfo.msgpool = (long)msginfo.msgmni *
71434ec45feSJung-uk Kim 		    (long)msginfo.msgmnb / 1024L;	/* XXX MSG_INFO. */
71534ec45feSJung-uk Kim 		linux_msginfo.msgmap = msginfo.msgmnb;	/* XXX MSG_INFO. */
71634ec45feSJung-uk Kim 		linux_msginfo.msgmax = msginfo.msgmax;
71734ec45feSJung-uk Kim 		linux_msginfo.msgmnb = msginfo.msgmnb;
71834ec45feSJung-uk Kim 		linux_msginfo.msgmni = msginfo.msgmni;
71934ec45feSJung-uk Kim 		linux_msginfo.msgssz = msginfo.msgssz;
72034ec45feSJung-uk Kim 		linux_msginfo.msgtql = msginfo.msgtql;	/* XXX MSG_INFO. */
72134ec45feSJung-uk Kim 		linux_msginfo.msgseg = msginfo.msgseg;
72234ec45feSJung-uk Kim 		error = copyout(&linux_msginfo, PTRIN(args->buf),
72334ec45feSJung-uk Kim 		    sizeof(linux_msginfo));
72434ec45feSJung-uk Kim 		if (error == 0)
72534ec45feSJung-uk Kim 		    td->td_retval[0] = msginfo.msgmni;	/* XXX */
72634ec45feSJung-uk Kim 
72734ec45feSJung-uk Kim 		return (error);
72834ec45feSJung-uk Kim 	}
72934ec45feSJung-uk Kim 
7307356a43cSRoman Divacky 	/*
7317356a43cSRoman Divacky 	 * TODO: implement this
7327356a43cSRoman Divacky 	 * case LINUX_MSG_STAT:
7337356a43cSRoman Divacky 	 */
7347356a43cSRoman Divacky 	case LINUX_IPC_STAT:
7357356a43cSRoman Divacky 		/* NOTHING */
7367356a43cSRoman Divacky 		break;
7377356a43cSRoman Divacky 
73834ec45feSJung-uk Kim 	case LINUX_IPC_SET:
7393ad9c842SMaxim Sobolev 		error = linux_msqid_pullup(args->cmd & LINUX_IPC_64,
740ab60bc84SDmitry Chagin 		    &linux_msqid64, PTRIN(args->buf));
7418042c504SDmitry Chagin 		if (error != 0)
7423ad9c842SMaxim Sobolev 			return (error);
743ab60bc84SDmitry Chagin 		linux_to_bsd_msqid_ds(&linux_msqid64, &bsd_msqid);
74434ec45feSJung-uk Kim 		break;
7457356a43cSRoman Divacky 
7467356a43cSRoman Divacky 	case LINUX_IPC_RMID:
7477356a43cSRoman Divacky 		/* NOTHING */
7487356a43cSRoman Divacky 		break;
7497356a43cSRoman Divacky 
7507356a43cSRoman Divacky 	default:
7517356a43cSRoman Divacky 		return (EINVAL);
7527356a43cSRoman Divacky 		break;
753f3ea244eSJohn Baldwin 	}
7543ad9c842SMaxim Sobolev 
75576951d21SJohn Baldwin 	error = kern_msgctl(td, args->msqid, bsd_cmd, &bsd_msqid);
756ab60bc84SDmitry Chagin 	if (error != 0) {
757ab60bc84SDmitry Chagin 		if (bsd_cmd == LINUX_IPC_RMID && error == EACCES)
758ab60bc84SDmitry Chagin 			return (EPERM);
759f4b6eb04SMaxim Sobolev 		if (bsd_cmd != LINUX_IPC_RMID || error != EINVAL)
7603ad9c842SMaxim Sobolev 			return (error);
761ab60bc84SDmitry Chagin 	}
7623ad9c842SMaxim Sobolev 
763f4b6eb04SMaxim Sobolev 	if (bsd_cmd == LINUX_IPC_STAT) {
764ab60bc84SDmitry Chagin 		bsd_to_linux_msqid_ds(&bsd_msqid, &linux_msqid64);
7653ad9c842SMaxim Sobolev 		return (linux_msqid_pushdown(args->cmd & LINUX_IPC_64,
766ab60bc84SDmitry Chagin 		    &linux_msqid64, PTRIN(args->buf)));
7673ad9c842SMaxim Sobolev 	}
7683ad9c842SMaxim Sobolev 
7693ad9c842SMaxim Sobolev 	return (0);
770c21dee17SSøren Schmidt }
771c21dee17SSøren Schmidt 
772afa66fa8SMarcel Moolenaar int
linux_shmat(struct thread * td,struct linux_shmat_args * args)773b40ce416SJulian Elischer linux_shmat(struct thread *td, struct linux_shmat_args *args)
774c21dee17SSøren Schmidt {
7753e0c56a7SDmitry Chagin 	struct shmat_args bsd_args = {
7763e0c56a7SDmitry Chagin 		.shmid = args->shmid,
7773e0c56a7SDmitry Chagin 		.shmaddr = PTRIN(args->shmaddr),
7783e0c56a7SDmitry Chagin 		.shmflg = args->shmflg
7793e0c56a7SDmitry Chagin 	};
780c21dee17SSøren Schmidt 
7817dabf89bSDmitry Chagin 	return (sys_shmat(td, &bsd_args));
782c21dee17SSøren Schmidt }
783c21dee17SSøren Schmidt 
784afa66fa8SMarcel Moolenaar int
linux_shmdt(struct thread * td,struct linux_shmdt_args * args)785b40ce416SJulian Elischer linux_shmdt(struct thread *td, struct linux_shmdt_args *args)
786c21dee17SSøren Schmidt {
7873e0c56a7SDmitry Chagin 	struct shmdt_args bsd_args = {
7883e0c56a7SDmitry Chagin 		.shmaddr = PTRIN(args->shmaddr)
7893e0c56a7SDmitry Chagin 	};
790c21dee17SSøren Schmidt 
7918451d0ddSKip Macy 	return (sys_shmdt(td, &bsd_args));
792c21dee17SSøren Schmidt }
793c21dee17SSøren Schmidt 
794afa66fa8SMarcel Moolenaar int
linux_shmget(struct thread * td,struct linux_shmget_args * args)795b40ce416SJulian Elischer linux_shmget(struct thread *td, struct linux_shmget_args *args)
796c21dee17SSøren Schmidt {
7973e0c56a7SDmitry Chagin 	struct shmget_args bsd_args = {
7983e0c56a7SDmitry Chagin 		.key = args->key,
7993e0c56a7SDmitry Chagin 		.size = args->size,
8003e0c56a7SDmitry Chagin 		.shmflg = args->shmflg
8013e0c56a7SDmitry Chagin 	};
802c21dee17SSøren Schmidt 
8038451d0ddSKip Macy 	return (sys_shmget(td, &bsd_args));
804c21dee17SSøren Schmidt }
805c21dee17SSøren Schmidt 
806afa66fa8SMarcel Moolenaar int
linux_shmctl(struct thread * td,struct linux_shmctl_args * args)807b40ce416SJulian Elischer linux_shmctl(struct thread *td, struct linux_shmctl_args *args)
808c21dee17SSøren Schmidt {
809ab60bc84SDmitry Chagin 	struct l_shmid64_ds linux_shmid64;
810ab60bc84SDmitry Chagin 	struct l_shminfo64 linux_shminfo64;
811491dec93SMichael Reifenberger 	struct l_shm_info linux_shm_info;
812f130dcf2SMartin Blapp 	struct shmid_ds bsd_shmid;
813c21dee17SSøren Schmidt 	int error;
814c21dee17SSøren Schmidt 
8156eee883aSEitan Adler 	memset(&linux_shm_info, 0, sizeof(linux_shm_info));
8166eee883aSEitan Adler 	memset(&linux_shmid64, 0, sizeof(linux_shmid64));
8176eee883aSEitan Adler 	memset(&linux_shminfo64, 0, sizeof(linux_shminfo64));
8186eee883aSEitan Adler 
8193ad9c842SMaxim Sobolev 	switch (args->cmd & ~LINUX_IPC_64) {
820f130dcf2SMartin Blapp 	case LINUX_IPC_INFO: {
821f130dcf2SMartin Blapp 		struct shminfo bsd_shminfo;
822f130dcf2SMartin Blapp 
823f130dcf2SMartin Blapp 		/* Perform shmctl wanting removed segments lookup */
824f130dcf2SMartin Blapp 		error = kern_shmctl(td, args->shmid, IPC_INFO,
8258528552bSJohn Baldwin 		    (void *)&bsd_shminfo, NULL);
8268042c504SDmitry Chagin 		if (error != 0)
82731f7ad15SDmitry Chagin 			return (error);
828f130dcf2SMartin Blapp 
829ab60bc84SDmitry Chagin 		bsd_to_linux_shminfo(&bsd_shminfo, &linux_shminfo64);
830f130dcf2SMartin Blapp 
8313ad9c842SMaxim Sobolev 		return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_64,
832ab60bc84SDmitry Chagin 		    &linux_shminfo64, PTRIN(args->buf)));
833f130dcf2SMartin Blapp 	}
834491dec93SMichael Reifenberger 
835f130dcf2SMartin Blapp 	case LINUX_SHM_INFO: {
836f130dcf2SMartin Blapp 		struct shm_info bsd_shm_info;
837f130dcf2SMartin Blapp 
838f130dcf2SMartin Blapp 		/* Perform shmctl wanting removed segments lookup */
839f130dcf2SMartin Blapp 		error = kern_shmctl(td, args->shmid, SHM_INFO,
8408528552bSJohn Baldwin 		    (void *)&bsd_shm_info, NULL);
8418042c504SDmitry Chagin 		if (error != 0)
84231f7ad15SDmitry Chagin 			return (error);
843f130dcf2SMartin Blapp 
844f130dcf2SMartin Blapp 		bsd_to_linux_shm_info(&bsd_shm_info, &linux_shm_info);
845f130dcf2SMartin Blapp 
84631f7ad15SDmitry Chagin 		return (copyout(&linux_shm_info, PTRIN(args->buf),
84731f7ad15SDmitry Chagin 		    sizeof(struct l_shm_info)));
848f130dcf2SMartin Blapp 	}
849491dec93SMichael Reifenberger 
850c21dee17SSøren Schmidt 	case LINUX_IPC_STAT:
851f130dcf2SMartin Blapp 		/* Perform shmctl wanting removed segments lookup */
852f130dcf2SMartin Blapp 		error = kern_shmctl(td, args->shmid, IPC_STAT,
8538528552bSJohn Baldwin 		    (void *)&bsd_shmid, NULL);
8548042c504SDmitry Chagin 		if (error != 0)
85531f7ad15SDmitry Chagin 			return (error);
856f130dcf2SMartin Blapp 
857ab60bc84SDmitry Chagin 		bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid64);
858f130dcf2SMartin Blapp 
8593ad9c842SMaxim Sobolev 		return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
860ab60bc84SDmitry Chagin 		    &linux_shmid64, PTRIN(args->buf)));
861c21dee17SSøren Schmidt 
862491dec93SMichael Reifenberger 	case LINUX_SHM_STAT:
863f130dcf2SMartin Blapp 		/* Perform shmctl wanting removed segments lookup */
864f130dcf2SMartin Blapp 		error = kern_shmctl(td, args->shmid, IPC_STAT,
8658528552bSJohn Baldwin 		    (void *)&bsd_shmid, NULL);
8668042c504SDmitry Chagin 		if (error != 0)
86731f7ad15SDmitry Chagin 			return (error);
868f130dcf2SMartin Blapp 
869ab60bc84SDmitry Chagin 		bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid64);
870f130dcf2SMartin Blapp 
8713ad9c842SMaxim Sobolev 		return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
872ab60bc84SDmitry Chagin 		    &linux_shmid64, PTRIN(args->buf)));
873491dec93SMichael Reifenberger 
874c21dee17SSøren Schmidt 	case LINUX_IPC_SET:
8753ad9c842SMaxim Sobolev 		error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
876ab60bc84SDmitry Chagin 		    &linux_shmid64, PTRIN(args->buf));
8778042c504SDmitry Chagin 		if (error != 0)
87831f7ad15SDmitry Chagin 			return (error);
879c21dee17SSøren Schmidt 
880ab60bc84SDmitry Chagin 		linux_to_bsd_shmid_ds(&linux_shmid64, &bsd_shmid);
881f130dcf2SMartin Blapp 
882f130dcf2SMartin Blapp 		/* Perform shmctl wanting removed segments lookup */
88331f7ad15SDmitry Chagin 		return (kern_shmctl(td, args->shmid, IPC_SET,
88431f7ad15SDmitry Chagin 		    (void *)&bsd_shmid, NULL));
885f130dcf2SMartin Blapp 
886f130dcf2SMartin Blapp 	case LINUX_IPC_RMID: {
887f130dcf2SMartin Blapp 		void *buf;
888f130dcf2SMartin Blapp 
8894af27623STim J. Robbins 		if (args->buf == 0)
890f130dcf2SMartin Blapp 			buf = NULL;
891ba988339SJordan K. Hubbard 		else {
8923ad9c842SMaxim Sobolev 			error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
893ab60bc84SDmitry Chagin 			    &linux_shmid64, PTRIN(args->buf));
8948042c504SDmitry Chagin 			if (error != 0)
89531f7ad15SDmitry Chagin 				return (error);
896ab60bc84SDmitry Chagin 			linux_to_bsd_shmid_ds(&linux_shmid64, &bsd_shmid);
897f130dcf2SMartin Blapp 			buf = (void *)&bsd_shmid;
898ba988339SJordan K. Hubbard 		}
89931f7ad15SDmitry Chagin 		return (kern_shmctl(td, args->shmid, IPC_RMID, buf, NULL));
900f130dcf2SMartin Blapp 	}
901c21dee17SSøren Schmidt 
902c21dee17SSøren Schmidt 	case LINUX_SHM_LOCK:
90331f7ad15SDmitry Chagin 		/* FALLTHROUGH */
904c21dee17SSøren Schmidt 	case LINUX_SHM_UNLOCK:
90531f7ad15SDmitry Chagin 		/* FALLTHROUGH */
906c21dee17SSøren Schmidt 	default:
90731f7ad15SDmitry Chagin 		linux_msg(td, "ipc type %d not implemented",
90831f7ad15SDmitry Chagin 		    args->cmd & ~LINUX_IPC_64);
90931f7ad15SDmitry Chagin 		return (EINVAL);
910c21dee17SSøren Schmidt 	}
911c21dee17SSøren Schmidt }
912813a5e14SJohn Baldwin 
913813a5e14SJohn Baldwin MODULE_DEPEND(linux, sysvmsg, 1, 1, 1);
914813a5e14SJohn Baldwin MODULE_DEPEND(linux, sysvsem, 1, 1, 1);
915813a5e14SJohn Baldwin MODULE_DEPEND(linux, sysvshm, 1, 1, 1);
916