The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/common/linux_ipc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: linux_ipc.c,v 1.28.4.1 2004/10/04 05:19:07 jmc Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Frank van der Linden and Eric Haszlakiewicz.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: linux_ipc.c,v 1.28.4.1 2004/10/04 05:19:07 jmc Exp $");
   41 
   42 #if defined(_KERNEL_OPT)
   43 #include "opt_sysv.h"
   44 #endif
   45 
   46 #include <sys/param.h>
   47 #include <sys/shm.h>
   48 #include <sys/sem.h>
   49 #include <sys/msg.h>
   50 #include <sys/proc.h>
   51 #include <sys/systm.h>
   52 
   53 #include <sys/mount.h>
   54 #include <sys/sa.h>
   55 #include <sys/syscallargs.h>
   56 
   57 #include <compat/linux/common/linux_types.h>
   58 #include <compat/linux/common/linux_signal.h>
   59 #include <compat/linux/common/linux_util.h>
   60 
   61 #include <compat/linux/linux_syscallargs.h>
   62 #include <compat/linux/linux_syscall.h>
   63 
   64 #include <compat/linux/common/linux_ipc.h>
   65 #include <compat/linux/common/linux_msg.h>
   66 #include <compat/linux/common/linux_shm.h>
   67 #include <compat/linux/common/linux_sem.h>
   68 #include <compat/linux/common/linux_ipccall.h>
   69 
   70 /*
   71  * Note: Not all linux architechtures have explicit versions
   72  *      of the SYSV* syscalls.  On the ones that don't
   73  *      we pretend that they are defined anyway.  *_args and
   74  *      prototypes are defined in individual headers;
   75  *      syscalls.master lists those syscalls as NOARGS.
   76  *
   77  *      The functions in multiarch are the ones that just need
   78  *      the arguments shuffled around and then use the
   79  *      normal NetBSD syscall.
   80  *
   81  * Function in multiarch:
   82  *      linux_sys_ipc           : linux_ipccall.c
   83  *      liunx_semop             : linux_ipccall.c
   84  *      linux_semget            : linux_ipccall.c
   85  *      linux_msgsnd            : linux_ipccall.c
   86  *      linux_msgrcv            : linux_ipccall.c
   87  *      linux_msgget            : linux_ipccall.c
   88  *      linux_shmdt             : linux_ipccall.c
   89  *      linux_shmget            : linux_ipccall.c
   90  */
   91 
   92 #if defined (SYSVSEM) || defined(SYSVSHM) || defined(SYSVMSG)
   93 /*
   94  * Convert between Linux and NetBSD ipc_perm structures. Only the
   95  * order of the fields is different.
   96  */
   97 void
   98 linux_to_bsd_ipc_perm(lpp, bpp)
   99         struct linux_ipc_perm *lpp;
  100         struct ipc_perm *bpp;
  101 {
  102 
  103         bpp->_key = lpp->l_key;
  104         bpp->uid = lpp->l_uid;
  105         bpp->gid = lpp->l_gid;
  106         bpp->cuid = lpp->l_cuid;
  107         bpp->cgid = lpp->l_cgid;
  108         bpp->mode = lpp->l_mode;
  109         bpp->_seq = lpp->l_seq;
  110 }
  111 
  112 void
  113 bsd_to_linux_ipc_perm(bpp, lpp)
  114         struct ipc_perm *bpp;
  115         struct linux_ipc_perm *lpp;
  116 {
  117 
  118         lpp->l_key = bpp->_key;
  119         lpp->l_uid = bpp->uid;
  120         lpp->l_gid = bpp->gid;
  121         lpp->l_cuid = bpp->cuid;
  122         lpp->l_cgid = bpp->cgid;
  123         lpp->l_mode = bpp->mode;
  124         lpp->l_seq = bpp->_seq;
  125 }
  126 #endif
  127 
  128 #ifdef SYSVSEM
  129 /*
  130  * Semaphore operations. Most constants and structures are the same on
  131  * both systems. Only semctl() needs some extra work.
  132  */
  133 
  134 /*
  135  * Convert between Linux and NetBSD semid_ds structures.
  136  */
  137 void
  138 bsd_to_linux_semid_ds(bs, ls)
  139         struct semid_ds *bs;
  140         struct linux_semid_ds *ls;
  141 {
  142 
  143         bsd_to_linux_ipc_perm(&bs->sem_perm, &ls->l_sem_perm);
  144         ls->l_sem_otime = bs->sem_otime;
  145         ls->l_sem_ctime = bs->sem_ctime;
  146         ls->l_sem_nsems = bs->sem_nsems;
  147         ls->l_sem_base = bs->_sem_base;
  148 }
  149 
  150 void
  151 linux_to_bsd_semid_ds(ls, bs)
  152         struct linux_semid_ds *ls;
  153         struct semid_ds *bs;
  154 {
  155 
  156         linux_to_bsd_ipc_perm(&ls->l_sem_perm, &bs->sem_perm);
  157         bs->sem_otime = ls->l_sem_otime;
  158         bs->sem_ctime = ls->l_sem_ctime;
  159         bs->sem_nsems = ls->l_sem_nsems;
  160         bs->_sem_base = ls->l_sem_base;
  161 }
  162 
  163 /*
  164  * Most of this can be handled by directly passing the arguments on; we
  165  * just need to frob the `cmd' and convert the semid_ds and semun.
  166  */
  167 int
  168 linux_sys_semctl(l, v, retval)
  169         struct lwp *l;
  170         void *v;
  171         register_t *retval;
  172 {
  173         struct linux_sys_semctl_args /* {
  174                 syscallarg(int) semid;
  175                 syscallarg(int) semnum;
  176                 syscallarg(int) cmd;
  177                 syscallarg(union linux_semun) arg;
  178         } */ *uap = v;
  179         struct proc *p = l->l_proc;
  180         struct semid_ds sembuf;
  181         struct linux_semid_ds lsembuf;
  182         union __semun semun;
  183         int cmd, error;
  184         void *pass_arg = NULL;
  185 
  186         cmd = SCARG(uap, cmd);
  187 
  188         switch (cmd) {
  189         case LINUX_IPC_SET:
  190                 pass_arg = &sembuf;
  191                 cmd = IPC_SET;
  192                 break;
  193 
  194         case LINUX_IPC_STAT:
  195                 pass_arg = &sembuf;
  196                 cmd = IPC_STAT;
  197                 break;
  198 
  199         case LINUX_IPC_RMID:
  200                 cmd = IPC_RMID;
  201                 break;
  202 
  203         case LINUX_GETVAL:
  204                 cmd = GETVAL;
  205                 break;
  206 
  207         case LINUX_GETPID:
  208                 cmd = GETPID;
  209                 break;
  210 
  211         case LINUX_GETNCNT:
  212                 cmd = GETNCNT;
  213                 break;
  214 
  215         case LINUX_GETZCNT:
  216                 cmd = GETZCNT;
  217                 break;
  218 
  219         case LINUX_GETALL:
  220                 pass_arg = &semun;
  221                 semun.array = SCARG(uap, arg).l_array;
  222                 cmd = GETALL;
  223                 break;
  224 
  225         case LINUX_SETVAL:
  226                 pass_arg = &semun;
  227                 semun.val = SCARG(uap, arg).l_val;
  228                 cmd = SETVAL;
  229                 break;
  230 
  231         case LINUX_SETALL:
  232                 pass_arg = &semun;
  233                 semun.array = SCARG(uap, arg).l_array;
  234                 cmd = SETALL;
  235                 break;
  236 
  237         default:
  238                 return (EINVAL);
  239         }
  240 
  241         if (cmd == IPC_SET) {
  242                 error = copyin(SCARG(uap, arg).l_buf, &lsembuf,
  243                     sizeof(lsembuf));
  244                 if (error)
  245                         return (error);
  246                 linux_to_bsd_semid_ds(&lsembuf, &sembuf);
  247         }
  248 
  249         error = semctl1(p, SCARG(uap, semid), SCARG(uap, semnum), cmd,
  250             pass_arg, retval);
  251 
  252         if (error == 0 && cmd == IPC_STAT) {
  253                 bsd_to_linux_semid_ds(&sembuf, &lsembuf);
  254                 error = copyout(&lsembuf, SCARG(uap, arg).l_buf,
  255                     sizeof(lsembuf));
  256         }
  257 
  258         return (error);
  259 }
  260 #endif /* SYSVSEM */
  261 
  262 #ifdef SYSVMSG
  263 
  264 void
  265 linux_to_bsd_msqid_ds(lmp, bmp)
  266         struct linux_msqid_ds *lmp;
  267         struct msqid_ds *bmp;
  268 {
  269 
  270         linux_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm);
  271         bmp->_msg_first = lmp->l_msg_first;
  272         bmp->_msg_last = lmp->l_msg_last;
  273         bmp->_msg_cbytes = lmp->l_msg_cbytes;
  274         bmp->msg_qnum = lmp->l_msg_qnum;
  275         bmp->msg_qbytes = lmp->l_msg_qbytes;
  276         bmp->msg_lspid = lmp->l_msg_lspid;
  277         bmp->msg_lrpid = lmp->l_msg_lrpid;
  278         bmp->msg_stime = lmp->l_msg_stime;
  279         bmp->msg_rtime = lmp->l_msg_rtime;
  280         bmp->msg_ctime = lmp->l_msg_ctime;
  281 }
  282 
  283 void
  284 bsd_to_linux_msqid_ds(bmp, lmp)
  285         struct msqid_ds *bmp;
  286         struct linux_msqid_ds *lmp;
  287 {
  288 
  289         bsd_to_linux_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm);
  290         lmp->l_msg_first = bmp->_msg_first;
  291         lmp->l_msg_last = bmp->_msg_last;
  292         lmp->l_msg_cbytes = bmp->_msg_cbytes;
  293         lmp->l_msg_qnum = bmp->msg_qnum;
  294         lmp->l_msg_qbytes = bmp->msg_qbytes;
  295         lmp->l_msg_lspid = bmp->msg_lspid;
  296         lmp->l_msg_lrpid = bmp->msg_lrpid;
  297         lmp->l_msg_stime = bmp->msg_stime;
  298         lmp->l_msg_rtime = bmp->msg_rtime;
  299         lmp->l_msg_ctime = bmp->msg_ctime;
  300 }
  301 
  302 int
  303 linux_sys_msgctl(l, v, retval)
  304         struct lwp *l;
  305         void *v;
  306         register_t *retval;
  307 {
  308         struct linux_sys_msgctl_args /* {
  309                 syscallarg(int) msqid;
  310                 syscallarg(int) cmd;
  311                 syscallarg(struct linux_msqid_ds *) buf;
  312         } */ *uap = v;
  313         struct proc *p = l->l_proc;
  314         caddr_t sg;
  315         struct sys___msgctl13_args nua;
  316         struct msqid_ds *bmp, bm;
  317         struct linux_msqid_ds lm;
  318         int error;
  319 
  320         SCARG(&nua, msqid) = SCARG(uap, msqid);
  321         switch (SCARG(uap, cmd)) {
  322         case LINUX_IPC_STAT:
  323                 sg = stackgap_init(p, 0);
  324                 bmp = stackgap_alloc(p, &sg, sizeof (struct msqid_ds));
  325                 SCARG(&nua, cmd) = IPC_STAT;
  326                 SCARG(&nua, buf) = bmp;
  327                 if ((error = sys___msgctl13(l, &nua, retval)))
  328                         return error;
  329                 if ((error = copyin(bmp, &bm, sizeof bm)))
  330                         return error;
  331                 bsd_to_linux_msqid_ds(&bm, &lm);
  332                 return copyout(&lm, SCARG(uap, buf), sizeof lm);
  333         case LINUX_IPC_SET:
  334                 if ((error = copyin(SCARG(uap, buf), &lm, sizeof lm)))
  335                         return error;
  336                 linux_to_bsd_msqid_ds(&lm, &bm);
  337                 sg = stackgap_init(p, 0);
  338                 bmp = stackgap_alloc(p, &sg, sizeof bm);
  339                 if ((error = copyout(&bm, bmp, sizeof bm)))
  340                         return error;
  341                 SCARG(&nua, cmd) = IPC_SET;
  342                 SCARG(&nua, buf) = bmp;
  343                 break;
  344         case LINUX_IPC_RMID:
  345                 SCARG(&nua, cmd) = IPC_RMID;
  346                 SCARG(&nua, buf) = NULL;
  347                 break;
  348         default:
  349                 return EINVAL;
  350         }
  351         return sys___msgctl13(l, &nua, retval);
  352 }
  353 #endif /* SYSVMSG */
  354 
  355 #ifdef SYSVSHM
  356 /*
  357  * shmget(2). Just make sure the Linux-compatible shmat() semantics
  358  * is enabled for the segment, so that shmat() succeeds even when
  359  * the segment would be removed.
  360  */
  361 int
  362 linux_sys_shmget(l, v, retval)
  363         struct lwp *l;
  364         void *v;
  365         register_t *retval;
  366 {
  367         struct sys_shmget_args /* {
  368                 syscallarg(key_t) key;
  369                 syscallarg(size_t) size;
  370                 syscallarg(int) shmflg;
  371         } */ *uap = v;
  372 
  373         SCARG(uap, shmflg) |= _SHM_RMLINGER;
  374         return sys_shmget(l, uap, retval);
  375 }
  376 
  377 /*
  378  * shmat(2). Very straightforward, except that Linux passes a pointer
  379  * in which the return value is to be passed. This is subsequently
  380  * handled by libc, apparently.
  381  */
  382 int
  383 linux_sys_shmat(l, v, retval)
  384         struct lwp *l;
  385         void *v;
  386         register_t *retval;
  387 {
  388         struct linux_sys_shmat_args /* {
  389                 syscallarg(int) shmid;
  390                 syscallarg(void *) shmaddr;
  391                 syscallarg(int) shmflg;
  392                 syscallarg(u_long *) raddr;
  393         } */ *uap = v;
  394         int error;
  395 
  396         if ((error = sys_shmat(l, uap, retval)))
  397                 return error;
  398 
  399         if ((error = copyout(&retval[0], (caddr_t) SCARG(uap, raddr),
  400              sizeof retval[0])))
  401                 return error;
  402         
  403         retval[0] = 0;
  404         return 0;
  405 }
  406 
  407 /*
  408  * Convert between Linux and NetBSD shmid_ds structures.
  409  * The order of the fields is once again the difference, and
  410  * we also need a place to store the internal data pointer
  411  * in, which is unfortunately stored in this structure.
  412  *
  413  * We abuse a Linux internal field for that.
  414  */
  415 void
  416 linux_to_bsd_shmid_ds(lsp, bsp)
  417         struct linux_shmid_ds *lsp;
  418         struct shmid_ds *bsp;
  419 {
  420 
  421         linux_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm);
  422         bsp->shm_segsz = lsp->l_shm_segsz;
  423         bsp->shm_lpid = lsp->l_shm_lpid;
  424         bsp->shm_cpid = lsp->l_shm_cpid;
  425         bsp->shm_nattch = lsp->l_shm_nattch;
  426         bsp->shm_atime = lsp->l_shm_atime;
  427         bsp->shm_dtime = lsp->l_shm_dtime;
  428         bsp->shm_ctime = lsp->l_shm_ctime;
  429         bsp->_shm_internal = lsp->l_private2;   /* XXX Oh well. */
  430 }
  431 
  432 void
  433 bsd_to_linux_shmid_ds(bsp, lsp)
  434         struct shmid_ds *bsp;
  435         struct linux_shmid_ds *lsp;
  436 {
  437 
  438         bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm);
  439         lsp->l_shm_segsz = bsp->shm_segsz;
  440         lsp->l_shm_lpid = bsp->shm_lpid;
  441         lsp->l_shm_cpid = bsp->shm_cpid;
  442         lsp->l_shm_nattch = bsp->shm_nattch;
  443         lsp->l_shm_atime = bsp->shm_atime;
  444         lsp->l_shm_dtime = bsp->shm_dtime;
  445         lsp->l_shm_ctime = bsp->shm_ctime;
  446         lsp->l_private2 = bsp->_shm_internal;   /* XXX */
  447 }
  448 
  449 /*
  450  * shmctl. Not implemented (for now): IPC_INFO, SHM_INFO, SHM_STAT
  451  * SHM_LOCK and SHM_UNLOCK are passed on, but currently not implemented
  452  * by NetBSD itself.
  453  *
  454  * The usual structure conversion and massaging is done.
  455  */
  456 int
  457 linux_sys_shmctl(l, v, retval)
  458         struct lwp *l;
  459         void *v;
  460         register_t *retval;
  461 {
  462         struct linux_sys_shmctl_args /* {
  463                 syscallarg(int) shmid;
  464                 syscallarg(int) cmd;
  465                 syscallarg(struct linux_shmid_ds *) buf;
  466         } */ *uap = v;
  467         struct proc *p = l->l_proc;
  468         caddr_t sg;
  469         struct sys___shmctl13_args nua;
  470         struct shmid_ds *bsp, bs;
  471         struct linux_shmid_ds ls;
  472         int error;
  473 
  474         SCARG(&nua, shmid) = SCARG(uap, shmid);
  475         switch (SCARG(uap, cmd)) {
  476         case LINUX_IPC_STAT:
  477                 sg = stackgap_init(p, 0);
  478                 bsp = stackgap_alloc(p, &sg, sizeof(struct shmid_ds));
  479                 SCARG(&nua, cmd) = IPC_STAT;
  480                 SCARG(&nua, buf) = bsp;
  481                 if ((error = sys___shmctl13(l, &nua, retval)))
  482                         return error;
  483                 if ((error = copyin(SCARG(&nua, buf), &bs, sizeof bs)))
  484                         return error;
  485                 bsd_to_linux_shmid_ds(&bs, &ls);
  486                 return copyout(&ls, SCARG(uap, buf), sizeof ls);
  487         case LINUX_IPC_SET:
  488                 if ((error = copyin(SCARG(uap, buf), &ls, sizeof ls)))
  489                         return error;
  490                 linux_to_bsd_shmid_ds(&ls, &bs);
  491                 sg = stackgap_init(p, 0);
  492                 bsp = stackgap_alloc(p, &sg, sizeof bs);
  493                 if ((error = copyout(&bs, bsp, sizeof bs)))
  494                         return error;
  495                 SCARG(&nua, cmd) = IPC_SET;
  496                 SCARG(&nua, buf) = bsp;
  497                 break;
  498         case LINUX_IPC_RMID:
  499                 SCARG(&nua, cmd) = IPC_RMID;
  500                 SCARG(&nua, buf) = NULL;
  501                 break;
  502         case LINUX_SHM_LOCK:
  503                 SCARG(&nua, cmd) = SHM_LOCK;
  504                 SCARG(&nua, buf) = NULL;
  505                 break;
  506         case LINUX_SHM_UNLOCK:
  507                 SCARG(&nua, cmd) = SHM_UNLOCK;
  508                 SCARG(&nua, buf) = NULL;
  509                 break;
  510         case LINUX_IPC_INFO:
  511         case LINUX_SHM_STAT:
  512         case LINUX_SHM_INFO:
  513         default:
  514                 return EINVAL;
  515         }
  516         return sys___shmctl13(l, &nua, retval);
  517 }
  518 #endif /* SYSVSHM */

Cache object: 72120ae6e472dbed3e81e8d72cf2d417


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.