linux_ipc.c revision 159991
1191783Srmacklem/*- 2191783Srmacklem * Copyright (c) 1994-1995 S�ren Schmidt 3191783Srmacklem * All rights reserved. 4191783Srmacklem * 5191783Srmacklem * Redistribution and use in source and binary forms, with or without 6191783Srmacklem * modification, are permitted provided that the following conditions 7191783Srmacklem * are met: 8191783Srmacklem * 1. Redistributions of source code must retain the above copyright 9191783Srmacklem * notice, this list of conditions and the following disclaimer 10191783Srmacklem * in this position and unchanged. 11191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 12191783Srmacklem * notice, this list of conditions and the following disclaimer in the 13191783Srmacklem * documentation and/or other materials provided with the distribution. 14191783Srmacklem * 3. The name of the author may not be used to endorse or promote products 15191783Srmacklem * derived from this software without specific prior written permission 16191783Srmacklem * 17191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18191783Srmacklem * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19191783Srmacklem * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20191783Srmacklem * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21191783Srmacklem * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22191783Srmacklem * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23191783Srmacklem * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24191783Srmacklem * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25191783Srmacklem * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26191783Srmacklem * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27191783Srmacklem */ 28191783Srmacklem 29191783Srmacklem#include <sys/cdefs.h> 30191783Srmacklem__FBSDID("$FreeBSD: head/sys/compat/linux/linux_ipc.c 159991 2006-06-27 18:28:50Z jhb $"); 31191783Srmacklem 32191783Srmacklem#include <sys/param.h> 33191783Srmacklem#include <sys/systm.h> 34191783Srmacklem#include <sys/syscallsubr.h> 35191783Srmacklem#include <sys/sysproto.h> 36207785Srmacklem#include <sys/proc.h> 37191783Srmacklem#include <sys/limits.h> 38191783Srmacklem#include <sys/msg.h> 39191783Srmacklem#include <sys/sem.h> 40191783Srmacklem#include <sys/shm.h> 41191783Srmacklem 42191783Srmacklem#include "opt_compat.h" 43191783Srmacklem 44191783Srmacklem#ifdef COMPAT_LINUX32 45191783Srmacklem#include <machine/../linux32/linux.h> 46191783Srmacklem#include <machine/../linux32/linux32_proto.h> 47191783Srmacklem#include <machine/../linux32/linux32_ipc64.h> 48191783Srmacklem#else 49191783Srmacklem#include <machine/../linux/linux.h> 50191783Srmacklem#include <machine/../linux/linux_proto.h> 51191783Srmacklem#include <machine/../linux/linux_ipc64.h> 52193066Sjamie#endif 53191783Srmacklem#include <compat/linux/linux_ipc.h> 54191783Srmacklem#include <compat/linux/linux_util.h> 55191783Srmacklem 56191783Srmacklemstruct l_seminfo { 57191783Srmacklem l_int semmap; 58191783Srmacklem l_int semmni; 59191783Srmacklem l_int semmns; 60191783Srmacklem l_int semmnu; 61191783Srmacklem l_int semmsl; 62191783Srmacklem l_int semopm; 63191783Srmacklem l_int semume; 64191783Srmacklem l_int semusz; 65191783Srmacklem l_int semvmx; 66191783Srmacklem l_int semaem; 67191783Srmacklem}; 68191783Srmacklem 69191783Srmacklemstruct l_shminfo { 70191783Srmacklem l_int shmmax; 71191783Srmacklem l_int shmmin; 72191783Srmacklem l_int shmmni; 73191783Srmacklem l_int shmseg; 74191783Srmacklem l_int shmall; 75191783Srmacklem}; 76191783Srmacklem 77191783Srmacklemstruct l_shm_info { 78191783Srmacklem l_int used_ids; 79191783Srmacklem l_ulong shm_tot; /* total allocated shm */ 80191783Srmacklem l_ulong shm_rss; /* total resident shm */ 81191783Srmacklem l_ulong shm_swp; /* total swapped shm */ 82191783Srmacklem l_ulong swap_attempts; 83191783Srmacklem l_ulong swap_successes; 84191783Srmacklem}; 85191783Srmacklem 86191783Srmacklemstatic void 87191783Srmacklembsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo *lpp) 88191783Srmacklem{ 89191783Srmacklem lpp->shmmax = bpp->shmmax; 90191783Srmacklem lpp->shmmin = bpp->shmmin; 91191783Srmacklem lpp->shmmni = bpp->shmmni; 92191783Srmacklem lpp->shmseg = bpp->shmseg; 93191783Srmacklem lpp->shmall = bpp->shmall; 94191783Srmacklem} 95191783Srmacklem 96191783Srmacklemstatic void 97191783Srmacklembsd_to_linux_shm_info( struct shm_info *bpp, struct l_shm_info *lpp) 98191783Srmacklem{ 99191783Srmacklem lpp->used_ids = bpp->used_ids ; 100191783Srmacklem lpp->shm_tot = bpp->shm_tot ; 101191783Srmacklem lpp->shm_rss = bpp->shm_rss ; 102191783Srmacklem lpp->shm_swp = bpp->shm_swp ; 103191783Srmacklem lpp->swap_attempts = bpp->swap_attempts ; 104191783Srmacklem lpp->swap_successes = bpp->swap_successes ; 105191783Srmacklem} 106191783Srmacklem 107191783Srmacklemstruct l_ipc_perm { 108191783Srmacklem l_key_t key; 109191783Srmacklem l_uid16_t uid; 110191783Srmacklem l_gid16_t gid; 111191783Srmacklem l_uid16_t cuid; 112191783Srmacklem l_gid16_t cgid; 113191783Srmacklem l_ushort mode; 114191783Srmacklem l_ushort seq; 115191783Srmacklem}; 116191783Srmacklem 117191783Srmacklemstatic void 118191783Srmacklemlinux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp) 119191783Srmacklem{ 120191783Srmacklem bpp->key = lpp->key; 121191783Srmacklem bpp->uid = lpp->uid; 122191783Srmacklem bpp->gid = lpp->gid; 123191783Srmacklem bpp->cuid = lpp->cuid; 124191783Srmacklem bpp->cgid = lpp->cgid; 125191783Srmacklem bpp->mode = lpp->mode; 126191783Srmacklem bpp->seq = lpp->seq; 127191783Srmacklem} 128191783Srmacklem 129191783Srmacklem 130191783Srmacklemstatic void 131191783Srmacklembsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp) 132191783Srmacklem{ 133191783Srmacklem lpp->key = bpp->key; 134191783Srmacklem lpp->uid = bpp->uid; 135191783Srmacklem lpp->gid = bpp->gid; 136191783Srmacklem lpp->cuid = bpp->cuid; 137191783Srmacklem lpp->cgid = bpp->cgid; 138191783Srmacklem lpp->mode = bpp->mode; 139191783Srmacklem lpp->seq = bpp->seq; 140191783Srmacklem} 141191783Srmacklem 142191783Srmacklemstruct l_msqid_ds { 143248188Sglebius struct l_ipc_perm msg_perm; 144191783Srmacklem l_uintptr_t msg_first; /* first message on queue,unused */ 145207170Srmacklem l_uintptr_t msg_last; /* last message in queue,unused */ 146248188Sglebius l_time_t msg_stime; /* last msgsnd time */ 147191783Srmacklem l_time_t msg_rtime; /* last msgrcv time */ 148191783Srmacklem l_time_t msg_ctime; /* last change time */ 149191783Srmacklem l_ulong msg_lcbytes; /* Reuse junk fields for 32 bit */ 150248188Sglebius l_ulong msg_lqbytes; /* ditto */ 151191783Srmacklem l_ushort msg_cbytes; /* current number of bytes on queue */ 152207170Srmacklem l_ushort msg_qnum; /* number of messages in queue */ 153248188Sglebius l_ushort msg_qbytes; /* max number of bytes on queue */ 154191783Srmacklem l_pid_t msg_lspid; /* pid of last msgsnd */ 155191783Srmacklem l_pid_t msg_lrpid; /* last receive pid */ 156191783Srmacklem} 157248188Sglebius#if defined(__amd64__) && defined(COMPAT_LINUX32) 158191783Srmacklem__packed 159207170Srmacklem#endif 160248188Sglebius; 161191783Srmacklem 162191783Srmacklemstruct l_semid_ds { 163191783Srmacklem struct l_ipc_perm sem_perm; 164191783Srmacklem l_time_t sem_otime; 165248188Sglebius l_time_t sem_ctime; 166191783Srmacklem l_uintptr_t sem_base; 167207170Srmacklem l_uintptr_t sem_pending; 168248188Sglebius l_uintptr_t sem_pending_last; 169191783Srmacklem l_uintptr_t undo; 170191783Srmacklem l_ushort sem_nsems; 171191783Srmacklem} 172191783Srmacklem#if defined(__amd64__) && defined(COMPAT_LINUX32) 173191783Srmacklem__packed 174191783Srmacklem#endif 175191783Srmacklem; 176191783Srmacklem 177191783Srmacklemstruct l_shmid_ds { 178191783Srmacklem struct l_ipc_perm shm_perm; 179191783Srmacklem l_int shm_segsz; 180191783Srmacklem l_time_t shm_atime; 181191783Srmacklem l_time_t shm_dtime; 182191783Srmacklem l_time_t shm_ctime; 183192152Srmacklem l_ushort shm_cpid; 184192152Srmacklem l_ushort shm_lpid; 185192152Srmacklem l_short shm_nattch; 186192152Srmacklem l_ushort private1; 187192152Srmacklem l_uintptr_t private2; 188192152Srmacklem l_uintptr_t private3; 189192152Srmacklem}; 190192152Srmacklem 191192152Srmacklemstatic void 192192152Srmacklemlinux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp) 193192152Srmacklem{ 194192152Srmacklem linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm); 195192152Srmacklem bsp->sem_otime = lsp->sem_otime; 196192152Srmacklem bsp->sem_ctime = lsp->sem_ctime; 197192152Srmacklem bsp->sem_nsems = lsp->sem_nsems; 198192152Srmacklem bsp->sem_base = PTRIN(lsp->sem_base); 199192152Srmacklem} 200192152Srmacklem 201192152Srmacklemstatic void 202192152Srmacklembsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp) 203192152Srmacklem{ 204192152Srmacklem bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm); 205192152Srmacklem lsp->sem_otime = bsp->sem_otime; 206192152Srmacklem lsp->sem_ctime = bsp->sem_ctime; 207192152Srmacklem lsp->sem_nsems = bsp->sem_nsems; 208192152Srmacklem lsp->sem_base = PTROUT(bsp->sem_base); 209192152Srmacklem} 210192152Srmacklem 211192152Srmacklemstatic void 212192152Srmacklemlinux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp) 213192152Srmacklem{ 214192152Srmacklem linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); 215192152Srmacklem bsp->shm_segsz = lsp->shm_segsz; 216192152Srmacklem bsp->shm_lpid = lsp->shm_lpid; 217192152Srmacklem bsp->shm_cpid = lsp->shm_cpid; 218192152Srmacklem bsp->shm_nattch = lsp->shm_nattch; 219192152Srmacklem bsp->shm_atime = lsp->shm_atime; 220192152Srmacklem bsp->shm_dtime = lsp->shm_dtime; 221192152Srmacklem bsp->shm_ctime = lsp->shm_ctime; 222192152Srmacklem /* this goes (yet) SOS */ 223192152Srmacklem bsp->shm_internal = PTRIN(lsp->private3); 224192152Srmacklem} 225192152Srmacklem 226192152Srmacklemstatic void 227192152Srmacklembsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp) 228192152Srmacklem{ 229192152Srmacklem bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); 230192152Srmacklem lsp->shm_segsz = bsp->shm_segsz; 231244042Srmacklem lsp->shm_lpid = bsp->shm_lpid; 232244042Srmacklem lsp->shm_cpid = bsp->shm_cpid; 233244042Srmacklem lsp->shm_nattch = bsp->shm_nattch; 234244042Srmacklem lsp->shm_atime = bsp->shm_atime; 235244042Srmacklem lsp->shm_dtime = bsp->shm_dtime; 236244042Srmacklem lsp->shm_ctime = bsp->shm_ctime; 237244042Srmacklem /* this goes (yet) SOS */ 238244042Srmacklem lsp->private3 = PTROUT(bsp->shm_internal); 239244042Srmacklem} 240244042Srmacklem 241244042Srmacklemstatic void 242244042Srmacklemlinux_to_bsd_msqid_ds(struct l_msqid_ds *lsp, struct msqid_ds *bsp) 243244042Srmacklem{ 244244042Srmacklem linux_to_bsd_ipc_perm(&lsp->msg_perm, &bsp->msg_perm); 245244042Srmacklem bsp->msg_cbytes = lsp->msg_cbytes; 246244042Srmacklem bsp->msg_qnum = lsp->msg_qnum; 247244042Srmacklem bsp->msg_qbytes = lsp->msg_qbytes; 248244042Srmacklem bsp->msg_lspid = lsp->msg_lspid; 249244042Srmacklem bsp->msg_lrpid = lsp->msg_lrpid; 250244042Srmacklem bsp->msg_stime = lsp->msg_stime; 251244042Srmacklem bsp->msg_rtime = lsp->msg_rtime; 252244042Srmacklem bsp->msg_ctime = lsp->msg_ctime; 253244042Srmacklem} 254244042Srmacklem 255244042Srmacklemstatic void 256244042Srmacklembsd_to_linux_msqid_ds(struct msqid_ds *bsp, struct l_msqid_ds *lsp) 257244042Srmacklem{ 258244042Srmacklem bsd_to_linux_ipc_perm(&bsp->msg_perm, &lsp->msg_perm); 259192781Srmacklem lsp->msg_cbytes = bsp->msg_cbytes; 260192781Srmacklem lsp->msg_qnum = bsp->msg_qnum; 261192781Srmacklem lsp->msg_qbytes = bsp->msg_qbytes; 262192152Srmacklem lsp->msg_lspid = bsp->msg_lspid; 263192152Srmacklem lsp->msg_lrpid = bsp->msg_lrpid; 264192152Srmacklem lsp->msg_stime = bsp->msg_stime; 265192152Srmacklem lsp->msg_rtime = bsp->msg_rtime; 266192152Srmacklem lsp->msg_ctime = bsp->msg_ctime; 267192152Srmacklem} 268192152Srmacklem 269192152Srmacklemstatic void 270192152Srmacklemlinux_ipc_perm_to_ipc64_perm(struct l_ipc_perm *in, struct l_ipc64_perm *out) 271192152Srmacklem{ 272192152Srmacklem 273192152Srmacklem /* XXX: do we really need to do something here? */ 274192152Srmacklem out->key = in->key; 275192152Srmacklem out->uid = in->uid; 276192152Srmacklem out->gid = in->gid; 277192152Srmacklem out->cuid = in->cuid; 278192152Srmacklem out->cgid = in->cgid; 279192152Srmacklem out->mode = in->mode; 280192152Srmacklem out->seq = in->seq; 281192152Srmacklem} 282192152Srmacklem 283192152Srmacklemstatic int 284192152Srmacklemlinux_msqid_pullup(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr) 285192152Srmacklem{ 286192152Srmacklem struct l_msqid64_ds linux_msqid64; 287192152Srmacklem int error; 288192152Srmacklem 289192152Srmacklem if (ver == LINUX_IPC_64) { 290192152Srmacklem error = copyin(uaddr, &linux_msqid64, sizeof(linux_msqid64)); 291192152Srmacklem if (error != 0) 292244042Srmacklem return (error); 293244042Srmacklem 294244042Srmacklem bzero(linux_msqid, sizeof(*linux_msqid)); 295244042Srmacklem 296244042Srmacklem linux_msqid->msg_perm.uid = linux_msqid64.msg_perm.uid; 297244042Srmacklem linux_msqid->msg_perm.gid = linux_msqid64.msg_perm.gid; 298244042Srmacklem linux_msqid->msg_perm.mode = linux_msqid64.msg_perm.mode; 299244042Srmacklem 300244042Srmacklem if (linux_msqid64.msg_qbytes > USHRT_MAX) 301244042Srmacklem linux_msqid->msg_lqbytes = linux_msqid64.msg_qbytes; 302244042Srmacklem else 303244042Srmacklem linux_msqid->msg_qbytes = linux_msqid64.msg_qbytes; 304244042Srmacklem } else { 305244042Srmacklem error = copyin(uaddr, linux_msqid, sizeof(*linux_msqid)); 306192152Srmacklem } 307192152Srmacklem return (error); 308192152Srmacklem} 309192152Srmacklem 310192152Srmacklemstatic int 311223280Srmacklemlinux_msqid_pushdown(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr) 312192152Srmacklem{ 313192152Srmacklem struct l_msqid64_ds linux_msqid64; 314192152Srmacklem 315192152Srmacklem if (ver == LINUX_IPC_64) { 316192152Srmacklem bzero(&linux_msqid64, sizeof(linux_msqid64)); 317192152Srmacklem 318192152Srmacklem linux_ipc_perm_to_ipc64_perm(&linux_msqid->msg_perm, 319192152Srmacklem &linux_msqid64.msg_perm); 320192152Srmacklem 321192152Srmacklem linux_msqid64.msg_stime = linux_msqid->msg_stime; 322192152Srmacklem linux_msqid64.msg_rtime = linux_msqid->msg_rtime; 323192152Srmacklem linux_msqid64.msg_ctime = linux_msqid->msg_ctime; 324192152Srmacklem 325192152Srmacklem if (linux_msqid->msg_cbytes == 0) 326192152Srmacklem linux_msqid64.msg_cbytes = linux_msqid->msg_lcbytes; 327192152Srmacklem else 328192152Srmacklem linux_msqid64.msg_cbytes = linux_msqid->msg_cbytes; 329192152Srmacklem 330192152Srmacklem linux_msqid64.msg_qnum = linux_msqid->msg_qnum; 331192152Srmacklem 332192152Srmacklem if (linux_msqid->msg_qbytes == 0) 333192152Srmacklem linux_msqid64.msg_qbytes = linux_msqid->msg_lqbytes; 334192152Srmacklem else 335192152Srmacklem linux_msqid64.msg_qbytes = linux_msqid->msg_qbytes; 336192152Srmacklem 337192152Srmacklem linux_msqid64.msg_lspid = linux_msqid->msg_lspid; 338244042Srmacklem linux_msqid64.msg_lrpid = linux_msqid->msg_lrpid; 339244042Srmacklem 340244042Srmacklem return (copyout(&linux_msqid64, uaddr, sizeof(linux_msqid64))); 341244042Srmacklem } else { 342244042Srmacklem return (copyout(linux_msqid, uaddr, sizeof(*linux_msqid))); 343244042Srmacklem } 344244042Srmacklem} 345244042Srmacklem 346244042Srmacklemstatic int 347244042Srmacklemlinux_semid_pullup(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr) 348244042Srmacklem{ 349244042Srmacklem struct l_semid64_ds linux_semid64; 350244042Srmacklem int error; 351244042Srmacklem 352244042Srmacklem if (ver == LINUX_IPC_64) { 353244042Srmacklem error = copyin(uaddr, &linux_semid64, sizeof(linux_semid64)); 354244042Srmacklem if (error != 0) 355244042Srmacklem return (error); 356244042Srmacklem 357244042Srmacklem bzero(linux_semid, sizeof(*linux_semid)); 358244042Srmacklem 359223280Srmacklem linux_semid->sem_perm.uid = linux_semid64.sem_perm.uid; 360192152Srmacklem linux_semid->sem_perm.gid = linux_semid64.sem_perm.gid; 361192152Srmacklem linux_semid->sem_perm.mode = linux_semid64.sem_perm.mode; 362192152Srmacklem } else { 363192152Srmacklem error = copyin(uaddr, linux_semid, sizeof(*linux_semid)); 364192152Srmacklem } 365192152Srmacklem return (error); 366192152Srmacklem} 367192152Srmacklem 368192152Srmacklemstatic int 369192152Srmacklemlinux_semid_pushdown(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr) 370192152Srmacklem{ 371192152Srmacklem struct l_semid64_ds linux_semid64; 372192152Srmacklem 373192152Srmacklem if (ver == LINUX_IPC_64) { 374192152Srmacklem bzero(&linux_semid64, sizeof(linux_semid64)); 375192152Srmacklem 376192152Srmacklem linux_ipc_perm_to_ipc64_perm(&linux_semid->sem_perm, 377192152Srmacklem &linux_semid64.sem_perm); 378192152Srmacklem 379192152Srmacklem linux_semid64.sem_otime = linux_semid->sem_otime; 380192152Srmacklem linux_semid64.sem_ctime = linux_semid->sem_ctime; 381192152Srmacklem linux_semid64.sem_nsems = linux_semid->sem_nsems; 382192152Srmacklem 383192152Srmacklem return (copyout(&linux_semid64, uaddr, sizeof(linux_semid64))); 384192152Srmacklem } else { 385192152Srmacklem return (copyout(linux_semid, uaddr, sizeof(*linux_semid))); 386192152Srmacklem } 387192152Srmacklem} 388192152Srmacklem 389192152Srmacklemstatic int 390192152Srmacklemlinux_shmid_pullup(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr) 391192152Srmacklem{ 392192152Srmacklem struct l_shmid64_ds linux_shmid64; 393192152Srmacklem int error; 394192152Srmacklem 395192152Srmacklem if (ver == LINUX_IPC_64) { 396192152Srmacklem error = copyin(uaddr, &linux_shmid64, sizeof(linux_shmid64)); 397192152Srmacklem if (error != 0) 398192152Srmacklem return (error); 399192152Srmacklem 400192152Srmacklem bzero(linux_shmid, sizeof(*linux_shmid)); 401192152Srmacklem 402192152Srmacklem linux_shmid->shm_perm.uid = linux_shmid64.shm_perm.uid; 403192152Srmacklem linux_shmid->shm_perm.gid = linux_shmid64.shm_perm.gid; 404192152Srmacklem linux_shmid->shm_perm.mode = linux_shmid64.shm_perm.mode; 405192152Srmacklem } else { 406192152Srmacklem error = copyin(uaddr, linux_shmid, sizeof(*linux_shmid)); 407192152Srmacklem } 408192152Srmacklem return (error); 409192152Srmacklem} 410192152Srmacklem 411192152Srmacklemstatic int 412192152Srmacklemlinux_shmid_pushdown(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr) 413192152Srmacklem{ 414192152Srmacklem struct l_shmid64_ds linux_shmid64; 415192152Srmacklem 416192152Srmacklem if (ver == LINUX_IPC_64) { 417192152Srmacklem bzero(&linux_shmid64, sizeof(linux_shmid64)); 418192152Srmacklem 419192152Srmacklem linux_ipc_perm_to_ipc64_perm(&linux_shmid->shm_perm, 420192152Srmacklem &linux_shmid64.shm_perm); 421192152Srmacklem 422192152Srmacklem linux_shmid64.shm_segsz = linux_shmid->shm_segsz; 423192152Srmacklem linux_shmid64.shm_atime = linux_shmid->shm_atime; 424192152Srmacklem linux_shmid64.shm_dtime = linux_shmid->shm_dtime; 425223280Srmacklem linux_shmid64.shm_ctime = linux_shmid->shm_ctime; 426192152Srmacklem linux_shmid64.shm_cpid = linux_shmid->shm_cpid; 427223280Srmacklem linux_shmid64.shm_lpid = linux_shmid->shm_lpid; 428192152Srmacklem linux_shmid64.shm_nattch = linux_shmid->shm_nattch; 429191783Srmacklem 430191783Srmacklem return (copyout(&linux_shmid64, uaddr, sizeof(linux_shmid64))); 431191783Srmacklem } else { 432191783Srmacklem return (copyout(linux_shmid, uaddr, sizeof(*linux_shmid))); 433191783Srmacklem } 434244042Srmacklem} 435191783Srmacklem 436191783Srmacklemstatic int 437191783Srmacklemlinux_shminfo_pushdown(l_int ver, struct l_shminfo *linux_shminfo, 438191783Srmacklem caddr_t uaddr) 439191783Srmacklem{ 440191783Srmacklem struct l_shminfo64 linux_shminfo64; 441221014Srmacklem 442191783Srmacklem if (ver == LINUX_IPC_64) { 443191783Srmacklem bzero(&linux_shminfo64, sizeof(linux_shminfo64)); 444191783Srmacklem 445191783Srmacklem linux_shminfo64.shmmax = linux_shminfo->shmmax; 446191783Srmacklem linux_shminfo64.shmmin = linux_shminfo->shmmin; 447191783Srmacklem linux_shminfo64.shmmni = linux_shminfo->shmmni; 448191783Srmacklem linux_shminfo64.shmseg = linux_shminfo->shmseg; 449191783Srmacklem linux_shminfo64.shmall = linux_shminfo->shmall; 450191783Srmacklem 451191783Srmacklem return (copyout(&linux_shminfo64, uaddr, 452191783Srmacklem sizeof(linux_shminfo64))); 453191783Srmacklem } else { 454191783Srmacklem return (copyout(linux_shminfo, uaddr, sizeof(*linux_shminfo))); 455191783Srmacklem } 456191783Srmacklem} 457191783Srmacklem 458191783Srmacklemint 459191783Srmacklemlinux_semop(struct thread *td, struct linux_semop_args *args) 460191783Srmacklem{ 461191783Srmacklem struct semop_args /* { 462191783Srmacklem int semid; 463191783Srmacklem struct sembuf *sops; 464191783Srmacklem int nsops; 465191783Srmacklem } */ bsd_args; 466191783Srmacklem 467191783Srmacklem bsd_args.semid = args->semid; 468191783Srmacklem bsd_args.sops = (struct sembuf *)PTRIN(args->tsops); 469191783Srmacklem bsd_args.nsops = args->nsops; 470191783Srmacklem return semop(td, &bsd_args); 471191783Srmacklem} 472191783Srmacklem 473191783Srmacklemint 474191783Srmacklemlinux_semget(struct thread *td, struct linux_semget_args *args) 475191783Srmacklem{ 476191783Srmacklem struct semget_args /* { 477191783Srmacklem key_t key; 478191783Srmacklem int nsems; 479191783Srmacklem int semflg; 480191783Srmacklem } */ bsd_args; 481191783Srmacklem 482191783Srmacklem if (args->nsems < 0) 483191783Srmacklem return (EINVAL); 484191783Srmacklem bsd_args.key = args->key; 485191783Srmacklem bsd_args.nsems = args->nsems; 486191783Srmacklem bsd_args.semflg = args->semflg; 487191783Srmacklem return semget(td, &bsd_args); 488191783Srmacklem} 489191783Srmacklem 490191783Srmacklemint 491191783Srmacklemlinux_semctl(struct thread *td, struct linux_semctl_args *args) 492191783Srmacklem{ 493191783Srmacklem struct l_semid_ds linux_semid; 494191783Srmacklem struct l_seminfo linux_seminfo; 495191783Srmacklem struct semid_ds semid; 496191783Srmacklem union semun semun; 497191783Srmacklem int cmd, error; 498191783Srmacklem 499191783Srmacklem switch (args->cmd & ~LINUX_IPC_64) { 500191783Srmacklem case LINUX_IPC_RMID: 501191783Srmacklem cmd = IPC_RMID; 502191783Srmacklem break; 503191783Srmacklem case LINUX_GETNCNT: 504191783Srmacklem cmd = GETNCNT; 505191783Srmacklem break; 506191783Srmacklem case LINUX_GETPID: 507191783Srmacklem cmd = GETPID; 508191783Srmacklem break; 509191783Srmacklem case LINUX_GETVAL: 510191783Srmacklem cmd = GETVAL; 511191783Srmacklem break; 512191783Srmacklem case LINUX_GETZCNT: 513191783Srmacklem cmd = GETZCNT; 514191783Srmacklem break; 515191783Srmacklem case LINUX_SETVAL: 516191783Srmacklem cmd = SETVAL; 517191783Srmacklem semun.val = args->arg.val; 518191783Srmacklem break; 519191783Srmacklem case LINUX_IPC_SET: 520191783Srmacklem cmd = IPC_SET; 521191783Srmacklem error = linux_semid_pullup(args->cmd & LINUX_IPC_64, 522191783Srmacklem &linux_semid, (caddr_t)PTRIN(args->arg.buf)); 523191783Srmacklem if (error) 524191783Srmacklem return (error); 525191783Srmacklem linux_to_bsd_semid_ds(&linux_semid, &semid); 526191783Srmacklem semun.buf = &semid; 527191783Srmacklem return kern_semctl(td, args->semid, args->semnum, cmd, &semun, 528191783Srmacklem UIO_SYSSPACE); 529191783Srmacklem case LINUX_IPC_STAT: 530191783Srmacklem case LINUX_SEM_STAT: 531191783Srmacklem if((args->cmd & ~LINUX_IPC_64) == LINUX_IPC_STAT) 532191783Srmacklem cmd = IPC_STAT; 533191783Srmacklem else 534191783Srmacklem cmd = SEM_STAT; 535191783Srmacklem semun.buf = &semid; 536191783Srmacklem error = kern_semctl(td, args->semid, args->semnum, cmd, &semun, 537191783Srmacklem UIO_SYSSPACE); 538191783Srmacklem if (error) 539191783Srmacklem return (error); 540191783Srmacklem td->td_retval[0] = (cmd == SEM_STAT) ? 541191783Srmacklem IXSEQ_TO_IPCID(args->semid, semid.sem_perm) : 542191783Srmacklem 0; 543191783Srmacklem bsd_to_linux_semid_ds(&semid, &linux_semid); 544191783Srmacklem return (linux_semid_pushdown(args->cmd & LINUX_IPC_64, 545191783Srmacklem &linux_semid, (caddr_t)PTRIN(args->arg.buf))); 546191783Srmacklem case LINUX_IPC_INFO: 547191783Srmacklem case LINUX_SEM_INFO: 548191783Srmacklem bcopy(&seminfo, &linux_seminfo, sizeof(linux_seminfo) ); 549191783Srmacklem/* XXX BSD equivalent? 550191783Srmacklem#define used_semids 10 551191783Srmacklem#define used_sems 10 552191783Srmacklem linux_seminfo.semusz = used_semids; 553191783Srmacklem linux_seminfo.semaem = used_sems; 554191783Srmacklem*/ 555191783Srmacklem error = copyout(&linux_seminfo, 556191783Srmacklem PTRIN(args->arg.buf), sizeof(linux_seminfo)); 557191783Srmacklem if (error) 558191783Srmacklem return error; 559191783Srmacklem td->td_retval[0] = seminfo.semmni; 560191783Srmacklem return 0; /* No need for __semctl call */ 561191783Srmacklem case LINUX_GETALL: 562191783Srmacklem /* FALLTHROUGH */ 563191783Srmacklem case LINUX_SETALL: 564191783Srmacklem /* FALLTHROUGH */ 565191783Srmacklem default: 566191783Srmacklem linux_msg(td, "ipc type %d is not implemented", 567191783Srmacklem args->cmd & ~LINUX_IPC_64); 568191783Srmacklem return EINVAL; 569191783Srmacklem } 570191783Srmacklem return kern_semctl(td, args->semid, args->semnum, cmd, &semun, 571191783Srmacklem UIO_USERSPACE); 572191783Srmacklem} 573191783Srmacklem 574191783Srmacklemint 575191783Srmacklemlinux_msgsnd(struct thread *td, struct linux_msgsnd_args *args) 576191783Srmacklem{ 577191783Srmacklem struct msgsnd_args /* { 578191783Srmacklem int msqid; 579191783Srmacklem void *msgp; 580191783Srmacklem size_t msgsz; 581191783Srmacklem int msgflg; 582191783Srmacklem } */ bsd_args; 583191783Srmacklem 584191783Srmacklem bsd_args.msqid = args->msqid; 585191783Srmacklem bsd_args.msgp = PTRIN(args->msgp); 586191783Srmacklem bsd_args.msgsz = args->msgsz; 587191783Srmacklem bsd_args.msgflg = args->msgflg; 588191783Srmacklem return msgsnd(td, &bsd_args); 589191783Srmacklem} 590191783Srmacklem 591191783Srmacklemint 592191783Srmacklemlinux_msgrcv(struct thread *td, struct linux_msgrcv_args *args) 593191783Srmacklem{ 594191783Srmacklem struct msgrcv_args /* { 595191783Srmacklem int msqid; 596191783Srmacklem void *msgp; 597191783Srmacklem size_t msgsz; 598191783Srmacklem long msgtyp; 599191783Srmacklem int msgflg; 600191783Srmacklem } */ bsd_args; 601191783Srmacklem 602205941Srmacklem bsd_args.msqid = args->msqid; 603191783Srmacklem bsd_args.msgp = PTRIN(args->msgp); 604191783Srmacklem bsd_args.msgsz = args->msgsz; 605191783Srmacklem bsd_args.msgtyp = args->msgtyp; 606191783Srmacklem bsd_args.msgflg = args->msgflg; 607191783Srmacklem return msgrcv(td, &bsd_args); 608191783Srmacklem} 609191783Srmacklem 610191783Srmacklemint 611191783Srmacklemlinux_msgget(struct thread *td, struct linux_msgget_args *args) 612191783Srmacklem{ 613191783Srmacklem struct msgget_args /* { 614191783Srmacklem key_t key; 615191783Srmacklem int msgflg; 616191783Srmacklem } */ bsd_args; 617191783Srmacklem 618191783Srmacklem bsd_args.key = args->key; 619191783Srmacklem bsd_args.msgflg = args->msgflg; 620191783Srmacklem return msgget(td, &bsd_args); 621191783Srmacklem} 622191783Srmacklem 623191783Srmacklemint 624191783Srmacklemlinux_msgctl(struct thread *td, struct linux_msgctl_args *args) 625191783Srmacklem{ 626191783Srmacklem int error, bsd_cmd; 627191783Srmacklem struct l_msqid_ds linux_msqid; 628191783Srmacklem struct msqid_ds bsd_msqid; 629191783Srmacklem 630191783Srmacklem error = linux_msqid_pullup(args->cmd & LINUX_IPC_64, 631191783Srmacklem &linux_msqid, (caddr_t)PTRIN(args->buf)); 632191783Srmacklem if (error != 0) 633191783Srmacklem return (error); 634191783Srmacklem bsd_cmd = args->cmd & ~LINUX_IPC_64; 635191783Srmacklem if (bsd_cmd == LINUX_IPC_SET) 636191783Srmacklem linux_to_bsd_msqid_ds(&linux_msqid, &bsd_msqid); 637191783Srmacklem 638244042Srmacklem error = kern_msgctl(td, args->msqid, bsd_cmd, &bsd_msqid); 639244042Srmacklem if (error != 0) 640269398Srmacklem if (bsd_cmd != LINUX_IPC_RMID || error != EINVAL) 641269398Srmacklem return (error); 642269398Srmacklem 643191783Srmacklem if (bsd_cmd == LINUX_IPC_STAT) { 644191783Srmacklem bsd_to_linux_msqid_ds(&bsd_msqid, &linux_msqid); 645191783Srmacklem return (linux_msqid_pushdown(args->cmd & LINUX_IPC_64, 646191783Srmacklem &linux_msqid, (caddr_t)PTRIN(args->buf))); 647191783Srmacklem } 648191783Srmacklem 649191783Srmacklem return (0); 650191783Srmacklem} 651191783Srmacklem 652191783Srmacklemint 653191783Srmacklemlinux_shmat(struct thread *td, struct linux_shmat_args *args) 654191783Srmacklem{ 655191783Srmacklem struct shmat_args /* { 656191783Srmacklem int shmid; 657191783Srmacklem void *shmaddr; 658191783Srmacklem int shmflg; 659191783Srmacklem } */ bsd_args; 660191783Srmacklem int error; 661191783Srmacklem#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 662191783Srmacklem l_uintptr_t addr; 663191783Srmacklem#endif 664191783Srmacklem 665191783Srmacklem bsd_args.shmid = args->shmid; 666191783Srmacklem bsd_args.shmaddr = PTRIN(args->shmaddr); 667191783Srmacklem bsd_args.shmflg = args->shmflg; 668191783Srmacklem if ((error = shmat(td, &bsd_args))) 669191783Srmacklem return error; 670191783Srmacklem#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 671191783Srmacklem addr = td->td_retval[0]; 672191783Srmacklem if ((error = copyout(&addr, PTRIN(args->raddr), sizeof(addr)))) 673191783Srmacklem return error; 674191783Srmacklem td->td_retval[0] = 0; 675191783Srmacklem#endif 676191783Srmacklem return 0; 677191783Srmacklem} 678191783Srmacklem 679191783Srmacklemint 680194292Srmacklemlinux_shmdt(struct thread *td, struct linux_shmdt_args *args) 681191783Srmacklem{ 682191783Srmacklem struct shmdt_args /* { 683191783Srmacklem void *shmaddr; 684191783Srmacklem } */ bsd_args; 685191783Srmacklem 686191783Srmacklem bsd_args.shmaddr = PTRIN(args->shmaddr); 687191783Srmacklem return shmdt(td, &bsd_args); 688191783Srmacklem} 689191783Srmacklem 690191783Srmacklemint 691191783Srmacklemlinux_shmget(struct thread *td, struct linux_shmget_args *args) 692191783Srmacklem{ 693191783Srmacklem struct shmget_args /* { 694191783Srmacklem key_t key; 695191783Srmacklem int size; 696191783Srmacklem int shmflg; 697191783Srmacklem } */ bsd_args; 698191783Srmacklem 699191783Srmacklem bsd_args.key = args->key; 700191783Srmacklem bsd_args.size = args->size; 701191783Srmacklem bsd_args.shmflg = args->shmflg; 702217922Sgnn return shmget(td, &bsd_args); 703191783Srmacklem} 704217922Sgnn 705191783Srmacklemint 706191783Srmacklemlinux_shmctl(struct thread *td, struct linux_shmctl_args *args) 707191783Srmacklem{ 708191783Srmacklem struct l_shmid_ds linux_shmid; 709191783Srmacklem struct l_shminfo linux_shminfo; 710191783Srmacklem struct l_shm_info linux_shm_info; 711191783Srmacklem struct shmid_ds bsd_shmid; 712191783Srmacklem size_t bufsz; 713191783Srmacklem int error; 714191783Srmacklem 715191783Srmacklem switch (args->cmd & ~LINUX_IPC_64) { 716191783Srmacklem 717191783Srmacklem case LINUX_IPC_INFO: { 718191783Srmacklem struct shminfo bsd_shminfo; 719191783Srmacklem 720191783Srmacklem /* Perform shmctl wanting removed segments lookup */ 721191783Srmacklem error = kern_shmctl(td, args->shmid, IPC_INFO, 722191783Srmacklem (void *)&bsd_shminfo, &bufsz); 723191783Srmacklem if (error) 724191783Srmacklem return error; 725191783Srmacklem 726191783Srmacklem bsd_to_linux_shminfo(&bsd_shminfo, &linux_shminfo); 727191783Srmacklem 728191783Srmacklem return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_64, 729191783Srmacklem &linux_shminfo, (caddr_t)PTRIN(args->buf))); 730191783Srmacklem } 731205941Srmacklem 732244042Srmacklem case LINUX_SHM_INFO: { 733244042Srmacklem struct shm_info bsd_shm_info; 734244042Srmacklem 735244042Srmacklem /* Perform shmctl wanting removed segments lookup */ 736244042Srmacklem error = kern_shmctl(td, args->shmid, SHM_INFO, 737244042Srmacklem (void *)&bsd_shm_info, &bufsz); 738269398Srmacklem if (error) 739191783Srmacklem return error; 740191783Srmacklem 741191783Srmacklem bsd_to_linux_shm_info(&bsd_shm_info, &linux_shm_info); 742191783Srmacklem 743191783Srmacklem return copyout(&linux_shm_info, (caddr_t)PTRIN(args->buf), 744191783Srmacklem sizeof(struct l_shm_info)); 745191783Srmacklem } 746191783Srmacklem 747191783Srmacklem case LINUX_IPC_STAT: 748191783Srmacklem /* Perform shmctl wanting removed segments lookup */ 749191783Srmacklem error = kern_shmctl(td, args->shmid, IPC_STAT, 750191783Srmacklem (void *)&bsd_shmid, &bufsz); 751191783Srmacklem if (error) 752191783Srmacklem return error; 753191783Srmacklem 754191783Srmacklem bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); 755191783Srmacklem 756191783Srmacklem return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64, 757205941Srmacklem &linux_shmid, (caddr_t)PTRIN(args->buf))); 758244042Srmacklem 759244042Srmacklem case LINUX_SHM_STAT: 760244042Srmacklem /* Perform shmctl wanting removed segments lookup */ 761244042Srmacklem error = kern_shmctl(td, args->shmid, IPC_STAT, 762244042Srmacklem (void *)&bsd_shmid, &bufsz); 763244042Srmacklem if (error) 764269398Srmacklem return error; 765191783Srmacklem 766191783Srmacklem bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); 767191783Srmacklem 768191783Srmacklem return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64, 769191783Srmacklem &linux_shmid, (caddr_t)PTRIN(args->buf))); 770191783Srmacklem 771191783Srmacklem case LINUX_IPC_SET: 772191783Srmacklem error = linux_shmid_pullup(args->cmd & LINUX_IPC_64, 773191783Srmacklem &linux_shmid, (caddr_t)PTRIN(args->buf)); 774191783Srmacklem if (error) 775191783Srmacklem return error; 776191783Srmacklem 777191783Srmacklem linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 778191783Srmacklem 779191783Srmacklem /* Perform shmctl wanting removed segments lookup */ 780191783Srmacklem return kern_shmctl(td, args->shmid, IPC_SET, 781191783Srmacklem (void *)&bsd_shmid, &bufsz); 782191783Srmacklem 783191783Srmacklem case LINUX_IPC_RMID: { 784191783Srmacklem void *buf; 785229272Sed 786191783Srmacklem if (args->buf == 0) 787191783Srmacklem buf = NULL; 788191783Srmacklem else { 789191783Srmacklem error = linux_shmid_pullup(args->cmd & LINUX_IPC_64, 790191783Srmacklem &linux_shmid, (caddr_t)PTRIN(args->buf)); 791191783Srmacklem if (error) 792191783Srmacklem return error; 793191783Srmacklem linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 794191783Srmacklem buf = (void *)&bsd_shmid; 795191783Srmacklem } 796191783Srmacklem return kern_shmctl(td, args->shmid, IPC_RMID, buf, &bufsz); 797191783Srmacklem } 798191783Srmacklem 799191783Srmacklem case LINUX_SHM_LOCK: 800191783Srmacklem case LINUX_SHM_UNLOCK: 801191783Srmacklem default: 802191783Srmacklem linux_msg(td, "ipc typ=%d not implemented", args->cmd & ~LINUX_IPC_64); 803191783Srmacklem return EINVAL; 804191783Srmacklem } 805191783Srmacklem} 806191783Srmacklem 807191783SrmacklemMODULE_DEPEND(linux, sysvmsg, 1, 1, 1); 808191783SrmacklemMODULE_DEPEND(linux, sysvsem, 1, 1, 1); 809249592SkenMODULE_DEPEND(linux, sysvshm, 1, 1, 1); 810191783Srmacklem