19313Ssos/*- 2230132Suqs * Copyright (c) 1994-1995 S��ren Schmidt 39313Ssos * All rights reserved. 49313Ssos * 59313Ssos * Redistribution and use in source and binary forms, with or without 69313Ssos * modification, are permitted provided that the following conditions 79313Ssos * are met: 89313Ssos * 1. Redistributions of source code must retain the above copyright 9111798Sdes * notice, this list of conditions and the following disclaimer 109313Ssos * in this position and unchanged. 119313Ssos * 2. Redistributions in binary form must reproduce the above copyright 129313Ssos * notice, this list of conditions and the following disclaimer in the 139313Ssos * documentation and/or other materials provided with the distribution. 149313Ssos * 3. The name of the author may not be used to endorse or promote products 1597748Sschweikh * derived from this software without specific prior written permission 169313Ssos * 179313Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 189313Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 199313Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 209313Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 219313Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 229313Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239313Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249313Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259313Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 269313Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279313Ssos */ 289313Ssos 29116173Sobrien#include <sys/cdefs.h> 30116173Sobrien__FBSDID("$FreeBSD: stable/10/sys/compat/linux/linux_ipc.c 332039 2018-04-04 17:45:05Z emaste $"); 31116173Sobrien 329313Ssos#include <sys/param.h> 339313Ssos#include <sys/systm.h> 34114724Smbr#include <sys/syscallsubr.h> 3512458Sbde#include <sys/sysproto.h> 369313Ssos#include <sys/proc.h> 37114216Skan#include <sys/limits.h> 38104893Ssobomax#include <sys/msg.h> 3930804Skato#include <sys/sem.h> 409313Ssos#include <sys/shm.h> 419313Ssos 42156874Sru#include "opt_compat.h" 43156874Sru 44140214Sobrien#ifdef COMPAT_LINUX32 45140214Sobrien#include <machine/../linux32/linux.h> 46140214Sobrien#include <machine/../linux32/linux32_proto.h> 47140214Sobrien#include <machine/../linux32/linux32_ipc64.h> 48140214Sobrien#else 4964906Smarcel#include <machine/../linux/linux.h> 5068583Smarcel#include <machine/../linux/linux_proto.h> 51104893Ssobomax#include <machine/../linux/linux_ipc64.h> 52133816Stjr#endif 5364906Smarcel#include <compat/linux/linux_ipc.h> 5464906Smarcel#include <compat/linux/linux_util.h> 559313Ssos 5683501Smrstruct l_seminfo { 5783501Smr l_int semmap; 5883501Smr l_int semmni; 5983501Smr l_int semmns; 6083501Smr l_int semmnu; 6183501Smr l_int semmsl; 6283501Smr l_int semopm; 6383501Smr l_int semume; 6483501Smr l_int semusz; 6583501Smr l_int semvmx; 6683501Smr l_int semaem; 6783501Smr}; 6883501Smr 6983501Smrstruct l_shminfo { 7083501Smr l_int shmmax; 7183501Smr l_int shmmin; 7283501Smr l_int shmmni; 7383501Smr l_int shmseg; 7483501Smr l_int shmall; 7583501Smr}; 7683501Smr 7783501Smrstruct l_shm_info { 7883501Smr l_int used_ids; 7983501Smr l_ulong shm_tot; /* total allocated shm */ 8083501Smr l_ulong shm_rss; /* total resident shm */ 8183501Smr l_ulong shm_swp; /* total swapped shm */ 8283501Smr l_ulong swap_attempts; 8383501Smr l_ulong swap_successes; 8483501Smr}; 8583501Smr 86165407Sjkimstruct l_msginfo { 87165407Sjkim l_int msgpool; 88165407Sjkim l_int msgmap; 89165407Sjkim l_int msgmax; 90165407Sjkim l_int msgmnb; 91165407Sjkim l_int msgmni; 92165407Sjkim l_int msgssz; 93165407Sjkim l_int msgtql; 94165407Sjkim l_ushort msgseg; 95165407Sjkim}; 96165407Sjkim 9785623Smrstatic void 9885623Smrbsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo *lpp) 9985623Smr{ 100219558Sdchagin 10185623Smr lpp->shmmax = bpp->shmmax; 10285623Smr lpp->shmmin = bpp->shmmin; 10385623Smr lpp->shmmni = bpp->shmmni; 10485623Smr lpp->shmseg = bpp->shmseg; 10585623Smr lpp->shmall = bpp->shmall; 10685623Smr} 10785623Smr 10885623Smrstatic void 10985623Smrbsd_to_linux_shm_info( struct shm_info *bpp, struct l_shm_info *lpp) 11085623Smr{ 111219558Sdchagin 11285623Smr lpp->used_ids = bpp->used_ids ; 11385623Smr lpp->shm_tot = bpp->shm_tot ; 11485623Smr lpp->shm_rss = bpp->shm_rss ; 11585623Smr lpp->shm_swp = bpp->shm_swp ; 11685623Smr lpp->swap_attempts = bpp->swap_attempts ; 11785623Smr lpp->swap_successes = bpp->swap_successes ; 11885623Smr} 11985623Smr 1209313Ssosstatic void 12183221Smarcellinux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp) 1229313Ssos{ 123219558Sdchagin 124219558Sdchagin bpp->key = lpp->key; 125219558Sdchagin bpp->uid = lpp->uid; 126219558Sdchagin bpp->gid = lpp->gid; 127219558Sdchagin bpp->cuid = lpp->cuid; 128219558Sdchagin bpp->cgid = lpp->cgid; 129219558Sdchagin bpp->mode = lpp->mode; 130219558Sdchagin bpp->seq = lpp->seq; 1319313Ssos} 1329313Ssos 1339313Ssos 1349313Ssosstatic void 13583221Smarcelbsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp) 1369313Ssos{ 137219558Sdchagin 138219558Sdchagin lpp->key = bpp->key; 139219558Sdchagin lpp->uid = bpp->uid; 140219558Sdchagin lpp->gid = bpp->gid; 141219558Sdchagin lpp->cuid = bpp->cuid; 142219558Sdchagin lpp->cgid = bpp->cgid; 143219558Sdchagin lpp->mode = bpp->mode; 144219558Sdchagin lpp->seq = bpp->seq; 1459313Ssos} 1469313Ssos 147104893Ssobomaxstruct l_msqid_ds { 148104893Ssobomax struct l_ipc_perm msg_perm; 149133816Stjr l_uintptr_t msg_first; /* first message on queue,unused */ 150133816Stjr l_uintptr_t msg_last; /* last message in queue,unused */ 151104893Ssobomax l_time_t msg_stime; /* last msgsnd time */ 152104893Ssobomax l_time_t msg_rtime; /* last msgrcv time */ 153104893Ssobomax l_time_t msg_ctime; /* last change time */ 154104893Ssobomax l_ulong msg_lcbytes; /* Reuse junk fields for 32 bit */ 155104893Ssobomax l_ulong msg_lqbytes; /* ditto */ 156104893Ssobomax l_ushort msg_cbytes; /* current number of bytes on queue */ 157104893Ssobomax l_ushort msg_qnum; /* number of messages in queue */ 158104893Ssobomax l_ushort msg_qbytes; /* max number of bytes on queue */ 159104893Ssobomax l_pid_t msg_lspid; /* pid of last msgsnd */ 160104893Ssobomax l_pid_t msg_lrpid; /* last receive pid */ 161133816Stjr} 162140214Sobrien#if defined(__amd64__) && defined(COMPAT_LINUX32) 163133816Stjr__packed 164133816Stjr#endif 165133816Stjr; 166104893Ssobomax 16783221Smarcelstruct l_semid_ds { 16883221Smarcel struct l_ipc_perm sem_perm; 16983221Smarcel l_time_t sem_otime; 17083221Smarcel l_time_t sem_ctime; 171133816Stjr l_uintptr_t sem_base; 172133816Stjr l_uintptr_t sem_pending; 173133816Stjr l_uintptr_t sem_pending_last; 174133816Stjr l_uintptr_t undo; 17583221Smarcel l_ushort sem_nsems; 176133816Stjr} 177140214Sobrien#if defined(__amd64__) && defined(COMPAT_LINUX32) 178133816Stjr__packed 179133816Stjr#endif 180133816Stjr; 18130804Skato 18283221Smarcelstruct l_shmid_ds { 18383221Smarcel struct l_ipc_perm shm_perm; 18483221Smarcel l_int shm_segsz; 18583221Smarcel l_time_t shm_atime; 18683221Smarcel l_time_t shm_dtime; 18783221Smarcel l_time_t shm_ctime; 18883221Smarcel l_ushort shm_cpid; 18983221Smarcel l_ushort shm_lpid; 19083221Smarcel l_short shm_nattch; 19183221Smarcel l_ushort private1; 192133816Stjr l_uintptr_t private2; 193133816Stjr l_uintptr_t private3; 1949313Ssos}; 1959313Ssos 1969313Ssosstatic void 19783221Smarcellinux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp) 19830804Skato{ 199219558Sdchagin 200219558Sdchagin linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm); 201219558Sdchagin bsp->sem_otime = lsp->sem_otime; 202219558Sdchagin bsp->sem_ctime = lsp->sem_ctime; 203219558Sdchagin bsp->sem_nsems = lsp->sem_nsems; 204219558Sdchagin bsp->sem_base = PTRIN(lsp->sem_base); 20530804Skato} 20630804Skato 20730804Skatostatic void 20883221Smarcelbsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp) 20930804Skato{ 210219558Sdchagin 21130804Skato bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm); 21230804Skato lsp->sem_otime = bsp->sem_otime; 21330804Skato lsp->sem_ctime = bsp->sem_ctime; 21430804Skato lsp->sem_nsems = bsp->sem_nsems; 215133816Stjr lsp->sem_base = PTROUT(bsp->sem_base); 21630804Skato} 21730804Skato 21830804Skatostatic void 21983221Smarcellinux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp) 2209313Ssos{ 221219558Sdchagin 222219558Sdchagin linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); 223219558Sdchagin bsp->shm_segsz = lsp->shm_segsz; 224219558Sdchagin bsp->shm_lpid = lsp->shm_lpid; 225219558Sdchagin bsp->shm_cpid = lsp->shm_cpid; 226219558Sdchagin bsp->shm_nattch = lsp->shm_nattch; 227219558Sdchagin bsp->shm_atime = lsp->shm_atime; 228219558Sdchagin bsp->shm_dtime = lsp->shm_dtime; 229219558Sdchagin bsp->shm_ctime = lsp->shm_ctime; 2309313Ssos} 2319313Ssos 2329313Ssosstatic void 23383221Smarcelbsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp) 2349313Ssos{ 235219558Sdchagin 236219558Sdchagin bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); 237219558Sdchagin if (bsp->shm_segsz > INT_MAX) 238219558Sdchagin lsp->shm_segsz = INT_MAX; 239219558Sdchagin else 240219558Sdchagin lsp->shm_segsz = bsp->shm_segsz; 241219558Sdchagin lsp->shm_lpid = bsp->shm_lpid; 242219558Sdchagin lsp->shm_cpid = bsp->shm_cpid; 243219558Sdchagin if (bsp->shm_nattch > SHRT_MAX) 244219558Sdchagin lsp->shm_nattch = SHRT_MAX; 245219558Sdchagin else 246219558Sdchagin lsp->shm_nattch = bsp->shm_nattch; 247219558Sdchagin lsp->shm_atime = bsp->shm_atime; 248219558Sdchagin lsp->shm_dtime = bsp->shm_dtime; 249219558Sdchagin lsp->shm_ctime = bsp->shm_ctime; 250219558Sdchagin lsp->private3 = 0; 2519313Ssos} 2529313Ssos 253104893Ssobomaxstatic void 254104893Ssobomaxlinux_to_bsd_msqid_ds(struct l_msqid_ds *lsp, struct msqid_ds *bsp) 255104893Ssobomax{ 256219558Sdchagin 257219558Sdchagin linux_to_bsd_ipc_perm(&lsp->msg_perm, &bsp->msg_perm); 258219558Sdchagin bsp->msg_cbytes = lsp->msg_cbytes; 259219558Sdchagin bsp->msg_qnum = lsp->msg_qnum; 260219558Sdchagin bsp->msg_qbytes = lsp->msg_qbytes; 261219558Sdchagin bsp->msg_lspid = lsp->msg_lspid; 262219558Sdchagin bsp->msg_lrpid = lsp->msg_lrpid; 263219558Sdchagin bsp->msg_stime = lsp->msg_stime; 264219558Sdchagin bsp->msg_rtime = lsp->msg_rtime; 265219558Sdchagin bsp->msg_ctime = lsp->msg_ctime; 266104893Ssobomax} 267104893Ssobomax 268104893Ssobomaxstatic void 269104893Ssobomaxbsd_to_linux_msqid_ds(struct msqid_ds *bsp, struct l_msqid_ds *lsp) 270104893Ssobomax{ 271219558Sdchagin 272219558Sdchagin bsd_to_linux_ipc_perm(&bsp->msg_perm, &lsp->msg_perm); 273219558Sdchagin lsp->msg_cbytes = bsp->msg_cbytes; 274219558Sdchagin lsp->msg_qnum = bsp->msg_qnum; 275219558Sdchagin lsp->msg_qbytes = bsp->msg_qbytes; 276219558Sdchagin lsp->msg_lspid = bsp->msg_lspid; 277219558Sdchagin lsp->msg_lrpid = bsp->msg_lrpid; 278219558Sdchagin lsp->msg_stime = bsp->msg_stime; 279219558Sdchagin lsp->msg_rtime = bsp->msg_rtime; 280219558Sdchagin lsp->msg_ctime = bsp->msg_ctime; 281104893Ssobomax} 282104893Ssobomax 283104893Ssobomaxstatic void 284104893Ssobomaxlinux_ipc_perm_to_ipc64_perm(struct l_ipc_perm *in, struct l_ipc64_perm *out) 285104893Ssobomax{ 286104893Ssobomax 287104893Ssobomax /* XXX: do we really need to do something here? */ 288104893Ssobomax out->key = in->key; 289104893Ssobomax out->uid = in->uid; 290104893Ssobomax out->gid = in->gid; 291104893Ssobomax out->cuid = in->cuid; 292104893Ssobomax out->cgid = in->cgid; 293104893Ssobomax out->mode = in->mode; 294104893Ssobomax out->seq = in->seq; 295104893Ssobomax} 296111798Sdes 297104893Ssobomaxstatic int 298104893Ssobomaxlinux_msqid_pullup(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr) 299104893Ssobomax{ 300104893Ssobomax struct l_msqid64_ds linux_msqid64; 301104893Ssobomax int error; 302104893Ssobomax 303104893Ssobomax if (ver == LINUX_IPC_64) { 304104893Ssobomax error = copyin(uaddr, &linux_msqid64, sizeof(linux_msqid64)); 305104893Ssobomax if (error != 0) 306104893Ssobomax return (error); 307104893Ssobomax 308104893Ssobomax bzero(linux_msqid, sizeof(*linux_msqid)); 309104893Ssobomax 310104893Ssobomax linux_msqid->msg_perm.uid = linux_msqid64.msg_perm.uid; 311104893Ssobomax linux_msqid->msg_perm.gid = linux_msqid64.msg_perm.gid; 312104893Ssobomax linux_msqid->msg_perm.mode = linux_msqid64.msg_perm.mode; 313104893Ssobomax 314104893Ssobomax if (linux_msqid64.msg_qbytes > USHRT_MAX) 315104893Ssobomax linux_msqid->msg_lqbytes = linux_msqid64.msg_qbytes; 316104893Ssobomax else 317104893Ssobomax linux_msqid->msg_qbytes = linux_msqid64.msg_qbytes; 318219558Sdchagin } else 319104893Ssobomax error = copyin(uaddr, linux_msqid, sizeof(*linux_msqid)); 320219558Sdchagin 321104893Ssobomax return (error); 322104893Ssobomax} 323104893Ssobomax 324104893Ssobomaxstatic int 325104893Ssobomaxlinux_msqid_pushdown(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr) 326104893Ssobomax{ 327104893Ssobomax struct l_msqid64_ds linux_msqid64; 328104893Ssobomax 329104893Ssobomax if (ver == LINUX_IPC_64) { 330104893Ssobomax bzero(&linux_msqid64, sizeof(linux_msqid64)); 331104893Ssobomax 332104893Ssobomax linux_ipc_perm_to_ipc64_perm(&linux_msqid->msg_perm, 333104893Ssobomax &linux_msqid64.msg_perm); 334104893Ssobomax 335104893Ssobomax linux_msqid64.msg_stime = linux_msqid->msg_stime; 336104893Ssobomax linux_msqid64.msg_rtime = linux_msqid->msg_rtime; 337104893Ssobomax linux_msqid64.msg_ctime = linux_msqid->msg_ctime; 338104893Ssobomax 339104893Ssobomax if (linux_msqid->msg_cbytes == 0) 340104893Ssobomax linux_msqid64.msg_cbytes = linux_msqid->msg_lcbytes; 341104893Ssobomax else 342104893Ssobomax linux_msqid64.msg_cbytes = linux_msqid->msg_cbytes; 343104893Ssobomax 344104893Ssobomax linux_msqid64.msg_qnum = linux_msqid->msg_qnum; 345104893Ssobomax 346104893Ssobomax if (linux_msqid->msg_qbytes == 0) 347104893Ssobomax linux_msqid64.msg_qbytes = linux_msqid->msg_lqbytes; 348104893Ssobomax else 349104893Ssobomax linux_msqid64.msg_qbytes = linux_msqid->msg_qbytes; 350104893Ssobomax 351104893Ssobomax linux_msqid64.msg_lspid = linux_msqid->msg_lspid; 352104893Ssobomax linux_msqid64.msg_lrpid = linux_msqid->msg_lrpid; 353104893Ssobomax 354104893Ssobomax return (copyout(&linux_msqid64, uaddr, sizeof(linux_msqid64))); 355219558Sdchagin } else 356104893Ssobomax return (copyout(linux_msqid, uaddr, sizeof(*linux_msqid))); 357104893Ssobomax} 358104893Ssobomax 359104893Ssobomaxstatic int 360104893Ssobomaxlinux_semid_pullup(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr) 361104893Ssobomax{ 362104893Ssobomax struct l_semid64_ds linux_semid64; 363104893Ssobomax int error; 364104893Ssobomax 365104893Ssobomax if (ver == LINUX_IPC_64) { 366104893Ssobomax error = copyin(uaddr, &linux_semid64, sizeof(linux_semid64)); 367104893Ssobomax if (error != 0) 368104893Ssobomax return (error); 369104893Ssobomax 370104893Ssobomax bzero(linux_semid, sizeof(*linux_semid)); 371104893Ssobomax 372104893Ssobomax linux_semid->sem_perm.uid = linux_semid64.sem_perm.uid; 373104893Ssobomax linux_semid->sem_perm.gid = linux_semid64.sem_perm.gid; 374104893Ssobomax linux_semid->sem_perm.mode = linux_semid64.sem_perm.mode; 375219558Sdchagin } else 376104893Ssobomax error = copyin(uaddr, linux_semid, sizeof(*linux_semid)); 377219558Sdchagin 378104893Ssobomax return (error); 379104893Ssobomax} 380104893Ssobomax 381104893Ssobomaxstatic int 382104893Ssobomaxlinux_semid_pushdown(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr) 383104893Ssobomax{ 384104893Ssobomax struct l_semid64_ds linux_semid64; 385104893Ssobomax 386104893Ssobomax if (ver == LINUX_IPC_64) { 387104893Ssobomax bzero(&linux_semid64, sizeof(linux_semid64)); 388104893Ssobomax 389104893Ssobomax linux_ipc_perm_to_ipc64_perm(&linux_semid->sem_perm, 390104893Ssobomax &linux_semid64.sem_perm); 391104893Ssobomax 392104893Ssobomax linux_semid64.sem_otime = linux_semid->sem_otime; 393104893Ssobomax linux_semid64.sem_ctime = linux_semid->sem_ctime; 394104893Ssobomax linux_semid64.sem_nsems = linux_semid->sem_nsems; 395104893Ssobomax 396104893Ssobomax return (copyout(&linux_semid64, uaddr, sizeof(linux_semid64))); 397219558Sdchagin } else 398104893Ssobomax return (copyout(linux_semid, uaddr, sizeof(*linux_semid))); 399104893Ssobomax} 400104893Ssobomax 401104893Ssobomaxstatic int 402104893Ssobomaxlinux_shmid_pullup(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr) 403104893Ssobomax{ 404104893Ssobomax struct l_shmid64_ds linux_shmid64; 405104893Ssobomax int error; 406104893Ssobomax 407104893Ssobomax if (ver == LINUX_IPC_64) { 408104893Ssobomax error = copyin(uaddr, &linux_shmid64, sizeof(linux_shmid64)); 409104893Ssobomax if (error != 0) 410104893Ssobomax return (error); 411104893Ssobomax 412104893Ssobomax bzero(linux_shmid, sizeof(*linux_shmid)); 413104893Ssobomax 414104893Ssobomax linux_shmid->shm_perm.uid = linux_shmid64.shm_perm.uid; 415104893Ssobomax linux_shmid->shm_perm.gid = linux_shmid64.shm_perm.gid; 416104893Ssobomax linux_shmid->shm_perm.mode = linux_shmid64.shm_perm.mode; 417219558Sdchagin } else 418104893Ssobomax error = copyin(uaddr, linux_shmid, sizeof(*linux_shmid)); 419219558Sdchagin 420104893Ssobomax return (error); 421104893Ssobomax} 422104893Ssobomax 423104893Ssobomaxstatic int 424104893Ssobomaxlinux_shmid_pushdown(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr) 425104893Ssobomax{ 426104893Ssobomax struct l_shmid64_ds linux_shmid64; 427104893Ssobomax 428194910Sjhb /* 429194910Sjhb * XXX: This is backwards and loses information in shm_nattch 430194910Sjhb * and shm_segsz. We should probably either expose the BSD 431194910Sjhb * shmid structure directly and convert it to either the 432194910Sjhb * non-64 or 64 variant directly or the code should always 433194910Sjhb * convert to the 64 variant and then truncate values into the 434194910Sjhb * non-64 variant if needed since the 64 variant has more 435194910Sjhb * precision. 436194910Sjhb */ 437104893Ssobomax if (ver == LINUX_IPC_64) { 438104893Ssobomax bzero(&linux_shmid64, sizeof(linux_shmid64)); 439104893Ssobomax 440104893Ssobomax linux_ipc_perm_to_ipc64_perm(&linux_shmid->shm_perm, 441104893Ssobomax &linux_shmid64.shm_perm); 442104893Ssobomax 443104893Ssobomax linux_shmid64.shm_segsz = linux_shmid->shm_segsz; 444104893Ssobomax linux_shmid64.shm_atime = linux_shmid->shm_atime; 445104893Ssobomax linux_shmid64.shm_dtime = linux_shmid->shm_dtime; 446104893Ssobomax linux_shmid64.shm_ctime = linux_shmid->shm_ctime; 447104893Ssobomax linux_shmid64.shm_cpid = linux_shmid->shm_cpid; 448104893Ssobomax linux_shmid64.shm_lpid = linux_shmid->shm_lpid; 449104893Ssobomax linux_shmid64.shm_nattch = linux_shmid->shm_nattch; 450104893Ssobomax 451104893Ssobomax return (copyout(&linux_shmid64, uaddr, sizeof(linux_shmid64))); 452219558Sdchagin } else 453104893Ssobomax return (copyout(linux_shmid, uaddr, sizeof(*linux_shmid))); 454104893Ssobomax} 455104893Ssobomax 456104893Ssobomaxstatic int 457104893Ssobomaxlinux_shminfo_pushdown(l_int ver, struct l_shminfo *linux_shminfo, 458104893Ssobomax caddr_t uaddr) 459104893Ssobomax{ 460104893Ssobomax struct l_shminfo64 linux_shminfo64; 461104893Ssobomax 462104893Ssobomax if (ver == LINUX_IPC_64) { 463104893Ssobomax bzero(&linux_shminfo64, sizeof(linux_shminfo64)); 464104893Ssobomax 465104893Ssobomax linux_shminfo64.shmmax = linux_shminfo->shmmax; 466104893Ssobomax linux_shminfo64.shmmin = linux_shminfo->shmmin; 467104893Ssobomax linux_shminfo64.shmmni = linux_shminfo->shmmni; 468104893Ssobomax linux_shminfo64.shmseg = linux_shminfo->shmseg; 469104893Ssobomax linux_shminfo64.shmall = linux_shminfo->shmall; 470104893Ssobomax 471104893Ssobomax return (copyout(&linux_shminfo64, uaddr, 472104893Ssobomax sizeof(linux_shminfo64))); 473219558Sdchagin } else 474104893Ssobomax return (copyout(linux_shminfo, uaddr, sizeof(*linux_shminfo))); 475104893Ssobomax} 476104893Ssobomax 47764906Smarcelint 47883366Sjulianlinux_semop(struct thread *td, struct linux_semop_args *args) 4799313Ssos{ 48030804Skato struct semop_args /* { 48130804Skato int semid; 48230804Skato struct sembuf *sops; 48330804Skato int nsops; 48430804Skato } */ bsd_args; 48530804Skato 48683221Smarcel bsd_args.semid = args->semid; 487163215Sjhb bsd_args.sops = PTRIN(args->tsops); 48883221Smarcel bsd_args.nsops = args->nsops; 489225617Skmacy return (sys_semop(td, &bsd_args)); 4909313Ssos} 4919313Ssos 49264906Smarcelint 49383366Sjulianlinux_semget(struct thread *td, struct linux_semget_args *args) 4949313Ssos{ 49530804Skato struct semget_args /* { 49630804Skato key_t key; 49730804Skato int nsems; 49830804Skato int semflg; 49930804Skato } */ bsd_args; 50030804Skato 501104893Ssobomax if (args->nsems < 0) 502104893Ssobomax return (EINVAL); 50383221Smarcel bsd_args.key = args->key; 50483221Smarcel bsd_args.nsems = args->nsems; 50583221Smarcel bsd_args.semflg = args->semflg; 506225617Skmacy return (sys_semget(td, &bsd_args)); 5079313Ssos} 5089313Ssos 50964906Smarcelint 51083366Sjulianlinux_semctl(struct thread *td, struct linux_semctl_args *args) 5119313Ssos{ 51283221Smarcel struct l_semid_ds linux_semid; 51383501Smr struct l_seminfo linux_seminfo; 514159991Sjhb struct semid_ds semid; 515159991Sjhb union semun semun; 516160187Sjhb register_t rval; 517159991Sjhb int cmd, error; 51830804Skato 519332032Semaste memset(&linux_seminfo, 0, sizeof(linux_seminfo)); 520332036Semaste memset(&linux_semid, 0, sizeof(linux_semid)); 521332032Semaste 522104893Ssobomax switch (args->cmd & ~LINUX_IPC_64) { 52330804Skato case LINUX_IPC_RMID: 524159991Sjhb cmd = IPC_RMID; 52530804Skato break; 52630804Skato case LINUX_GETNCNT: 527159991Sjhb cmd = GETNCNT; 52830804Skato break; 52930804Skato case LINUX_GETPID: 530159991Sjhb cmd = GETPID; 53130804Skato break; 53230804Skato case LINUX_GETVAL: 533159991Sjhb cmd = GETVAL; 53430804Skato break; 53530804Skato case LINUX_GETZCNT: 536159991Sjhb cmd = GETZCNT; 53730804Skato break; 53830804Skato case LINUX_SETVAL: 539159991Sjhb cmd = SETVAL; 540159991Sjhb semun.val = args->arg.val; 54130804Skato break; 54230804Skato case LINUX_IPC_SET: 543159991Sjhb cmd = IPC_SET; 544104893Ssobomax error = linux_semid_pullup(args->cmd & LINUX_IPC_64, 545163215Sjhb &linux_semid, PTRIN(args->arg.buf)); 54630804Skato if (error) 54783221Smarcel return (error); 548159991Sjhb linux_to_bsd_semid_ds(&linux_semid, &semid); 549159991Sjhb semun.buf = &semid; 550160187Sjhb return (kern_semctl(td, args->semid, args->semnum, cmd, &semun, 551160187Sjhb td->td_retval)); 55230804Skato case LINUX_IPC_STAT: 55383501Smr case LINUX_SEM_STAT: 554160187Sjhb if ((args->cmd & ~LINUX_IPC_64) == LINUX_IPC_STAT) 555159991Sjhb cmd = IPC_STAT; 55683501Smr else 557159991Sjhb cmd = SEM_STAT; 558159991Sjhb semun.buf = &semid; 559159991Sjhb error = kern_semctl(td, args->semid, args->semnum, cmd, &semun, 560160187Sjhb &rval); 56130804Skato if (error) 562159991Sjhb return (error); 563159991Sjhb bsd_to_linux_semid_ds(&semid, &linux_semid); 564160187Sjhb error = linux_semid_pushdown(args->cmd & LINUX_IPC_64, 565163215Sjhb &linux_semid, PTRIN(args->arg.buf)); 566160187Sjhb if (error == 0) 567160187Sjhb td->td_retval[0] = (cmd == SEM_STAT) ? rval : 0; 568160187Sjhb return (error); 56983501Smr case LINUX_IPC_INFO: 57083501Smr case LINUX_SEM_INFO: 571224016Sbz bcopy(&seminfo, &linux_seminfo.semmni, sizeof(linux_seminfo) - 572224016Sbz sizeof(linux_seminfo.semmap) ); 573224016Sbz /* 574224123Sbz * Linux does not use the semmap field but populates it with 575224123Sbz * the defined value from SEMMAP, which really is redefined to 576224123Sbz * SEMMNS, which they define as SEMMNI * SEMMSL. Try to 577224123Sbz * simulate this returning our dynamic semmns value. 578224016Sbz */ 579224016Sbz linux_seminfo.semmap = linux_seminfo.semmns; 58083501Smr/* XXX BSD equivalent? 58183501Smr#define used_semids 10 58283501Smr#define used_sems 10 58383501Smr linux_seminfo.semusz = used_semids; 58483501Smr linux_seminfo.semaem = used_sems; 58583501Smr*/ 586133816Stjr error = copyout(&linux_seminfo, 587133816Stjr PTRIN(args->arg.buf), sizeof(linux_seminfo)); 58883501Smr if (error) 589219558Sdchagin return (error); 59083501Smr td->td_retval[0] = seminfo.semmni; 591219558Sdchagin return (0); /* No need for __semctl call */ 59230804Skato case LINUX_GETALL: 593166008Snetchild cmd = GETALL; 594166008Snetchild semun.val = args->arg.val; 595166008Snetchild break; 59630804Skato case LINUX_SETALL: 597166008Snetchild cmd = SETALL; 598166008Snetchild semun.val = args->arg.val; 599166008Snetchild break; 60030804Skato default: 601108541Salfred linux_msg(td, "ipc type %d is not implemented", 602104893Ssobomax args->cmd & ~LINUX_IPC_64); 603219558Sdchagin return (EINVAL); 60430804Skato } 605160187Sjhb return (kern_semctl(td, args->semid, args->semnum, cmd, &semun, 606160187Sjhb td->td_retval)); 6079313Ssos} 6089313Ssos 60964906Smarcelint 61083366Sjulianlinux_msgsnd(struct thread *td, struct linux_msgsnd_args *args) 6119313Ssos{ 612165404Sjkim const void *msgp; 613165404Sjkim long mtype; 614165404Sjkim l_long lmtype; 615165404Sjkim int error; 61613111Ssos 617165407Sjkim if ((l_long)args->msgsz < 0 || args->msgsz > (l_long)msginfo.msgmax) 618165404Sjkim return (EINVAL); 619165404Sjkim msgp = PTRIN(args->msgp); 620165404Sjkim if ((error = copyin(msgp, &lmtype, sizeof(lmtype))) != 0) 621165404Sjkim return (error); 622165404Sjkim mtype = (long)lmtype; 623165404Sjkim return (kern_msgsnd(td, args->msqid, 624165404Sjkim (const char *)msgp + sizeof(lmtype), 625165404Sjkim args->msgsz, args->msgflg, mtype)); 6269313Ssos} 6279313Ssos 62864906Smarcelint 62983366Sjulianlinux_msgrcv(struct thread *td, struct linux_msgrcv_args *args) 6309313Ssos{ 631165404Sjkim void *msgp; 632165404Sjkim long mtype; 633165404Sjkim l_long lmtype; 634165404Sjkim int error; 63513111Ssos 636165407Sjkim if ((l_long)args->msgsz < 0 || args->msgsz > (l_long)msginfo.msgmax) 637165404Sjkim return (EINVAL); 638165404Sjkim msgp = PTRIN(args->msgp); 639165404Sjkim if ((error = kern_msgrcv(td, args->msqid, 640165404Sjkim (char *)msgp + sizeof(lmtype), args->msgsz, 641165404Sjkim args->msgtyp, args->msgflg, &mtype)) != 0) 642165404Sjkim return (error); 643165404Sjkim lmtype = (l_long)mtype; 644165404Sjkim return (copyout(&lmtype, msgp, sizeof(lmtype))); 6459313Ssos} 6469313Ssos 64764906Smarcelint 64883366Sjulianlinux_msgget(struct thread *td, struct linux_msgget_args *args) 6499313Ssos{ 650219558Sdchagin struct msgget_args /* { 651219558Sdchagin key_t key; 652219558Sdchagin int msgflg; 653219558Sdchagin } */ bsd_args; 65413111Ssos 655219558Sdchagin bsd_args.key = args->key; 656219558Sdchagin bsd_args.msgflg = args->msgflg; 657225617Skmacy return (sys_msgget(td, &bsd_args)); 6589313Ssos} 6599313Ssos 66064906Smarcelint 66183366Sjulianlinux_msgctl(struct thread *td, struct linux_msgctl_args *args) 6629313Ssos{ 663219558Sdchagin int error, bsd_cmd; 664219558Sdchagin struct l_msqid_ds linux_msqid; 665219558Sdchagin struct msqid_ds bsd_msqid; 66613111Ssos 667332039Semaste memset(&linux_msqid, 0, sizeof(linux_msqid)); 668332032Semaste 669219558Sdchagin bsd_cmd = args->cmd & ~LINUX_IPC_64; 670219558Sdchagin switch (bsd_cmd) { 671219558Sdchagin case LINUX_IPC_INFO: 672219558Sdchagin case LINUX_MSG_INFO: { 673219558Sdchagin struct l_msginfo linux_msginfo; 674165407Sjkim 675332032Semaste memset(&linux_msginfo, 0, sizeof(linux_msginfo)); 676219558Sdchagin /* 677219558Sdchagin * XXX MSG_INFO uses the same data structure but returns different 678219558Sdchagin * dynamic counters in msgpool, msgmap, and msgtql fields. 679219558Sdchagin */ 680219558Sdchagin linux_msginfo.msgpool = (long)msginfo.msgmni * 681219558Sdchagin (long)msginfo.msgmnb / 1024L; /* XXX MSG_INFO. */ 682219558Sdchagin linux_msginfo.msgmap = msginfo.msgmnb; /* XXX MSG_INFO. */ 683219558Sdchagin linux_msginfo.msgmax = msginfo.msgmax; 684219558Sdchagin linux_msginfo.msgmnb = msginfo.msgmnb; 685219558Sdchagin linux_msginfo.msgmni = msginfo.msgmni; 686219558Sdchagin linux_msginfo.msgssz = msginfo.msgssz; 687219558Sdchagin linux_msginfo.msgtql = msginfo.msgtql; /* XXX MSG_INFO. */ 688219558Sdchagin linux_msginfo.msgseg = msginfo.msgseg; 689219558Sdchagin error = copyout(&linux_msginfo, PTRIN(args->buf), 690219558Sdchagin sizeof(linux_msginfo)); 691219558Sdchagin if (error == 0) 692219558Sdchagin td->td_retval[0] = msginfo.msgmni; /* XXX */ 693165407Sjkim 694219558Sdchagin return (error); 695219558Sdchagin } 696165407Sjkim 697219558Sdchagin /* 698219558Sdchagin * TODO: implement this 699219558Sdchagin * case LINUX_MSG_STAT: 700219558Sdchagin */ 701219558Sdchagin case LINUX_IPC_STAT: 702219558Sdchagin /* NOTHING */ 703219558Sdchagin break; 704185337Srdivacky 705219558Sdchagin case LINUX_IPC_SET: 706219558Sdchagin error = linux_msqid_pullup(args->cmd & LINUX_IPC_64, 707219558Sdchagin &linux_msqid, PTRIN(args->buf)); 708219558Sdchagin if (error) 709219558Sdchagin return (error); 710219558Sdchagin linux_to_bsd_msqid_ds(&linux_msqid, &bsd_msqid); 711219558Sdchagin break; 712185337Srdivacky 713219558Sdchagin case LINUX_IPC_RMID: 714219558Sdchagin /* NOTHING */ 715219558Sdchagin break; 716185337Srdivacky 717219558Sdchagin default: 718219558Sdchagin return (EINVAL); 719219558Sdchagin break; 720219558Sdchagin } 721104893Ssobomax 722219558Sdchagin error = kern_msgctl(td, args->msqid, bsd_cmd, &bsd_msqid); 723219558Sdchagin if (error != 0) 724219558Sdchagin if (bsd_cmd != LINUX_IPC_RMID || error != EINVAL) 725219558Sdchagin return (error); 726104893Ssobomax 727219558Sdchagin if (bsd_cmd == LINUX_IPC_STAT) { 728219558Sdchagin bsd_to_linux_msqid_ds(&bsd_msqid, &linux_msqid); 729219558Sdchagin return (linux_msqid_pushdown(args->cmd & LINUX_IPC_64, 730219558Sdchagin &linux_msqid, PTRIN(args->buf))); 731219558Sdchagin } 732104893Ssobomax 733219558Sdchagin return (0); 7349313Ssos} 7359313Ssos 73664906Smarcelint 73783366Sjulianlinux_shmat(struct thread *td, struct linux_shmat_args *args) 7389313Ssos{ 739219558Sdchagin struct shmat_args /* { 740219558Sdchagin int shmid; 741219558Sdchagin void *shmaddr; 742219558Sdchagin int shmflg; 743219558Sdchagin } */ bsd_args; 744219558Sdchagin int error; 745140214Sobrien#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 746219558Sdchagin l_uintptr_t addr; 747133816Stjr#endif 7489313Ssos 749219558Sdchagin bsd_args.shmid = args->shmid; 750219558Sdchagin bsd_args.shmaddr = PTRIN(args->shmaddr); 751219558Sdchagin bsd_args.shmflg = args->shmflg; 752225617Skmacy if ((error = sys_shmat(td, &bsd_args))) 753219558Sdchagin return (error); 754140214Sobrien#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 755219558Sdchagin addr = td->td_retval[0]; 756219558Sdchagin if ((error = copyout(&addr, PTRIN(args->raddr), sizeof(addr)))) 757219558Sdchagin return (error); 758219558Sdchagin td->td_retval[0] = 0; 75968214Sgallatin#endif 760219558Sdchagin return (0); 7619313Ssos} 7629313Ssos 76364906Smarcelint 76483366Sjulianlinux_shmdt(struct thread *td, struct linux_shmdt_args *args) 7659313Ssos{ 766219558Sdchagin struct shmdt_args /* { 767219558Sdchagin void *shmaddr; 768219558Sdchagin } */ bsd_args; 7699313Ssos 770219558Sdchagin bsd_args.shmaddr = PTRIN(args->shmaddr); 771225617Skmacy return (sys_shmdt(td, &bsd_args)); 7729313Ssos} 7739313Ssos 77464906Smarcelint 77583366Sjulianlinux_shmget(struct thread *td, struct linux_shmget_args *args) 7769313Ssos{ 777219558Sdchagin struct shmget_args /* { 778219558Sdchagin key_t key; 779219558Sdchagin int size; 780219558Sdchagin int shmflg; 781219558Sdchagin } */ bsd_args; 7829313Ssos 783219558Sdchagin bsd_args.key = args->key; 784219558Sdchagin bsd_args.size = args->size; 785219558Sdchagin bsd_args.shmflg = args->shmflg; 786225617Skmacy return (sys_shmget(td, &bsd_args)); 7879313Ssos} 7889313Ssos 78964906Smarcelint 79083366Sjulianlinux_shmctl(struct thread *td, struct linux_shmctl_args *args) 7919313Ssos{ 792219558Sdchagin struct l_shmid_ds linux_shmid; 79385623Smr struct l_shminfo linux_shminfo; 79485623Smr struct l_shm_info linux_shm_info; 795114724Smbr struct shmid_ds bsd_shmid; 796219558Sdchagin int error; 7979313Ssos 798332032Semaste memset(&linux_shm_info, 0, sizeof(linux_shm_info)); 799332039Semaste memset(&linux_shmid, 0, sizeof(linux_shmid)); 800332039Semaste memset(&linux_shminfo, 0, sizeof(linux_shminfo)); 801332032Semaste 802219558Sdchagin switch (args->cmd & ~LINUX_IPC_64) { 80385623Smr 804114724Smbr case LINUX_IPC_INFO: { 805219558Sdchagin struct shminfo bsd_shminfo; 806114724Smbr 807219558Sdchagin /* Perform shmctl wanting removed segments lookup */ 808219558Sdchagin error = kern_shmctl(td, args->shmid, IPC_INFO, 809219558Sdchagin (void *)&bsd_shminfo, NULL); 810219558Sdchagin if (error) 811219558Sdchagin return (error); 81285623Smr 813219558Sdchagin bsd_to_linux_shminfo(&bsd_shminfo, &linux_shminfo); 814219558Sdchagin 815219558Sdchagin return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_64, 816219558Sdchagin &linux_shminfo, PTRIN(args->buf))); 817114724Smbr } 81885623Smr 819114724Smbr case LINUX_SHM_INFO: { 820219558Sdchagin struct shm_info bsd_shm_info; 8219313Ssos 822219558Sdchagin /* Perform shmctl wanting removed segments lookup */ 823219558Sdchagin error = kern_shmctl(td, args->shmid, SHM_INFO, 824219558Sdchagin (void *)&bsd_shm_info, NULL); 825219558Sdchagin if (error) 826219558Sdchagin return (error); 827114724Smbr 828219558Sdchagin bsd_to_linux_shm_info(&bsd_shm_info, &linux_shm_info); 829114724Smbr 830219558Sdchagin return (copyout(&linux_shm_info, PTRIN(args->buf), 831219558Sdchagin sizeof(struct l_shm_info))); 83285623Smr } 833114724Smbr 834114724Smbr case LINUX_IPC_STAT: 835219558Sdchagin /* Perform shmctl wanting removed segments lookup */ 836219558Sdchagin error = kern_shmctl(td, args->shmid, IPC_STAT, 837219558Sdchagin (void *)&bsd_shmid, NULL); 838219558Sdchagin if (error) 839219558Sdchagin return (error); 840114724Smbr 841219558Sdchagin bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); 842114724Smbr 843219558Sdchagin return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64, 844219558Sdchagin &linux_shmid, PTRIN(args->buf))); 84585623Smr 846219558Sdchagin case LINUX_SHM_STAT: 847219558Sdchagin /* Perform shmctl wanting removed segments lookup */ 848219558Sdchagin error = kern_shmctl(td, args->shmid, IPC_STAT, 849219558Sdchagin (void *)&bsd_shmid, NULL); 850219558Sdchagin if (error) 851219558Sdchagin return (error); 852114724Smbr 853219558Sdchagin bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); 854114724Smbr 855219558Sdchagin return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64, 856219558Sdchagin &linux_shmid, PTRIN(args->buf))); 8579313Ssos 858219558Sdchagin case LINUX_IPC_SET: 859219558Sdchagin error = linux_shmid_pullup(args->cmd & LINUX_IPC_64, 860163215Sjhb &linux_shmid, PTRIN(args->buf)); 861114724Smbr if (error) 862219558Sdchagin return (error); 863219558Sdchagin 864114724Smbr linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 865219558Sdchagin 866219558Sdchagin /* Perform shmctl wanting removed segments lookup */ 867219558Sdchagin return (kern_shmctl(td, args->shmid, IPC_SET, 868219558Sdchagin (void *)&bsd_shmid, NULL)); 869219558Sdchagin 870219558Sdchagin case LINUX_IPC_RMID: { 871219558Sdchagin void *buf; 872219558Sdchagin 873219558Sdchagin if (args->buf == 0) 874219558Sdchagin buf = NULL; 875219558Sdchagin else { 876219558Sdchagin error = linux_shmid_pullup(args->cmd & LINUX_IPC_64, 877219558Sdchagin &linux_shmid, PTRIN(args->buf)); 878219558Sdchagin if (error) 879219558Sdchagin return (error); 880219558Sdchagin linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 881219558Sdchagin buf = (void *)&bsd_shmid; 882219558Sdchagin } 883219558Sdchagin return (kern_shmctl(td, args->shmid, IPC_RMID, buf, NULL)); 88436587Sjkh } 8859313Ssos 886219558Sdchagin case LINUX_SHM_LOCK: 887219558Sdchagin /* FALLTHROUGH */ 888219558Sdchagin case LINUX_SHM_UNLOCK: 889219558Sdchagin /* FALLTHROUGH */ 890219558Sdchagin default: 891219558Sdchagin linux_msg(td, "ipc type %d not implemented", 892219558Sdchagin args->cmd & ~LINUX_IPC_64); 893219558Sdchagin return (EINVAL); 894219558Sdchagin } 8959313Ssos} 896148540Sjhb 897148540SjhbMODULE_DEPEND(linux, sysvmsg, 1, 1, 1); 898148540SjhbMODULE_DEPEND(linux, sysvsem, 1, 1, 1); 899148540SjhbMODULE_DEPEND(linux, sysvshm, 1, 1, 1); 900