File: | modules/linux64/../../compat/linux/linux_ipc.c |
Warning: | line 820, column 11 Copies out a struct with uncleared padding (>= 4 bytes) |
1 | /*- | |||
2 | * Copyright (c) 1994-1995 Søren Schmidt | |||
3 | * All rights reserved. | |||
4 | * | |||
5 | * Redistribution and use in source and binary forms, with or without | |||
6 | * modification, are permitted provided that the following conditions | |||
7 | * are met: | |||
8 | * 1. Redistributions of source code must retain the above copyright | |||
9 | * notice, this list of conditions and the following disclaimer | |||
10 | * in this position and unchanged. | |||
11 | * 2. Redistributions in binary form must reproduce the above copyright | |||
12 | * notice, this list of conditions and the following disclaimer in the | |||
13 | * documentation and/or other materials provided with the distribution. | |||
14 | * 3. The name of the author may not be used to endorse or promote products | |||
15 | * derived from this software without specific prior written permission | |||
16 | * | |||
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
27 | */ | |||
28 | ||||
29 | #include <sys/cdefs.h> | |||
30 | __FBSDID("$FreeBSD: releng/11.0/sys/compat/linux/linux_ipc.c 283416 2015-05-24 15:44:41Z dchagin $")__asm__(".ident\t\"" "$FreeBSD: releng/11.0/sys/compat/linux/linux_ipc.c 283416 2015-05-24 15:44:41Z dchagin $" "\""); | |||
31 | ||||
32 | #include <sys/param.h> | |||
33 | #include <sys/systm.h> | |||
34 | #include <sys/syscallsubr.h> | |||
35 | #include <sys/sysproto.h> | |||
36 | #include <sys/proc.h> | |||
37 | #include <sys/limits.h> | |||
38 | #include <sys/msg.h> | |||
39 | #include <sys/sem.h> | |||
40 | #include <sys/shm.h> | |||
41 | ||||
42 | #include "opt_compat.h" | |||
43 | ||||
44 | #ifdef COMPAT_LINUX32 | |||
45 | #include <machine/../linux32/linux.h> | |||
46 | #include <machine/../linux32/linux32_proto.h> | |||
47 | #include <machine/../linux32/linux32_ipc64.h> | |||
48 | #else | |||
49 | #include <machine/../linux/linux.h> | |||
50 | #include <machine/../linux/linux_proto.h> | |||
51 | #include <machine/../linux/linux_ipc64.h> | |||
52 | #endif | |||
53 | #include <compat/linux/linux_ipc.h> | |||
54 | #include <compat/linux/linux_util.h> | |||
55 | ||||
56 | struct l_seminfo { | |||
57 | l_int semmap; | |||
58 | l_int semmni; | |||
59 | l_int semmns; | |||
60 | l_int semmnu; | |||
61 | l_int semmsl; | |||
62 | l_int semopm; | |||
63 | l_int semume; | |||
64 | l_int semusz; | |||
65 | l_int semvmx; | |||
66 | l_int semaem; | |||
67 | }; | |||
68 | ||||
69 | struct l_shminfo { | |||
70 | l_int shmmax; | |||
71 | l_int shmmin; | |||
72 | l_int shmmni; | |||
73 | l_int shmseg; | |||
74 | l_int shmall; | |||
75 | }; | |||
76 | ||||
77 | struct l_shm_info { | |||
78 | l_int used_ids; | |||
79 | l_ulong shm_tot; /* total allocated shm */ | |||
80 | l_ulong shm_rss; /* total resident shm */ | |||
81 | l_ulong shm_swp; /* total swapped shm */ | |||
82 | l_ulong swap_attempts; | |||
83 | l_ulong swap_successes; | |||
84 | }; | |||
85 | ||||
86 | struct l_msginfo { | |||
87 | l_int msgpool; | |||
88 | l_int msgmap; | |||
89 | l_int msgmax; | |||
90 | l_int msgmnb; | |||
91 | l_int msgmni; | |||
92 | l_int msgssz; | |||
93 | l_int msgtql; | |||
94 | l_ushort msgseg; | |||
95 | }; | |||
96 | ||||
97 | static void | |||
98 | bsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo *lpp) | |||
99 | { | |||
100 | ||||
101 | lpp->shmmax = bpp->shmmax; | |||
102 | lpp->shmmin = bpp->shmmin; | |||
103 | lpp->shmmni = bpp->shmmni; | |||
104 | lpp->shmseg = bpp->shmseg; | |||
105 | lpp->shmall = bpp->shmall; | |||
106 | } | |||
107 | ||||
108 | static void | |||
109 | bsd_to_linux_shm_info( struct shm_info *bpp, struct l_shm_info *lpp) | |||
110 | { | |||
111 | ||||
112 | lpp->used_ids = bpp->used_ids ; | |||
113 | lpp->shm_tot = bpp->shm_tot ; | |||
114 | lpp->shm_rss = bpp->shm_rss ; | |||
115 | lpp->shm_swp = bpp->shm_swp ; | |||
116 | lpp->swap_attempts = bpp->swap_attempts ; | |||
117 | lpp->swap_successes = bpp->swap_successes ; | |||
118 | } | |||
119 | ||||
120 | static void | |||
121 | linux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp) | |||
122 | { | |||
123 | ||||
124 | bpp->key = lpp->key; | |||
125 | bpp->uid = lpp->uid; | |||
126 | bpp->gid = lpp->gid; | |||
127 | bpp->cuid = lpp->cuid; | |||
128 | bpp->cgid = lpp->cgid; | |||
129 | bpp->mode = lpp->mode; | |||
130 | bpp->seq = lpp->seq; | |||
131 | } | |||
132 | ||||
133 | ||||
134 | static void | |||
135 | bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp) | |||
136 | { | |||
137 | ||||
138 | lpp->key = bpp->key; | |||
139 | lpp->uid = bpp->uid; | |||
140 | lpp->gid = bpp->gid; | |||
141 | lpp->cuid = bpp->cuid; | |||
142 | lpp->cgid = bpp->cgid; | |||
143 | lpp->mode = bpp->mode; | |||
144 | lpp->seq = bpp->seq; | |||
145 | } | |||
146 | ||||
147 | struct l_msqid_ds { | |||
148 | struct l_ipc_perm msg_perm; | |||
149 | l_uintptr_t msg_first; /* first message on queue,unused */ | |||
150 | l_uintptr_t msg_last; /* last message in queue,unused */ | |||
151 | l_time_t msg_stime; /* last msgsnd time */ | |||
152 | l_time_t msg_rtime; /* last msgrcv time */ | |||
153 | l_time_t msg_ctime; /* last change time */ | |||
154 | l_ulong msg_lcbytes; /* Reuse junk fields for 32 bit */ | |||
155 | l_ulong msg_lqbytes; /* ditto */ | |||
156 | l_ushort msg_cbytes; /* current number of bytes on queue */ | |||
157 | l_ushort msg_qnum; /* number of messages in queue */ | |||
158 | l_ushort msg_qbytes; /* max number of bytes on queue */ | |||
159 | l_pid_t msg_lspid; /* pid of last msgsnd */ | |||
160 | l_pid_t msg_lrpid; /* last receive pid */ | |||
161 | } | |||
162 | #if defined(__amd64__1) && defined(COMPAT_LINUX32) | |||
163 | __packed__attribute__((__packed__)) | |||
164 | #endif | |||
165 | ; | |||
166 | ||||
167 | struct l_semid_ds { | |||
168 | struct l_ipc_perm sem_perm; | |||
169 | l_time_t sem_otime; | |||
170 | l_time_t sem_ctime; | |||
171 | l_uintptr_t sem_base; | |||
172 | l_uintptr_t sem_pending; | |||
173 | l_uintptr_t sem_pending_last; | |||
174 | l_uintptr_t undo; | |||
175 | l_ushort sem_nsems; | |||
176 | } | |||
177 | #if defined(__amd64__1) && defined(COMPAT_LINUX32) | |||
178 | __packed__attribute__((__packed__)) | |||
179 | #endif | |||
180 | ; | |||
181 | ||||
182 | struct l_shmid_ds { | |||
183 | struct l_ipc_perm shm_perm; | |||
184 | l_int shm_segsz; | |||
185 | l_time_t shm_atime; | |||
186 | l_time_t shm_dtime; | |||
187 | l_time_t shm_ctime; | |||
188 | l_ushort shm_cpid; | |||
189 | l_ushort shm_lpid; | |||
190 | l_short shm_nattch; | |||
191 | l_ushort private1; | |||
192 | l_uintptr_t private2; | |||
193 | l_uintptr_t private3; | |||
194 | }; | |||
195 | ||||
196 | static void | |||
197 | linux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp) | |||
198 | { | |||
199 | ||||
200 | linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm); | |||
201 | bsp->sem_otime = lsp->sem_otime; | |||
202 | bsp->sem_ctime = lsp->sem_ctime; | |||
203 | bsp->sem_nsems = lsp->sem_nsems; | |||
204 | bsp->sem_base = PTRIN(lsp->sem_base)(void *)(lsp->sem_base); | |||
205 | } | |||
206 | ||||
207 | static void | |||
208 | bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp) | |||
209 | { | |||
210 | ||||
211 | bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm); | |||
212 | lsp->sem_otime = bsp->sem_otime; | |||
213 | lsp->sem_ctime = bsp->sem_ctime; | |||
214 | lsp->sem_nsems = bsp->sem_nsems; | |||
215 | lsp->sem_base = PTROUT(bsp->sem_base)(uintptr_t)(bsp->sem_base); | |||
216 | } | |||
217 | ||||
218 | static void | |||
219 | linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp) | |||
220 | { | |||
221 | ||||
222 | linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); | |||
223 | bsp->shm_segsz = lsp->shm_segsz; | |||
224 | bsp->shm_lpid = lsp->shm_lpid; | |||
225 | bsp->shm_cpid = lsp->shm_cpid; | |||
226 | bsp->shm_nattch = lsp->shm_nattch; | |||
227 | bsp->shm_atime = lsp->shm_atime; | |||
228 | bsp->shm_dtime = lsp->shm_dtime; | |||
229 | bsp->shm_ctime = lsp->shm_ctime; | |||
230 | } | |||
231 | ||||
232 | static void | |||
233 | bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp) | |||
234 | { | |||
235 | ||||
236 | bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); | |||
237 | if (bsp->shm_segsz > INT_MAX0x7fffffff) | |||
238 | lsp->shm_segsz = INT_MAX0x7fffffff; | |||
239 | else | |||
240 | lsp->shm_segsz = bsp->shm_segsz; | |||
241 | lsp->shm_lpid = bsp->shm_lpid; | |||
242 | lsp->shm_cpid = bsp->shm_cpid; | |||
243 | if (bsp->shm_nattch > SHRT_MAX0x7fff) | |||
244 | lsp->shm_nattch = SHRT_MAX0x7fff; | |||
245 | else | |||
246 | lsp->shm_nattch = bsp->shm_nattch; | |||
247 | lsp->shm_atime = bsp->shm_atime; | |||
248 | lsp->shm_dtime = bsp->shm_dtime; | |||
249 | lsp->shm_ctime = bsp->shm_ctime; | |||
250 | lsp->private3 = 0; | |||
251 | } | |||
252 | ||||
253 | static void | |||
254 | linux_to_bsd_msqid_ds(struct l_msqid_ds *lsp, struct msqid_ds *bsp) | |||
255 | { | |||
256 | ||||
257 | linux_to_bsd_ipc_perm(&lsp->msg_perm, &bsp->msg_perm); | |||
258 | bsp->msg_cbytes = lsp->msg_cbytes; | |||
259 | bsp->msg_qnum = lsp->msg_qnum; | |||
260 | bsp->msg_qbytes = lsp->msg_qbytes; | |||
261 | bsp->msg_lspid = lsp->msg_lspid; | |||
262 | bsp->msg_lrpid = lsp->msg_lrpid; | |||
263 | bsp->msg_stime = lsp->msg_stime; | |||
264 | bsp->msg_rtime = lsp->msg_rtime; | |||
265 | bsp->msg_ctime = lsp->msg_ctime; | |||
266 | } | |||
267 | ||||
268 | static void | |||
269 | bsd_to_linux_msqid_ds(struct msqid_ds *bsp, struct l_msqid_ds *lsp) | |||
270 | { | |||
271 | ||||
272 | bsd_to_linux_ipc_perm(&bsp->msg_perm, &lsp->msg_perm); | |||
273 | lsp->msg_cbytes = bsp->msg_cbytes; | |||
274 | lsp->msg_qnum = bsp->msg_qnum; | |||
275 | lsp->msg_qbytes = bsp->msg_qbytes; | |||
276 | lsp->msg_lspid = bsp->msg_lspid; | |||
277 | lsp->msg_lrpid = bsp->msg_lrpid; | |||
278 | lsp->msg_stime = bsp->msg_stime; | |||
279 | lsp->msg_rtime = bsp->msg_rtime; | |||
280 | lsp->msg_ctime = bsp->msg_ctime; | |||
281 | } | |||
282 | ||||
283 | static void | |||
284 | linux_ipc_perm_to_ipc64_perm(struct l_ipc_perm *in, struct l_ipc64_perm *out) | |||
285 | { | |||
286 | ||||
287 | /* XXX: do we really need to do something here? */ | |||
288 | out->key = in->key; | |||
289 | out->uid = in->uid; | |||
290 | out->gid = in->gid; | |||
291 | out->cuid = in->cuid; | |||
292 | out->cgid = in->cgid; | |||
293 | out->mode = in->mode; | |||
294 | out->seq = in->seq; | |||
295 | } | |||
296 | ||||
297 | static int | |||
298 | linux_msqid_pullup(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr) | |||
299 | { | |||
300 | struct l_msqid64_ds linux_msqid64; | |||
301 | int error; | |||
302 | ||||
303 | if (ver == LINUX_IPC_640x0100) { | |||
304 | error = copyin(uaddr, &linux_msqid64, sizeof(linux_msqid64)); | |||
305 | if (error != 0) | |||
306 | return (error); | |||
307 | ||||
308 | bzero(linux_msqid, sizeof(*linux_msqid)); | |||
309 | ||||
310 | linux_msqid->msg_perm.uid = linux_msqid64.msg_perm.uid; | |||
311 | linux_msqid->msg_perm.gid = linux_msqid64.msg_perm.gid; | |||
312 | linux_msqid->msg_perm.mode = linux_msqid64.msg_perm.mode; | |||
313 | ||||
314 | if (linux_msqid64.msg_qbytes > USHRT_MAX0xffff) | |||
315 | linux_msqid->msg_lqbytes = linux_msqid64.msg_qbytes; | |||
316 | else | |||
317 | linux_msqid->msg_qbytes = linux_msqid64.msg_qbytes; | |||
318 | } else | |||
319 | error = copyin(uaddr, linux_msqid, sizeof(*linux_msqid)); | |||
320 | ||||
321 | return (error); | |||
322 | } | |||
323 | ||||
324 | static int | |||
325 | linux_msqid_pushdown(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr) | |||
326 | { | |||
327 | struct l_msqid64_ds linux_msqid64; | |||
328 | ||||
329 | if (ver == LINUX_IPC_640x0100) { | |||
330 | bzero(&linux_msqid64, sizeof(linux_msqid64)); | |||
331 | ||||
332 | linux_ipc_perm_to_ipc64_perm(&linux_msqid->msg_perm, | |||
333 | &linux_msqid64.msg_perm); | |||
334 | ||||
335 | linux_msqid64.msg_stime = linux_msqid->msg_stime; | |||
336 | linux_msqid64.msg_rtime = linux_msqid->msg_rtime; | |||
337 | linux_msqid64.msg_ctime = linux_msqid->msg_ctime; | |||
338 | ||||
339 | if (linux_msqid->msg_cbytes == 0) | |||
340 | linux_msqid64.msg_cbytes = linux_msqid->msg_lcbytes; | |||
341 | else | |||
342 | linux_msqid64.msg_cbytes = linux_msqid->msg_cbytes; | |||
343 | ||||
344 | linux_msqid64.msg_qnum = linux_msqid->msg_qnum; | |||
345 | ||||
346 | if (linux_msqid->msg_qbytes == 0) | |||
347 | linux_msqid64.msg_qbytes = linux_msqid->msg_lqbytes; | |||
348 | else | |||
349 | linux_msqid64.msg_qbytes = linux_msqid->msg_qbytes; | |||
350 | ||||
351 | linux_msqid64.msg_lspid = linux_msqid->msg_lspid; | |||
352 | linux_msqid64.msg_lrpid = linux_msqid->msg_lrpid; | |||
353 | ||||
354 | return (copyout(&linux_msqid64, uaddr, sizeof(linux_msqid64))); | |||
355 | } else | |||
356 | return (copyout(linux_msqid, uaddr, sizeof(*linux_msqid))); | |||
357 | } | |||
358 | ||||
359 | static int | |||
360 | linux_semid_pullup(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr) | |||
361 | { | |||
362 | struct l_semid64_ds linux_semid64; | |||
363 | int error; | |||
364 | ||||
365 | if (ver == LINUX_IPC_640x0100) { | |||
366 | error = copyin(uaddr, &linux_semid64, sizeof(linux_semid64)); | |||
367 | if (error != 0) | |||
368 | return (error); | |||
369 | ||||
370 | bzero(linux_semid, sizeof(*linux_semid)); | |||
371 | ||||
372 | linux_semid->sem_perm.uid = linux_semid64.sem_perm.uid; | |||
373 | linux_semid->sem_perm.gid = linux_semid64.sem_perm.gid; | |||
374 | linux_semid->sem_perm.mode = linux_semid64.sem_perm.mode; | |||
375 | } else | |||
376 | error = copyin(uaddr, linux_semid, sizeof(*linux_semid)); | |||
377 | ||||
378 | return (error); | |||
379 | } | |||
380 | ||||
381 | static int | |||
382 | linux_semid_pushdown(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr) | |||
383 | { | |||
384 | struct l_semid64_ds linux_semid64; | |||
385 | ||||
386 | if (ver == LINUX_IPC_640x0100) { | |||
387 | bzero(&linux_semid64, sizeof(linux_semid64)); | |||
388 | ||||
389 | linux_ipc_perm_to_ipc64_perm(&linux_semid->sem_perm, | |||
390 | &linux_semid64.sem_perm); | |||
391 | ||||
392 | linux_semid64.sem_otime = linux_semid->sem_otime; | |||
393 | linux_semid64.sem_ctime = linux_semid->sem_ctime; | |||
394 | linux_semid64.sem_nsems = linux_semid->sem_nsems; | |||
395 | ||||
396 | return (copyout(&linux_semid64, uaddr, sizeof(linux_semid64))); | |||
397 | } else | |||
398 | return (copyout(linux_semid, uaddr, sizeof(*linux_semid))); | |||
399 | } | |||
400 | ||||
401 | static int | |||
402 | linux_shmid_pullup(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr) | |||
403 | { | |||
404 | struct l_shmid64_ds linux_shmid64; | |||
405 | int error; | |||
406 | ||||
407 | if (ver == LINUX_IPC_640x0100) { | |||
408 | error = copyin(uaddr, &linux_shmid64, sizeof(linux_shmid64)); | |||
409 | if (error != 0) | |||
410 | return (error); | |||
411 | ||||
412 | bzero(linux_shmid, sizeof(*linux_shmid)); | |||
413 | ||||
414 | linux_shmid->shm_perm.uid = linux_shmid64.shm_perm.uid; | |||
415 | linux_shmid->shm_perm.gid = linux_shmid64.shm_perm.gid; | |||
416 | linux_shmid->shm_perm.mode = linux_shmid64.shm_perm.mode; | |||
417 | } else | |||
418 | error = copyin(uaddr, linux_shmid, sizeof(*linux_shmid)); | |||
419 | ||||
420 | return (error); | |||
421 | } | |||
422 | ||||
423 | static int | |||
424 | linux_shmid_pushdown(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr) | |||
425 | { | |||
426 | struct l_shmid64_ds linux_shmid64; | |||
427 | ||||
428 | /* | |||
429 | * XXX: This is backwards and loses information in shm_nattch | |||
430 | * and shm_segsz. We should probably either expose the BSD | |||
431 | * shmid structure directly and convert it to either the | |||
432 | * non-64 or 64 variant directly or the code should always | |||
433 | * convert to the 64 variant and then truncate values into the | |||
434 | * non-64 variant if needed since the 64 variant has more | |||
435 | * precision. | |||
436 | */ | |||
437 | if (ver == LINUX_IPC_640x0100) { | |||
438 | bzero(&linux_shmid64, sizeof(linux_shmid64)); | |||
439 | ||||
440 | linux_ipc_perm_to_ipc64_perm(&linux_shmid->shm_perm, | |||
441 | &linux_shmid64.shm_perm); | |||
442 | ||||
443 | linux_shmid64.shm_segsz = linux_shmid->shm_segsz; | |||
444 | linux_shmid64.shm_atime = linux_shmid->shm_atime; | |||
445 | linux_shmid64.shm_dtime = linux_shmid->shm_dtime; | |||
446 | linux_shmid64.shm_ctime = linux_shmid->shm_ctime; | |||
447 | linux_shmid64.shm_cpid = linux_shmid->shm_cpid; | |||
448 | linux_shmid64.shm_lpid = linux_shmid->shm_lpid; | |||
449 | linux_shmid64.shm_nattch = linux_shmid->shm_nattch; | |||
450 | ||||
451 | return (copyout(&linux_shmid64, uaddr, sizeof(linux_shmid64))); | |||
452 | } else | |||
453 | return (copyout(linux_shmid, uaddr, sizeof(*linux_shmid))); | |||
454 | } | |||
455 | ||||
456 | static int | |||
457 | linux_shminfo_pushdown(l_int ver, struct l_shminfo *linux_shminfo, | |||
458 | caddr_t uaddr) | |||
459 | { | |||
460 | struct l_shminfo64 linux_shminfo64; | |||
461 | ||||
462 | if (ver == LINUX_IPC_640x0100) { | |||
463 | bzero(&linux_shminfo64, sizeof(linux_shminfo64)); | |||
464 | ||||
465 | linux_shminfo64.shmmax = linux_shminfo->shmmax; | |||
466 | linux_shminfo64.shmmin = linux_shminfo->shmmin; | |||
467 | linux_shminfo64.shmmni = linux_shminfo->shmmni; | |||
468 | linux_shminfo64.shmseg = linux_shminfo->shmseg; | |||
469 | linux_shminfo64.shmall = linux_shminfo->shmall; | |||
470 | ||||
471 | return (copyout(&linux_shminfo64, uaddr, | |||
472 | sizeof(linux_shminfo64))); | |||
473 | } else | |||
474 | return (copyout(linux_shminfo, uaddr, sizeof(*linux_shminfo))); | |||
475 | } | |||
476 | ||||
477 | int | |||
478 | linux_semop(struct thread *td, struct linux_semop_args *args) | |||
479 | { | |||
480 | struct semop_args /* { | |||
481 | int semid; | |||
482 | struct sembuf *sops; | |||
483 | int nsops; | |||
484 | } */ bsd_args; | |||
485 | ||||
486 | bsd_args.semid = args->semid; | |||
487 | bsd_args.sops = PTRIN(args->tsops)(void *)(args->tsops); | |||
488 | bsd_args.nsops = args->nsops; | |||
489 | return (sys_semop(td, &bsd_args)); | |||
490 | } | |||
491 | ||||
492 | int | |||
493 | linux_semget(struct thread *td, struct linux_semget_args *args) | |||
494 | { | |||
495 | struct semget_args /* { | |||
496 | key_t key; | |||
497 | int nsems; | |||
498 | int semflg; | |||
499 | } */ bsd_args; | |||
500 | ||||
501 | if (args->nsems < 0) | |||
502 | return (EINVAL22); | |||
503 | bsd_args.key = args->key; | |||
504 | bsd_args.nsems = args->nsems; | |||
505 | bsd_args.semflg = args->semflg; | |||
506 | return (sys_semget(td, &bsd_args)); | |||
507 | } | |||
508 | ||||
509 | int | |||
510 | linux_semctl(struct thread *td, struct linux_semctl_args *args) | |||
511 | { | |||
512 | struct l_semid_ds linux_semid; | |||
513 | struct l_seminfo linux_seminfo; | |||
514 | struct semid_ds semid; | |||
515 | union semun semun; | |||
516 | register_t rval; | |||
517 | int cmd, error; | |||
518 | ||||
519 | switch (args->cmd & ~LINUX_IPC_640x0100) { | |||
520 | case LINUX_IPC_RMID0: | |||
521 | cmd = IPC_RMID0; | |||
522 | break; | |||
523 | case LINUX_GETNCNT14: | |||
524 | cmd = GETNCNT3; | |||
525 | break; | |||
526 | case LINUX_GETPID11: | |||
527 | cmd = GETPID4; | |||
528 | break; | |||
529 | case LINUX_GETVAL12: | |||
530 | cmd = GETVAL5; | |||
531 | break; | |||
532 | case LINUX_GETZCNT15: | |||
533 | cmd = GETZCNT7; | |||
534 | break; | |||
535 | case LINUX_SETVAL16: | |||
536 | cmd = SETVAL8; | |||
537 | semun.val = args->arg.val; | |||
538 | break; | |||
539 | case LINUX_IPC_SET1: | |||
540 | cmd = IPC_SET1; | |||
541 | error = linux_semid_pullup(args->cmd & LINUX_IPC_640x0100, | |||
542 | &linux_semid, PTRIN(args->arg.buf)(void *)(args->arg.buf)); | |||
543 | if (error) | |||
544 | return (error); | |||
545 | linux_to_bsd_semid_ds(&linux_semid, &semid); | |||
546 | semun.buf = &semid; | |||
547 | return (kern_semctl(td, args->semid, args->semnum, cmd, &semun, | |||
548 | td->td_retvaltd_uretoff.tdu_retval)); | |||
549 | case LINUX_IPC_STAT2: | |||
550 | case LINUX_SEM_STAT18: | |||
551 | if ((args->cmd & ~LINUX_IPC_640x0100) == LINUX_IPC_STAT2) | |||
552 | cmd = IPC_STAT2; | |||
553 | else | |||
554 | cmd = SEM_STAT10; | |||
555 | semun.buf = &semid; | |||
556 | error = kern_semctl(td, args->semid, args->semnum, cmd, &semun, | |||
557 | &rval); | |||
558 | if (error) | |||
559 | return (error); | |||
560 | bsd_to_linux_semid_ds(&semid, &linux_semid); | |||
561 | error = linux_semid_pushdown(args->cmd & LINUX_IPC_640x0100, | |||
562 | &linux_semid, PTRIN(args->arg.buf)(void *)(args->arg.buf)); | |||
563 | if (error == 0) | |||
564 | td->td_retvaltd_uretoff.tdu_retval[0] = (cmd == SEM_STAT10) ? rval : 0; | |||
565 | return (error); | |||
566 | case LINUX_IPC_INFO3: | |||
567 | case LINUX_SEM_INFO19: | |||
568 | bcopy(&seminfo, &linux_seminfo.semmni, sizeof(linux_seminfo) - | |||
569 | sizeof(linux_seminfo.semmap) ); | |||
570 | /* | |||
571 | * Linux does not use the semmap field but populates it with | |||
572 | * the defined value from SEMMAP, which really is redefined to | |||
573 | * SEMMNS, which they define as SEMMNI * SEMMSL. Try to | |||
574 | * simulate this returning our dynamic semmns value. | |||
575 | */ | |||
576 | linux_seminfo.semmap = linux_seminfo.semmns; | |||
577 | /* XXX BSD equivalent? | |||
578 | #define used_semids 10 | |||
579 | #define used_sems 10 | |||
580 | linux_seminfo.semusz = used_semids; | |||
581 | linux_seminfo.semaem = used_sems; | |||
582 | */ | |||
583 | error = copyout(&linux_seminfo, | |||
584 | PTRIN(args->arg.buf)(void *)(args->arg.buf), sizeof(linux_seminfo)); | |||
585 | if (error) | |||
586 | return (error); | |||
587 | td->td_retvaltd_uretoff.tdu_retval[0] = seminfo.semmni; | |||
588 | return (0); /* No need for __semctl call */ | |||
589 | case LINUX_GETALL13: | |||
590 | cmd = GETALL6; | |||
591 | semun.val = args->arg.val; | |||
592 | break; | |||
593 | case LINUX_SETALL17: | |||
594 | cmd = SETALL9; | |||
595 | semun.val = args->arg.val; | |||
596 | break; | |||
597 | default: | |||
598 | linux_msg(td, "ipc type %d is not implemented", | |||
599 | args->cmd & ~LINUX_IPC_640x0100); | |||
600 | return (EINVAL22); | |||
601 | } | |||
602 | return (kern_semctl(td, args->semid, args->semnum, cmd, &semun, | |||
603 | td->td_retvaltd_uretoff.tdu_retval)); | |||
604 | } | |||
605 | ||||
606 | int | |||
607 | linux_msgsnd(struct thread *td, struct linux_msgsnd_args *args) | |||
608 | { | |||
609 | const void *msgp; | |||
610 | long mtype; | |||
611 | l_long lmtype; | |||
612 | int error; | |||
613 | ||||
614 | if ((l_long)args->msgsz < 0 || args->msgsz > (l_long)msginfo.msgmax) | |||
615 | return (EINVAL22); | |||
616 | msgp = PTRIN(args->msgp)(void *)(args->msgp); | |||
617 | if ((error = copyin(msgp, &lmtype, sizeof(lmtype))) != 0) | |||
618 | return (error); | |||
619 | mtype = (long)lmtype; | |||
620 | return (kern_msgsnd(td, args->msqid, | |||
621 | (const char *)msgp + sizeof(lmtype), | |||
622 | args->msgsz, args->msgflg, mtype)); | |||
623 | } | |||
624 | ||||
625 | int | |||
626 | linux_msgrcv(struct thread *td, struct linux_msgrcv_args *args) | |||
627 | { | |||
628 | void *msgp; | |||
629 | long mtype; | |||
630 | l_long lmtype; | |||
631 | int error; | |||
632 | ||||
633 | if ((l_long)args->msgsz < 0 || args->msgsz > (l_long)msginfo.msgmax) | |||
634 | return (EINVAL22); | |||
635 | msgp = PTRIN(args->msgp)(void *)(args->msgp); | |||
636 | if ((error = kern_msgrcv(td, args->msqid, | |||
637 | (char *)msgp + sizeof(lmtype), args->msgsz, | |||
638 | args->msgtyp, args->msgflg, &mtype)) != 0) | |||
639 | return (error); | |||
640 | lmtype = (l_long)mtype; | |||
641 | return (copyout(&lmtype, msgp, sizeof(lmtype))); | |||
642 | } | |||
643 | ||||
644 | int | |||
645 | linux_msgget(struct thread *td, struct linux_msgget_args *args) | |||
646 | { | |||
647 | struct msgget_args /* { | |||
648 | key_t key; | |||
649 | int msgflg; | |||
650 | } */ bsd_args; | |||
651 | ||||
652 | bsd_args.key = args->key; | |||
653 | bsd_args.msgflg = args->msgflg; | |||
654 | return (sys_msgget(td, &bsd_args)); | |||
655 | } | |||
656 | ||||
657 | int | |||
658 | linux_msgctl(struct thread *td, struct linux_msgctl_args *args) | |||
659 | { | |||
660 | int error, bsd_cmd; | |||
661 | struct l_msqid_ds linux_msqid; | |||
662 | struct msqid_ds bsd_msqid; | |||
663 | ||||
664 | bsd_cmd = args->cmd & ~LINUX_IPC_640x0100; | |||
665 | switch (bsd_cmd) { | |||
666 | case LINUX_IPC_INFO3: | |||
667 | case LINUX_MSG_INFO12: { | |||
668 | struct l_msginfo linux_msginfo; | |||
669 | ||||
670 | /* | |||
671 | * XXX MSG_INFO uses the same data structure but returns different | |||
672 | * dynamic counters in msgpool, msgmap, and msgtql fields. | |||
673 | */ | |||
674 | linux_msginfo.msgpool = (long)msginfo.msgmni * | |||
675 | (long)msginfo.msgmnb / 1024L; /* XXX MSG_INFO. */ | |||
676 | linux_msginfo.msgmap = msginfo.msgmnb; /* XXX MSG_INFO. */ | |||
677 | linux_msginfo.msgmax = msginfo.msgmax; | |||
678 | linux_msginfo.msgmnb = msginfo.msgmnb; | |||
679 | linux_msginfo.msgmni = msginfo.msgmni; | |||
680 | linux_msginfo.msgssz = msginfo.msgssz; | |||
681 | linux_msginfo.msgtql = msginfo.msgtql; /* XXX MSG_INFO. */ | |||
682 | linux_msginfo.msgseg = msginfo.msgseg; | |||
683 | error = copyout(&linux_msginfo, PTRIN(args->buf)(void *)(args->buf), | |||
684 | sizeof(linux_msginfo)); | |||
685 | if (error == 0) | |||
686 | td->td_retvaltd_uretoff.tdu_retval[0] = msginfo.msgmni; /* XXX */ | |||
687 | ||||
688 | return (error); | |||
689 | } | |||
690 | ||||
691 | /* | |||
692 | * TODO: implement this | |||
693 | * case LINUX_MSG_STAT: | |||
694 | */ | |||
695 | case LINUX_IPC_STAT2: | |||
696 | /* NOTHING */ | |||
697 | break; | |||
698 | ||||
699 | case LINUX_IPC_SET1: | |||
700 | error = linux_msqid_pullup(args->cmd & LINUX_IPC_640x0100, | |||
701 | &linux_msqid, PTRIN(args->buf)(void *)(args->buf)); | |||
702 | if (error) | |||
703 | return (error); | |||
704 | linux_to_bsd_msqid_ds(&linux_msqid, &bsd_msqid); | |||
705 | break; | |||
706 | ||||
707 | case LINUX_IPC_RMID0: | |||
708 | /* NOTHING */ | |||
709 | break; | |||
710 | ||||
711 | default: | |||
712 | return (EINVAL22); | |||
713 | break; | |||
714 | } | |||
715 | ||||
716 | error = kern_msgctl(td, args->msqid, bsd_cmd, &bsd_msqid); | |||
717 | if (error != 0) | |||
718 | if (bsd_cmd != LINUX_IPC_RMID0 || error != EINVAL22) | |||
719 | return (error); | |||
720 | ||||
721 | if (bsd_cmd == LINUX_IPC_STAT2) { | |||
722 | bsd_to_linux_msqid_ds(&bsd_msqid, &linux_msqid); | |||
723 | return (linux_msqid_pushdown(args->cmd & LINUX_IPC_640x0100, | |||
724 | &linux_msqid, PTRIN(args->buf)(void *)(args->buf))); | |||
725 | } | |||
726 | ||||
727 | return (0); | |||
728 | } | |||
729 | ||||
730 | int | |||
731 | linux_shmat(struct thread *td, struct linux_shmat_args *args) | |||
732 | { | |||
733 | struct shmat_args /* { | |||
734 | int shmid; | |||
735 | void *shmaddr; | |||
736 | int shmflg; | |||
737 | } */ bsd_args; | |||
738 | int error; | |||
739 | #if defined(__i386__) || (defined(__amd64__1) && defined(COMPAT_LINUX32)) | |||
740 | l_uintptr_t addr; | |||
741 | #endif | |||
742 | ||||
743 | bsd_args.shmid = args->shmid; | |||
744 | bsd_args.shmaddr = PTRIN(args->shmaddr)(void *)(args->shmaddr); | |||
745 | bsd_args.shmflg = args->shmflg; | |||
746 | if ((error = sys_shmat(td, &bsd_args))) | |||
747 | return (error); | |||
748 | #if defined(__i386__) || (defined(__amd64__1) && defined(COMPAT_LINUX32)) | |||
749 | addr = td->td_retvaltd_uretoff.tdu_retval[0]; | |||
750 | if ((error = copyout(&addr, PTRIN(args->raddr)(void *)(args->raddr), sizeof(addr)))) | |||
751 | return (error); | |||
752 | td->td_retvaltd_uretoff.tdu_retval[0] = 0; | |||
753 | #endif | |||
754 | return (0); | |||
755 | } | |||
756 | ||||
757 | int | |||
758 | linux_shmdt(struct thread *td, struct linux_shmdt_args *args) | |||
759 | { | |||
760 | struct shmdt_args /* { | |||
761 | void *shmaddr; | |||
762 | } */ bsd_args; | |||
763 | ||||
764 | bsd_args.shmaddr = PTRIN(args->shmaddr)(void *)(args->shmaddr); | |||
765 | return (sys_shmdt(td, &bsd_args)); | |||
766 | } | |||
767 | ||||
768 | int | |||
769 | linux_shmget(struct thread *td, struct linux_shmget_args *args) | |||
770 | { | |||
771 | struct shmget_args /* { | |||
772 | key_t key; | |||
773 | int size; | |||
774 | int shmflg; | |||
775 | } */ bsd_args; | |||
776 | ||||
777 | bsd_args.key = args->key; | |||
778 | bsd_args.size = args->size; | |||
779 | bsd_args.shmflg = args->shmflg; | |||
780 | return (sys_shmget(td, &bsd_args)); | |||
781 | } | |||
782 | ||||
783 | int | |||
784 | linux_shmctl(struct thread *td, struct linux_shmctl_args *args) | |||
785 | { | |||
786 | struct l_shmid_ds linux_shmid; | |||
787 | struct l_shminfo linux_shminfo; | |||
788 | struct l_shm_info linux_shm_info; | |||
789 | struct shmid_ds bsd_shmid; | |||
790 | int error; | |||
791 | ||||
792 | switch (args->cmd & ~LINUX_IPC_640x0100) { | |||
| ||||
793 | ||||
794 | case LINUX_IPC_INFO3: { | |||
795 | struct shminfo bsd_shminfo; | |||
796 | ||||
797 | /* Perform shmctl wanting removed segments lookup */ | |||
798 | error = kern_shmctl(td, args->shmid, IPC_INFO3, | |||
799 | (void *)&bsd_shminfo, NULL((void *)0)); | |||
800 | if (error) | |||
801 | return (error); | |||
802 | ||||
803 | bsd_to_linux_shminfo(&bsd_shminfo, &linux_shminfo); | |||
804 | ||||
805 | return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_640x0100, | |||
806 | &linux_shminfo, PTRIN(args->buf)(void *)(args->buf))); | |||
807 | } | |||
808 | ||||
809 | case LINUX_SHM_INFO14: { | |||
810 | struct shm_info bsd_shm_info; | |||
811 | ||||
812 | /* Perform shmctl wanting removed segments lookup */ | |||
813 | error = kern_shmctl(td, args->shmid, SHM_INFO14, | |||
814 | (void *)&bsd_shm_info, NULL((void *)0)); | |||
815 | if (error) | |||
816 | return (error); | |||
817 | ||||
818 | bsd_to_linux_shm_info(&bsd_shm_info, &linux_shm_info); | |||
819 | ||||
820 | return (copyout(&linux_shm_info, PTRIN(args->buf)(void *)(args->buf), | |||
| ||||
821 | sizeof(struct l_shm_info))); | |||
822 | } | |||
823 | ||||
824 | case LINUX_IPC_STAT2: | |||
825 | /* Perform shmctl wanting removed segments lookup */ | |||
826 | error = kern_shmctl(td, args->shmid, IPC_STAT2, | |||
827 | (void *)&bsd_shmid, NULL((void *)0)); | |||
828 | if (error) | |||
829 | return (error); | |||
830 | ||||
831 | bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); | |||
832 | ||||
833 | return (linux_shmid_pushdown(args->cmd & LINUX_IPC_640x0100, | |||
834 | &linux_shmid, PTRIN(args->buf)(void *)(args->buf))); | |||
835 | ||||
836 | case LINUX_SHM_STAT13: | |||
837 | /* Perform shmctl wanting removed segments lookup */ | |||
838 | error = kern_shmctl(td, args->shmid, IPC_STAT2, | |||
839 | (void *)&bsd_shmid, NULL((void *)0)); | |||
840 | if (error) | |||
841 | return (error); | |||
842 | ||||
843 | bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); | |||
844 | ||||
845 | return (linux_shmid_pushdown(args->cmd & LINUX_IPC_640x0100, | |||
846 | &linux_shmid, PTRIN(args->buf)(void *)(args->buf))); | |||
847 | ||||
848 | case LINUX_IPC_SET1: | |||
849 | error = linux_shmid_pullup(args->cmd & LINUX_IPC_640x0100, | |||
850 | &linux_shmid, PTRIN(args->buf)(void *)(args->buf)); | |||
851 | if (error) | |||
852 | return (error); | |||
853 | ||||
854 | linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); | |||
855 | ||||
856 | /* Perform shmctl wanting removed segments lookup */ | |||
857 | return (kern_shmctl(td, args->shmid, IPC_SET1, | |||
858 | (void *)&bsd_shmid, NULL((void *)0))); | |||
859 | ||||
860 | case LINUX_IPC_RMID0: { | |||
861 | void *buf; | |||
862 | ||||
863 | if (args->buf == 0) | |||
864 | buf = NULL((void *)0); | |||
865 | else { | |||
866 | error = linux_shmid_pullup(args->cmd & LINUX_IPC_640x0100, | |||
867 | &linux_shmid, PTRIN(args->buf)(void *)(args->buf)); | |||
868 | if (error) | |||
869 | return (error); | |||
870 | linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); | |||
871 | buf = (void *)&bsd_shmid; | |||
872 | } | |||
873 | return (kern_shmctl(td, args->shmid, IPC_RMID0, buf, NULL((void *)0))); | |||
874 | } | |||
875 | ||||
876 | case LINUX_SHM_LOCK11: | |||
877 | /* FALLTHROUGH */ | |||
878 | case LINUX_SHM_UNLOCK12: | |||
879 | /* FALLTHROUGH */ | |||
880 | default: | |||
881 | linux_msg(td, "ipc type %d not implemented", | |||
882 | args->cmd & ~LINUX_IPC_640x0100); | |||
883 | return (EINVAL22); | |||
884 | } | |||
885 | } | |||
886 | ||||
887 | MODULE_DEPEND(linux, sysvmsg, 1, 1, 1)static struct mod_depend _linux_depend_on_sysvmsg __attribute__ ((__section__(".data"))) = { 1, 1, 1 }; static struct mod_metadata _mod_metadata_md_linux_on_sysvmsg = { 1, 1, &_linux_depend_on_sysvmsg , "sysvmsg" }; __asm__(".globl " "__start_set_modmetadata_set" ); __asm__(".globl " "__stop_set_modmetadata_set"); static void const * const __set_modmetadata_set_sym__mod_metadata_md_linux_on_sysvmsg __attribute__((__section__("set_" "modmetadata_set"))) __attribute__ ((__used__)) = &(_mod_metadata_md_linux_on_sysvmsg); | |||
888 | MODULE_DEPEND(linux, sysvsem, 1, 1, 1)static struct mod_depend _linux_depend_on_sysvsem __attribute__ ((__section__(".data"))) = { 1, 1, 1 }; static struct mod_metadata _mod_metadata_md_linux_on_sysvsem = { 1, 1, &_linux_depend_on_sysvsem , "sysvsem" }; __asm__(".globl " "__start_set_modmetadata_set" ); __asm__(".globl " "__stop_set_modmetadata_set"); static void const * const __set_modmetadata_set_sym__mod_metadata_md_linux_on_sysvsem __attribute__((__section__("set_" "modmetadata_set"))) __attribute__ ((__used__)) = &(_mod_metadata_md_linux_on_sysvsem); | |||
889 | MODULE_DEPEND(linux, sysvshm, 1, 1, 1)static struct mod_depend _linux_depend_on_sysvshm __attribute__ ((__section__(".data"))) = { 1, 1, 1 }; static struct mod_metadata _mod_metadata_md_linux_on_sysvshm = { 1, 1, &_linux_depend_on_sysvshm , "sysvshm" }; __asm__(".globl " "__start_set_modmetadata_set" ); __asm__(".globl " "__stop_set_modmetadata_set"); static void const * const __set_modmetadata_set_sym__mod_metadata_md_linux_on_sysvshm __attribute__((__section__("set_" "modmetadata_set"))) __attribute__ ((__used__)) = &(_mod_metadata_md_linux_on_sysvshm); |