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/kern/sysv_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: sysv_ipc.c,v 1.18 2006/11/25 21:40:05 christos Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Charles M. Hannum.
    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: sysv_ipc.c,v 1.18 2006/11/25 21:40:05 christos Exp $");
   41 
   42 #include "opt_sysv.h"
   43 
   44 #include <sys/param.h>
   45 #include <sys/kernel.h>
   46 #include <sys/proc.h>
   47 #include <sys/ipc.h>
   48 #ifdef SYSVMSG
   49 #include <sys/msg.h>
   50 #endif
   51 #ifdef SYSVSEM
   52 #include <sys/sem.h>
   53 #endif
   54 #ifdef SYSVSHM
   55 #include <sys/shm.h>
   56 #endif
   57 #include <sys/systm.h>
   58 #include <sys/malloc.h>
   59 #include <sys/mount.h>
   60 #include <sys/vnode.h>
   61 #include <sys/stat.h>
   62 #include <sys/sysctl.h>
   63 #include <sys/kauth.h>
   64 
   65 /*
   66  * Check for ipc permission
   67  */
   68 
   69 int
   70 ipcperm(kauth_cred_t cred, struct ipc_perm *perm, int mode)
   71 {
   72         mode_t mask;
   73         int ismember = 0;
   74 
   75         if (kauth_cred_geteuid(cred) == 0)
   76                 return (0);
   77 
   78         if (mode == IPC_M) {
   79                 if (kauth_cred_geteuid(cred) == perm->uid ||
   80                     kauth_cred_geteuid(cred) == perm->cuid)
   81                         return (0);
   82                 return (EPERM);
   83         }
   84 
   85         mask = 0;
   86 
   87         if (kauth_cred_geteuid(cred) == perm->uid ||
   88             kauth_cred_geteuid(cred) == perm->cuid) {
   89                 if (mode & IPC_R)
   90                         mask |= S_IRUSR;
   91                 if (mode & IPC_W)
   92                         mask |= S_IWUSR;
   93                 return ((perm->mode & mask) == mask ? 0 : EACCES);
   94         }
   95 
   96         if (kauth_cred_getegid(cred) == perm->gid ||
   97             (kauth_cred_ismember_gid(cred, perm->gid, &ismember) == 0 && ismember) ||
   98             kauth_cred_getegid(cred) == perm->cgid ||
   99             (kauth_cred_ismember_gid(cred, perm->cgid, &ismember) == 0 && ismember)) {
  100                 if (mode & IPC_R)
  101                         mask |= S_IRGRP;
  102                 if (mode & IPC_W)
  103                         mask |= S_IWGRP;
  104                 return ((perm->mode & mask) == mask ? 0 : EACCES);
  105         }
  106 
  107         if (mode & IPC_R)
  108                 mask |= S_IROTH;
  109         if (mode & IPC_W)
  110                 mask |= S_IWOTH;
  111         return ((perm->mode & mask) == mask ? 0 : EACCES);
  112 }
  113 
  114 /*
  115  * sysctl helper routine for kern.ipc.sysvipc_info subtree.
  116  */
  117 
  118 #define FILL_PERM(src, dst) do { \
  119         (dst)._key = (src)._key; \
  120         (dst).uid = (src).uid; \
  121         (dst).gid = (src).gid; \
  122         (dst).cuid = (src).cuid; \
  123         (dst).cgid = (src).cgid; \
  124         (dst).mode = (src).mode; \
  125         (dst)._seq = (src)._seq; \
  126 } while (/*CONSTCOND*/ 0);
  127 
  128 #define FILL_MSG(src, dst) do { \
  129         FILL_PERM((src).msg_perm, (dst).msg_perm); \
  130         (dst).msg_qnum = (src).msg_qnum; \
  131         (dst).msg_qbytes = (src).msg_qbytes; \
  132         (dst)._msg_cbytes = (src)._msg_cbytes; \
  133         (dst).msg_lspid = (src).msg_lspid; \
  134         (dst).msg_lrpid = (src).msg_lrpid; \
  135         (dst).msg_stime = (src).msg_stime; \
  136         (dst).msg_rtime = (src).msg_rtime; \
  137         (dst).msg_ctime = (src).msg_ctime; \
  138 } while (/*CONSTCOND*/ 0)
  139 
  140 #define FILL_SEM(src, dst) do { \
  141         FILL_PERM((src).sem_perm, (dst).sem_perm); \
  142         (dst).sem_nsems = (src).sem_nsems; \
  143         (dst).sem_otime = (src).sem_otime; \
  144         (dst).sem_ctime = (src).sem_ctime; \
  145 } while (/*CONSTCOND*/ 0)
  146 
  147 #define FILL_SHM(src, dst) do { \
  148         FILL_PERM((src).shm_perm, (dst).shm_perm); \
  149         (dst).shm_segsz = (src).shm_segsz; \
  150         (dst).shm_lpid = (src).shm_lpid; \
  151         (dst).shm_cpid = (src).shm_cpid; \
  152         (dst).shm_atime = (src).shm_atime; \
  153         (dst).shm_dtime = (src).shm_dtime; \
  154         (dst).shm_ctime = (src).shm_ctime; \
  155         (dst).shm_nattch = (src).shm_nattch; \
  156 } while (/*CONSTCOND*/ 0)
  157 
  158 static int
  159 sysctl_kern_sysvipc(SYSCTLFN_ARGS)
  160 {
  161         void *where = oldp;
  162         size_t *sizep = oldlenp;
  163 #ifdef SYSVMSG
  164         struct msg_sysctl_info *msgsi = NULL;
  165 #endif
  166 #ifdef SYSVSEM
  167         struct sem_sysctl_info *semsi = NULL;
  168 #endif
  169 #ifdef SYSVSHM
  170         struct shm_sysctl_info *shmsi = NULL;
  171 #endif
  172         size_t infosize, dssize, tsize, buflen;
  173         void *bf = NULL;
  174         char *start;
  175         int32_t nds;
  176         int i, error, ret;
  177 
  178         if (namelen != 1)
  179                 return EINVAL;
  180 
  181         start = where;
  182         buflen = *sizep;
  183 
  184         switch (*name) {
  185         case KERN_SYSVIPC_MSG_INFO:
  186 #ifdef SYSVMSG
  187                 infosize = sizeof(msgsi->msginfo);
  188                 nds = msginfo.msgmni;
  189                 dssize = sizeof(msgsi->msgids[0]);
  190                 break;
  191 #else
  192                 return EINVAL;
  193 #endif
  194         case KERN_SYSVIPC_SEM_INFO:
  195 #ifdef SYSVSEM
  196                 infosize = sizeof(semsi->seminfo);
  197                 nds = seminfo.semmni;
  198                 dssize = sizeof(semsi->semids[0]);
  199                 break;
  200 #else
  201                 return EINVAL;
  202 #endif
  203         case KERN_SYSVIPC_SHM_INFO:
  204 #ifdef SYSVSHM
  205                 infosize = sizeof(shmsi->shminfo);
  206                 nds = shminfo.shmmni;
  207                 dssize = sizeof(shmsi->shmids[0]);
  208                 break;
  209 #else
  210                 return EINVAL;
  211 #endif
  212         default:
  213                 return EINVAL;
  214         }
  215         /*
  216          * Round infosize to 64 bit boundary if requesting more than just
  217          * the info structure or getting the total data size.
  218          */
  219         if (where == NULL || *sizep > infosize)
  220                 infosize = roundup(infosize, sizeof(quad_t));
  221         tsize = infosize + nds * dssize;
  222 
  223         /* Return just the total size required. */
  224         if (where == NULL) {
  225                 *sizep = tsize;
  226                 return 0;
  227         }
  228 
  229         /* Not enough room for even the info struct. */
  230         if (buflen < infosize) {
  231                 *sizep = 0;
  232                 return ENOMEM;
  233         }
  234         bf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK | M_ZERO);
  235 
  236         switch (*name) {
  237 #ifdef SYSVMSG
  238         case KERN_SYSVIPC_MSG_INFO:
  239                 msgsi = (struct msg_sysctl_info *)bf;
  240                 msgsi->msginfo = msginfo;
  241                 break;
  242 #endif
  243 #ifdef SYSVSEM
  244         case KERN_SYSVIPC_SEM_INFO:
  245                 semsi = (struct sem_sysctl_info *)bf;
  246                 semsi->seminfo = seminfo;
  247                 break;
  248 #endif
  249 #ifdef SYSVSHM
  250         case KERN_SYSVIPC_SHM_INFO:
  251                 shmsi = (struct shm_sysctl_info *)bf;
  252                 shmsi->shminfo = shminfo;
  253                 break;
  254 #endif
  255         }
  256         buflen -= infosize;
  257 
  258         ret = 0;
  259         if (buflen > 0) {
  260                 /* Fill in the IPC data structures.  */
  261                 for (i = 0; i < nds; i++) {
  262                         if (buflen < dssize) {
  263                                 ret = ENOMEM;
  264                                 break;
  265                         }
  266                         switch (*name) {
  267 #ifdef SYSVMSG
  268                         case KERN_SYSVIPC_MSG_INFO:
  269                                 FILL_MSG(msqids[i], msgsi->msgids[i]);
  270                                 break;
  271 #endif
  272 #ifdef SYSVSEM
  273                         case KERN_SYSVIPC_SEM_INFO:
  274                                 FILL_SEM(sema[i], semsi->semids[i]);
  275                                 break;
  276 #endif
  277 #ifdef SYSVSHM
  278                         case KERN_SYSVIPC_SHM_INFO:
  279                                 FILL_SHM(shmsegs[i], shmsi->shmids[i]);
  280                                 break;
  281 #endif
  282                         }
  283                         buflen -= dssize;
  284                 }
  285         }
  286         *sizep -= buflen;
  287         error = copyout(bf, start, *sizep);
  288         /* If copyout succeeded, use return code set earlier. */
  289         if (error == 0)
  290                 error = ret;
  291         if (bf)
  292                 free(bf, M_TEMP);
  293         return error;
  294 }
  295 
  296 #undef FILL_PERM
  297 #undef FILL_MSG
  298 #undef FILL_SEM
  299 #undef FILL_SHM
  300 
  301 SYSCTL_SETUP(sysctl_ipc_setup, "sysctl kern.ipc subtree setup")
  302 {
  303         sysctl_createv(clog, 0, NULL, NULL,
  304                 CTLFLAG_PERMANENT,
  305                 CTLTYPE_NODE, "kern", NULL,
  306                 NULL, 0, NULL, 0,
  307                 CTL_KERN, CTL_EOL);
  308 
  309         sysctl_createv(clog, 0, NULL, NULL,
  310                 CTLFLAG_PERMANENT,
  311                 CTLTYPE_NODE, "ipc",
  312                 SYSCTL_DESCR("SysV IPC options"),
  313                 NULL, 0, NULL, 0,
  314                 CTL_KERN, KERN_SYSVIPC, CTL_EOL);
  315 
  316         sysctl_createv(clog, 0, NULL, NULL,
  317                 CTLFLAG_PERMANENT,
  318                 CTLTYPE_STRUCT, "sysvipc_info",
  319                 SYSCTL_DESCR("System V style IPC information"),
  320                 sysctl_kern_sysvipc, 0, NULL, 0,
  321                 CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_INFO, CTL_EOL);
  322 }

Cache object: b8e956f1ca2d2bd13a1d0cd972a39dc1


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