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.57 2019/08/23 10:22:15 maxv 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  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: linux_ipc.c,v 1.57 2019/08/23 10:22:15 maxv Exp $");
   34 
   35 #if defined(_KERNEL_OPT)
   36 #include "opt_sysv.h"
   37 #endif
   38 
   39 #include <sys/param.h>
   40 #include <sys/shm.h>
   41 #include <sys/sem.h>
   42 #include <sys/msg.h>
   43 #include <sys/proc.h>
   44 #include <sys/systm.h>
   45 #include <sys/vnode.h>
   46 
   47 #include <sys/mount.h>
   48 #include <sys/syscallargs.h>
   49 
   50 #include <compat/linux/common/linux_types.h>
   51 #include <compat/linux/common/linux_signal.h>
   52 #include <compat/linux/common/linux_util.h>
   53 #include <compat/linux/common/linux_ipc.h>
   54 #include <compat/linux/common/linux_msg.h>
   55 #include <compat/linux/common/linux_shm.h>
   56 #include <compat/linux/common/linux_sem.h>
   57 
   58 #include <compat/linux/linux_syscallargs.h>
   59 #include <compat/linux/linux_syscall.h>
   60 
   61 #include <compat/linux/common/linux_ipccall.h>
   62 #include <compat/linux/common/linux_machdep.h>
   63 
   64 /*
   65  * Note: Not all linux architechtures have explicit versions
   66  *      of the SYSV* syscalls.  On the ones that don't
   67  *      we pretend that they are defined anyway.  *_args and
   68  *      prototypes are defined in individual headers;
   69  *      syscalls.master lists those syscalls as NOARGS.
   70  *
   71  *      The functions in multiarch are the ones that just need
   72  *      the arguments shuffled around and then use the
   73  *      normal NetBSD syscall.
   74  *
   75  * Function in multiarch:
   76  *      linux_sys_ipc           : linux_ipccall.c
   77  *      linux_semop             : linux_ipccall.c
   78  *      linux_semget            : linux_ipccall.c
   79  *      linux_msgsnd            : linux_ipccall.c
   80  *      linux_msgrcv            : linux_ipccall.c
   81  *      linux_msgget            : linux_ipccall.c
   82  *      linux_shmdt             : linux_ipccall.c
   83  *      linux_shmget            : linux_ipccall.c
   84  */
   85 
   86 #if defined (SYSVSEM) || defined(SYSVSHM) || defined(SYSVMSG)
   87 /*
   88  * Convert between Linux and NetBSD ipc_perm structures. Only the
   89  * order of the fields is different.
   90  */
   91 void
   92 linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
   93 {
   94 
   95         bpp->_key = lpp->l_key;
   96         bpp->uid = lpp->l_uid;
   97         bpp->gid = lpp->l_gid;
   98         bpp->cuid = lpp->l_cuid;
   99         bpp->cgid = lpp->l_cgid;
  100         bpp->mode = lpp->l_mode;
  101         bpp->_seq = lpp->l_seq;
  102 }
  103 
  104 void
  105 linux_to_bsd_ipc64_perm(struct linux_ipc64_perm *lpp, struct ipc_perm *bpp)
  106 {
  107         bpp->_key = lpp->l_key;
  108         bpp->uid = lpp->l_uid;
  109         bpp->gid = lpp->l_gid;
  110         bpp->cuid = lpp->l_cuid;
  111         bpp->cgid = lpp->l_cgid;
  112         bpp->mode = lpp->l_mode;
  113         bpp->_seq = lpp->l_seq;
  114 }
  115 
  116 void
  117 bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
  118 {
  119 
  120         memset(lpp, 0, sizeof *lpp);
  121         lpp->l_key = bpp->_key;
  122         lpp->l_uid = bpp->uid;
  123         lpp->l_gid = bpp->gid;
  124         lpp->l_cuid = bpp->cuid;
  125         lpp->l_cgid = bpp->cgid;
  126         lpp->l_mode = bpp->mode;
  127         lpp->l_seq = bpp->_seq;
  128 }
  129 
  130 void
  131 bsd_to_linux_ipc64_perm(struct ipc_perm *bpp, struct linux_ipc64_perm *lpp)
  132 {
  133 
  134         memset(lpp, 0, sizeof *lpp);
  135         lpp->l_key = bpp->_key;
  136         lpp->l_uid = bpp->uid;
  137         lpp->l_gid = bpp->gid;
  138         lpp->l_cuid = bpp->cuid;
  139         lpp->l_cgid = bpp->cgid;
  140         lpp->l_mode = bpp->mode;
  141         lpp->l_seq = bpp->_seq;
  142 }
  143 
  144 #endif
  145 
  146 #ifdef SYSVSEM
  147 /*
  148  * Semaphore operations. Most constants and structures are the same on
  149  * both systems. Only semctl() needs some extra work.
  150  */
  151 
  152 /*
  153  * Convert between Linux and NetBSD semid_ds structures.
  154  */
  155 void
  156 bsd_to_linux_semid_ds(struct semid_ds *bs, struct linux_semid_ds *ls)
  157 {
  158 
  159         memset(ls, 0, sizeof *ls);
  160         bsd_to_linux_ipc_perm(&bs->sem_perm, &ls->l_sem_perm);
  161         ls->l_sem_otime = bs->sem_otime;
  162         ls->l_sem_ctime = bs->sem_ctime;
  163         ls->l_sem_nsems = bs->sem_nsems;
  164 }
  165 
  166 void
  167 bsd_to_linux_semid64_ds(struct semid_ds *bs, struct linux_semid64_ds *ls)
  168 {
  169 
  170         memset(ls, 0, sizeof *ls);
  171         bsd_to_linux_ipc64_perm(&bs->sem_perm, &ls->l_sem_perm);
  172         ls->l_sem_otime = bs->sem_otime;
  173         ls->l_sem_ctime = bs->sem_ctime;
  174         ls->l_sem_nsems = bs->sem_nsems;
  175 }
  176 
  177 void
  178 linux_to_bsd_semid_ds(struct linux_semid_ds *ls, struct semid_ds *bs)
  179 {
  180 
  181         linux_to_bsd_ipc_perm(&ls->l_sem_perm, &bs->sem_perm);
  182         bs->sem_otime = ls->l_sem_otime;
  183         bs->sem_ctime = ls->l_sem_ctime;
  184         bs->sem_nsems = ls->l_sem_nsems;
  185 }
  186 
  187 void
  188 linux_to_bsd_semid64_ds(struct linux_semid64_ds *ls, struct semid_ds *bs)
  189 {
  190 
  191         linux_to_bsd_ipc64_perm(&ls->l_sem_perm, &bs->sem_perm);
  192         bs->sem_otime = ls->l_sem_otime;
  193         bs->sem_ctime = ls->l_sem_ctime;
  194         bs->sem_nsems = ls->l_sem_nsems;
  195 }
  196 
  197 /*
  198  * Most of this can be handled by directly passing the arguments on; we
  199  * just need to frob the `cmd' and convert the semid_ds and semun.
  200  */
  201 int
  202 linux_sys_semctl(struct lwp *l, const struct linux_sys_semctl_args *uap, register_t *retval)
  203 {
  204         /* {
  205                 syscallarg(int) semid;
  206                 syscallarg(int) semnum;
  207                 syscallarg(int) cmd;
  208                 syscallarg(union linux_semun) arg;
  209         } */
  210         struct semid_ds sembuf;
  211         struct linux_semid_ds lsembuf;
  212         struct linux_semid64_ds lsembuf64;
  213         union __semun semun;
  214         int cmd, lcmd, error;
  215         void *pass_arg = NULL;
  216 
  217         lcmd = SCARG(uap, cmd);
  218 #ifdef LINUX_IPC_FORCE64
  219         lcmd |= LINUX_IPC_64;
  220 #endif
  221 
  222         switch (lcmd & ~LINUX_IPC_64) {
  223         case LINUX_IPC_SET:
  224                 if (lcmd & LINUX_IPC_64) {
  225                         error = copyin(SCARG(uap, arg).l_buf, &lsembuf64,
  226                             sizeof(lsembuf64));
  227                         linux_to_bsd_semid64_ds(&lsembuf64, &sembuf);
  228                 } else {
  229                         error = copyin(SCARG(uap, arg).l_buf, &lsembuf,
  230                            sizeof(lsembuf));
  231                         linux_to_bsd_semid_ds(&lsembuf, &sembuf);
  232                 }
  233                 if (error)
  234                         return (error);
  235                 pass_arg = &sembuf;
  236                 cmd = IPC_SET;
  237                 break;
  238 
  239         case LINUX_IPC_STAT:
  240                 pass_arg = &sembuf;
  241                 cmd = IPC_STAT;
  242                 break;
  243 
  244         case LINUX_IPC_RMID:
  245                 cmd = IPC_RMID;
  246                 break;
  247 
  248         case LINUX_GETVAL:
  249                 cmd = GETVAL;
  250                 break;
  251 
  252         case LINUX_GETPID:
  253                 cmd = GETPID;
  254                 break;
  255 
  256         case LINUX_GETNCNT:
  257                 cmd = GETNCNT;
  258                 break;
  259 
  260         case LINUX_GETZCNT:
  261                 cmd = GETZCNT;
  262                 break;
  263 
  264         case LINUX_GETALL:
  265                 pass_arg = &semun;
  266                 semun.array = SCARG(uap, arg).l_array;
  267                 cmd = GETALL;
  268                 break;
  269 
  270         case LINUX_SETVAL:
  271                 pass_arg = &semun;
  272                 semun.val = SCARG(uap, arg).l_val;
  273                 cmd = SETVAL;
  274                 break;
  275 
  276         case LINUX_SETALL:
  277                 pass_arg = &semun;
  278                 semun.array = SCARG(uap, arg).l_array;
  279                 cmd = SETALL;
  280                 break;
  281 
  282         default:
  283                 return (EINVAL);
  284         }
  285 
  286         error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd,
  287             pass_arg, retval);
  288         if (error)
  289                 return error;
  290 
  291         switch (lcmd) {
  292         case LINUX_IPC_STAT:
  293                 bsd_to_linux_semid_ds(&sembuf, &lsembuf);
  294                 error = copyout(&lsembuf, SCARG(uap, arg).l_buf,
  295                     sizeof(lsembuf));
  296                 break;
  297         case LINUX_IPC_STAT | LINUX_IPC_64:
  298                 bsd_to_linux_semid64_ds(&sembuf, &lsembuf64);
  299                 error = copyout(&lsembuf64, SCARG(uap, arg).l_buf,
  300                     sizeof(lsembuf64));
  301                 break;
  302         default:
  303                 break;
  304         }
  305 
  306         return (error);
  307 }
  308 #endif /* SYSVSEM */
  309 
  310 #ifdef SYSVMSG
  311 
  312 void
  313 linux_to_bsd_msqid_ds(struct linux_msqid_ds *lmp, struct msqid_ds *bmp)
  314 {
  315 
  316         memset(bmp, 0, sizeof(*bmp));
  317         linux_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm);
  318         bmp->_msg_cbytes = lmp->l_msg_cbytes;
  319         bmp->msg_qnum = lmp->l_msg_qnum;
  320         bmp->msg_qbytes = lmp->l_msg_qbytes;
  321         bmp->msg_lspid = lmp->l_msg_lspid;
  322         bmp->msg_lrpid = lmp->l_msg_lrpid;
  323         bmp->msg_stime = lmp->l_msg_stime;
  324         bmp->msg_rtime = lmp->l_msg_rtime;
  325         bmp->msg_ctime = lmp->l_msg_ctime;
  326 }
  327 
  328 void
  329 linux_to_bsd_msqid64_ds(struct linux_msqid64_ds *lmp, struct msqid_ds *bmp)
  330 {
  331 
  332         memset(bmp, 0, sizeof(*bmp));
  333         linux_to_bsd_ipc64_perm(&lmp->l_msg_perm, &bmp->msg_perm);
  334         bmp->_msg_cbytes = lmp->l_msg_cbytes;
  335         bmp->msg_stime = lmp->l_msg_stime;
  336         bmp->msg_rtime = lmp->l_msg_rtime;
  337         bmp->msg_ctime = lmp->l_msg_ctime;
  338         bmp->msg_qnum = lmp->l_msg_qnum;
  339         bmp->msg_qbytes = lmp->l_msg_qbytes;
  340         bmp->msg_lspid = lmp->l_msg_lspid;
  341         bmp->msg_lrpid = lmp->l_msg_lrpid;
  342 }
  343 
  344 void
  345 bsd_to_linux_msqid_ds(struct msqid_ds *bmp, struct linux_msqid_ds *lmp)
  346 {
  347 
  348         memset(lmp, 0, sizeof(*lmp));
  349         bsd_to_linux_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm);
  350         lmp->l_msg_cbytes = bmp->_msg_cbytes;
  351         lmp->l_msg_qnum = bmp->msg_qnum;
  352         lmp->l_msg_qbytes = bmp->msg_qbytes;
  353         lmp->l_msg_lspid = bmp->msg_lspid;
  354         lmp->l_msg_lrpid = bmp->msg_lrpid;
  355         lmp->l_msg_stime = bmp->msg_stime;
  356         lmp->l_msg_rtime = bmp->msg_rtime;
  357         lmp->l_msg_ctime = bmp->msg_ctime;
  358 }
  359 
  360 void
  361 bsd_to_linux_msqid64_ds(struct msqid_ds *bmp, struct linux_msqid64_ds *lmp)
  362 {
  363 
  364         memset(lmp, 0, sizeof(*lmp));
  365         bsd_to_linux_ipc64_perm(&bmp->msg_perm, &lmp->l_msg_perm);
  366         lmp->l_msg_cbytes = bmp->_msg_cbytes;
  367         lmp->l_msg_stime = bmp->msg_stime;
  368         lmp->l_msg_rtime = bmp->msg_rtime;
  369         lmp->l_msg_ctime = bmp->msg_ctime;
  370         lmp->l_msg_cbytes = bmp->_msg_cbytes;
  371         lmp->l_msg_qnum = bmp->msg_qnum;
  372         lmp->l_msg_qbytes = bmp->msg_qbytes;
  373         lmp->l_msg_lspid = bmp->msg_lspid;
  374         lmp->l_msg_lrpid = bmp->msg_lrpid;
  375 }
  376 
  377 int
  378 linux_sys_msgctl(struct lwp *l, const struct linux_sys_msgctl_args *uap, register_t *retval)
  379 {
  380         /* {
  381                 syscallarg(int) msqid;
  382                 syscallarg(int) cmd;
  383                 syscallarg(struct linux_msqid_ds *) buf;
  384         } */
  385         struct msqid_ds bm, *bmp = NULL;
  386         struct linux_msqid_ds lm;
  387         struct linux_msqid64_ds lm64;
  388         int cmd, lcmd, error;
  389 
  390         lcmd = SCARG(uap, cmd);
  391 #ifdef LINUX_IPC_FORCE64
  392         lcmd |= LINUX_IPC_64;
  393 #endif
  394 
  395         switch (lcmd & ~LINUX_IPC_64) {
  396         case LINUX_IPC_STAT:
  397                 cmd = IPC_STAT;
  398                 bmp = &bm;
  399                 break;
  400         case LINUX_IPC_SET:
  401                 if (lcmd & LINUX_IPC_64) {
  402                         error = copyin(SCARG(uap, buf), &lm64, sizeof lm64);
  403                         linux_to_bsd_msqid64_ds(&lm64, &bm);
  404                 } else {
  405                         error = copyin(SCARG(uap, buf), &lm, sizeof lm);
  406                         linux_to_bsd_msqid_ds(&lm, &bm);
  407                 }
  408                 if (error)
  409                         return error;
  410                 cmd = IPC_SET;
  411                 bmp = &bm;
  412                 break;
  413         case LINUX_IPC_RMID:
  414                 cmd = IPC_RMID;
  415                 break;
  416         default:
  417                 return EINVAL;
  418         }
  419 
  420         if ((error = msgctl1(l, SCARG(uap, msqid), cmd, bmp)))
  421                 return error;
  422 
  423         switch (lcmd) {
  424         case LINUX_IPC_STAT:
  425                 bsd_to_linux_msqid_ds(&bm, &lm);
  426                 error = copyout(&lm, SCARG(uap, buf), sizeof lm);
  427                 break;
  428         case LINUX_IPC_STAT|LINUX_IPC_64:
  429                 bsd_to_linux_msqid64_ds(&bm, &lm64);
  430                 error = copyout(&lm64, SCARG(uap, buf), sizeof lm64);
  431                 break;
  432         default:
  433                 break;
  434         }
  435 
  436         return error;
  437 }
  438 #endif /* SYSVMSG */
  439 
  440 #ifdef SYSVSHM
  441 /*
  442  * shmget(2). Just make sure the Linux-compatible shmat() semantics
  443  * is enabled for the segment, so that shmat() succeeds even when
  444  * the segment would be removed.
  445  */
  446 int
  447 linux_sys_shmget(struct lwp *l, const struct linux_sys_shmget_args *uap, register_t *retval)
  448 {
  449         /* {
  450                 syscallarg(key_t) key;
  451                 syscallarg(size_t) size;
  452                 syscallarg(int) shmflg;
  453         } */
  454         struct sys_shmget_args bsd_ua;
  455 
  456         SCARG(&bsd_ua, key) = SCARG(uap, key);
  457         SCARG(&bsd_ua, size) = SCARG(uap, size);
  458         SCARG(&bsd_ua, shmflg) = SCARG(uap, shmflg) | _SHM_RMLINGER;
  459 
  460         return sys_shmget(l, &bsd_ua, retval);
  461 }
  462 
  463 /*
  464  * shmat(2). Very straightforward, except that Linux passes a pointer
  465  * in which the return value is to be passed. This is subsequently
  466  * handled by libc, apparently.
  467  */
  468 #ifndef __amd64__
  469 int
  470 linux_sys_shmat(struct lwp *l, const struct linux_sys_shmat_args *uap, register_t *retval)
  471 {
  472         /* {
  473                 syscallarg(int) shmid;
  474                 syscallarg(void *) shmaddr;
  475                 syscallarg(int) shmflg;
  476                 syscallarg(u_long *) raddr;
  477         } */
  478         int error;
  479 
  480         if ((error = sys_shmat(l, (const void *)uap, retval)))
  481                 return error;
  482 
  483         if ((error = copyout(&retval[0], SCARG(uap, raddr), sizeof retval[0])))
  484                 return error;
  485 
  486         retval[0] = 0;
  487         return 0;
  488 }
  489 #endif /* __amd64__ */
  490 
  491 /*
  492  * Convert between Linux and NetBSD shmid_ds structures.
  493  * The order of the fields is once again the difference, and
  494  * we also need a place to store the internal data pointer
  495  * in, which is unfortunately stored in this structure.
  496  *
  497  * We abuse a Linux internal field for that.
  498  */
  499 void
  500 linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
  501 {
  502 
  503         linux_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm);
  504         bsp->shm_segsz = lsp->l_shm_segsz;
  505         bsp->shm_lpid = lsp->l_shm_lpid;
  506         bsp->shm_cpid = lsp->l_shm_cpid;
  507         bsp->shm_nattch = lsp->l_shm_nattch;
  508         bsp->shm_atime = lsp->l_shm_atime;
  509         bsp->shm_dtime = lsp->l_shm_dtime;
  510         bsp->shm_ctime = lsp->l_shm_ctime;
  511 }
  512 
  513 void
  514 linux_to_bsd_shmid64_ds(struct linux_shmid64_ds *lsp, struct shmid_ds *bsp)
  515 {
  516 
  517         linux_to_bsd_ipc64_perm(&lsp->l_shm_perm, &bsp->shm_perm);
  518         bsp->shm_segsz = lsp->l_shm_segsz;
  519         bsp->shm_lpid = lsp->l_shm_lpid;
  520         bsp->shm_cpid = lsp->l_shm_cpid;
  521         bsp->shm_nattch = lsp->l_shm_nattch;
  522         bsp->shm_atime = lsp->l_shm_atime;
  523         bsp->shm_dtime = lsp->l_shm_dtime;
  524         bsp->shm_ctime = lsp->l_shm_ctime;
  525 }
  526 
  527 void
  528 bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
  529 {
  530 
  531         memset(lsp, 0, sizeof *lsp);
  532         bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm);
  533         lsp->l_shm_segsz = bsp->shm_segsz;
  534         lsp->l_shm_lpid = bsp->shm_lpid;
  535         lsp->l_shm_cpid = bsp->shm_cpid;
  536         lsp->l_shm_nattch = bsp->shm_nattch;
  537         lsp->l_shm_atime = bsp->shm_atime;
  538         lsp->l_shm_dtime = bsp->shm_dtime;
  539         lsp->l_shm_ctime = bsp->shm_ctime;
  540 }
  541 
  542 void
  543 bsd_to_linux_shmid64_ds(struct shmid_ds *bsp, struct linux_shmid64_ds *lsp)
  544 {
  545 
  546         memset(lsp, 0, sizeof *lsp);
  547         bsd_to_linux_ipc64_perm(&bsp->shm_perm, &lsp->l_shm_perm);
  548         lsp->l_shm_segsz = bsp->shm_segsz;
  549         lsp->l_shm_lpid = bsp->shm_lpid;
  550         lsp->l_shm_cpid = bsp->shm_cpid;
  551         lsp->l_shm_nattch = bsp->shm_nattch;
  552         lsp->l_shm_atime = bsp->shm_atime;
  553         lsp->l_shm_dtime = bsp->shm_dtime;
  554         lsp->l_shm_ctime = bsp->shm_ctime;
  555 }
  556 
  557 /*
  558  * shmctl.
  559  *
  560  * The usual structure conversion and massaging is done.
  561  */
  562 int
  563 linux_sys_shmctl(struct lwp *l, const struct linux_sys_shmctl_args *uap, register_t *retval)
  564 {
  565         /* {
  566                 syscallarg(int) shmid;
  567                 syscallarg(int) cmd;
  568                 syscallarg(struct linux_shmid_ds *) buf;
  569         } */
  570         struct shmid_ds bs;
  571         struct ipc_perm perm;
  572         struct linux_shmid_ds ls;
  573         struct linux_shmid64_ds ls64;
  574         struct linux_shminfo64 lsi64;
  575         struct linux_shm_info lsi;
  576         int error, i, cmd, shmid;
  577 
  578         shmid = SCARG(uap, shmid);
  579         cmd = SCARG(uap, cmd);
  580 #ifdef LINUX_IPC_FORCE64
  581         cmd |= LINUX_IPC_64;
  582 #endif
  583 
  584         switch (cmd & ~LINUX_IPC_64) {
  585         case LINUX_SHM_STAT:
  586                 error = shm_find_segment_perm_by_index(shmid, &perm);
  587                 if (error)
  588                         return error;
  589                 shmid = IXSEQ_TO_IPCID(shmid, perm);
  590                 retval[0] = shmid;
  591                 /*FALLTHROUGH*/
  592 
  593         case LINUX_IPC_STAT:
  594                 error = shmctl1(l, shmid, IPC_STAT, &bs);
  595                 if (error != 0)
  596                         return error;
  597                 if (cmd & LINUX_IPC_64) {
  598                         bsd_to_linux_shmid64_ds(&bs, &ls64);
  599                         error = copyout(&ls64, SCARG(uap, buf), sizeof ls64);
  600                 } else {
  601                         bsd_to_linux_shmid_ds(&bs, &ls);
  602                         error = copyout(&ls, SCARG(uap, buf), sizeof ls);
  603                 }
  604                 return error;
  605 
  606         case LINUX_IPC_SET:
  607                 if (cmd & LINUX_IPC_64) {
  608                         error = copyin(SCARG(uap, buf), &ls64, sizeof ls64);
  609                         linux_to_bsd_shmid64_ds(&ls64, &bs);
  610                 } else {
  611                         error = copyin(SCARG(uap, buf), &ls, sizeof ls);
  612                         linux_to_bsd_shmid_ds(&ls, &bs);
  613                 }
  614                 if (error != 0)
  615                         return error;
  616                 return shmctl1(l, shmid, IPC_SET, &bs);
  617 
  618         case LINUX_IPC_RMID:
  619                 return shmctl1(l, shmid, IPC_RMID, NULL);
  620 
  621         case LINUX_SHM_LOCK:
  622                 return shmctl1(l, shmid, SHM_LOCK, NULL);
  623 
  624         case LINUX_SHM_UNLOCK:
  625                 return shmctl1(l, shmid, SHM_UNLOCK, NULL);
  626 
  627         case LINUX_IPC_INFO:
  628                 memset(&lsi64, 0, sizeof lsi64);
  629                 lsi64.l_shmmax = shminfo.shmmax;
  630                 lsi64.l_shmmin = shminfo.shmmin;
  631                 lsi64.l_shmmni = shminfo.shmmni;
  632                 lsi64.l_shmseg = shminfo.shmseg;
  633                 lsi64.l_shmall = shminfo.shmall;
  634                 for (i = shminfo.shmmni - 1; i > 0; i--)
  635                         if (shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED)
  636                                 break;
  637                 retval[0] = i;
  638                 return copyout(&lsi64, SCARG(uap, buf), sizeof lsi64);
  639 
  640         case LINUX_SHM_INFO:
  641                 (void)memset(&lsi, 0, sizeof lsi);
  642                 lsi.l_used_ids = shm_nused;
  643                 for (i = 0; i < shminfo.shmmni; i++)
  644                         if (shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED)
  645                                 lsi.l_shm_tot +=
  646                                     round_page(shmsegs[i].shm_segsz) /
  647                                     uvmexp.pagesize;
  648                 lsi.l_shm_rss = 0;
  649                 lsi.l_shm_swp = 0;
  650                 lsi.l_swap_attempts = 0;
  651                 lsi.l_swap_successes = 0;
  652                 for (i = shminfo.shmmni - 1; i > 0; i--)
  653                         if (shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED)
  654                                 break;
  655                 retval[0] = i;
  656                 return copyout(&lsi, SCARG(uap, buf), sizeof lsi);
  657 
  658         default:
  659 #ifdef DEBUG
  660                 printf("linux_sys_shmctl cmd %d\n", SCARG(uap, cmd));
  661 #endif
  662                 return EINVAL;
  663         }
  664 }
  665 #endif /* SYSVSHM */

Cache object: 9896e6cfcad985b4f3fb757bfae6907e


[ 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.