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/ipc/msgutil.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 /*
    2  * linux/ipc/msgutil.c
    3  * Copyright (C) 1999, 2004 Manfred Spraul
    4  *
    5  * This file is released under GNU General Public Licence version 2 or
    6  * (at your option) any later version.
    7  *
    8  * See the file COPYING for more details.
    9  */
   10 
   11 #include <linux/spinlock.h>
   12 #include <linux/init.h>
   13 #include <linux/security.h>
   14 #include <linux/slab.h>
   15 #include <linux/ipc.h>
   16 #include <linux/msg.h>
   17 #include <linux/ipc_namespace.h>
   18 #include <linux/utsname.h>
   19 #include <linux/proc_fs.h>
   20 #include <asm/uaccess.h>
   21 
   22 #include "util.h"
   23 
   24 DEFINE_SPINLOCK(mq_lock);
   25 
   26 /*
   27  * The next 2 defines are here bc this is the only file
   28  * compiled when either CONFIG_SYSVIPC and CONFIG_POSIX_MQUEUE
   29  * and not CONFIG_IPC_NS.
   30  */
   31 struct ipc_namespace init_ipc_ns = {
   32         .count          = ATOMIC_INIT(1),
   33         .user_ns = &init_user_ns,
   34         .proc_inum = PROC_IPC_INIT_INO,
   35 };
   36 
   37 atomic_t nr_ipc_ns = ATOMIC_INIT(1);
   38 
   39 struct msg_msgseg {
   40         struct msg_msgseg* next;
   41         /* the next part of the message follows immediately */
   42 };
   43 
   44 #define DATALEN_MSG     (PAGE_SIZE-sizeof(struct msg_msg))
   45 #define DATALEN_SEG     (PAGE_SIZE-sizeof(struct msg_msgseg))
   46 
   47 struct msg_msg *load_msg(const void __user *src, int len)
   48 {
   49         struct msg_msg *msg;
   50         struct msg_msgseg **pseg;
   51         int err;
   52         int alen;
   53 
   54         alen = len;
   55         if (alen > DATALEN_MSG)
   56                 alen = DATALEN_MSG;
   57 
   58         msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
   59         if (msg == NULL)
   60                 return ERR_PTR(-ENOMEM);
   61 
   62         msg->next = NULL;
   63         msg->security = NULL;
   64 
   65         if (copy_from_user(msg + 1, src, alen)) {
   66                 err = -EFAULT;
   67                 goto out_err;
   68         }
   69 
   70         len -= alen;
   71         src = ((char __user *)src) + alen;
   72         pseg = &msg->next;
   73         while (len > 0) {
   74                 struct msg_msgseg *seg;
   75                 alen = len;
   76                 if (alen > DATALEN_SEG)
   77                         alen = DATALEN_SEG;
   78                 seg = kmalloc(sizeof(*seg) + alen,
   79                                                  GFP_KERNEL);
   80                 if (seg == NULL) {
   81                         err = -ENOMEM;
   82                         goto out_err;
   83                 }
   84                 *pseg = seg;
   85                 seg->next = NULL;
   86                 if (copy_from_user(seg + 1, src, alen)) {
   87                         err = -EFAULT;
   88                         goto out_err;
   89                 }
   90                 pseg = &seg->next;
   91                 len -= alen;
   92                 src = ((char __user *)src) + alen;
   93         }
   94 
   95         err = security_msg_msg_alloc(msg);
   96         if (err)
   97                 goto out_err;
   98 
   99         return msg;
  100 
  101 out_err:
  102         free_msg(msg);
  103         return ERR_PTR(err);
  104 }
  105 #ifdef CONFIG_CHECKPOINT_RESTORE
  106 struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
  107 {
  108         struct msg_msgseg *dst_pseg, *src_pseg;
  109         int len = src->m_ts;
  110         int alen;
  111 
  112         BUG_ON(dst == NULL);
  113         if (src->m_ts > dst->m_ts)
  114                 return ERR_PTR(-EINVAL);
  115 
  116         alen = len;
  117         if (alen > DATALEN_MSG)
  118                 alen = DATALEN_MSG;
  119 
  120         dst->next = NULL;
  121         dst->security = NULL;
  122 
  123         memcpy(dst + 1, src + 1, alen);
  124 
  125         len -= alen;
  126         dst_pseg = dst->next;
  127         src_pseg = src->next;
  128         while (len > 0) {
  129                 alen = len;
  130                 if (alen > DATALEN_SEG)
  131                         alen = DATALEN_SEG;
  132                 memcpy(dst_pseg + 1, src_pseg + 1, alen);
  133                 dst_pseg = dst_pseg->next;
  134                 len -= alen;
  135                 src_pseg = src_pseg->next;
  136         }
  137 
  138         dst->m_type = src->m_type;
  139         dst->m_ts = src->m_ts;
  140 
  141         return dst;
  142 }
  143 #else
  144 struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
  145 {
  146         return ERR_PTR(-ENOSYS);
  147 }
  148 #endif
  149 int store_msg(void __user *dest, struct msg_msg *msg, int len)
  150 {
  151         int alen;
  152         struct msg_msgseg *seg;
  153 
  154         alen = len;
  155         if (alen > DATALEN_MSG)
  156                 alen = DATALEN_MSG;
  157         if (copy_to_user(dest, msg + 1, alen))
  158                 return -1;
  159 
  160         len -= alen;
  161         dest = ((char __user *)dest) + alen;
  162         seg = msg->next;
  163         while (len > 0) {
  164                 alen = len;
  165                 if (alen > DATALEN_SEG)
  166                         alen = DATALEN_SEG;
  167                 if (copy_to_user(dest, seg + 1, alen))
  168                         return -1;
  169                 len -= alen;
  170                 dest = ((char __user *)dest) + alen;
  171                 seg = seg->next;
  172         }
  173         return 0;
  174 }
  175 
  176 void free_msg(struct msg_msg *msg)
  177 {
  178         struct msg_msgseg *seg;
  179 
  180         security_msg_msg_free(msg);
  181 
  182         seg = msg->next;
  183         kfree(msg);
  184         while (seg != NULL) {
  185                 struct msg_msgseg *tmp = seg->next;
  186                 kfree(seg);
  187                 seg = tmp;
  188         }
  189 }

Cache object: 8859881b27512f86816c1a82cb5f6404


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