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/osfmk/ipc/ipc_kmsg.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  * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /*
   29  * @OSF_COPYRIGHT@
   30  */
   31 /* 
   32  * Mach Operating System
   33  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
   34  * All Rights Reserved.
   35  * 
   36  * Permission to use, copy, modify and distribute this software and its
   37  * documentation is hereby granted, provided that both the copyright
   38  * notice and this permission notice appear in all copies of the
   39  * software, derivative works or modified versions, and any portions
   40  * thereof, and that both notices appear in supporting documentation.
   41  * 
   42  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   43  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   44  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   45  * 
   46  * Carnegie Mellon requests users of this software to return to
   47  * 
   48  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   49  *  School of Computer Science
   50  *  Carnegie Mellon University
   51  *  Pittsburgh PA 15213-3890
   52  * 
   53  * any improvements or extensions that they make and grant Carnegie Mellon
   54  * the rights to redistribute these changes.
   55  */
   56 /*
   57  * NOTICE: This file was modified by McAfee Research in 2004 to introduce
   58  * support for mandatory and extensible security protections.  This notice
   59  * is included in support of clause 2.2 (b) of the Apple Public License,
   60  * Version 2.0.
   61  * Copyright (c) 2005 SPARTA, Inc.
   62  */
   63 /*
   64  */
   65 /*
   66  *      File:   ipc/ipc_kmsg.c
   67  *      Author: Rich Draves
   68  *      Date:   1989
   69  *
   70  *      Operations on kernel messages.
   71  */
   72 
   73 #include <norma_vm.h>
   74 
   75 #include <mach/mach_types.h>
   76 #include <mach/boolean.h>
   77 #include <mach/kern_return.h>
   78 #include <mach/message.h>
   79 #include <mach/port.h>
   80 #include <mach/vm_map.h>
   81 #include <mach/mach_vm.h>
   82 #include <mach/vm_statistics.h>
   83 
   84 #include <kern/kern_types.h>
   85 #include <kern/assert.h>
   86 #include <kern/debug.h>
   87 #include <kern/ipc_kobject.h>
   88 #include <kern/kalloc.h>
   89 #include <kern/zalloc.h>
   90 #include <kern/processor.h>
   91 #include <kern/thread.h>
   92 #include <kern/sched_prim.h>
   93 #include <kern/spl.h>
   94 #include <kern/misc_protos.h>
   95 #include <kern/counters.h>
   96 #include <kern/cpu_data.h>
   97 
   98 #include <machine/machlimits.h>
   99 
  100 #include <vm/vm_map.h>
  101 #include <vm/vm_object.h>
  102 #include <vm/vm_kern.h>
  103 
  104 #include <ipc/port.h>
  105 #include <ipc/ipc_types.h>
  106 #include <ipc/ipc_entry.h>
  107 #include <ipc/ipc_kmsg.h>
  108 #include <ipc/ipc_notify.h>
  109 #include <ipc/ipc_object.h>
  110 #include <ipc/ipc_space.h>
  111 #include <ipc/ipc_port.h>
  112 #include <ipc/ipc_right.h>
  113 #include <ipc/ipc_hash.h>
  114 #include <ipc/ipc_table.h>
  115 
  116 #include <security/mac_mach_internal.h>
  117 
  118 #include <string.h>
  119 
  120 #ifdef ppc
  121 #include <ppc/Firmware.h>
  122 #include <ppc/low_trace.h>
  123 #endif
  124 
  125 #if DEBUG
  126 #define DEBUG_MSGS_K64 1
  127 #endif
  128 
  129 #pragma pack(4)
  130 
  131 typedef struct 
  132 {
  133   mach_msg_bits_t       msgh_bits;
  134   mach_msg_size_t       msgh_size;
  135   uint32_t              msgh_remote_port;
  136   uint32_t              msgh_local_port;
  137   mach_msg_size_t       msgh_reserved;
  138   mach_msg_id_t         msgh_id;
  139 } mach_msg_legacy_header_t;
  140 
  141 typedef struct
  142 {
  143         mach_msg_legacy_header_t       header;
  144         mach_msg_body_t         body;
  145 } mach_msg_legacy_base_t;
  146 
  147 typedef struct
  148 {
  149   mach_port_name_t                              name;
  150   mach_msg_size_t                               pad1;
  151   uint32_t                                              pad2 : 16;
  152   mach_msg_type_name_t                  disposition : 8;
  153   mach_msg_descriptor_type_t    type : 8;
  154 } mach_msg_legacy_port_descriptor_t;
  155 
  156 
  157 typedef union
  158 {
  159   mach_msg_legacy_port_descriptor_t                     port;
  160   mach_msg_ool_descriptor32_t           out_of_line32;
  161   mach_msg_ool_ports_descriptor32_t     ool_ports32;
  162   mach_msg_type_descriptor_t                    type;
  163 } mach_msg_legacy_descriptor_t;
  164 
  165 #pragma pack()
  166 
  167 #define LEGACY_HEADER_SIZE_DELTA ((mach_msg_size_t)(sizeof(mach_msg_header_t) - sizeof(mach_msg_legacy_header_t)))
  168 // END LP64 fixes
  169 
  170 
  171 #if DEBUG_MSGS_K64
  172 extern void ipc_pset_print64(
  173                         ipc_pset_t      pset);
  174 
  175 extern void     ipc_kmsg_print64(
  176                         ipc_kmsg_t      kmsg,
  177                         const char      *str);
  178 
  179 extern void     ipc_msg_print64(
  180                 mach_msg_header_t       *msgh);
  181 
  182 extern ipc_port_t ipc_name_to_data64(
  183                         task_t                  task,
  184                         mach_port_name_t        name);
  185 
  186 /*
  187  * Forward declarations
  188  */
  189 void ipc_msg_print_untyped64(
  190         mach_msg_body_t         *body);
  191 
  192 const char * ipc_type_name64(
  193         int             type_name,
  194         boolean_t       received);
  195 
  196 void ipc_print_type_name64(
  197         int     type_name);
  198 
  199 const char *
  200 msgh_bit_decode64(
  201         mach_msg_bits_t bit);
  202 
  203 const char *
  204 mm_copy_options_string64(
  205         mach_msg_copy_options_t option);
  206 
  207 void db_print_msg_uid64(mach_msg_header_t *);
  208 
  209 static void
  210 ipc_msg_body_print64(void *body, int size)
  211 {
  212         uint32_t        *word = (uint32_t *) body;
  213         uint32_t        *end  = (uint32_t *)(((uintptr_t) body) + size
  214                                                 - sizeof(mach_msg_header_t));
  215         int             i;
  216 
  217         kprintf("  body(%p-%p):\n    %p: ", body, end, word);
  218         for (;;) {
  219                 for (i = 0; i < 8; i++, word++) {
  220                         if (word >= end) {
  221                                 kprintf("\n");
  222                                 return;
  223                         }
  224                         kprintf("%08x ", *word); 
  225                 }
  226                 kprintf("\n    %p: ", word);
  227         }
  228 }
  229 
  230 
  231 const char *
  232 ipc_type_name64(
  233         int             type_name,
  234         boolean_t       received)
  235 {
  236         switch (type_name) {
  237                 case MACH_MSG_TYPE_PORT_NAME:
  238                 return "port_name";
  239                 
  240                 case MACH_MSG_TYPE_MOVE_RECEIVE:
  241                 if (received) {
  242                         return "port_receive";
  243                 } else {
  244                         return "move_receive";
  245                 }
  246                 
  247                 case MACH_MSG_TYPE_MOVE_SEND:
  248                 if (received) {
  249                         return "port_send";
  250                 } else {
  251                         return "move_send";
  252                 }
  253                 
  254                 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
  255                 if (received) {
  256                         return "port_send_once";
  257                 } else {
  258                         return "move_send_once";
  259                 }
  260                 
  261                 case MACH_MSG_TYPE_COPY_SEND:
  262                 return "copy_send";
  263                 
  264                 case MACH_MSG_TYPE_MAKE_SEND:
  265                 return "make_send";
  266                 
  267                 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
  268                 return "make_send_once";
  269                 
  270                 default:
  271                 return (char *) 0;
  272         }
  273 }
  274                 
  275 void
  276 ipc_print_type_name64(
  277         int     type_name)
  278 {
  279         const char *name = ipc_type_name64(type_name, TRUE);
  280         if (name) {
  281                 kprintf("%s", name);
  282         } else {
  283                 kprintf("type%d", type_name);
  284         }
  285 }
  286 
  287 /*
  288  * ipc_kmsg_print64     [ debug ]
  289  */
  290 void
  291 ipc_kmsg_print64(
  292         ipc_kmsg_t      kmsg,
  293         const char      *str)
  294 {
  295         kprintf("%s kmsg=%p:\n", str, kmsg);
  296         kprintf("  next=%p, prev=%p, size=%d",
  297                 kmsg->ikm_next,
  298                 kmsg->ikm_prev,
  299                 kmsg->ikm_size);
  300         kprintf("\n");
  301         ipc_msg_print64(kmsg->ikm_header);
  302 }
  303 
  304 const char *
  305 msgh_bit_decode64(
  306         mach_msg_bits_t bit)
  307 {
  308         switch (bit) {
  309             case MACH_MSGH_BITS_COMPLEX:        return "complex";
  310             case MACH_MSGH_BITS_CIRCULAR:       return "circular";
  311             default:                            return (char *) 0;
  312         }
  313 }
  314 
  315 /*
  316  * ipc_msg_print64      [ debug ]
  317  */
  318 void
  319 ipc_msg_print64(
  320         mach_msg_header_t       *msgh)
  321 {
  322         mach_msg_bits_t mbits;
  323         unsigned int    bit, i;
  324         const char      *bit_name;
  325         int             needs_comma;
  326 
  327         mbits = msgh->msgh_bits;
  328         kprintf("  msgh_bits=0x%x: l=0x%x,r=0x%x\n",
  329                 mbits,
  330                 MACH_MSGH_BITS_LOCAL(msgh->msgh_bits),
  331                 MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
  332 
  333         mbits = MACH_MSGH_BITS_OTHER(mbits) & MACH_MSGH_BITS_USED;
  334         kprintf("  decoded bits:  ");
  335         needs_comma = 0;
  336         for (i = 0, bit = 1; i < sizeof(mbits) * 8; ++i, bit <<= 1) {
  337                 if ((mbits & bit) == 0)
  338                         continue;
  339                 bit_name = msgh_bit_decode64((mach_msg_bits_t)bit);
  340                 if (bit_name)
  341                         kprintf("%s%s", needs_comma ? "," : "", bit_name);
  342                 else
  343                         kprintf("%sunknown(0x%x),", needs_comma ? "," : "", bit);
  344                 ++needs_comma;
  345         }
  346         if (msgh->msgh_bits & ~MACH_MSGH_BITS_USED) {
  347                 kprintf("%sunused=0x%x,", needs_comma ? "," : "",
  348                        msgh->msgh_bits & ~MACH_MSGH_BITS_USED);
  349         }
  350         kprintf("\n");
  351 
  352         needs_comma = 1;
  353         if (msgh->msgh_remote_port) {
  354                 kprintf("  remote=%p(", msgh->msgh_remote_port);
  355                 ipc_print_type_name64(MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
  356                 kprintf(")");
  357         } else {
  358                 kprintf("  remote=null");
  359         }
  360 
  361         if (msgh->msgh_local_port) {
  362                 kprintf("%slocal=%p(", needs_comma ? "," : "",
  363                        msgh->msgh_local_port);
  364                 ipc_print_type_name64(MACH_MSGH_BITS_LOCAL(msgh->msgh_bits));
  365                 kprintf(")\n");
  366         } else {
  367                 kprintf("local=null\n");
  368         }
  369 
  370         kprintf("  msgh_id=%d, size=%d\n",
  371                 msgh->msgh_id,
  372                 msgh->msgh_size);
  373 
  374         if (mbits & MACH_MSGH_BITS_COMPLEX) {   
  375                 ipc_msg_print_untyped64((mach_msg_body_t *) (msgh + 1));
  376         }
  377 
  378         ipc_msg_body_print64((void *)(msgh + 1), msgh->msgh_size);
  379 }
  380 
  381 
  382 const char *
  383 mm_copy_options_string64(
  384         mach_msg_copy_options_t option)
  385 {
  386         const char      *name;
  387 
  388         switch (option) {
  389             case MACH_MSG_PHYSICAL_COPY:
  390                 name = "PHYSICAL";
  391                 break;
  392             case MACH_MSG_VIRTUAL_COPY:
  393                 name = "VIRTUAL";
  394                 break;
  395             case MACH_MSG_OVERWRITE:
  396                 name = "OVERWRITE";
  397                 break;
  398             case MACH_MSG_ALLOCATE:
  399                 name = "ALLOCATE";
  400                 break;
  401             case MACH_MSG_KALLOC_COPY_T:
  402                 name = "KALLOC_COPY_T";
  403                 break;
  404             default:
  405                 name = "unknown";
  406                 break;
  407         }
  408         return name;
  409 }
  410 
  411 void
  412 ipc_msg_print_untyped64(
  413         mach_msg_body_t         *body)
  414 {
  415     mach_msg_descriptor_t       *saddr, *send;
  416     mach_msg_descriptor_type_t  type;
  417 
  418     kprintf("  %d descriptors: \n", body->msgh_descriptor_count);
  419 
  420     saddr = (mach_msg_descriptor_t *) (body + 1);
  421     send = saddr + body->msgh_descriptor_count;
  422 
  423     for ( ; saddr < send; saddr++ ) {
  424         
  425         type = saddr->type.type;
  426 
  427         switch (type) {
  428             
  429             case MACH_MSG_PORT_DESCRIPTOR: {
  430                 mach_msg_port_descriptor_t *dsc;
  431 
  432                 dsc = &saddr->port;
  433                 kprintf("    PORT name = %p disp = ", dsc->name);
  434                 ipc_print_type_name64(dsc->disposition);
  435                 kprintf("\n");
  436                 break;
  437             }
  438             case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
  439             case MACH_MSG_OOL_DESCRIPTOR: {
  440                 mach_msg_ool_descriptor_t *dsc;
  441                 
  442                 dsc = (mach_msg_ool_descriptor_t *) &saddr->out_of_line;
  443                 kprintf("    OOL%s addr = %p size = 0x%x copy = %s %s\n",
  444                         type == MACH_MSG_OOL_DESCRIPTOR ? "" : " VOLATILE",
  445                         dsc->address, dsc->size,
  446                         mm_copy_options_string64(dsc->copy),
  447                         dsc->deallocate ? "DEALLOC" : "");
  448                 break;
  449             } 
  450             case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
  451                 mach_msg_ool_ports_descriptor_t *dsc;
  452 
  453                 dsc = (mach_msg_ool_ports_descriptor_t *) &saddr->ool_ports;
  454 
  455                 kprintf("    OOL_PORTS addr = %p count = 0x%x ",
  456                           dsc->address, dsc->count);
  457                 kprintf("disp = ");
  458                 ipc_print_type_name64(dsc->disposition);
  459                 kprintf(" copy = %s %s\n",
  460                        mm_copy_options_string64(dsc->copy),
  461                        dsc->deallocate ? "DEALLOC" : "");
  462                 break;
  463             }
  464 
  465             default: {
  466                 kprintf("    UNKNOWN DESCRIPTOR 0x%x\n", type);
  467                 break;
  468             }
  469         }
  470     }
  471 }
  472 
  473 #define DEBUG_IPC_KMSG_PRINT(kmsg,string)       \
  474         if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {    \
  475                 ipc_kmsg_print64(kmsg, string); \
  476         }
  477 #define DEBUG_IPC_MSG_BODY_PRINT(body,size)     \
  478         if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {    \
  479                 ipc_msg_body_print64(body,size);\
  480         }
  481 #else /* !DEBUG_MSGS_K64 */
  482 #define DEBUG_IPC_KMSG_PRINT(kmsg,string)
  483 #define DEBUG_IPC_MSG_BODY_PRINT(body,size)
  484 #endif  /* !DEBUG_MSGS_K64 */
  485 
  486 extern vm_map_t         ipc_kernel_copy_map;
  487 extern vm_size_t        ipc_kmsg_max_vm_space;
  488 extern vm_size_t        msg_ool_size_small;
  489 
  490 #define MSG_OOL_SIZE_SMALL      msg_ool_size_small
  491 
  492 #if defined(__LP64__)
  493 #define MAP_SIZE_DIFFERS(map)   (map->max_offset < MACH_VM_MAX_ADDRESS)
  494 #define OTHER_OOL_DESCRIPTOR    mach_msg_ool_descriptor32_t
  495 #define OTHER_OOL_PORTS_DESCRIPTOR      mach_msg_ool_ports_descriptor32_t
  496 #else
  497 #define MAP_SIZE_DIFFERS(map)   (map->max_offset > VM_MAX_ADDRESS)
  498 #define OTHER_OOL_DESCRIPTOR    mach_msg_ool_descriptor64_t
  499 #define OTHER_OOL_PORTS_DESCRIPTOR      mach_msg_ool_ports_descriptor64_t
  500 #endif
  501 
  502 #define DESC_SIZE_ADJUSTMENT    ((mach_msg_size_t)(sizeof(mach_msg_ool_descriptor64_t) - \
  503                                  sizeof(mach_msg_ool_descriptor32_t)))
  504 
  505 /* scatter list macros */
  506 
  507 #define SKIP_PORT_DESCRIPTORS(s, c)                                     \
  508 MACRO_BEGIN                                                             \
  509         if ((s) != MACH_MSG_DESCRIPTOR_NULL) {                          \
  510                 while ((c) > 0) {                                       \
  511                         if ((s)->type.type != MACH_MSG_PORT_DESCRIPTOR) \
  512                                 break;                                  \
  513                         (s)++; (c)--;                                   \
  514                 }                                                       \
  515                 if (c == 0)                                             \
  516                         (s) = MACH_MSG_DESCRIPTOR_NULL;                 \
  517         }                                                               \
  518 MACRO_END
  519 
  520 #define INCREMENT_SCATTER(s, c, d)                                      \
  521 MACRO_BEGIN                                                             \
  522         if ((s) != MACH_MSG_DESCRIPTOR_NULL) {                          \
  523             s = (d) ? (mach_msg_descriptor_t *)                         \
  524                 ((OTHER_OOL_DESCRIPTOR *)(s) + 1) :                     \
  525                 (s + 1);                                                \
  526                 (c)--;                                                  \
  527         }                                                               \
  528 MACRO_END
  529 
  530 /* zone for cached ipc_kmsg_t structures */
  531 zone_t                  ipc_kmsg_zone;
  532 
  533 /*
  534  * Forward declarations
  535  */
  536 
  537 void ipc_kmsg_clean(
  538         ipc_kmsg_t      kmsg);
  539 
  540 void ipc_kmsg_clean_body(
  541         ipc_kmsg_t      kmsg,
  542         mach_msg_type_number_t  number,
  543         mach_msg_descriptor_t   *desc);
  544 
  545 void ipc_kmsg_clean_partial(
  546         ipc_kmsg_t              kmsg,
  547         mach_msg_type_number_t  number,
  548         mach_msg_descriptor_t   *desc,
  549         vm_offset_t             paddr,
  550         vm_size_t               length);
  551 
  552 mach_msg_return_t ipc_kmsg_copyin_body(
  553         ipc_kmsg_t              kmsg,
  554         ipc_space_t             space,
  555         vm_map_t                map);
  556 
  557 /*
  558  *      We keep a per-processor cache of kernel message buffers.
  559  *      The cache saves the overhead/locking of using kalloc/kfree.
  560  *      The per-processor cache seems to miss less than a per-thread cache,
  561  *      and it also uses less memory.  Access to the cache doesn't
  562  *      require locking.
  563  */
  564 
  565 /*
  566  *      Routine:        ipc_kmsg_alloc
  567  *      Purpose:
  568  *              Allocate a kernel message structure.  If we can get one from
  569  *              the cache, that is best.  Otherwise, allocate a new one.
  570  *      Conditions:
  571  *              Nothing locked.
  572  */
  573 ipc_kmsg_t
  574 ipc_kmsg_alloc(
  575         mach_msg_size_t msg_and_trailer_size)
  576 {
  577         mach_msg_size_t max_expanded_size;
  578         ipc_kmsg_t kmsg;
  579 
  580         /*
  581          * LP64support -
  582          * Pad the allocation in case we need to expand the
  583          * message descrptors for user spaces with pointers larger than
  584          * the kernel's own, or vice versa.  We don't know how many descriptors
  585          * there are yet, so just assume the whole body could be
  586          * descriptors (if there could be any at all).
  587          *
  588          * The expansion space is left in front of the header,
  589          * because it is easier to pull the header and descriptors
  590          * forward as we process them than it is to push all the
  591          * data backwards.
  592          */
  593         mach_msg_size_t size = msg_and_trailer_size - MAX_TRAILER_SIZE;
  594         if (size > sizeof(mach_msg_base_t)) {
  595                 mach_msg_size_t max_desc = (mach_msg_size_t)(((size - sizeof(mach_msg_base_t)) /
  596                                            sizeof(mach_msg_ool_descriptor32_t)) *
  597                                            DESC_SIZE_ADJUSTMENT);
  598                 if (msg_and_trailer_size >= MACH_MSG_SIZE_MAX - max_desc)
  599                         return IKM_NULL;
  600 
  601                 max_expanded_size = msg_and_trailer_size + max_desc;
  602         } else
  603                 max_expanded_size = msg_and_trailer_size;
  604 
  605         if (max_expanded_size > ikm_less_overhead(MACH_MSG_SIZE_MAX))
  606                 return IKM_NULL;
  607         else if (max_expanded_size < IKM_SAVED_MSG_SIZE)
  608                 max_expanded_size = IKM_SAVED_MSG_SIZE;         /* round up for ikm_cache */
  609 
  610         if (max_expanded_size == IKM_SAVED_MSG_SIZE) {
  611                 struct ikm_cache        *cache;
  612                 unsigned int            i;
  613 
  614                 disable_preemption();
  615                 cache = &PROCESSOR_DATA(current_processor(), ikm_cache);
  616                 if ((i = cache->avail) > 0) {
  617                         assert(i <= IKM_STASH);
  618                         kmsg = cache->entries[--i];
  619                         cache->avail = i;
  620                         ikm_check_init(kmsg, max_expanded_size);
  621                         enable_preemption();
  622                         kmsg->ikm_header = (mach_msg_header_t *)
  623                                            ((vm_offset_t)(kmsg + 1) +
  624                                             max_expanded_size -
  625                                             msg_and_trailer_size);
  626                         return (kmsg);
  627                 }
  628                 enable_preemption();
  629                 kmsg = (ipc_kmsg_t)zalloc(ipc_kmsg_zone);
  630         } else {
  631                 kmsg = (ipc_kmsg_t)kalloc(ikm_plus_overhead(max_expanded_size));
  632         }
  633 
  634         if (kmsg != IKM_NULL) {
  635                 ikm_init(kmsg, max_expanded_size);
  636                 kmsg->ikm_header = (mach_msg_header_t *)
  637                                    ((vm_offset_t)(kmsg + 1) +
  638                                     max_expanded_size -
  639                                     msg_and_trailer_size);
  640         }
  641 
  642         return(kmsg);
  643 }
  644 
  645 /*
  646  *      Routine:        ipc_kmsg_free
  647  *      Purpose:
  648  *              Free a kernel message buffer.  If the kms is preallocated
  649  *              to a port, just "put it back (marked unused)."  We have to
  650  *              do this with the port locked.  The port may have its hold
  651  *              on our message released.  In that case, we have to just
  652  *              revert the message to a traditional one and free it normally.
  653  *      Conditions:
  654  *              Nothing locked.
  655  */
  656 
  657 void
  658 ipc_kmsg_free(
  659         ipc_kmsg_t      kmsg)
  660 {
  661         mach_msg_size_t size = kmsg->ikm_size;
  662         ipc_port_t port;
  663 
  664 #if CONFIG_MACF_MACH
  665         if (kmsg->ikm_sender != NULL) {
  666                 task_deallocate(kmsg->ikm_sender);
  667                 kmsg->ikm_sender = NULL;
  668         }
  669 #endif
  670 
  671         /*
  672          * Check to see if the message is bound to the port.  If so,
  673          * mark it not in use.  If the port isn't already dead, then
  674          * leave the message associated with it.  Otherwise, free it.
  675          */
  676         port = ikm_prealloc_inuse_port(kmsg);
  677         if (port != IP_NULL) {
  678                 ip_lock(port);
  679                 ikm_prealloc_clear_inuse(kmsg, port);
  680                 if (ip_active(port) && (port->ip_premsg == kmsg)) {
  681                         assert(IP_PREALLOC(port));
  682                         ip_unlock(port);
  683                         return;
  684                 }
  685                 ip_check_unlock(port);  /* May be last reference */
  686         }
  687 
  688         /*
  689          * Peek and see if it has to go back in the cache.
  690          */
  691         if (kmsg->ikm_size == IKM_SAVED_MSG_SIZE) {
  692                 struct ikm_cache        *cache;
  693                 unsigned int            i;
  694 
  695                 disable_preemption();
  696                 cache = &PROCESSOR_DATA(current_processor(), ikm_cache);
  697                 if ((i = cache->avail) < IKM_STASH) {
  698                         cache->entries[i] = kmsg;
  699                         cache->avail = i + 1;
  700                         enable_preemption();
  701                         return;
  702                 }
  703                 enable_preemption();
  704                 zfree(ipc_kmsg_zone, kmsg);
  705                 return;
  706         }
  707         kfree(kmsg, ikm_plus_overhead(size));
  708 }
  709 
  710 
  711 /*
  712  *      Routine:        ipc_kmsg_enqueue
  713  *      Purpose:
  714  *              Enqueue a kmsg.
  715  */
  716 
  717 void
  718 ipc_kmsg_enqueue(
  719         ipc_kmsg_queue_t        queue,
  720         ipc_kmsg_t              kmsg)
  721 {
  722         ipc_kmsg_enqueue_macro(queue, kmsg);
  723 }
  724 
  725 /*
  726  *      Routine:        ipc_kmsg_dequeue
  727  *      Purpose:
  728  *              Dequeue and return a kmsg.
  729  */
  730 
  731 ipc_kmsg_t
  732 ipc_kmsg_dequeue(
  733         ipc_kmsg_queue_t        queue)
  734 {
  735         ipc_kmsg_t first;
  736 
  737         first = ipc_kmsg_queue_first(queue);
  738 
  739         if (first != IKM_NULL)
  740                 ipc_kmsg_rmqueue_first_macro(queue, first);
  741 
  742         return first;
  743 }
  744 
  745 /*
  746  *      Routine:        ipc_kmsg_rmqueue
  747  *      Purpose:
  748  *              Pull a kmsg out of a queue.
  749  */
  750 
  751 void
  752 ipc_kmsg_rmqueue(
  753         ipc_kmsg_queue_t        queue,
  754         ipc_kmsg_t              kmsg)
  755 {
  756         ipc_kmsg_t next, prev;
  757 
  758         assert(queue->ikmq_base != IKM_NULL);
  759 
  760         next = kmsg->ikm_next;
  761         prev = kmsg->ikm_prev;
  762 
  763         if (next == kmsg) {
  764                 assert(prev == kmsg);
  765                 assert(queue->ikmq_base == kmsg);
  766 
  767                 queue->ikmq_base = IKM_NULL;
  768         } else {
  769                 if (queue->ikmq_base == kmsg)
  770                         queue->ikmq_base = next;
  771 
  772                 next->ikm_prev = prev;
  773                 prev->ikm_next = next;
  774         }
  775         /* XXX Temporary debug logic */
  776         assert((kmsg->ikm_next = IKM_BOGUS) == IKM_BOGUS);
  777         assert((kmsg->ikm_prev = IKM_BOGUS) == IKM_BOGUS);
  778 }
  779 
  780 /*
  781  *      Routine:        ipc_kmsg_queue_next
  782  *      Purpose:
  783  *              Return the kmsg following the given kmsg.
  784  *              (Or IKM_NULL if it is the last one in the queue.)
  785  */
  786 
  787 ipc_kmsg_t
  788 ipc_kmsg_queue_next(
  789         ipc_kmsg_queue_t        queue,
  790         ipc_kmsg_t              kmsg)
  791 {
  792         ipc_kmsg_t next;
  793 
  794         assert(queue->ikmq_base != IKM_NULL);
  795 
  796         next = kmsg->ikm_next;
  797         if (queue->ikmq_base == next)
  798                 next = IKM_NULL;
  799 
  800         return next;
  801 }
  802 
  803 /*
  804  *      Routine:        ipc_kmsg_destroy
  805  *      Purpose:
  806  *              Destroys a kernel message.  Releases all rights,
  807  *              references, and memory held by the message.
  808  *              Frees the message.
  809  *      Conditions:
  810  *              No locks held.
  811  */
  812 
  813 void
  814 ipc_kmsg_destroy(
  815         ipc_kmsg_t      kmsg)
  816 {
  817         ipc_kmsg_queue_t queue;
  818         boolean_t empty;
  819 
  820         /*
  821          *      ipc_kmsg_clean can cause more messages to be destroyed.
  822          *      Curtail recursion by queueing messages.  If a message
  823          *      is already queued, then this is a recursive call.
  824          */
  825 
  826         queue = &(current_thread()->ith_messages);
  827         empty = ipc_kmsg_queue_empty(queue);
  828         ipc_kmsg_enqueue(queue, kmsg);
  829 
  830         if (empty) {
  831                 /* must leave kmsg in queue while cleaning it */
  832 
  833                 while ((kmsg = ipc_kmsg_queue_first(queue)) != IKM_NULL) {
  834                         ipc_kmsg_clean(kmsg);
  835                         ipc_kmsg_rmqueue(queue, kmsg);
  836                         ipc_kmsg_free(kmsg);
  837                 }
  838         }
  839 }
  840 
  841 /*
  842  *      Routine:        ipc_kmsg_destroy_dest
  843  *      Purpose:
  844  *              Destroys a kernel message.  Releases all rights,
  845  *              references, and memory held by the message (including
  846  *              the destination port reference.
  847  *              Frees the message.
  848  *      Conditions:
  849  *              No locks held.
  850  */
  851 void
  852 ipc_kmsg_destroy_dest(
  853         ipc_kmsg_t kmsg)
  854 {
  855     ipc_port_t port;
  856         
  857     port = kmsg->ikm_header->msgh_remote_port;
  858 
  859     ipc_port_release(port);
  860     kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
  861     ipc_kmsg_destroy(kmsg);
  862 }
  863 
  864 /*
  865  *      Routine:        ipc_kmsg_clean_body
  866  *      Purpose:
  867  *              Cleans the body of a kernel message.
  868  *              Releases all rights, references, and memory.
  869  *
  870  *      Conditions:
  871  *              No locks held.
  872  */
  873 
  874 void
  875 ipc_kmsg_clean_body(
  876         __unused ipc_kmsg_t     kmsg,
  877         mach_msg_type_number_t  number,
  878         mach_msg_descriptor_t   *saddr)
  879 {
  880     mach_msg_type_number_t      i;
  881 
  882     if ( number == 0 )
  883         return;
  884 
  885     for (i = 0 ; i < number; i++, saddr++ ) {
  886         
  887         switch (saddr->type.type) {
  888             
  889             case MACH_MSG_PORT_DESCRIPTOR: {
  890                 mach_msg_port_descriptor_t *dsc;
  891 
  892                 dsc = &saddr->port;
  893 
  894                 /* 
  895                  * Destroy port rights carried in the message 
  896                  */
  897                 if (!IO_VALID((ipc_object_t) dsc->name))
  898                     continue;
  899                 ipc_object_destroy((ipc_object_t) dsc->name, dsc->disposition);
  900                 break;
  901             }
  902             case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
  903             case MACH_MSG_OOL_DESCRIPTOR : {
  904                 mach_msg_ool_descriptor_t *dsc;
  905 
  906                 dsc = (mach_msg_ool_descriptor_t *)&saddr->out_of_line;
  907                 
  908                 /* 
  909                  * Destroy memory carried in the message 
  910                  */
  911                 if (dsc->size == 0) {
  912                         assert(dsc->address == (void *) 0);
  913                 } else {
  914                         vm_map_copy_discard((vm_map_copy_t) dsc->address);
  915                 }
  916                 break;
  917             }
  918             case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
  919                 ipc_object_t                    *objects;
  920                 mach_msg_type_number_t          j;
  921                 mach_msg_ool_ports_descriptor_t *dsc;
  922 
  923                 dsc = (mach_msg_ool_ports_descriptor_t  *)&saddr->ool_ports;
  924                 objects = (ipc_object_t *) dsc->address;
  925 
  926                 if (dsc->count == 0) {
  927                         break;
  928                 }
  929 
  930                 assert(objects != (ipc_object_t *) 0);
  931                 
  932                 /* destroy port rights carried in the message */
  933                 
  934                 for (j = 0; j < dsc->count; j++) {
  935                     ipc_object_t object = objects[j];
  936                     
  937                     if (!IO_VALID(object))
  938                         continue;
  939                     
  940                     ipc_object_destroy(object, dsc->disposition);
  941                 }
  942 
  943                 /* destroy memory carried in the message */
  944 
  945                 assert(dsc->count != 0);
  946 
  947                 kfree(dsc->address, 
  948                      (vm_size_t) dsc->count * sizeof(mach_port_t));
  949                 break;
  950             }
  951             default : {
  952                 printf("cleanup: don't understand this type of descriptor\n");
  953             }
  954         }
  955     }
  956 }
  957 
  958 /*
  959  *      Routine:        ipc_kmsg_clean_partial
  960  *      Purpose:
  961  *              Cleans a partially-acquired kernel message.
  962  *              number is the index of the type descriptor
  963  *              in the body of the message that contained the error.
  964  *              If dolast, the memory and port rights in this last
  965  *              type spec are also cleaned.  In that case, number
  966  *              specifies the number of port rights to clean.
  967  *      Conditions:
  968  *              Nothing locked.
  969  */
  970 
  971 void
  972 ipc_kmsg_clean_partial(
  973         ipc_kmsg_t              kmsg,
  974         mach_msg_type_number_t  number,
  975         mach_msg_descriptor_t   *desc,
  976         vm_offset_t             paddr,
  977         vm_size_t               length)
  978 {
  979         ipc_object_t object;
  980         mach_msg_bits_t mbits = kmsg->ikm_header->msgh_bits;
  981 
  982         object = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
  983         assert(IO_VALID(object));
  984         ipc_object_destroy(object, MACH_MSGH_BITS_REMOTE(mbits));
  985 
  986         object = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
  987         if (IO_VALID(object))
  988                 ipc_object_destroy(object, MACH_MSGH_BITS_LOCAL(mbits));
  989 
  990         if (paddr) {
  991                 (void) vm_deallocate(ipc_kernel_copy_map, paddr, length);
  992         }
  993 
  994         ipc_kmsg_clean_body(kmsg, number, desc);
  995 }
  996 
  997 /*
  998  *      Routine:        ipc_kmsg_clean
  999  *      Purpose:
 1000  *              Cleans a kernel message.  Releases all rights,
 1001  *              references, and memory held by the message.
 1002  *      Conditions:
 1003  *              No locks held.
 1004  */
 1005 
 1006 void
 1007 ipc_kmsg_clean(
 1008         ipc_kmsg_t      kmsg)
 1009 {
 1010         ipc_object_t object;
 1011         mach_msg_bits_t mbits;
 1012 
 1013         mbits = kmsg->ikm_header->msgh_bits;
 1014         object = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
 1015         if (IO_VALID(object))
 1016                 ipc_object_destroy(object, MACH_MSGH_BITS_REMOTE(mbits));
 1017 
 1018         object = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
 1019         if (IO_VALID(object))
 1020                 ipc_object_destroy(object, MACH_MSGH_BITS_LOCAL(mbits));
 1021 
 1022         if (mbits & MACH_MSGH_BITS_COMPLEX) {
 1023                 mach_msg_body_t *body;
 1024 
 1025                 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
 1026                 ipc_kmsg_clean_body(kmsg, body->msgh_descriptor_count,
 1027                                     (mach_msg_descriptor_t *)(body + 1));
 1028         }
 1029 
 1030 #if CONFIG_MACF_MACH
 1031         if (kmsg->ikm_sender != NULL) {
 1032                 task_deallocate(kmsg->ikm_sender);
 1033                 kmsg->ikm_sender = NULL;
 1034         }
 1035 #endif
 1036 }
 1037 
 1038 /*
 1039  *      Routine:        ipc_kmsg_set_prealloc
 1040  *      Purpose:
 1041  *              Assign a kmsg as a preallocated message buffer to a port.
 1042  *      Conditions:
 1043  *              port locked.
 1044  */
 1045 
 1046 void
 1047 ipc_kmsg_set_prealloc(
 1048         ipc_kmsg_t              kmsg,
 1049         ipc_port_t              port)
 1050 {
 1051         assert(kmsg->ikm_prealloc == IP_NULL);
 1052   
 1053         kmsg->ikm_prealloc = IP_NULL;
 1054         IP_SET_PREALLOC(port, kmsg);
 1055 }
 1056 
 1057 /*
 1058  *      Routine:        ipc_kmsg_clear_prealloc
 1059  *      Purpose:
 1060  *              Release the Assignment of a preallocated message buffer from a port.
 1061  *      Conditions:
 1062  *              port locked.
 1063  */
 1064 void
 1065 ipc_kmsg_clear_prealloc(
 1066         ipc_kmsg_t              kmsg,
 1067         ipc_port_t              port)
 1068 {
 1069         assert(kmsg->ikm_prealloc == port);
 1070   
 1071         kmsg->ikm_prealloc = IP_NULL;
 1072         IP_CLEAR_PREALLOC(port, kmsg);
 1073 }
 1074 
 1075 
 1076 
 1077 /*
 1078  *      Routine:        ipc_kmsg_get
 1079  *      Purpose:
 1080  *              Allocates a kernel message buffer.
 1081  *              Copies a user message to the message buffer.
 1082  *      Conditions:
 1083  *              Nothing locked.
 1084  *      Returns:
 1085  *              MACH_MSG_SUCCESS        Acquired a message buffer.
 1086  *              MACH_SEND_MSG_TOO_SMALL Message smaller than a header.
 1087  *              MACH_SEND_MSG_TOO_SMALL Message size not long-word multiple.
 1088  *              MACH_SEND_NO_BUFFER     Couldn't allocate a message buffer.
 1089  *              MACH_SEND_INVALID_DATA  Couldn't copy message data.
 1090  */
 1091 
 1092 mach_msg_return_t
 1093 ipc_kmsg_get(
 1094         mach_vm_address_t       msg_addr,
 1095         mach_msg_size_t size,
 1096         ipc_kmsg_t              *kmsgp)
 1097 {
 1098         mach_msg_size_t                 msg_and_trailer_size;
 1099         ipc_kmsg_t                      kmsg;
 1100         mach_msg_max_trailer_t          *trailer;
 1101         mach_msg_legacy_base_t      legacy_base;
 1102         mach_msg_size_t             len_copied;
 1103         legacy_base.body.msgh_descriptor_count = 0;
 1104 
 1105         if ((size < sizeof(mach_msg_legacy_header_t)) || (size & 3))
 1106                 return MACH_SEND_MSG_TOO_SMALL;
 1107 
 1108         if (size > MACH_MSG_SIZE_MAX - MAX_TRAILER_SIZE)
 1109                 return MACH_SEND_TOO_LARGE;
 1110 
 1111         if(size == sizeof(mach_msg_legacy_header_t))
 1112                 len_copied = sizeof(mach_msg_legacy_header_t);
 1113         else
 1114                 len_copied = sizeof(mach_msg_legacy_base_t);
 1115 
 1116         if (copyinmsg(msg_addr, (char *)&legacy_base, len_copied))
 1117                 return MACH_SEND_INVALID_DATA;
 1118 
 1119         msg_addr += sizeof(legacy_base.header);
 1120 #if defined(__LP64__)
 1121         size += LEGACY_HEADER_SIZE_DELTA;
 1122 #endif
 1123         if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {
 1124                 unsigned int j;
 1125                 for (j=0; j<sizeof(legacy_base.header); j++) {
 1126                         kprintf("%02x\n", ((unsigned char*)&legacy_base.header)[j]);
 1127                 }
 1128         }
 1129 
 1130         msg_and_trailer_size = size + MAX_TRAILER_SIZE;
 1131         kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
 1132         if (kmsg == IKM_NULL)
 1133                 return MACH_SEND_NO_BUFFER;
 1134 
 1135         kmsg->ikm_header->msgh_size                     = size;
 1136         kmsg->ikm_header->msgh_bits                     = legacy_base.header.msgh_bits;
 1137         kmsg->ikm_header->msgh_remote_port      = CAST_MACH_NAME_TO_PORT(legacy_base.header.msgh_remote_port);
 1138         kmsg->ikm_header->msgh_local_port       = CAST_MACH_NAME_TO_PORT(legacy_base.header.msgh_local_port);
 1139         kmsg->ikm_header->msgh_reserved         = legacy_base.header.msgh_reserved;
 1140         kmsg->ikm_header->msgh_id                       = legacy_base.header.msgh_id;
 1141 
 1142         DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_get header:\n"
 1143                                                          "  size:               0x%.8x\n"
 1144                                                          "  bits:               0x%.8x\n"
 1145                                                          "  remote_port:        %p\n"
 1146                                                          "  local_port: %p\n"
 1147                                                          "  reserved:   0x%.8x\n"
 1148                                                          "  id:         %.8d\n",
 1149                                                          kmsg->ikm_header->msgh_size,
 1150                                                          kmsg->ikm_header->msgh_bits,
 1151                                                          kmsg->ikm_header->msgh_remote_port,
 1152                                                          kmsg->ikm_header->msgh_local_port,
 1153                                                          kmsg->ikm_header->msgh_reserved,
 1154                                                          kmsg->ikm_header->msgh_id);
 1155 
 1156         if (copyinmsg(msg_addr, (char *)(kmsg->ikm_header + 1), size - (mach_msg_size_t)sizeof(mach_msg_header_t))) {
 1157                 ipc_kmsg_free(kmsg);
 1158                 return MACH_SEND_INVALID_DATA;
 1159         }
 1160 
 1161         if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK))
 1162         {
 1163                 kprintf("body: size: %lu\n", (size - sizeof(mach_msg_header_t)));
 1164                 uint32_t i;
 1165                 for(i=0;i*4 < (size - sizeof(mach_msg_header_t));i++)
 1166                 {
 1167                         kprintf("%.4x\n",((uint32_t *)(kmsg->ikm_header + 1))[i]);
 1168                 }
 1169         }
 1170         DEBUG_IPC_KMSG_PRINT(kmsg, "ipc_kmsg_get()");
 1171 
 1172         /* 
 1173          * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
 1174          * However, the internal size field of the trailer (msgh_trailer_size)
 1175          * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to optimize
 1176          * the cases where no implicit data is requested.
 1177          */
 1178         trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + size);
 1179         trailer->msgh_sender = current_thread()->task->sec_token;
 1180         trailer->msgh_audit = current_thread()->task->audit_token;
 1181         trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
 1182         trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
 1183 
 1184 #ifdef ppc
 1185         if(trcWork.traceMask) dbgTrace(0x1100, (unsigned int)kmsg->ikm_header->msgh_id, 
 1186                 (unsigned int)kmsg->ikm_header->msgh_remote_port, 
 1187                 (unsigned int)kmsg->ikm_header->msgh_local_port, 0); 
 1188 #endif
 1189 
 1190 #if CONFIG_MACF_MACH
 1191         /* XXX - why do we zero sender labels here instead of in mach_msg()? */
 1192         task_t cur = current_task();
 1193         if (cur) {
 1194                 task_reference(cur);
 1195                 kmsg->ikm_sender = cur;
 1196         } else
 1197                 trailer->msgh_labels.sender = 0;
 1198 #else
 1199         trailer->msgh_labels.sender = 0;
 1200 #endif
 1201 
 1202         *kmsgp = kmsg;
 1203         return MACH_MSG_SUCCESS;
 1204 }
 1205 
 1206 /*
 1207  *      Routine:        ipc_kmsg_get_from_kernel
 1208  *      Purpose:
 1209  *              First checks for a preallocated message
 1210  *              reserved for kernel clients.  If not found -
 1211  *              allocates a new kernel message buffer.
 1212  *              Copies a kernel message to the message buffer.
 1213  *              Only resource errors are allowed.
 1214  *      Conditions:
 1215  *              Nothing locked.
 1216  *              Ports in header are ipc_port_t.
 1217  *      Returns:
 1218  *              MACH_MSG_SUCCESS        Acquired a message buffer.
 1219  *              MACH_SEND_NO_BUFFER     Couldn't allocate a message buffer.
 1220  */
 1221 
 1222 mach_msg_return_t
 1223 ipc_kmsg_get_from_kernel(
 1224         mach_msg_header_t       *msg,
 1225         mach_msg_size_t size,
 1226         ipc_kmsg_t              *kmsgp)
 1227 {
 1228         ipc_kmsg_t      kmsg;
 1229         mach_msg_size_t msg_and_trailer_size;
 1230         mach_msg_max_trailer_t *trailer;
 1231         ipc_port_t      dest_port;
 1232 
 1233         assert(size >= sizeof(mach_msg_header_t));
 1234 //      assert((size & 3) == 0);
 1235 
 1236         assert(IP_VALID((ipc_port_t) msg->msgh_remote_port));
 1237         dest_port = (ipc_port_t)msg->msgh_remote_port;
 1238 
 1239         msg_and_trailer_size = size + MAX_TRAILER_SIZE;
 1240 
 1241         /*
 1242          * See if the port has a pre-allocated kmsg for kernel
 1243          * clients.  These are set up for those kernel clients
 1244          * which cannot afford to wait.
 1245          */
 1246 #ifndef __LP64__
 1247         /* LP64todo - does the prealloc kmsg need ikm_header padding?
 1248          */
 1249         if (IP_PREALLOC(dest_port)) {
 1250                 ip_lock(dest_port);
 1251                 if (!ip_active(dest_port)) {
 1252                         ip_unlock(dest_port);
 1253                         return MACH_SEND_NO_BUFFER;
 1254                 }
 1255                 assert(IP_PREALLOC(dest_port));
 1256                 kmsg = dest_port->ip_premsg;
 1257                 if (msg_and_trailer_size > kmsg->ikm_size) {
 1258                         ip_unlock(dest_port);
 1259                         return MACH_SEND_TOO_LARGE;
 1260                 }
 1261                 if (ikm_prealloc_inuse(kmsg)) {
 1262                         ip_unlock(dest_port);
 1263                         return MACH_SEND_NO_BUFFER;
 1264                 }
 1265                 ikm_prealloc_set_inuse(kmsg, dest_port);
 1266                 ip_unlock(dest_port);
 1267         }
 1268         else
 1269 #endif /* !__LP64__ */
 1270         {
 1271                 kmsg = ipc_kmsg_alloc(msg_and_trailer_size);
 1272                 if (kmsg == IKM_NULL)
 1273                         return MACH_SEND_NO_BUFFER;
 1274         }
 1275 
 1276         (void) memcpy((void *) kmsg->ikm_header, (const void *) msg, size);
 1277 
 1278         kmsg->ikm_header->msgh_size = size;
 1279 
 1280         /* 
 1281          * I reserve for the trailer the largest space (MAX_TRAILER_SIZE)
 1282          * However, the internal size field of the trailer (msgh_trailer_size)
 1283          * is initialized to the minimum (sizeof(mach_msg_trailer_t)), to
 1284          * optimize the cases where no implicit data is requested.
 1285          */
 1286         trailer = (mach_msg_max_trailer_t *) 
 1287                   ((vm_offset_t)kmsg->ikm_header + size);
 1288         trailer->msgh_sender = KERNEL_SECURITY_TOKEN;
 1289         trailer->msgh_audit = KERNEL_AUDIT_TOKEN;
 1290         trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
 1291         trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
 1292 
 1293         trailer->msgh_labels.sender = 0;
 1294 
 1295 #if CONFIG_MACF_MACH
 1296         kmsg->ikm_sender = NULL;
 1297 #endif
 1298         *kmsgp = kmsg;
 1299         return MACH_MSG_SUCCESS;
 1300 }
 1301 
 1302 /*
 1303  *      Routine:        ipc_kmsg_send
 1304  *      Purpose:
 1305  *              Send a message.  The message holds a reference
 1306  *              for the destination port in the msgh_remote_port field.
 1307  *
 1308  *              If unsuccessful, the caller still has possession of
 1309  *              the message and must do something with it.  If successful,
 1310  *              the message is queued, given to a receiver, destroyed,
 1311  *              or handled directly by the kernel via mach_msg.
 1312  *      Conditions:
 1313  *              Nothing locked.
 1314  *      Returns:
 1315  *              MACH_MSG_SUCCESS        The message was accepted.
 1316  *              MACH_SEND_TIMED_OUT     Caller still has message.
 1317  *              MACH_SEND_INTERRUPTED   Caller still has message.
 1318  */
 1319 mach_msg_return_t
 1320 ipc_kmsg_send(
 1321         ipc_kmsg_t              kmsg,
 1322         mach_msg_option_t       option,
 1323         mach_msg_timeout_t      send_timeout)
 1324 {
 1325         ipc_port_t port;
 1326         mach_msg_return_t error = MACH_MSG_SUCCESS;
 1327         spl_t s;
 1328 
 1329         port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
 1330         assert(IP_VALID(port));
 1331 
 1332         if ((option & ~(MACH_SEND_TIMEOUT|MACH_SEND_ALWAYS)) != 0)
 1333                 printf("ipc_kmsg_send: bad option 0x%x\n", option);
 1334 
 1335         ip_lock(port);
 1336 
 1337         if (port->ip_receiver == ipc_space_kernel) {
 1338 
 1339                 /*
 1340                  *      We can check ip_receiver == ipc_space_kernel
 1341                  *      before checking that the port is active because
 1342                  *      ipc_port_dealloc_kernel clears ip_receiver
 1343                  *      before destroying a kernel port.
 1344                  */
 1345                 assert(ip_active(port));
 1346                 port->ip_messages.imq_seqno++;
 1347                 ip_unlock(port);
 1348 
 1349                 current_task()->messages_sent++;
 1350 
 1351                 /*
 1352                  * Call the server routine, and get the reply message to send.
 1353                  */
 1354                 kmsg = ipc_kobject_server(kmsg);
 1355                 if (kmsg == IKM_NULL)
 1356                         return MACH_MSG_SUCCESS;
 1357 
 1358                 port = (ipc_port_t) kmsg->ikm_header->msgh_remote_port;
 1359                 assert(IP_VALID(port));
 1360                 ip_lock(port);
 1361                 /* fall thru with reply - same options */
 1362         }
 1363 
 1364         /*
 1365          *      Can't deliver to a dead port.
 1366          *      However, we can pretend it got sent
 1367          *      and was then immediately destroyed.
 1368          */
 1369         if (!ip_active(port)) {
 1370                 /*
 1371                  *      We can't let ipc_kmsg_destroy deallocate
 1372                  *      the port right, because we might end up
 1373                  *      in an infinite loop trying to deliver
 1374                  *      a send-once notification.
 1375                  */
 1376 
 1377                 ip_release(port);
 1378                 ip_check_unlock(port);
 1379                 kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
 1380                 ipc_kmsg_destroy(kmsg);
 1381                 return MACH_MSG_SUCCESS;
 1382         }
 1383 
 1384         if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_CIRCULAR) {
 1385                 ip_unlock(port);
 1386 
 1387                 /* don't allow the creation of a circular loop */
 1388 
 1389                 ipc_kmsg_destroy(kmsg);
 1390                 return MACH_MSG_SUCCESS;
 1391         }
 1392 
 1393         /*
 1394          * We have a valid message and a valid reference on the port.
 1395          * we can unlock the port and call mqueue_send() on its message
 1396          * queue. Lock message queue while port is locked.
 1397          */
 1398         s = splsched();
 1399         imq_lock(&port->ip_messages);
 1400         ip_unlock(port);
 1401         error = ipc_mqueue_send(&port->ip_messages, kmsg, option, 
 1402                         send_timeout, s);
 1403 
 1404         /*
 1405          * If the port has been destroyed while we wait, treat the message
 1406          * as a successful delivery (like we do for an inactive port).
 1407          */
 1408         if (error == MACH_SEND_INVALID_DEST) {
 1409                 kmsg->ikm_header->msgh_remote_port = MACH_PORT_NULL;
 1410                 ipc_kmsg_destroy(kmsg);
 1411                 return MACH_MSG_SUCCESS;
 1412         }
 1413         return error;
 1414 }
 1415 
 1416 /*
 1417  *      Routine:        ipc_kmsg_put
 1418  *      Purpose:
 1419  *              Copies a message buffer to a user message.
 1420  *              Copies only the specified number of bytes.
 1421  *              Frees the message buffer.
 1422  *      Conditions:
 1423  *              Nothing locked.  The message buffer must have clean
 1424  *              header fields.
 1425  *      Returns:
 1426  *              MACH_MSG_SUCCESS        Copied data out of message buffer.
 1427  *              MACH_RCV_INVALID_DATA   Couldn't copy to user message.
 1428  */
 1429 
 1430 mach_msg_return_t
 1431 ipc_kmsg_put(
 1432         mach_vm_address_t       msg_addr,
 1433         ipc_kmsg_t              kmsg,
 1434         mach_msg_size_t         size)
 1435 {
 1436         mach_msg_return_t mr;
 1437 
 1438         DEBUG_IPC_KMSG_PRINT(kmsg, "ipc_kmsg_put()");
 1439 
 1440 
 1441         DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_put header:\n"
 1442                                                          "  size:               0x%.8x\n"
 1443                                                          "  bits:               0x%.8x\n"
 1444                                                          "  remote_port:        %p\n"
 1445                                                          "  local_port: %p\n"
 1446                                                          "  reserved:   0x%.8x\n"
 1447                                                          "  id:         %.8d\n",
 1448                                                          kmsg->ikm_header->msgh_size,
 1449                                                          kmsg->ikm_header->msgh_bits,
 1450                                                          kmsg->ikm_header->msgh_remote_port,
 1451                                                          kmsg->ikm_header->msgh_local_port,
 1452                                                          kmsg->ikm_header->msgh_reserved,
 1453                                                          kmsg->ikm_header->msgh_id);
 1454 
 1455 #if defined(__LP64__)
 1456         if (current_task() != kernel_task) { /* don't if receiver expects fully-cooked in-kernel msg; ux_exception */
 1457                 mach_msg_legacy_header_t *legacy_header = 
 1458                         (mach_msg_legacy_header_t *)((vm_offset_t)(kmsg->ikm_header) + LEGACY_HEADER_SIZE_DELTA);
 1459 
 1460                 mach_msg_bits_t         bits            = kmsg->ikm_header->msgh_bits;
 1461                 mach_msg_size_t         msg_size        = kmsg->ikm_header->msgh_size;
 1462                 mach_port_name_t        remote_port     = CAST_MACH_PORT_TO_NAME(kmsg->ikm_header->msgh_remote_port);
 1463                 mach_port_name_t        local_port      = CAST_MACH_PORT_TO_NAME(kmsg->ikm_header->msgh_local_port);
 1464                 mach_msg_size_t         reserved        = kmsg->ikm_header->msgh_reserved;
 1465                 mach_msg_id_t           id                      = kmsg->ikm_header->msgh_id;
 1466 
 1467                 legacy_header->msgh_id                  = id;
 1468                 legacy_header->msgh_reserved    = reserved;
 1469                 legacy_header->msgh_local_port  = local_port;
 1470                 legacy_header->msgh_remote_port = remote_port;
 1471                 legacy_header->msgh_size                = msg_size - LEGACY_HEADER_SIZE_DELTA;
 1472                 legacy_header->msgh_bits                = bits;
 1473 
 1474                 size -= LEGACY_HEADER_SIZE_DELTA;
 1475                 kmsg->ikm_header = (mach_msg_header_t *)legacy_header;
 1476         }
 1477 #endif
 1478 
 1479         if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK)) {
 1480                 kprintf("ipc_kmsg_put header+body: %d\n", (size));
 1481                 uint32_t i;
 1482                 for(i=0;i*4 < size;i++)
 1483                 {
 1484                         kprintf("%.4x\n",((uint32_t *)kmsg->ikm_header)[i]);
 1485                 }
 1486                 kprintf("type: %d\n", ((mach_msg_type_descriptor_t *)(((mach_msg_base_t *)kmsg->ikm_header)+1))->type);
 1487         }
 1488         if (copyoutmsg((const char *) kmsg->ikm_header, msg_addr, size))
 1489                 mr = MACH_RCV_INVALID_DATA;
 1490         else
 1491                 mr = MACH_MSG_SUCCESS;
 1492 
 1493         ipc_kmsg_free(kmsg);
 1494         return mr;
 1495 }
 1496 
 1497 /*
 1498  *      Routine:        ipc_kmsg_put_to_kernel
 1499  *      Purpose:
 1500  *              Copies a message buffer to a kernel message.
 1501  *              Frees the message buffer.
 1502  *              No errors allowed.
 1503  *      Conditions:
 1504  *              Nothing locked.
 1505  */
 1506 
 1507 void
 1508 ipc_kmsg_put_to_kernel(
 1509         mach_msg_header_t       *msg,
 1510         ipc_kmsg_t              kmsg,
 1511         mach_msg_size_t         size)
 1512 {
 1513         (void) memcpy((void *) msg, (const void *) kmsg->ikm_header, size);
 1514 
 1515         ipc_kmsg_free(kmsg);
 1516 }
 1517 
 1518 /*
 1519  *      Routine:        ipc_kmsg_copyin_header
 1520  *      Purpose:
 1521  *              "Copy-in" port rights in the header of a message.
 1522  *              Operates atomically; if it doesn't succeed the
 1523  *              message header and the space are left untouched.
 1524  *              If it does succeed the remote/local port fields
 1525  *              contain object pointers instead of port names,
 1526  *              and the bits field is updated.  The destination port
 1527  *              will be a valid port pointer.
 1528  *
 1529  *              The notify argument implements the MACH_SEND_CANCEL option.
 1530  *              If it is not MACH_PORT_NULL, it should name a receive right.
 1531  *              If the processing of the destination port would generate
 1532  *              a port-deleted notification (because the right for the
 1533  *              destination port is destroyed and it had a request for
 1534  *              a dead-name notification registered), and the port-deleted
 1535  *              notification would be sent to the named receive right,
 1536  *              then it isn't sent and the send-once right for the notify
 1537  *              port is quietly destroyed.
 1538  *
 1539  *      Conditions:
 1540  *              Nothing locked.
 1541  *      Returns:
 1542  *              MACH_MSG_SUCCESS        Successful copyin.
 1543  *              MACH_SEND_INVALID_HEADER
 1544  *                      Illegal value in the message header bits.
 1545  *              MACH_SEND_INVALID_DEST  The space is dead.
 1546  *              MACH_SEND_INVALID_NOTIFY
 1547  *                      Notify is non-null and doesn't name a receive right.
 1548  *                      (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
 1549  *              MACH_SEND_INVALID_DEST  Can't copyin destination port.
 1550  *                      (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
 1551  *              MACH_SEND_INVALID_REPLY Can't copyin reply port.
 1552  *                      (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
 1553  */
 1554 
 1555 mach_msg_return_t
 1556 ipc_kmsg_copyin_header(
 1557         mach_msg_header_t       *msg,
 1558         ipc_space_t             space,
 1559         mach_port_name_t        notify)
 1560 {
 1561         mach_msg_bits_t mbits = msg->msgh_bits & MACH_MSGH_BITS_USER;
 1562         mach_port_name_t dest_name = CAST_MACH_PORT_TO_NAME(msg->msgh_remote_port);
 1563         mach_port_name_t reply_name = CAST_MACH_PORT_TO_NAME(msg->msgh_local_port);
 1564         kern_return_t kr;
 1565 
 1566         mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
 1567         mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
 1568         ipc_object_t dest_port, reply_port;
 1569         ipc_port_t dest_soright, reply_soright;
 1570         ipc_port_t notify_port;
 1571         ipc_entry_t entry;
 1572 
 1573         if ((mbits != msg->msgh_bits) ||
 1574             (!MACH_MSG_TYPE_PORT_ANY_SEND(dest_type)) ||
 1575             ((reply_type == 0) ?
 1576              (reply_name != MACH_PORT_NULL) :
 1577              !MACH_MSG_TYPE_PORT_ANY_SEND(reply_type)))
 1578                 return MACH_SEND_INVALID_HEADER;
 1579 
 1580         reply_soright = IP_NULL; /* in case we go to invalid dest early */
 1581 
 1582         is_write_lock(space);
 1583         if (!space->is_active)
 1584                 goto invalid_dest;
 1585 
 1586         if (!MACH_PORT_VALID(dest_name))
 1587                 goto invalid_dest;
 1588 
 1589 #if CONFIG_MACF_MACH
 1590         /*
 1591          * We do the port send check here instead of in ipc_kmsg_send()
 1592          * because copying the header involves copying the port rights too
 1593          * and we need to do the send check before anything is actually copied.
 1594          */
 1595         entry = ipc_entry_lookup(space, dest_name);
 1596         if (entry != IE_NULL) {
 1597                 int error = 0;
 1598                 ipc_port_t port = (ipc_port_t) entry->ie_object;
 1599                 if (port == IP_NULL)
 1600                         goto invalid_dest;
 1601                 ip_lock(port);
 1602                 if (ip_active(port)) {
 1603                         task_t self = current_task();
 1604                         tasklabel_lock(self);
 1605                         error = mac_port_check_send(&self->maclabel,
 1606                             &port->ip_label);
 1607                         tasklabel_unlock(self);
 1608                 }
 1609                 ip_unlock(port);
 1610                 if (error != 0)
 1611                         goto invalid_dest;
 1612         }
 1613 #endif
 1614 
 1615         if (notify != MACH_PORT_NULL) {
 1616                 if ((entry = ipc_entry_lookup(space, notify)) == IE_NULL) {
 1617                         is_write_unlock(space);
 1618                         return MACH_SEND_INVALID_NOTIFY;
 1619                 }
 1620                 if((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) {
 1621                         is_write_unlock(space);
 1622                         return MACH_SEND_INVALID_NOTIFY;
 1623                 }
 1624 
 1625                 notify_port = (ipc_port_t) entry->ie_object;
 1626         } else
 1627                 notify_port = IP_NULL;
 1628 
 1629         if (dest_name == reply_name) {
 1630                 mach_port_name_t name = dest_name;
 1631 
 1632                 /*
 1633                  *      Destination and reply ports are the same!
 1634                  *      This is a little tedious to make atomic, because
 1635                  *      there are 25 combinations of dest_type/reply_type.
 1636                  *      However, most are easy.  If either is move-sonce,
 1637                  *      then there must be an error.  If either are
 1638                  *      make-send or make-sonce, then we must be looking
 1639                  *      at a receive right so the port can't die.
 1640                  *      The hard cases are the combinations of
 1641                  *      copy-send and make-send.
 1642                  */
 1643 
 1644                 entry = ipc_entry_lookup(space, name);
 1645                 if (entry == IE_NULL)
 1646                         goto invalid_dest;
 1647 
 1648                 assert(reply_type != 0); /* because name not null */
 1649 
 1650                 if (!ipc_right_copyin_check(space, name, entry, reply_type))
 1651                         goto invalid_reply;
 1652 
 1653                 if ((dest_type == MACH_MSG_TYPE_MOVE_SEND_ONCE) ||
 1654                     (reply_type == MACH_MSG_TYPE_MOVE_SEND_ONCE)) {
 1655                         /*
 1656                          *      Why must there be an error?  To get a valid
 1657                          *      destination, this entry must name a live
 1658                          *      port (not a dead name or dead port).  However
 1659                          *      a successful move-sonce will destroy a
 1660                          *      live entry.  Therefore the other copyin,
 1661                          *      whatever it is, would fail.  We've already
 1662                          *      checked for reply port errors above,
 1663                          *      so report a destination error.
 1664                          */
 1665 
 1666                         goto invalid_dest;
 1667                 } else if ((dest_type == MACH_MSG_TYPE_MAKE_SEND) ||
 1668                            (dest_type == MACH_MSG_TYPE_MAKE_SEND_ONCE) ||
 1669                            (reply_type == MACH_MSG_TYPE_MAKE_SEND) ||
 1670                            (reply_type == MACH_MSG_TYPE_MAKE_SEND_ONCE)) {
 1671                         kr = ipc_right_copyin(space, name, entry,
 1672                                               dest_type, FALSE,
 1673                                               &dest_port, &dest_soright);
 1674                         if (kr != KERN_SUCCESS)
 1675                                 goto invalid_dest;
 1676 
 1677                         /*
 1678                          *      Either dest or reply needs a receive right.
 1679                          *      We know the receive right is there, because
 1680                          *      of the copyin_check and copyin calls.  Hence
 1681                          *      the port is not in danger of dying.  If dest
 1682                          *      used the receive right, then the right needed
 1683                          *      by reply (and verified by copyin_check) will
 1684                          *      still be there.
 1685                          */
 1686 
 1687                         assert(IO_VALID(dest_port));
 1688                         assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
 1689                         assert(dest_soright == IP_NULL);
 1690 
 1691                         kr = ipc_right_copyin(space, name, entry,
 1692                                               reply_type, TRUE,
 1693                                               &reply_port, &reply_soright);
 1694 
 1695                         assert(kr == KERN_SUCCESS);
 1696                         assert(reply_port == dest_port);
 1697                         assert(entry->ie_bits & MACH_PORT_TYPE_RECEIVE);
 1698                         assert(reply_soright == IP_NULL);
 1699                 } else if ((dest_type == MACH_MSG_TYPE_COPY_SEND) &&
 1700                            (reply_type == MACH_MSG_TYPE_COPY_SEND)) {
 1701                         /*
 1702                          *      To make this atomic, just do one copy-send,
 1703                          *      and dup the send right we get out.
 1704                          */
 1705 
 1706                         kr = ipc_right_copyin(space, name, entry,
 1707                                               dest_type, FALSE,
 1708                                               &dest_port, &dest_soright);
 1709                         if (kr != KERN_SUCCESS)
 1710                                 goto invalid_dest;
 1711 
 1712                         assert(entry->ie_bits & MACH_PORT_TYPE_SEND);
 1713                         assert(dest_soright == IP_NULL);
 1714 
 1715                         /*
 1716                          *      It's OK if the port we got is dead now,
 1717                          *      so reply_port is IP_DEAD, because the msg
 1718                          *      won't go anywhere anyway.
 1719                          */
 1720 
 1721                         reply_port = (ipc_object_t)
 1722                                 ipc_port_copy_send((ipc_port_t) dest_port);
 1723                         reply_soright = IP_NULL;
 1724                 } else if ((dest_type == MACH_MSG_TYPE_MOVE_SEND) &&
 1725                            (reply_type == MACH_MSG_TYPE_MOVE_SEND)) {
 1726                         /*
 1727                          *      This is an easy case.  Just use our
 1728                          *      handy-dandy special-purpose copyin call
 1729                          *      to get two send rights for the price of one.
 1730                          */
 1731 
 1732                         kr = ipc_right_copyin_two(space, name, entry,
 1733                                                   &dest_port, &dest_soright);
 1734                         if (kr != KERN_SUCCESS)
 1735                                 goto invalid_dest;
 1736 
 1737                         /* the entry might need to be deallocated */
 1738                         if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
 1739                                 ipc_entry_dealloc(space, name, entry);
 1740 
 1741                         reply_port = dest_port;
 1742                         reply_soright = IP_NULL;
 1743                 } else {
 1744                         ipc_port_t soright;
 1745 
 1746                         assert(((dest_type == MACH_MSG_TYPE_COPY_SEND) &&
 1747                                 (reply_type == MACH_MSG_TYPE_MOVE_SEND)) ||
 1748                                ((dest_type == MACH_MSG_TYPE_MOVE_SEND) &&
 1749                                 (reply_type == MACH_MSG_TYPE_COPY_SEND)));
 1750 
 1751                         /*
 1752                          *      To make this atomic, just do a move-send,
 1753                          *      and dup the send right we get out.
 1754                          */
 1755 
 1756                         kr = ipc_right_copyin(space, name, entry,
 1757                                               MACH_MSG_TYPE_MOVE_SEND, FALSE,
 1758                                               &dest_port, &soright);
 1759                         if (kr != KERN_SUCCESS)
 1760                                 goto invalid_dest;
 1761 
 1762                         /* the entry might need to be deallocated */
 1763 
 1764                         if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
 1765                                 ipc_entry_dealloc(space, name, entry);
 1766 
 1767                         /*
 1768                          *      It's OK if the port we got is dead now,
 1769                          *      so reply_port is IP_DEAD, because the msg
 1770                          *      won't go anywhere anyway.
 1771                          */
 1772 
 1773                         reply_port = (ipc_object_t)
 1774                                 ipc_port_copy_send((ipc_port_t) dest_port);
 1775 
 1776                         if (dest_type == MACH_MSG_TYPE_MOVE_SEND) {
 1777                                 dest_soright = soright;
 1778                                 reply_soright = IP_NULL;
 1779                         } else {
 1780                                 dest_soright = IP_NULL;
 1781                                 reply_soright = soright;
 1782                         }
 1783                 }
 1784         } else if (!MACH_PORT_VALID(reply_name)) {
 1785                 /*
 1786                  *      No reply port!  This is an easy case
 1787                  *      to make atomic.  Just copyin the destination.
 1788                  */
 1789 
 1790                 entry = ipc_entry_lookup(space, dest_name);
 1791                 if (entry == IE_NULL)
 1792                         goto invalid_dest;
 1793 
 1794                 kr = ipc_right_copyin(space, dest_name, entry,
 1795                                       dest_type, FALSE,
 1796                                       &dest_port, &dest_soright);
 1797                 if (kr != KERN_SUCCESS)
 1798                         goto invalid_dest;
 1799 
 1800                 /* the entry might need to be deallocated */
 1801 
 1802                 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
 1803                         ipc_entry_dealloc(space, dest_name, entry);
 1804 
 1805                 reply_port = (ipc_object_t)CAST_MACH_NAME_TO_PORT(reply_name);
 1806                 reply_soright = IP_NULL;
 1807         } else {
 1808                 ipc_entry_t dest_entry, reply_entry;
 1809 
 1810                 /*
 1811                  *      This is the tough case to make atomic.
 1812                  *      The difficult problem is serializing with port death.
 1813                  *      At the time we copyin dest_port, it must be alive.
 1814                  *      If reply_port is alive when we copyin it, then
 1815                  *      we are OK, because we serialize before the death
 1816                  *      of both ports.  Assume reply_port is dead at copyin.
 1817                  *      Then if dest_port dies/died after reply_port died,
 1818                  *      we are OK, because we serialize between the death
 1819                  *      of the two ports.  So the bad case is when dest_port
 1820                  *      dies after its copyin, reply_port dies before its
 1821                  *      copyin, and dest_port dies before reply_port.  Then
 1822                  *      the copyins operated as if dest_port was alive
 1823                  *      and reply_port was dead, which shouldn't have happened
 1824                  *      because they died in the other order.
 1825                  *
 1826                  *      Note that it is easy for a user task to tell if
 1827                  *      a copyin happened before or after a port died.
 1828                  *      For example, suppose both dest and reply are
 1829                  *      send-once rights (types are both move-sonce) and
 1830                  *      both rights have dead-name requests registered.
 1831                  *      If a port dies before copyin, a dead-name notification
 1832                  *      is generated and the dead name's urefs are incremented,
 1833                  *      and if the copyin happens first, a port-deleted
 1834                  *      notification is generated.
 1835                  *
 1836                  *      Note that although the entries are different,
 1837                  *      dest_port and reply_port might still be the same.
 1838                  *
 1839                  * JMM - The code to handle this was too expensive and, anyway,
 1840                  * we intend to separate the dest lookup from the reply copyin
 1841                  * by a wide margin, so the user will have to learn to deal!
 1842                  * I will be making the change soon!
 1843                  */
 1844 
 1845                 dest_entry = ipc_entry_lookup(space, dest_name);
 1846                 if (dest_entry == IE_NULL)
 1847                         goto invalid_dest;
 1848 
 1849                 reply_entry = ipc_entry_lookup(space, reply_name);
 1850                 if (reply_entry == IE_NULL)
 1851                         goto invalid_reply;
 1852 
 1853                 assert(dest_entry != reply_entry); /* names are not equal */
 1854                 assert(reply_type != 0); /* because reply_name not null */
 1855 
 1856                 if (!ipc_right_copyin_check(space, reply_name, reply_entry,
 1857                                             reply_type))
 1858                         goto invalid_reply;
 1859 
 1860                 kr = ipc_right_copyin(space, dest_name, dest_entry,
 1861                                       dest_type, FALSE,
 1862                                       &dest_port, &dest_soright);
 1863                 if (kr != KERN_SUCCESS)
 1864                         goto invalid_dest;
 1865 
 1866                 assert(IO_VALID(dest_port));
 1867 
 1868                 kr = ipc_right_copyin(space, reply_name, reply_entry,
 1869                                       reply_type, TRUE,
 1870                                       &reply_port, &reply_soright);
 1871 
 1872                 assert(kr == KERN_SUCCESS);
 1873 
 1874                 /* the entries might need to be deallocated */
 1875 
 1876                 if (IE_BITS_TYPE(reply_entry->ie_bits) == MACH_PORT_TYPE_NONE)
 1877                         ipc_entry_dealloc(space, reply_name, reply_entry);
 1878 
 1879                 if (IE_BITS_TYPE(dest_entry->ie_bits) == MACH_PORT_TYPE_NONE)
 1880                         ipc_entry_dealloc(space, dest_name, dest_entry);
 1881         }
 1882 
 1883         /*
 1884          *      At this point, dest_port, reply_port,
 1885          *      dest_soright, reply_soright are all initialized.
 1886          *      Any defunct entries have been deallocated.
 1887          *      The space is still write-locked, and we need to
 1888          *      make the MACH_SEND_CANCEL check.  The notify_port pointer
 1889          *      is still usable, because the copyin code above won't ever
 1890          *      deallocate a receive right, so its entry still exists
 1891          *      and holds a ref.  Note notify_port might even equal
 1892          *      dest_port or reply_port.
 1893          */
 1894 
 1895         if ((notify != MACH_PORT_NULL) &&
 1896             (dest_soright == notify_port)) {
 1897                 ipc_port_release_sonce(dest_soright);
 1898                 dest_soright = IP_NULL;
 1899         }
 1900 
 1901         is_write_unlock(space);
 1902 
 1903         if (dest_soright != IP_NULL)
 1904                 ipc_notify_port_deleted(dest_soright, dest_name);
 1905 
 1906         if (reply_soright != IP_NULL)
 1907                 ipc_notify_port_deleted(reply_soright, reply_name);
 1908 
 1909         dest_type = ipc_object_copyin_type(dest_type);
 1910         reply_type = ipc_object_copyin_type(reply_type);
 1911 
 1912         msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
 1913                           MACH_MSGH_BITS(dest_type, reply_type));
 1914         msg->msgh_remote_port = (ipc_port_t)dest_port;
 1915         msg->msgh_local_port = (ipc_port_t)reply_port;
 1916 
 1917         return MACH_MSG_SUCCESS;
 1918 
 1919 invalid_reply:
 1920         is_write_unlock(space);
 1921         return MACH_SEND_INVALID_REPLY;
 1922 
 1923 invalid_dest:
 1924         is_write_unlock(space);
 1925         if (reply_soright != IP_NULL)
 1926                 ipc_notify_port_deleted(reply_soright, reply_name);
 1927         return MACH_SEND_INVALID_DEST;
 1928 }
 1929 
 1930 mach_msg_descriptor_t *ipc_kmsg_copyin_port_descriptor(
 1931         volatile mach_msg_port_descriptor_t *dsc,
 1932         mach_msg_legacy_port_descriptor_t *user_dsc,
 1933         ipc_space_t space,
 1934         ipc_object_t dest,
 1935         ipc_kmsg_t kmsg,
 1936         mach_msg_return_t *mr);
 1937 
 1938 void ipc_print_type_name(
 1939    int type_name);
 1940 mach_msg_descriptor_t *
 1941 ipc_kmsg_copyin_port_descriptor(
 1942         volatile mach_msg_port_descriptor_t *dsc,
 1943         mach_msg_legacy_port_descriptor_t *user_dsc_in,
 1944         ipc_space_t space,
 1945         ipc_object_t dest,
 1946         ipc_kmsg_t kmsg,
 1947         mach_msg_return_t *mr)
 1948 {
 1949     volatile mach_msg_legacy_port_descriptor_t *user_dsc = user_dsc_in;
 1950     mach_msg_type_name_t        user_disp;
 1951     mach_msg_type_name_t        result_disp;
 1952     mach_port_name_t            name;
 1953     ipc_object_t                        object;
 1954 
 1955     user_disp = user_dsc->disposition;
 1956     result_disp = ipc_object_copyin_type(user_disp);
 1957 
 1958     name = (mach_port_name_t)user_dsc->name;
 1959     if (MACH_PORT_VALID(name)) {
 1960 
 1961         kern_return_t kr = ipc_object_copyin(space, name, user_disp, &object);
 1962         if (kr != KERN_SUCCESS) {
 1963             *mr = MACH_SEND_INVALID_RIGHT;
 1964             return NULL;
 1965         }
 1966 
 1967         if ((result_disp == MACH_MSG_TYPE_PORT_RECEIVE) &&
 1968                 ipc_port_check_circularity((ipc_port_t) object,
 1969                     (ipc_port_t) dest)) {
 1970             kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
 1971         }
 1972         dsc->name = (ipc_port_t) object;
 1973     } else {
 1974         dsc->name = CAST_MACH_NAME_TO_PORT(name);
 1975     }
 1976     dsc->disposition = result_disp;
 1977     dsc->type = MACH_MSG_PORT_DESCRIPTOR;
 1978 
 1979     dsc->pad_end = 0; // debug, unnecessary
 1980 
 1981     return (mach_msg_descriptor_t *)(user_dsc_in+1);
 1982 }
 1983 
 1984 mach_msg_descriptor_t * ipc_kmsg_copyin_ool_descriptor(
 1985         mach_msg_ool_descriptor_t *dsc,
 1986         mach_msg_descriptor_t *user_dsc,
 1987         int is_64bit,
 1988         vm_offset_t *paddr,
 1989         vm_map_copy_t *copy,
 1990         vm_size_t *space_needed,
 1991         vm_map_t map,
 1992         mach_msg_return_t *mr);
 1993 mach_msg_descriptor_t *
 1994 ipc_kmsg_copyin_ool_descriptor(
 1995         mach_msg_ool_descriptor_t *dsc,
 1996         mach_msg_descriptor_t *user_dsc,
 1997         int is_64bit,
 1998         vm_offset_t *paddr,
 1999         vm_map_copy_t *copy,
 2000         vm_size_t *space_needed,
 2001         vm_map_t map,
 2002         mach_msg_return_t *mr)
 2003 {
 2004     vm_size_t                           length;
 2005     boolean_t                           dealloc;
 2006     mach_msg_copy_options_t             copy_options;
 2007     mach_vm_offset_t            addr;
 2008     mach_msg_descriptor_type_t  dsc_type;
 2009 
 2010     if (is_64bit) {
 2011         mach_msg_ool_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
 2012 
 2013         addr = (mach_vm_offset_t) user_ool_dsc->address;
 2014         length = user_ool_dsc->size;
 2015         dealloc = user_ool_dsc->deallocate;
 2016         copy_options = user_ool_dsc->copy;
 2017         dsc_type = user_ool_dsc->type;
 2018 
 2019         user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
 2020     } else {
 2021         mach_msg_ool_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
 2022 
 2023         addr = CAST_USER_ADDR_T(user_ool_dsc->address);
 2024         dealloc = user_ool_dsc->deallocate;
 2025         copy_options = user_ool_dsc->copy;
 2026         dsc_type = user_ool_dsc->type;
 2027         length = user_ool_dsc->size;
 2028 
 2029         user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
 2030     }
 2031 
 2032     dsc->size = (mach_msg_size_t)length;
 2033     dsc->deallocate = dealloc;
 2034     dsc->copy = copy_options;
 2035     dsc->type = dsc_type;
 2036 
 2037     if (length == 0) {
 2038         dsc->address = NULL;
 2039     } else if ((length >= MSG_OOL_SIZE_SMALL) &&
 2040             (copy_options == MACH_MSG_PHYSICAL_COPY) && !dealloc) {
 2041 
 2042         /*
 2043          * If the request is a physical copy and the source
 2044          * is not being deallocated, then allocate space
 2045          * in the kernel's pageable ipc copy map and copy
 2046          * the data in.  The semantics guarantee that the
 2047          * data will have been physically copied before
 2048          * the send operation terminates.  Thus if the data
 2049          * is not being deallocated, we must be prepared
 2050          * to page if the region is sufficiently large.
 2051          */
 2052         if (copyin(addr, (char *)*paddr, length)) {
 2053             *mr = MACH_SEND_INVALID_MEMORY;
 2054             return NULL;
 2055         }       
 2056 
 2057         /*
 2058          * The kernel ipc copy map is marked no_zero_fill.
 2059          * If the transfer is not a page multiple, we need
 2060          * to zero fill the balance.
 2061          */
 2062         if (!page_aligned(length)) {
 2063             (void) memset((void *) (*paddr + length), 0,
 2064                     round_page(length) - length);
 2065         }
 2066         if (vm_map_copyin(ipc_kernel_copy_map, (vm_map_address_t)*paddr,
 2067                     (vm_map_size_t)length, TRUE, copy) != KERN_SUCCESS) {
 2068             *mr = MACH_MSG_VM_KERNEL;
 2069             return NULL;
 2070         }
 2071         dsc->address = (void *)*copy;
 2072         *paddr += round_page(length);
 2073         *space_needed -= round_page(length);
 2074     } else {
 2075 
 2076         /*
 2077          * Make a vm_map_copy_t of the of the data.  If the
 2078          * data is small, this will do an optimized physical
 2079          * copy.  Otherwise, it will do a virtual copy.
 2080          *
 2081          * NOTE: A virtual copy is OK if the original is being
 2082          * deallocted, even if a physical copy was requested.
 2083          */
 2084         kern_return_t kr = vm_map_copyin(map, addr, 
 2085                 (vm_map_size_t)length, dealloc, copy);
 2086         if (kr != KERN_SUCCESS) {
 2087             *mr = (kr == KERN_RESOURCE_SHORTAGE) ?
 2088                 MACH_MSG_VM_KERNEL :
 2089                 MACH_SEND_INVALID_MEMORY;
 2090             return NULL;
 2091         }
 2092         dsc->address = (void *)*copy;
 2093     }
 2094     return user_dsc;
 2095 }
 2096 
 2097 mach_msg_descriptor_t * ipc_kmsg_copyin_ool_ports_descriptor(
 2098         mach_msg_ool_ports_descriptor_t *dsc,
 2099         mach_msg_descriptor_t *user_dsc,
 2100         int is_64bit,
 2101         vm_map_t map,
 2102         ipc_space_t space,
 2103         ipc_object_t dest,
 2104         ipc_kmsg_t kmsg,
 2105         mach_msg_return_t *mr);
 2106 mach_msg_descriptor_t *
 2107 ipc_kmsg_copyin_ool_ports_descriptor(
 2108         mach_msg_ool_ports_descriptor_t *dsc,
 2109         mach_msg_descriptor_t *user_dsc,
 2110         int is_64bit,
 2111         vm_map_t map,
 2112         ipc_space_t space,
 2113         ipc_object_t dest,
 2114         ipc_kmsg_t kmsg,
 2115         mach_msg_return_t *mr)
 2116 {
 2117     void                                        *data;
 2118     ipc_object_t                        *objects;
 2119     unsigned int                                i;
 2120     mach_vm_offset_t                            addr;
 2121     mach_msg_type_name_t                user_disp;
 2122     mach_msg_type_name_t                result_disp;
 2123     mach_msg_type_number_t                      count;
 2124     mach_msg_copy_options_t                     copy_option;
 2125     boolean_t                           deallocate;
 2126     mach_msg_descriptor_type_t      type;
 2127     vm_size_t                           ports_length, names_length;
 2128 
 2129     if (is_64bit) {
 2130         mach_msg_ool_ports_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
 2131 
 2132         addr = (mach_vm_offset_t)user_ool_dsc->address;
 2133         count = user_ool_dsc->count;
 2134         deallocate = user_ool_dsc->deallocate;
 2135         copy_option = user_ool_dsc->copy;
 2136         user_disp = user_ool_dsc->disposition;
 2137         type = user_ool_dsc->type;
 2138 
 2139         user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
 2140     } else {
 2141         mach_msg_ool_ports_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
 2142 
 2143         addr = CAST_USER_ADDR_T(user_ool_dsc->address);
 2144         count = user_ool_dsc->count;
 2145         deallocate = user_ool_dsc->deallocate;
 2146         copy_option = user_ool_dsc->copy;
 2147         user_disp = user_ool_dsc->disposition;
 2148         type = user_ool_dsc->type;
 2149 
 2150         user_dsc = (typeof(user_dsc))(user_ool_dsc+1);
 2151     }
 2152 
 2153     dsc->deallocate = deallocate;
 2154     dsc->copy = copy_option;
 2155     dsc->type = type;
 2156     dsc->count = count;
 2157     dsc->address = NULL;  /* for now */
 2158 
 2159     result_disp = ipc_object_copyin_type(user_disp);
 2160     dsc->disposition = result_disp;
 2161 
 2162     if (count > (INT_MAX / sizeof(mach_port_t))) {
 2163         *mr = MACH_SEND_TOO_LARGE;
 2164         return NULL;
 2165     }
 2166 
 2167     /* calculate length of data in bytes, rounding up */
 2168     ports_length = count * sizeof(mach_port_t);
 2169     names_length = count * sizeof(mach_port_name_t);
 2170 
 2171     if (ports_length == 0) {
 2172         return user_dsc;
 2173     }
 2174 
 2175     data = kalloc(ports_length);
 2176 
 2177     if (data == NULL) {
 2178         *mr = MACH_SEND_NO_BUFFER;
 2179         return NULL;
 2180     }
 2181     
 2182 #ifdef __LP64__
 2183     mach_port_name_t *names = &((mach_port_name_t *)data)[count];
 2184 #else
 2185     mach_port_name_t *names = ((mach_port_name_t *)data);
 2186 #endif
 2187 
 2188     if (copyinmap(map, addr, names, names_length) != KERN_SUCCESS) {
 2189         kfree(data, ports_length);
 2190         *mr = MACH_SEND_INVALID_MEMORY;
 2191         return NULL;
 2192     }
 2193 
 2194     if (deallocate) {
 2195         (void) mach_vm_deallocate(map, addr, (mach_vm_size_t)ports_length);
 2196     }
 2197 
 2198     objects = (ipc_object_t *) data;
 2199     dsc->address = data;
 2200 
 2201     for ( i = 0; i < count; i++) {
 2202         mach_port_name_t name = names[i];
 2203         ipc_object_t object;
 2204 
 2205         if (!MACH_PORT_VALID(name)) {
 2206             objects[i] = (ipc_object_t)CAST_MACH_NAME_TO_PORT(name);
 2207             continue;
 2208         }
 2209 
 2210         kern_return_t kr = ipc_object_copyin(space, name, user_disp, &object);
 2211 
 2212         if (kr != KERN_SUCCESS) {
 2213             unsigned int j;
 2214 
 2215             for(j = 0; j < i; j++) {
 2216                 object = objects[j];
 2217                 if (IPC_OBJECT_VALID(object))
 2218                     ipc_object_destroy(object, result_disp);
 2219             }
 2220             kfree(data, ports_length);
 2221             dsc->address = NULL;
 2222             *mr = MACH_SEND_INVALID_RIGHT;
 2223             return NULL;
 2224         }
 2225 
 2226         if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
 2227                 ipc_port_check_circularity(
 2228                     (ipc_port_t) object,
 2229                     (ipc_port_t) dest))
 2230             kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
 2231 
 2232         objects[i] = object;
 2233     }
 2234 
 2235     return user_dsc;
 2236 }
 2237 
 2238 /*
 2239  *      Routine:        ipc_kmsg_copyin_body
 2240  *      Purpose:
 2241  *              "Copy-in" port rights and out-of-line memory
 2242  *              in the message body.
 2243  *
 2244  *              In all failure cases, the message is left holding
 2245  *              no rights or memory.  However, the message buffer
 2246  *              is not deallocated.  If successful, the message
 2247  *              contains a valid destination port.
 2248  *      Conditions:
 2249  *              Nothing locked.
 2250  *      Returns:
 2251  *              MACH_MSG_SUCCESS        Successful copyin.
 2252  *              MACH_SEND_INVALID_MEMORY        Can't grab out-of-line memory.
 2253  *              MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
 2254  *              MACH_SEND_INVALID_TYPE  Bad type specification.
 2255  *              MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
 2256  *              MACH_SEND_INVALID_RT_OOL_SIZE OOL Buffer too large for RT
 2257  *              MACH_MSG_INVALID_RT_DESCRIPTOR Dealloc and RT are incompatible
 2258  */
 2259 
 2260 mach_msg_return_t
 2261 ipc_kmsg_copyin_body(
 2262         ipc_kmsg_t      kmsg,
 2263         ipc_space_t     space,
 2264         vm_map_t        map)
 2265 {
 2266     ipc_object_t                dest;
 2267     mach_msg_body_t             *body;
 2268     mach_msg_descriptor_t       *daddr, *naddr;
 2269     mach_msg_descriptor_t       *user_addr, *kern_addr;
 2270     mach_msg_type_number_t      dsc_count;
 2271     boolean_t                   is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
 2272     boolean_t                   complex = FALSE;
 2273     vm_size_t                   space_needed = 0;
 2274     vm_offset_t                 paddr = 0;
 2275     vm_map_copy_t               copy = VM_MAP_COPY_NULL;
 2276     mach_msg_type_number_t      i;
 2277     mach_msg_return_t           mr = MACH_MSG_SUCCESS;
 2278 
 2279     vm_size_t           descriptor_size = 0;
 2280 
 2281     /*
 2282      * Determine if the target is a kernel port.
 2283      */
 2284     dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
 2285     body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
 2286     naddr = (mach_msg_descriptor_t *) (body + 1);
 2287 
 2288     dsc_count = body->msgh_descriptor_count;
 2289     if (dsc_count == 0)
 2290         return MACH_MSG_SUCCESS;
 2291 
 2292     /*
 2293      * Make an initial pass to determine kernal VM space requirements for
 2294      * physical copies and possible contraction of the descriptors from
 2295      * processes with pointers larger than the kernel's.
 2296      */
 2297     daddr = NULL;
 2298     for (i = 0; i < dsc_count; i++) {
 2299         daddr = naddr;
 2300 
 2301         /* make sure the descriptor fits in the message */
 2302         if (is_task_64bit) {
 2303             switch (daddr->type.type) {
 2304             case MACH_MSG_OOL_DESCRIPTOR:
 2305             case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
 2306             case MACH_MSG_OOL_PORTS_DESCRIPTOR:
 2307                     descriptor_size += 16;
 2308             naddr = (typeof(naddr))((vm_offset_t)daddr + 16);
 2309             break;
 2310             default:
 2311                     descriptor_size += 12;
 2312             naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
 2313             break;
 2314             }
 2315         } else {
 2316         descriptor_size += 12;
 2317         naddr = (typeof(naddr))((vm_offset_t)daddr + 12);
 2318         }
 2319 
 2320         if (naddr > (mach_msg_descriptor_t *)
 2321             ((vm_offset_t)kmsg->ikm_header + kmsg->ikm_header->msgh_size)) {
 2322             ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
 2323             mr = MACH_SEND_MSG_TOO_SMALL;
 2324             goto out;
 2325         }
 2326 
 2327         switch (daddr->type.type) {
 2328             mach_msg_size_t size;
 2329 
 2330         case MACH_MSG_OOL_DESCRIPTOR:
 2331         case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
 2332         size = (is_task_64bit) ?
 2333                 ((mach_msg_ool_descriptor64_t *)daddr)->size :
 2334             daddr->out_of_line.size;
 2335 
 2336             if (daddr->out_of_line.copy != MACH_MSG_PHYSICAL_COPY &&
 2337                 daddr->out_of_line.copy != MACH_MSG_VIRTUAL_COPY) {
 2338                 /*
 2339                  * Invalid copy option
 2340                  */
 2341                 ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
 2342                 mr = MACH_SEND_INVALID_TYPE;
 2343                 goto out;
 2344             }
 2345             
 2346             if ((size >= MSG_OOL_SIZE_SMALL) &&
 2347                 (daddr->out_of_line.copy == MACH_MSG_PHYSICAL_COPY) &&
 2348                 !(daddr->out_of_line.deallocate)) {
 2349 
 2350                 /*
 2351                  * Out-of-line memory descriptor, accumulate kernel
 2352                  * memory requirements
 2353                  */
 2354                 space_needed += round_page(size);
 2355                 if (space_needed > ipc_kmsg_max_vm_space) {
 2356                     
 2357                     /*
 2358                      * Per message kernel memory limit exceeded
 2359                      */
 2360                     ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
 2361                     mr = MACH_MSG_VM_KERNEL;
 2362                     goto out;
 2363                 }
 2364             }
 2365         }
 2366     }
 2367 
 2368     /*
 2369      * Allocate space in the pageable kernel ipc copy map for all the
 2370      * ool data that is to be physically copied.  Map is marked wait for
 2371      * space.
 2372      */
 2373     if (space_needed) {
 2374         if (vm_allocate(ipc_kernel_copy_map, &paddr, space_needed, 
 2375                     VM_FLAGS_ANYWHERE) != KERN_SUCCESS) {
 2376             ipc_kmsg_clean_partial(kmsg, 0, NULL, 0, 0);
 2377             mr = MACH_MSG_VM_KERNEL;
 2378             goto out;
 2379         }
 2380     }
 2381 
 2382     /* user_addr = just after base as it was copied in */
 2383     user_addr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
 2384     /* Shift the mach_msg_base_t down to make for dsc_count*16bytes of descriptors */
 2385     if(descriptor_size != 16*dsc_count) {
 2386         vm_offset_t dsc_adjust = 16*dsc_count - descriptor_size;
 2387         memmove((char *)(((vm_offset_t)kmsg->ikm_header) - dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
 2388         kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header - dsc_adjust);
 2389         /* Update the message size for the larger in-kernel representation */
 2390         kmsg->ikm_header->msgh_size += (mach_msg_size_t)dsc_adjust;
 2391     }
 2392 
 2393 
 2394     /* kern_addr = just after base after it has been (conditionally) moved */
 2395     kern_addr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
 2396 
 2397     /* handle the OOL regions and port descriptors. */
 2398     for(i=0;i<dsc_count;i++) {
 2399         switch (user_addr->type.type) {
 2400             case MACH_MSG_PORT_DESCRIPTOR:
 2401                 user_addr = ipc_kmsg_copyin_port_descriptor((mach_msg_port_descriptor_t *)kern_addr, 
 2402                         (mach_msg_legacy_port_descriptor_t *)user_addr, space, dest, kmsg, &mr);
 2403                 kern_addr++;
 2404                 complex = TRUE;
 2405                 break;
 2406             case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
 2407             case MACH_MSG_OOL_DESCRIPTOR: 
 2408                 user_addr = ipc_kmsg_copyin_ool_descriptor((mach_msg_ool_descriptor_t *)kern_addr, 
 2409                         user_addr, is_task_64bit, &paddr, &copy, &space_needed, map, &mr);
 2410                 kern_addr++;
 2411                 complex = TRUE;
 2412                 break;
 2413             case MACH_MSG_OOL_PORTS_DESCRIPTOR: 
 2414                 user_addr = ipc_kmsg_copyin_ool_ports_descriptor((mach_msg_ool_ports_descriptor_t *)kern_addr, 
 2415                         user_addr, is_task_64bit, map, space, dest, kmsg, &mr);
 2416                 kern_addr++;
 2417                 complex = TRUE;
 2418                 break;
 2419             default:
 2420                 /* Invalid descriptor */
 2421                 mr = MACH_SEND_INVALID_TYPE;
 2422                 break;
 2423         }
 2424 
 2425         if (MACH_MSG_SUCCESS != mr) {
 2426             /* clean from start of message descriptors to i */
 2427             ipc_kmsg_clean_partial(kmsg, i,
 2428                     (mach_msg_descriptor_t *)((mach_msg_base_t *)kmsg->ikm_header + 1),
 2429                     paddr, space_needed);
 2430             goto out;
 2431         }
 2432     } /* End of loop */ 
 2433     
 2434     if (!complex) {
 2435         kmsg->ikm_header->msgh_bits &= ~MACH_MSGH_BITS_COMPLEX;
 2436     }
 2437  out:
 2438     return mr;
 2439 }
 2440 
 2441 
 2442 /*
 2443  *      Routine:        ipc_kmsg_copyin
 2444  *      Purpose:
 2445  *              "Copy-in" port rights and out-of-line memory
 2446  *              in the message.
 2447  *
 2448  *              In all failure cases, the message is left holding
 2449  *              no rights or memory.  However, the message buffer
 2450  *              is not deallocated.  If successful, the message
 2451  *              contains a valid destination port.
 2452  *      Conditions:
 2453  *              Nothing locked.
 2454  *      Returns:
 2455  *              MACH_MSG_SUCCESS        Successful copyin.
 2456  *              MACH_SEND_INVALID_HEADER
 2457  *                      Illegal value in the message header bits.
 2458  *              MACH_SEND_INVALID_NOTIFY        Bad notify port.
 2459  *              MACH_SEND_INVALID_DEST  Can't copyin destination port.
 2460  *              MACH_SEND_INVALID_REPLY Can't copyin reply port.
 2461  *              MACH_SEND_INVALID_MEMORY        Can't grab out-of-line memory.
 2462  *              MACH_SEND_INVALID_RIGHT Can't copyin port right in body.
 2463  *              MACH_SEND_INVALID_TYPE  Bad type specification.
 2464  *              MACH_SEND_MSG_TOO_SMALL Body is too small for types/data.
 2465  */
 2466 
 2467 mach_msg_return_t
 2468 ipc_kmsg_copyin(
 2469         ipc_kmsg_t              kmsg,
 2470         ipc_space_t             space,
 2471         vm_map_t                map,
 2472         mach_port_name_t        notify)
 2473 {
 2474     mach_msg_return_t           mr;
 2475     
 2476     mr = ipc_kmsg_copyin_header(kmsg->ikm_header, space, notify);
 2477     if (mr != MACH_MSG_SUCCESS)
 2478         return mr;
 2479     
 2480         DEBUG_KPRINT_SYSCALL_IPC("ipc_kmsg_copyin header:\n%.8x\n%.8x\n%p\n%p\n%.8x\n%.8x\n",
 2481                                                          kmsg->ikm_header->msgh_size,
 2482                                                          kmsg->ikm_header->msgh_bits,
 2483                                                          kmsg->ikm_header->msgh_remote_port,
 2484                                                          kmsg->ikm_header->msgh_local_port,
 2485                                                          kmsg->ikm_header->msgh_reserved,
 2486                                                          kmsg->ikm_header->msgh_id);
 2487 
 2488     if ((kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0)
 2489         return MACH_MSG_SUCCESS;
 2490     
 2491         mr = ipc_kmsg_copyin_body( kmsg, space, map);
 2492 
 2493         if (DEBUG_KPRINT_SYSCALL_PREDICATE(DEBUG_KPRINT_SYSCALL_IPC_MASK))
 2494         {
 2495                 kprintf("body:\n");
 2496                 uint32_t i;
 2497                 for(i=0;i*4 < (kmsg->ikm_header->msgh_size - sizeof(mach_msg_header_t));i++)
 2498                 {
 2499                         kprintf("%.4x\n",((uint32_t *)(kmsg->ikm_header + 1))[i]);
 2500                 }
 2501         }
 2502         return mr;
 2503 }
 2504 
 2505 /*
 2506  *      Routine:        ipc_kmsg_copyin_from_kernel
 2507  *      Purpose:
 2508  *              "Copy-in" port rights and out-of-line memory
 2509  *              in a message sent from the kernel.
 2510  *
 2511  *              Because the message comes from the kernel,
 2512  *              the implementation assumes there are no errors
 2513  *              or peculiarities in the message.
 2514  *
 2515  *              Returns TRUE if queueing the message
 2516  *              would result in a circularity.
 2517  *      Conditions:
 2518  *              Nothing locked.
 2519  */
 2520 
 2521 void
 2522 ipc_kmsg_copyin_from_kernel(
 2523         ipc_kmsg_t      kmsg)
 2524 {
 2525         mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
 2526         mach_msg_type_name_t rname = MACH_MSGH_BITS_REMOTE(bits);
 2527         mach_msg_type_name_t lname = MACH_MSGH_BITS_LOCAL(bits);
 2528         ipc_object_t remote = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
 2529         ipc_object_t local = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
 2530 
 2531         /* translate the destination and reply ports */
 2532 
 2533         ipc_object_copyin_from_kernel(remote, rname);
 2534         if (IO_VALID(local))
 2535                 ipc_object_copyin_from_kernel(local, lname);
 2536 
 2537         /*
 2538          *      The common case is a complex message with no reply port,
 2539          *      because that is what the memory_object interface uses.
 2540          */
 2541 
 2542         if (bits == (MACH_MSGH_BITS_COMPLEX |
 2543                      MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0))) {
 2544                 bits = (MACH_MSGH_BITS_COMPLEX |
 2545                         MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0));
 2546 
 2547                 kmsg->ikm_header->msgh_bits = bits;
 2548         } else {
 2549                 bits = (MACH_MSGH_BITS_OTHER(bits) |
 2550                         MACH_MSGH_BITS(ipc_object_copyin_type(rname),
 2551                                        ipc_object_copyin_type(lname)));
 2552 
 2553                 kmsg->ikm_header->msgh_bits = bits;
 2554                 if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
 2555                         return;
 2556         }
 2557     {
 2558         mach_msg_descriptor_t   *saddr;
 2559         mach_msg_body_t         *body;
 2560         mach_msg_type_number_t  i, count;
 2561 
 2562         body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
 2563         saddr = (mach_msg_descriptor_t *) (body + 1);
 2564         count = body->msgh_descriptor_count;
 2565 
 2566         for (i = 0; i < count; i++, saddr++) {
 2567 
 2568             switch (saddr->type.type) {
 2569             
 2570                 case MACH_MSG_PORT_DESCRIPTOR: {
 2571                     mach_msg_type_name_t        name;
 2572                     ipc_object_t                object;
 2573                     mach_msg_port_descriptor_t  *dsc;
 2574                 
 2575                     dsc = &saddr->port;
 2576                 
 2577                     /* this is really the type SEND, SEND_ONCE, etc. */
 2578                     name = dsc->disposition;
 2579                     object = (ipc_object_t) dsc->name;
 2580                     dsc->disposition = ipc_object_copyin_type(name);
 2581                 
 2582                     if (!IO_VALID(object)) {
 2583                         break;
 2584                     }
 2585 
 2586                     ipc_object_copyin_from_kernel(object, name);
 2587                     
 2588                     /* CDY avoid circularity when the destination is also */
 2589                     /* the kernel.  This check should be changed into an  */
 2590                     /* assert when the new kobject model is in place since*/
 2591                     /* ports will not be used in kernel to kernel chats   */
 2592                         
 2593                     if (((ipc_port_t)remote)->ip_receiver != ipc_space_kernel) {
 2594                        if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
 2595                            ipc_port_check_circularity((ipc_port_t) object, 
 2596                                                 (ipc_port_t) remote)) {
 2597                            kmsg->ikm_header->msgh_bits |= 
 2598                                         MACH_MSGH_BITS_CIRCULAR;
 2599                        }
 2600                     }
 2601                     break;
 2602                 }
 2603                 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
 2604                 case MACH_MSG_OOL_DESCRIPTOR: {
 2605                     /*
 2606                      * The sender should supply ready-made memory, i.e.
 2607                      * a vm_map_copy_t, so we don't need to do anything.
 2608                      */
 2609                     break;
 2610                 }
 2611                 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
 2612                     ipc_object_t                        *objects;
 2613                     unsigned int                        j;
 2614                     mach_msg_type_name_t                name;
 2615                     mach_msg_ool_ports_descriptor_t     *dsc;
 2616                 
 2617                     dsc = (mach_msg_ool_ports_descriptor_t *)&saddr->ool_ports;
 2618 
 2619                     /* this is really the type SEND, SEND_ONCE, etc. */
 2620                     name = dsc->disposition;
 2621                     dsc->disposition = ipc_object_copyin_type(name);
 2622                 
 2623                     objects = (ipc_object_t *) dsc->address;
 2624                 
 2625                     for ( j = 0; j < dsc->count; j++) {
 2626                         ipc_object_t object = objects[j];
 2627                         
 2628                         if (!IO_VALID(object))
 2629                             continue;
 2630                         
 2631                         ipc_object_copyin_from_kernel(object, name);
 2632     
 2633                         if ((dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
 2634                             ipc_port_check_circularity(
 2635                                                        (ipc_port_t) object,
 2636                                                        (ipc_port_t) remote))
 2637                             kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
 2638                     }
 2639                     break;
 2640                 }
 2641                 default: {
 2642 #if     MACH_ASSERT
 2643                     panic("ipc_kmsg_copyin_from_kernel:  bad descriptor");
 2644 #endif  /* MACH_ASSERT */
 2645                 }
 2646             }
 2647         }
 2648     }
 2649 }
 2650 
 2651 #if IKM_SUPPORT_LEGACY
 2652 void
 2653 ipc_kmsg_copyin_from_kernel_legacy(
 2654         ipc_kmsg_t      kmsg)
 2655 {
 2656         mach_msg_bits_t bits = kmsg->ikm_header->msgh_bits;
 2657         mach_msg_type_name_t rname = MACH_MSGH_BITS_REMOTE(bits);
 2658         mach_msg_type_name_t lname = MACH_MSGH_BITS_LOCAL(bits);
 2659         ipc_object_t remote = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
 2660         ipc_object_t local = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
 2661 
 2662         /* translate the destination and reply ports */
 2663 
 2664         ipc_object_copyin_from_kernel(remote, rname);
 2665         if (IO_VALID(local))
 2666                 ipc_object_copyin_from_kernel(local, lname);
 2667 
 2668         /*
 2669          *      The common case is a complex message with no reply port,
 2670          *      because that is what the memory_object interface uses.
 2671          */
 2672 
 2673         if (bits == (MACH_MSGH_BITS_COMPLEX |
 2674                      MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0))) {
 2675                 bits = (MACH_MSGH_BITS_COMPLEX |
 2676                         MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0));
 2677 
 2678                 kmsg->ikm_header->msgh_bits = bits;
 2679         } else {
 2680                 bits = (MACH_MSGH_BITS_OTHER(bits) |
 2681                         MACH_MSGH_BITS(ipc_object_copyin_type(rname),
 2682                                        ipc_object_copyin_type(lname)));
 2683 
 2684                 kmsg->ikm_header->msgh_bits = bits;
 2685                 if ((bits & MACH_MSGH_BITS_COMPLEX) == 0)
 2686                         return;
 2687         }
 2688     {
 2689         mach_msg_legacy_descriptor_t    *saddr;
 2690         mach_msg_descriptor_t   *daddr;
 2691         mach_msg_body_t         *body;
 2692         mach_msg_type_number_t  i, count;
 2693 
 2694         body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
 2695         saddr = (typeof(saddr)) (body + 1);
 2696         count = body->msgh_descriptor_count;
 2697 
 2698     if(count) {
 2699         vm_offset_t dsc_adjust = 4*count;
 2700         memmove((char *)(((vm_offset_t)kmsg->ikm_header) - dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
 2701         kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header - dsc_adjust);
 2702         /* Update the message size for the larger in-kernel representation */
 2703         kmsg->ikm_header->msgh_size += dsc_adjust;
 2704     }
 2705     daddr = (mach_msg_descriptor_t *)((vm_offset_t)kmsg->ikm_header + sizeof(mach_msg_base_t));
 2706 
 2707         for (i = 0; i < count; i++, saddr++, daddr++) {
 2708             switch (saddr->type.type) {
 2709             
 2710                 case MACH_MSG_PORT_DESCRIPTOR: {
 2711                     mach_msg_type_name_t        name;
 2712                     ipc_object_t                object;
 2713                     mach_msg_legacy_port_descriptor_t   *dsc;
 2714                     mach_msg_port_descriptor_t  *dest_dsc;
 2715                 
 2716                     dsc = (typeof(dsc))&saddr->port;
 2717             dest_dsc = &daddr->port;
 2718                 
 2719                     /* this is really the type SEND, SEND_ONCE, etc. */
 2720                     name = dsc->disposition;
 2721                     object = (ipc_object_t) CAST_MACH_NAME_TO_PORT(dsc->name);
 2722                     dest_dsc->disposition = ipc_object_copyin_type(name);
 2723             dest_dsc->name = (mach_port_t)object;
 2724             dest_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
 2725                 
 2726                     if (!IO_VALID(object)) {
 2727                         break;
 2728                     }
 2729 
 2730                     ipc_object_copyin_from_kernel(object, name);
 2731                     
 2732                     /* CDY avoid circularity when the destination is also */
 2733                     /* the kernel.  This check should be changed into an  */
 2734                     /* assert when the new kobject model is in place since*/
 2735                     /* ports will not be used in kernel to kernel chats   */
 2736                         
 2737                     if (((ipc_port_t)remote)->ip_receiver != ipc_space_kernel) {
 2738                        if ((dest_dsc->disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
 2739                            ipc_port_check_circularity((ipc_port_t) object, 
 2740                                                 (ipc_port_t) remote)) {
 2741                            kmsg->ikm_header->msgh_bits |= 
 2742                                         MACH_MSGH_BITS_CIRCULAR;
 2743                        }
 2744                     }
 2745                     break;
 2746                 }
 2747                 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
 2748         case MACH_MSG_OOL_DESCRIPTOR: {
 2749                     /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
 2750              * so we don't need to do anything special. */
 2751 
 2752                     mach_msg_ool_descriptor32_t *source_dsc = &saddr->out_of_line32;
 2753                     mach_msg_ool_descriptor_t   *dest_dsc = (typeof(dest_dsc))&daddr->out_of_line;
 2754 
 2755             vm_offset_t             address = source_dsc->address;
 2756             vm_size_t                           size = source_dsc->size;
 2757             boolean_t                           deallocate = source_dsc->deallocate;
 2758             mach_msg_copy_options_t             copy = source_dsc->copy;
 2759             mach_msg_descriptor_type_t  type = source_dsc->type;
 2760 
 2761             dest_dsc->address = (void *)address;
 2762             dest_dsc->size = size;
 2763             dest_dsc->deallocate = deallocate;
 2764             dest_dsc->copy = copy;
 2765             dest_dsc->type = type;
 2766                     break;
 2767                 }
 2768         case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
 2769                     ipc_object_t                        *objects;
 2770                     unsigned int                        j;
 2771                     mach_msg_type_name_t                name;
 2772                     mach_msg_ool_ports_descriptor_t     *dest_dsc;
 2773                 
 2774                     mach_msg_ool_ports_descriptor32_t   *source_dsc = &saddr->ool_ports32;
 2775             dest_dsc = (typeof(dest_dsc))&daddr->ool_ports;
 2776 
 2777             boolean_t deallocate = source_dsc->deallocate;
 2778             mach_msg_copy_options_t copy = source_dsc->copy;
 2779             mach_msg_size_t port_count = source_dsc->count;
 2780             mach_msg_type_name_t disposition = source_dsc->disposition;
 2781 
 2782                     /* this is really the type SEND, SEND_ONCE, etc. */
 2783                     name = disposition;
 2784                     disposition = ipc_object_copyin_type(name);
 2785                 
 2786                     objects = (ipc_object_t *) (uintptr_t)source_dsc->address;
 2787                 
 2788                     for ( j = 0; j < port_count; j++) {
 2789                         ipc_object_t object = objects[j];
 2790                         
 2791                         if (!IO_VALID(object))
 2792                             continue;
 2793                         
 2794                         ipc_object_copyin_from_kernel(object, name);
 2795     
 2796                         if ((disposition == MACH_MSG_TYPE_PORT_RECEIVE) &&
 2797                             ipc_port_check_circularity(
 2798                                                        (ipc_port_t) object,
 2799                                                        (ipc_port_t) remote))
 2800                             kmsg->ikm_header->msgh_bits |= MACH_MSGH_BITS_CIRCULAR;
 2801                     }
 2802 
 2803             dest_dsc->address = objects;
 2804             dest_dsc->deallocate = deallocate;
 2805             dest_dsc->copy = copy;
 2806             dest_dsc->disposition = disposition;
 2807             dest_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
 2808             dest_dsc->count = port_count;
 2809                     break;
 2810                 }
 2811                 default: {
 2812 #if     MACH_ASSERT
 2813                     panic("ipc_kmsg_copyin_from_kernel:  bad descriptor");
 2814 #endif  /* MACH_ASSERT */
 2815                 }
 2816             }
 2817         }
 2818     }
 2819 }
 2820 #endif /* IKM_SUPPORT_LEGACY */
 2821 
 2822 /*
 2823  *      Routine:        ipc_kmsg_copyout_header
 2824  *      Purpose:
 2825  *              "Copy-out" port rights in the header of a message.
 2826  *              Operates atomically; if it doesn't succeed the
 2827  *              message header and the space are left untouched.
 2828  *              If it does succeed the remote/local port fields
 2829  *              contain port names instead of object pointers,
 2830  *              and the bits field is updated.
 2831  *
 2832  *              The notify argument implements the MACH_RCV_NOTIFY option.
 2833  *              If it is not MACH_PORT_NULL, it should name a receive right.
 2834  *              If the process of receiving the reply port creates a
 2835  *              new right in the receiving task, then the new right is
 2836  *              automatically registered for a dead-name notification,
 2837  *              with the notify port supplying the send-once right.
 2838  *      Conditions:
 2839  *              Nothing locked.
 2840  *      Returns:
 2841  *              MACH_MSG_SUCCESS        Copied out port rights.
 2842  *              MACH_RCV_INVALID_NOTIFY 
 2843  *                      Notify is non-null and doesn't name a receive right.
 2844  *                      (Either KERN_INVALID_NAME or KERN_INVALID_RIGHT.)
 2845  *              MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
 2846  *                      The space is dead.
 2847  *              MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE
 2848  *                      No room in space for another name.
 2849  *              MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
 2850  *                      Couldn't allocate memory for the reply port.
 2851  *              MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_KERNEL
 2852  *                      Couldn't allocate memory for the dead-name request.
 2853  */
 2854 
 2855 mach_msg_return_t
 2856 ipc_kmsg_copyout_header(
 2857         mach_msg_header_t       *msg,
 2858         ipc_space_t             space,
 2859         mach_port_name_t        notify)
 2860 {
 2861         mach_msg_bits_t mbits = msg->msgh_bits;
 2862         ipc_port_t dest = (ipc_port_t) msg->msgh_remote_port;
 2863 
 2864         assert(IP_VALID(dest));
 2865 
 2866     {
 2867         mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
 2868         mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
 2869         ipc_port_t reply = (ipc_port_t) msg->msgh_local_port;
 2870         mach_port_name_t dest_name, reply_name;
 2871 
 2872         if (IP_VALID(reply)) {
 2873                 ipc_port_t notify_port;
 2874                 ipc_entry_t entry;
 2875                 kern_return_t kr;
 2876 
 2877                 /*
 2878                  *      Handling notify (for MACH_RCV_NOTIFY) is tricky.
 2879                  *      The problem is atomically making a send-once right
 2880                  *      from the notify port and installing it for a
 2881                  *      dead-name request in the new entry, because this
 2882                  *      requires two port locks (on the notify port and
 2883                  *      the reply port).  However, we can safely make
 2884                  *      and consume send-once rights for the notify port
 2885                  *      as long as we hold the space locked.  This isn't
 2886                  *      an atomicity problem, because the only way
 2887                  *      to detect that a send-once right has been created
 2888                  *      and then consumed if it wasn't needed is by getting
 2889                  *      at the receive right to look at ip_sorights, and
 2890                  *      because the space is write-locked status calls can't
 2891                  *      lookup the notify port receive right.  When we make
 2892                  *      the send-once right, we lock the notify port,
 2893                  *      so any status calls in progress will be done.
 2894                  */
 2895 
 2896                 is_write_lock(space);
 2897 
 2898                 for (;;) {
 2899                         ipc_port_request_index_t request;
 2900 
 2901                         if (!space->is_active) {
 2902                                 is_write_unlock(space);
 2903                                 return (MACH_RCV_HEADER_ERROR|
 2904                                         MACH_MSG_IPC_SPACE);
 2905                         }
 2906 
 2907                         if (notify != MACH_PORT_NULL) {
 2908                                 notify_port = ipc_port_lookup_notify(space,
 2909                                                                      notify);
 2910                                 if (notify_port == IP_NULL) {
 2911                                         printf("ipc_kmsg_copyout_header: no notify port\n");
 2912                                         is_write_unlock(space);
 2913                                         return MACH_RCV_INVALID_NOTIFY;
 2914                                 }
 2915                         } else
 2916                                 notify_port = IP_NULL;
 2917 
 2918                         if ((reply_type != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
 2919                             ipc_right_reverse(space, (ipc_object_t) reply,
 2920                                               &reply_name, &entry)) {
 2921                                 /* reply port is locked and active */
 2922 
 2923                                 /*
 2924                                  *      We don't need the notify_port
 2925                                  *      send-once right, but we can't release
 2926                                  *      it here because reply port is locked.
 2927                                  *      Wait until after the copyout to
 2928                                  *      release the notify port right.
 2929                                  */
 2930 
 2931                                 assert(entry->ie_bits &
 2932                                        MACH_PORT_TYPE_SEND_RECEIVE);
 2933                                 break;
 2934                         }
 2935 
 2936                         ip_lock(reply);
 2937                         if (!ip_active(reply)) {
 2938                                 ip_release(reply);
 2939                                 ip_check_unlock(reply);
 2940 
 2941                                 if (notify_port != IP_NULL)
 2942                                         ipc_port_release_sonce(notify_port);
 2943 
 2944                                 ip_lock(dest);
 2945                                 is_write_unlock(space);
 2946 
 2947                                 reply = IP_DEAD;
 2948                                 reply_name = MACH_PORT_DEAD;
 2949                                 goto copyout_dest;
 2950                         }
 2951 
 2952                         reply_name = CAST_MACH_PORT_TO_NAME(reply);
 2953                         kr = ipc_entry_get(space, &reply_name, &entry);
 2954                         if (kr != KERN_SUCCESS) {
 2955                                 ip_unlock(reply);
 2956 
 2957                                 if (notify_port != IP_NULL)
 2958                                         ipc_port_release_sonce(notify_port);
 2959 
 2960                                 /* space is locked */
 2961                                 kr = ipc_entry_grow_table(space,
 2962                                                           ITS_SIZE_NONE);
 2963                                 if (kr != KERN_SUCCESS) {
 2964                                         /* space is unlocked */
 2965 
 2966                                         if (kr == KERN_RESOURCE_SHORTAGE) {
 2967                                                 printf("ipc_kmsg_copyout_header: can't grow kernel ipc space\n");
 2968                                                 return (MACH_RCV_HEADER_ERROR|
 2969                                                         MACH_MSG_IPC_KERNEL);
 2970                                         } else {
 2971                                                 printf("ipc_kmsg_copyout_header: can't grow user ipc space\n");
 2972                                                 return (MACH_RCV_HEADER_ERROR|
 2973                                                         MACH_MSG_IPC_SPACE);
 2974                                         }
 2975                                 }
 2976                                 /* space is locked again; start over */
 2977 
 2978                                 continue;
 2979                         }
 2980                         assert(IE_BITS_TYPE(entry->ie_bits) ==
 2981                                MACH_PORT_TYPE_NONE);
 2982                         assert(entry->ie_object == IO_NULL); 
 2983 
 2984                         if (notify_port == IP_NULL) {
 2985                                 /* not making a dead-name request */
 2986 
 2987                                 entry->ie_object = (ipc_object_t) reply;
 2988                                 break;
 2989                         }
 2990 
 2991                         kr = ipc_port_dnrequest(reply, reply_name,
 2992                                                 notify_port, &request);
 2993                         if (kr != KERN_SUCCESS) {
 2994                                 ip_unlock(reply);
 2995 
 2996                                 ipc_port_release_sonce(notify_port);
 2997 
 2998                                 ipc_entry_dealloc(space, reply_name, entry);
 2999                                 is_write_unlock(space);
 3000 
 3001                                 ip_lock(reply);
 3002                                 if (!ip_active(reply)) {
 3003                                         /* will fail next time around loop */
 3004 
 3005                                         ip_unlock(reply);
 3006                                         is_write_lock(space);
 3007                                         continue;
 3008                                 }
 3009 
 3010                                 kr = ipc_port_dngrow(reply, ITS_SIZE_NONE);
 3011                                 /* port is unlocked */
 3012                                 if (kr != KERN_SUCCESS) {
 3013                                         printf("ipc_kmsg_copyout_header: can't grow kernel ipc space2\n");
 3014                                         return (MACH_RCV_HEADER_ERROR|
 3015                                                 MACH_MSG_IPC_KERNEL);
 3016                                 }
 3017 
 3018                                 is_write_lock(space);
 3019                                 continue;
 3020                         }
 3021 
 3022                         notify_port = IP_NULL; /* don't release right below */
 3023 
 3024                         entry->ie_object = (ipc_object_t) reply;
 3025                         entry->ie_request = request;
 3026                         break;
 3027                 }
 3028 
 3029                 /* space and reply port are locked and active */
 3030 
 3031                 ip_reference(reply);    /* hold onto the reply port */
 3032 
 3033                 kr = ipc_right_copyout(space, reply_name, entry,
 3034                                        reply_type, TRUE, (ipc_object_t) reply);
 3035                 /* reply port is unlocked */
 3036                 assert(kr == KERN_SUCCESS);
 3037 
 3038                 if (notify_port != IP_NULL)
 3039                         ipc_port_release_sonce(notify_port);
 3040 
 3041                 ip_lock(dest);
 3042                 is_write_unlock(space);
 3043         } else {
 3044                 /*
 3045                  *      No reply port!  This is an easy case.
 3046                  *      We only need to have the space locked
 3047                  *      when checking notify and when locking
 3048                  *      the destination (to ensure atomicity).
 3049                  */
 3050 
 3051                 is_read_lock(space);
 3052                 if (!space->is_active) {
 3053                         is_read_unlock(space);
 3054                         return MACH_RCV_HEADER_ERROR|MACH_MSG_IPC_SPACE;
 3055                 }
 3056 
 3057                 if (notify != MACH_PORT_NULL) {
 3058                         ipc_entry_t entry;
 3059 
 3060                         /* must check notify even though it won't be used */
 3061 
 3062                         if ((entry = ipc_entry_lookup(space, notify)) == IE_NULL) {
 3063                                 printf("ipc_kmsg_copyout_header: ipc_entry_lookup failed\n");
 3064                                 is_read_unlock(space);
 3065                                 return MACH_RCV_INVALID_NOTIFY;
 3066                         }
 3067         
 3068                         if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) {
 3069                                 printf("ipc_kmsg_copyout_header: MACH_PORT_TYPE_RECEIVE not set!\n");
 3070                                 is_read_unlock(space);
 3071                                 return MACH_RCV_INVALID_NOTIFY;
 3072                         }
 3073                 }
 3074 
 3075                 ip_lock(dest);
 3076                 is_read_unlock(space);
 3077 
 3078                 reply_name = CAST_MACH_PORT_TO_NAME(reply);
 3079         }
 3080 
 3081         /*
 3082          *      At this point, the space is unlocked and the destination
 3083          *      port is locked.  (Lock taken while space was locked.)
 3084          *      reply_name is taken care of; we still need dest_name.
 3085          *      We still hold a ref for reply (if it is valid).
 3086          *
 3087          *      If the space holds receive rights for the destination,
 3088          *      we return its name for the right.  Otherwise the task
 3089          *      managed to destroy or give away the receive right between
 3090          *      receiving the message and this copyout.  If the destination
 3091          *      is dead, return MACH_PORT_DEAD, and if the receive right
 3092          *      exists somewhere else (another space, in transit)
 3093          *      return MACH_PORT_NULL.
 3094          *
 3095          *      Making this copyout operation atomic with the previous
 3096          *      copyout of the reply port is a bit tricky.  If there was
 3097          *      no real reply port (it wasn't IP_VALID) then this isn't
 3098          *      an issue.  If the reply port was dead at copyout time,
 3099          *      then we are OK, because if dest is dead we serialize
 3100          *      after the death of both ports and if dest is alive
 3101          *      we serialize after reply died but before dest's (later) death.
 3102          *      So assume reply was alive when we copied it out.  If dest
 3103          *      is alive, then we are OK because we serialize before
 3104          *      the ports' deaths.  So assume dest is dead when we look at it.
 3105          *      If reply dies/died after dest, then we are OK because
 3106          *      we serialize after dest died but before reply dies.
 3107          *      So the hard case is when reply is alive at copyout,
 3108          *      dest is dead at copyout, and reply died before dest died.
 3109          *      In this case pretend that dest is still alive, so
 3110          *      we serialize while both ports are alive.
 3111          *
 3112          *      Because the space lock is held across the copyout of reply
 3113          *      and locking dest, the receive right for dest can't move
 3114          *      in or out of the space while the copyouts happen, so
 3115          *      that isn't an atomicity problem.  In the last hard case
 3116          *      above, this implies that when dest is dead that the
 3117          *      space couldn't have had receive rights for dest at
 3118          *      the time reply was copied-out, so when we pretend
 3119          *      that dest is still alive, we can return MACH_PORT_NULL.
 3120          *
 3121          *      If dest == reply, then we have to make it look like
 3122          *      either both copyouts happened before the port died,
 3123          *      or both happened after the port died.  This special
 3124          *      case works naturally if the timestamp comparison
 3125          *      is done correctly.
 3126          */
 3127 
 3128     copyout_dest:
 3129 
 3130         if (ip_active(dest)) {
 3131                 ipc_object_copyout_dest(space, (ipc_object_t) dest,
 3132                                         dest_type, &dest_name);
 3133                 /* dest is unlocked */
 3134         } else {
 3135                 ipc_port_timestamp_t timestamp;
 3136 
 3137                 timestamp = dest->ip_timestamp;
 3138                 ip_release(dest);
 3139                 ip_check_unlock(dest);
 3140 
 3141                 if (IP_VALID(reply)) {
 3142                         ip_lock(reply);
 3143                         if (ip_active(reply) ||
 3144                             IP_TIMESTAMP_ORDER(timestamp,
 3145                                                reply->ip_timestamp))
 3146                                 dest_name = MACH_PORT_DEAD;
 3147                         else
 3148                                 dest_name = MACH_PORT_NULL;
 3149                         ip_unlock(reply);
 3150                 } else
 3151                         dest_name = MACH_PORT_DEAD;
 3152         }
 3153 
 3154         if (IP_VALID(reply))
 3155                 ipc_port_release(reply);
 3156 
 3157         msg->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
 3158                           MACH_MSGH_BITS(reply_type, dest_type));
 3159         msg->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
 3160         msg->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
 3161     }
 3162 
 3163         return MACH_MSG_SUCCESS;
 3164 }
 3165 
 3166 /*
 3167  *      Routine:        ipc_kmsg_copyout_object
 3168  *      Purpose:
 3169  *              Copy-out a port right.  Always returns a name,
 3170  *              even for unsuccessful return codes.  Always
 3171  *              consumes the supplied object.
 3172  *      Conditions:
 3173  *              Nothing locked.
 3174  *      Returns:
 3175  *              MACH_MSG_SUCCESS        The space acquired the right
 3176  *                      (name is valid) or the object is dead (MACH_PORT_DEAD).
 3177  *              MACH_MSG_IPC_SPACE      No room in space for the right,
 3178  *                      or the space is dead.  (Name is MACH_PORT_NULL.)
 3179  *              MACH_MSG_IPC_KERNEL     Kernel resource shortage.
 3180  *                      (Name is MACH_PORT_NULL.)
 3181  */
 3182 
 3183 mach_msg_return_t
 3184 ipc_kmsg_copyout_object(
 3185         ipc_space_t             space,
 3186         ipc_object_t            object,
 3187         mach_msg_type_name_t    msgt_name,
 3188         mach_port_name_t        *namep)
 3189 {
 3190         kern_return_t kr;
 3191 
 3192         if (!IO_VALID(object)) {
 3193                 *namep = CAST_MACH_PORT_TO_NAME(object);
 3194                 return MACH_MSG_SUCCESS;
 3195         }
 3196 
 3197         kr = ipc_object_copyout(space, object, msgt_name, TRUE, namep);
 3198         if (kr != KERN_SUCCESS) {
 3199                 ipc_object_destroy(object, msgt_name);
 3200 
 3201                 if (kr == KERN_INVALID_CAPABILITY)
 3202                         *namep = MACH_PORT_DEAD;
 3203                 else {
 3204                         *namep = MACH_PORT_NULL;
 3205 
 3206                         if (kr == KERN_RESOURCE_SHORTAGE)
 3207                                 return MACH_MSG_IPC_KERNEL;
 3208                         else
 3209                                 return MACH_MSG_IPC_SPACE;
 3210                 }
 3211         }
 3212 
 3213         return MACH_MSG_SUCCESS;
 3214 }
 3215 
 3216 mach_msg_descriptor_t *
 3217 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t *dsc,
 3218         mach_msg_descriptor_t *user_dsc,
 3219         ipc_space_t space,
 3220         kern_return_t *mr);
 3221 mach_msg_descriptor_t *
 3222 ipc_kmsg_copyout_port_descriptor(mach_msg_descriptor_t *dsc,
 3223         mach_msg_descriptor_t *dest_dsc,
 3224         ipc_space_t space, 
 3225         kern_return_t *mr)
 3226 {
 3227     mach_port_t                 port;
 3228     mach_port_name_t            name;
 3229     mach_msg_type_name_t                disp;
 3230 
 3231 
 3232     /* Copyout port right carried in the message */
 3233     port = dsc->port.name;
 3234     disp = dsc->port.disposition;
 3235     *mr |= ipc_kmsg_copyout_object(space, 
 3236             (ipc_object_t)port, 
 3237             disp, 
 3238             &name);
 3239 
 3240     if(current_task() == kernel_task)
 3241     {
 3242         mach_msg_port_descriptor_t *user_dsc = (typeof(user_dsc))dest_dsc;
 3243         user_dsc--; // point to the start of this port descriptor
 3244         user_dsc->name = CAST_MACH_NAME_TO_PORT(name);
 3245         user_dsc->disposition = disp;
 3246         user_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
 3247         dest_dsc = (typeof(dest_dsc))user_dsc;
 3248     } else {
 3249         mach_msg_legacy_port_descriptor_t *user_dsc = (typeof(user_dsc))dest_dsc;
 3250         user_dsc--; // point to the start of this port descriptor
 3251         user_dsc->name = CAST_MACH_PORT_TO_NAME(name);
 3252         user_dsc->disposition = disp;
 3253         user_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
 3254         dest_dsc = (typeof(dest_dsc))user_dsc;
 3255     }
 3256 
 3257     return (mach_msg_descriptor_t *)dest_dsc;
 3258 }
 3259 
 3260 mach_msg_descriptor_t *
 3261 ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t *dsc, mach_msg_descriptor_t *user_dsc, int is_64bit, vm_map_t map, mach_msg_return_t *mr);
 3262 mach_msg_descriptor_t *
 3263 ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t *dsc, mach_msg_descriptor_t *user_dsc, int is_64bit, vm_map_t map, mach_msg_return_t *mr)
 3264 {
 3265     vm_map_copy_t                       copy;
 3266     mach_vm_offset_t            rcv_addr;
 3267     mach_msg_copy_options_t             copy_options;
 3268     mach_msg_size_t                     size;
 3269     mach_msg_descriptor_type_t  dsc_type;
 3270 
 3271     //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
 3272 
 3273     copy = (vm_map_copy_t) dsc->address;
 3274     size = dsc->size;
 3275     copy_options = dsc->copy;
 3276     assert(copy_options != MACH_MSG_KALLOC_COPY_T);
 3277     dsc_type = dsc->type;
 3278     rcv_addr = 0;
 3279 
 3280     if (copy != VM_MAP_COPY_NULL) {
 3281         /*
 3282          * Check to see if there is an overwrite descriptor
 3283          * specified in the scatter list for this ool data.
 3284          * The descriptor has already been verified.
 3285          */
 3286 #if 0
 3287         if (saddr != MACH_MSG_DESCRIPTOR_NULL) {
 3288             if (differs) {
 3289                 OTHER_OOL_DESCRIPTOR *scatter_dsc;
 3290 
 3291                 scatter_dsc = (OTHER_OOL_DESCRIPTOR *)saddr;
 3292                 if (scatter_dsc->copy == MACH_MSG_OVERWRITE) {
 3293                     rcv_addr = (mach_vm_offset_t) scatter_dsc->address;
 3294                     copy_options = MACH_MSG_OVERWRITE;
 3295                 } else {
 3296                     copy_options = MACH_MSG_VIRTUAL_COPY;
 3297                 }
 3298             } else {
 3299                 mach_msg_ool_descriptor_t *scatter_dsc;
 3300 
 3301                 scatter_dsc = &saddr->out_of_line;
 3302                 if (scatter_dsc->copy == MACH_MSG_OVERWRITE) {
 3303                     rcv_addr = CAST_USER_ADDR_T(scatter_dsc->address);
 3304                     copy_options = MACH_MSG_OVERWRITE;
 3305                 } else {
 3306                     copy_options = MACH_MSG_VIRTUAL_COPY;
 3307                 }
 3308             }
 3309             INCREMENT_SCATTER(saddr, sdsc_count, differs);
 3310         }
 3311 #endif
 3312 
 3313 
 3314         /*
 3315          * Whether the data was virtually or physically
 3316          * copied we have a vm_map_copy_t for it.
 3317          * If there's an overwrite region specified
 3318          * overwrite it, otherwise do a virtual copy out.
 3319          */
 3320         kern_return_t kr;
 3321         if (copy_options == MACH_MSG_OVERWRITE && rcv_addr != 0) {
 3322             kr = vm_map_copy_overwrite(map, rcv_addr,
 3323                     copy, TRUE);
 3324         } else {
 3325             kr = vm_map_copyout(map, &rcv_addr, copy);
 3326         }       
 3327         if (kr != KERN_SUCCESS) {
 3328             if (kr == KERN_RESOURCE_SHORTAGE)
 3329                 *mr |= MACH_MSG_VM_KERNEL;
 3330             else
 3331                 *mr |= MACH_MSG_VM_SPACE;
 3332             vm_map_copy_discard(copy);
 3333             rcv_addr = 0;
 3334             size = 0;
 3335         }
 3336     } else {
 3337         rcv_addr = 0;
 3338         size = 0;
 3339     }
 3340 
 3341     /*
 3342      * Now update the descriptor as the user would see it.
 3343      * This may require expanding the descriptor to the user
 3344      * visible size.  There is already space allocated for
 3345      * this in what naddr points to.
 3346      */
 3347     if(current_task() == kernel_task)
 3348     {
 3349         mach_msg_ool_descriptor_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
 3350         user_ool_dsc--;
 3351 
 3352         user_ool_dsc->address = (void *)(uintptr_t)rcv_addr;
 3353         user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
 3354             TRUE : FALSE;
 3355         user_ool_dsc->copy = copy_options;
 3356         user_ool_dsc->type = dsc_type;
 3357         user_ool_dsc->size = size;
 3358 
 3359         user_dsc = (typeof(user_dsc))user_ool_dsc;
 3360     } else if (is_64bit) {
 3361         mach_msg_ool_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
 3362         user_ool_dsc--;
 3363 
 3364         user_ool_dsc->address = rcv_addr;
 3365         user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
 3366             TRUE : FALSE;
 3367         user_ool_dsc->copy = copy_options;
 3368         user_ool_dsc->type = dsc_type;
 3369         user_ool_dsc->size = size;
 3370 
 3371         user_dsc = (typeof(user_dsc))user_ool_dsc;
 3372     } else {
 3373         mach_msg_ool_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
 3374         user_ool_dsc--;
 3375 
 3376         user_ool_dsc->address = CAST_DOWN_EXPLICIT(uint32_t, rcv_addr);
 3377         user_ool_dsc->size = size;
 3378         user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
 3379             TRUE : FALSE;
 3380         user_ool_dsc->copy = copy_options;
 3381         user_ool_dsc->type = dsc_type;
 3382 
 3383         user_dsc = (typeof(user_dsc))user_ool_dsc;
 3384     }
 3385     return user_dsc;
 3386 }
 3387 
 3388 mach_msg_descriptor_t *
 3389 ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t *dsc,
 3390         mach_msg_descriptor_t *user_dsc,
 3391         int is_64bit,
 3392         vm_map_t map,
 3393         ipc_space_t space,
 3394         ipc_kmsg_t kmsg,
 3395         mach_msg_return_t *mr);
 3396 mach_msg_descriptor_t *
 3397 ipc_kmsg_copyout_ool_ports_descriptor(mach_msg_ool_ports_descriptor_t *dsc,
 3398         mach_msg_descriptor_t *user_dsc,
 3399         int is_64bit,
 3400         vm_map_t map,
 3401         ipc_space_t space,
 3402         ipc_kmsg_t kmsg,
 3403         mach_msg_return_t *mr)
 3404 {
 3405     mach_vm_offset_t            rcv_addr;
 3406     mach_msg_type_name_t                disp;
 3407     mach_msg_type_number_t              count, i;
 3408     vm_size_t                           ports_length, names_length;
 3409 
 3410     mach_msg_copy_options_t copy_options = MACH_MSG_VIRTUAL_COPY;
 3411 
 3412     //SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
 3413 
 3414     count = dsc->count;
 3415     disp = dsc->disposition;
 3416     ports_length = count * sizeof(mach_port_t);
 3417     names_length = count * sizeof(mach_port_name_t);
 3418 
 3419     if (ports_length != 0 && dsc->address != 0) {
 3420 
 3421         /*
 3422          * Check to see if there is an overwrite descriptor
 3423          * specified in the scatter list for this ool data.
 3424          * The descriptor has already been verified.
 3425          */
 3426 #if 0
 3427         if (saddr != MACH_MSG_DESCRIPTOR_NULL) {
 3428             if (differs) {
 3429                 OTHER_OOL_DESCRIPTOR *scatter_dsc;
 3430 
 3431                 scatter_dsc = (OTHER_OOL_DESCRIPTOR *)saddr;
 3432                 rcv_addr = (mach_vm_offset_t) scatter_dsc->address;
 3433                 copy_options = scatter_dsc->copy;
 3434             } else {
 3435                 mach_msg_ool_descriptor_t *scatter_dsc;
 3436 
 3437                 scatter_dsc = &saddr->out_of_line;
 3438                 rcv_addr = CAST_USER_ADDR_T(scatter_dsc->address);
 3439                 copy_options = scatter_dsc->copy;
 3440             }
 3441             INCREMENT_SCATTER(saddr, sdsc_count, differs);
 3442         }
 3443 #endif
 3444 
 3445         if (copy_options == MACH_MSG_VIRTUAL_COPY) {
 3446             /*
 3447              * Dynamically allocate the region
 3448              */
 3449             int anywhere = VM_MAKE_TAG(VM_MEMORY_MACH_MSG)|
 3450                 VM_FLAGS_ANYWHERE;
 3451 
 3452             kern_return_t kr;
 3453             if ((kr = mach_vm_allocate(map, &rcv_addr, 
 3454                             (mach_vm_size_t)names_length,
 3455                             anywhere)) != KERN_SUCCESS) {
 3456                 ipc_kmsg_clean_body(kmsg, 1, (mach_msg_descriptor_t *)dsc);
 3457                 rcv_addr = 0;
 3458 
 3459                 if (kr == KERN_RESOURCE_SHORTAGE){
 3460                     *mr |= MACH_MSG_VM_KERNEL;
 3461                 } else {
 3462                     *mr |= MACH_MSG_VM_SPACE;
 3463                 }
 3464             }
 3465         }
 3466 
 3467         /*
 3468          * Handle the port rights and copy out the names
 3469          * for those rights out to user-space.
 3470          */
 3471         if (rcv_addr != 0) {
 3472             mach_port_t *objects = (mach_port_t *) dsc->address;
 3473             mach_port_name_t *names = (mach_port_name_t *) dsc->address;
 3474 
 3475             /* copyout port rights carried in the message */
 3476 
 3477             for ( i = 0; i < count ; i++) {
 3478                 ipc_object_t object = (ipc_object_t)objects[i];
 3479 
 3480                 *mr |= ipc_kmsg_copyout_object(space, object,
 3481                         disp, &names[i]);
 3482             }
 3483 
 3484             /* copyout to memory allocated above */
 3485             void *data = dsc->address;
 3486             if (copyoutmap(map, data, rcv_addr, names_length) != KERN_SUCCESS)
 3487                 *mr |= MACH_MSG_VM_SPACE;
 3488             kfree(data, ports_length);
 3489         }
 3490     } else {
 3491         rcv_addr = 0;
 3492     }
 3493 
 3494     /*
 3495      * Now update the descriptor based on the information
 3496      * calculated above.
 3497      */
 3498     if(current_task() == kernel_task) {
 3499         mach_msg_ool_ports_descriptor_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
 3500         user_ool_dsc--;
 3501 
 3502         user_ool_dsc->address = (void *)(uintptr_t)rcv_addr;
 3503         user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
 3504             TRUE : FALSE;
 3505         user_ool_dsc->copy = copy_options;
 3506         user_ool_dsc->disposition = disp;
 3507         user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
 3508         user_ool_dsc->count = count;
 3509 
 3510         user_dsc = (typeof(user_dsc))user_ool_dsc;
 3511     } if (is_64bit) {
 3512         mach_msg_ool_ports_descriptor64_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
 3513         user_ool_dsc--;
 3514 
 3515         user_ool_dsc->address = rcv_addr;
 3516         user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
 3517             TRUE : FALSE;
 3518         user_ool_dsc->copy = copy_options;
 3519         user_ool_dsc->disposition = disp;
 3520         user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
 3521         user_ool_dsc->count = count;
 3522 
 3523         user_dsc = (typeof(user_dsc))user_ool_dsc;
 3524     } else {
 3525         mach_msg_ool_ports_descriptor32_t *user_ool_dsc = (typeof(user_ool_dsc))user_dsc;
 3526         user_ool_dsc--;
 3527 
 3528         user_ool_dsc->address = CAST_DOWN_EXPLICIT(uint32_t, rcv_addr);
 3529         user_ool_dsc->count = count;
 3530         user_ool_dsc->deallocate = (copy_options == MACH_MSG_VIRTUAL_COPY) ?
 3531             TRUE : FALSE;
 3532         user_ool_dsc->copy = copy_options;
 3533         user_ool_dsc->disposition = disp;
 3534         user_ool_dsc->type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
 3535 
 3536         user_dsc = (typeof(user_dsc))user_ool_dsc;
 3537     }
 3538     return user_dsc;
 3539 }
 3540 
 3541 /*
 3542  *      Routine:        ipc_kmsg_copyout_body
 3543  *      Purpose:
 3544  *              "Copy-out" port rights and out-of-line memory
 3545  *              in the body of a message.
 3546  *
 3547  *              The error codes are a combination of special bits.
 3548  *              The copyout proceeds despite errors.
 3549  *      Conditions:
 3550  *              Nothing locked.
 3551  *      Returns:
 3552  *              MACH_MSG_SUCCESS        Successful copyout.
 3553  *              MACH_MSG_IPC_SPACE      No room for port right in name space.
 3554  *              MACH_MSG_VM_SPACE       No room for memory in address space.
 3555  *              MACH_MSG_IPC_KERNEL     Resource shortage handling port right.
 3556  *              MACH_MSG_VM_KERNEL      Resource shortage handling memory.
 3557  *              MACH_MSG_INVALID_RT_DESCRIPTOR Descriptor incompatible with RT
 3558  */
 3559 
 3560 mach_msg_return_t
 3561 ipc_kmsg_copyout_body(
 3562         ipc_kmsg_t              kmsg,
 3563         ipc_space_t             space,
 3564         vm_map_t                map,
 3565         mach_msg_body_t         *slist)
 3566 {
 3567     mach_msg_body_t             *body;
 3568     mach_msg_descriptor_t       *kern_dsc, *user_dsc;
 3569     mach_msg_descriptor_t       *saddr;
 3570     mach_msg_type_number_t      dsc_count, sdsc_count;
 3571     int i;
 3572     mach_msg_return_t           mr = MACH_MSG_SUCCESS;
 3573     boolean_t                   is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
 3574 
 3575     body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
 3576     dsc_count = body->msgh_descriptor_count;
 3577     kern_dsc = (mach_msg_descriptor_t *) (body + 1);
 3578     /* Point user_dsc just after the end of all the descriptors */
 3579     user_dsc = &kern_dsc[dsc_count];
 3580 
 3581     /* Do scatter list setup */
 3582     if (slist != MACH_MSG_BODY_NULL) {
 3583     panic("Scatter lists disabled");
 3584         saddr = (mach_msg_descriptor_t *) (slist + 1);
 3585         sdsc_count = slist->msgh_descriptor_count;
 3586     }
 3587     else {
 3588         saddr = MACH_MSG_DESCRIPTOR_NULL;
 3589         sdsc_count = 0;
 3590     }
 3591 
 3592     /* Now process the descriptors */
 3593     for (i = dsc_count-1; i >= 0; i--) {
 3594         switch (kern_dsc[i].type.type) {
 3595 
 3596             case MACH_MSG_PORT_DESCRIPTOR: 
 3597                 user_dsc = ipc_kmsg_copyout_port_descriptor(&kern_dsc[i], user_dsc, space, &mr);
 3598                 break;
 3599             case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
 3600             case MACH_MSG_OOL_DESCRIPTOR : 
 3601                 user_dsc = ipc_kmsg_copyout_ool_descriptor(
 3602                         (mach_msg_ool_descriptor_t *)&kern_dsc[i], user_dsc, is_task_64bit, map, &mr);
 3603                 break;
 3604             case MACH_MSG_OOL_PORTS_DESCRIPTOR : 
 3605                 user_dsc = ipc_kmsg_copyout_ool_ports_descriptor(
 3606                         (mach_msg_ool_ports_descriptor_t *)&kern_dsc[i], user_dsc, is_task_64bit, map, space, kmsg, &mr);
 3607                 break;
 3608             default : {
 3609                           panic("untyped IPC copyout body: invalid message descriptor");
 3610                       }
 3611         }
 3612     }
 3613 
 3614     if(user_dsc != kern_dsc) {
 3615         vm_offset_t dsc_adjust = (vm_offset_t)user_dsc - (vm_offset_t)kern_dsc;
 3616         memmove((char *)((vm_offset_t)kmsg->ikm_header + dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
 3617         kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header + dsc_adjust);
 3618         /* Update the message size for the smaller user representation */
 3619         kmsg->ikm_header->msgh_size -= (mach_msg_size_t)dsc_adjust;
 3620     }
 3621 
 3622     return mr;
 3623 }
 3624 
 3625 /*
 3626  *      Routine:        ipc_kmsg_copyout_size
 3627  *      Purpose:
 3628  *              Compute the size of the message as copied out to the given
 3629  *              map. If the destination map's pointers are a different size
 3630  *              than the kernel's, we have to allow for expansion/
 3631  *              contraction of the descriptors as appropriate.
 3632  *      Conditions:
 3633  *              Nothing locked.
 3634  *      Returns:
 3635  *              size of the message as it would be received.
 3636  */
 3637 
 3638 mach_msg_size_t
 3639 ipc_kmsg_copyout_size(
 3640         ipc_kmsg_t              kmsg,
 3641         vm_map_t                map)
 3642 {
 3643     mach_msg_size_t             send_size;
 3644 
 3645     send_size = kmsg->ikm_header->msgh_size;
 3646 
 3647     boolean_t is_task_64bit = (map->max_offset > VM_MAX_ADDRESS);
 3648 
 3649 #if defined(__LP64__)
 3650         send_size -= LEGACY_HEADER_SIZE_DELTA;
 3651 #endif
 3652 
 3653     if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
 3654 
 3655         mach_msg_body_t *body;
 3656         mach_msg_descriptor_t *saddr, *eaddr;
 3657 
 3658         body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
 3659         saddr = (mach_msg_descriptor_t *) (body + 1);
 3660         eaddr = saddr + body->msgh_descriptor_count;
 3661 
 3662         for ( ; saddr < eaddr; saddr++ ) {
 3663             switch (saddr->type.type) {
 3664                 case MACH_MSG_OOL_DESCRIPTOR:
 3665                 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
 3666                 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
 3667                     if(!is_task_64bit)
 3668                         send_size -= DESC_SIZE_ADJUSTMENT;
 3669                     break;
 3670                 case MACH_MSG_PORT_DESCRIPTOR:
 3671                     send_size -= DESC_SIZE_ADJUSTMENT;
 3672                     break;
 3673                 default:
 3674                     break;
 3675             }
 3676         }
 3677     }
 3678     return send_size;
 3679 }
 3680 
 3681 /*
 3682  *      Routine:        ipc_kmsg_copyout
 3683  *      Purpose:
 3684  *              "Copy-out" port rights and out-of-line memory
 3685  *              in the message.
 3686  *      Conditions:
 3687  *              Nothing locked.
 3688  *      Returns:
 3689  *              MACH_MSG_SUCCESS        Copied out all rights and memory.
 3690  *              MACH_RCV_INVALID_NOTIFY Bad notify port.
 3691  *                      Rights and memory in the message are intact.
 3692  *              MACH_RCV_HEADER_ERROR + special bits
 3693  *                      Rights and memory in the message are intact.
 3694  *              MACH_RCV_BODY_ERROR + special bits
 3695  *                      The message header was successfully copied out.
 3696  *                      As much of the body was handled as possible.
 3697  */
 3698 
 3699 mach_msg_return_t
 3700 ipc_kmsg_copyout(
 3701         ipc_kmsg_t              kmsg,
 3702         ipc_space_t             space,
 3703         vm_map_t                map,
 3704         mach_port_name_t        notify,
 3705         mach_msg_body_t         *slist)
 3706 {
 3707         mach_msg_return_t mr;
 3708 
 3709         mr = ipc_kmsg_copyout_header(kmsg->ikm_header, space, notify);
 3710         if (mr != MACH_MSG_SUCCESS) {
 3711                 return mr;
 3712         }
 3713 
 3714         if (kmsg->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
 3715                 mr = ipc_kmsg_copyout_body(kmsg, space, map, slist);
 3716 
 3717                 if (mr != MACH_MSG_SUCCESS)
 3718                         mr |= MACH_RCV_BODY_ERROR;
 3719         }
 3720 
 3721         return mr;
 3722 }
 3723 
 3724 /*
 3725  *      Routine:        ipc_kmsg_copyout_pseudo
 3726  *      Purpose:
 3727  *              Does a pseudo-copyout of the message.
 3728  *              This is like a regular copyout, except
 3729  *              that the ports in the header are handled
 3730  *              as if they are in the body.  They aren't reversed.
 3731  *
 3732  *              The error codes are a combination of special bits.
 3733  *              The copyout proceeds despite errors.
 3734  *      Conditions:
 3735  *              Nothing locked.
 3736  *      Returns:
 3737  *              MACH_MSG_SUCCESS        Successful copyout.
 3738  *              MACH_MSG_IPC_SPACE      No room for port right in name space.
 3739  *              MACH_MSG_VM_SPACE       No room for memory in address space.
 3740  *              MACH_MSG_IPC_KERNEL     Resource shortage handling port right.
 3741  *              MACH_MSG_VM_KERNEL      Resource shortage handling memory.
 3742  */
 3743 
 3744 mach_msg_return_t
 3745 ipc_kmsg_copyout_pseudo(
 3746         ipc_kmsg_t              kmsg,
 3747         ipc_space_t             space,
 3748         vm_map_t                map,
 3749         mach_msg_body_t         *slist)
 3750 {
 3751         mach_msg_bits_t mbits = kmsg->ikm_header->msgh_bits;
 3752         ipc_object_t dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
 3753         ipc_object_t reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
 3754         mach_msg_type_name_t dest_type = MACH_MSGH_BITS_REMOTE(mbits);
 3755         mach_msg_type_name_t reply_type = MACH_MSGH_BITS_LOCAL(mbits);
 3756         mach_port_name_t dest_name, reply_name;
 3757         mach_msg_return_t mr;
 3758 
 3759         assert(IO_VALID(dest));
 3760 
 3761         mr = (ipc_kmsg_copyout_object(space, dest, dest_type, &dest_name) |
 3762               ipc_kmsg_copyout_object(space, reply, reply_type, &reply_name));
 3763 
 3764         kmsg->ikm_header->msgh_bits = mbits &~ MACH_MSGH_BITS_CIRCULAR;
 3765         kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(dest_name);
 3766         kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(reply_name);
 3767 
 3768         if (mbits & MACH_MSGH_BITS_COMPLEX) {
 3769                 mr |= ipc_kmsg_copyout_body(kmsg, space, map, slist);
 3770         }
 3771 
 3772         return mr;
 3773 }
 3774 
 3775 /*
 3776  *      Routine:        ipc_kmsg_copyout_dest
 3777  *      Purpose:
 3778  *              Copies out the destination port in the message.
 3779  *              Destroys all other rights and memory in the message.
 3780  *      Conditions:
 3781  *              Nothing locked.
 3782  */
 3783 
 3784 void
 3785 ipc_kmsg_copyout_dest(
 3786         ipc_kmsg_t      kmsg,
 3787         ipc_space_t     space)
 3788 {
 3789         mach_msg_bits_t mbits;
 3790         ipc_object_t dest;
 3791         ipc_object_t reply;
 3792         mach_msg_type_name_t dest_type;
 3793         mach_msg_type_name_t reply_type;
 3794         mach_port_name_t dest_name, reply_name;
 3795 
 3796         mbits = kmsg->ikm_header->msgh_bits;
 3797         dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
 3798         reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
 3799         dest_type = MACH_MSGH_BITS_REMOTE(mbits);
 3800         reply_type = MACH_MSGH_BITS_LOCAL(mbits);
 3801 
 3802         assert(IO_VALID(dest));
 3803 
 3804         io_lock(dest);
 3805         if (io_active(dest)) {
 3806                 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
 3807                 /* dest is unlocked */
 3808         } else {
 3809                 io_release(dest);
 3810                 io_check_unlock(dest);
 3811                 dest_name = MACH_PORT_DEAD;
 3812         }
 3813 
 3814         if (IO_VALID(reply)) {
 3815                 ipc_object_destroy(reply, reply_type);
 3816                 reply_name = MACH_PORT_NULL;
 3817         } else
 3818                 reply_name = CAST_MACH_PORT_TO_NAME(reply);
 3819 
 3820         kmsg->ikm_header->msgh_bits = (MACH_MSGH_BITS_OTHER(mbits) |
 3821                                       MACH_MSGH_BITS(reply_type, dest_type));
 3822         kmsg->ikm_header->msgh_local_port = CAST_MACH_NAME_TO_PORT(dest_name);
 3823         kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
 3824 
 3825         if (mbits & MACH_MSGH_BITS_COMPLEX) {
 3826                 mach_msg_body_t *body;
 3827 
 3828                 body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
 3829                 ipc_kmsg_clean_body(kmsg, body->msgh_descriptor_count, 
 3830                                     (mach_msg_descriptor_t *)(body + 1));
 3831         }
 3832 }
 3833 
 3834 /*
 3835  *      Routine:        ipc_kmsg_copyin_scatter
 3836  *      Purpose:
 3837  *              allocate and copyin a scatter list
 3838  *      Algorithm:
 3839  *              The gather (kmsg) is valid since it has been copied in.
 3840  *              Gather list descriptors are sequentially paired with scatter
 3841  *              list descriptors, with port descriptors in either list ignored.
 3842  *              Descriptors are consistent if the type fileds match and size
 3843  *              of the scatter descriptor is less than or equal to the
 3844  *              size of the gather descriptor.  A MACH_MSG_ALLOCATE copy
 3845  *              strategy in a scatter descriptor matches any size in the
 3846  *              corresponding gather descriptor assuming they are the same type.
 3847  *              Either list may be larger than the other.  During the
 3848  *              subsequent copy out, excess scatter descriptors are ignored
 3849  *              and excess gather descriptors default to dynamic allocation.
 3850  *
 3851  *              In the case of a size error, the scatter list is released.
 3852  *      Conditions:
 3853  *              Nothing locked.
 3854  *      Returns:
 3855  *              the allocated message body containing the scatter list.
 3856  */
 3857 
 3858 mach_msg_body_t *
 3859 ipc_kmsg_get_scatter(
 3860         mach_vm_address_t       msg_addr,
 3861        mach_msg_size_t         slist_size,
 3862         ipc_kmsg_t              kmsg)
 3863 {
 3864         mach_msg_body_t         *slist;
 3865         mach_msg_body_t         *body;
 3866         mach_msg_descriptor_t   *gstart, *gend;
 3867         mach_msg_descriptor_t   *sstart, *send;
 3868 
 3869 #if defined(__LP64__)
 3870         panic("ipc_kmsg_get_scatter called!");
 3871 #endif
 3872 
 3873         if (slist_size < sizeof(mach_msg_base_t))
 3874                 return MACH_MSG_BODY_NULL;
 3875 
 3876         slist_size -= (mach_msg_size_t)sizeof(mach_msg_header_t);
 3877         slist = (mach_msg_body_t *)kalloc(slist_size);
 3878         if (slist == MACH_MSG_BODY_NULL)
 3879                 return slist;
 3880 
 3881         if (copyin(msg_addr + sizeof(mach_msg_header_t), (char *)slist, slist_size)) {
 3882                 kfree(slist, slist_size);
 3883                 return MACH_MSG_BODY_NULL;
 3884         }
 3885 
 3886         if ((slist->msgh_descriptor_count* sizeof(mach_msg_descriptor_t)
 3887              + sizeof(mach_msg_size_t)) > slist_size) {
 3888                 kfree(slist, slist_size);
 3889                 return MACH_MSG_BODY_NULL;
 3890         }
 3891 
 3892         body = (mach_msg_body_t *) (kmsg->ikm_header + 1);
 3893         gstart = (mach_msg_descriptor_t *) (body + 1);
 3894         gend = gstart + body->msgh_descriptor_count;
 3895 
 3896         sstart = (mach_msg_descriptor_t *) (slist + 1);
 3897         send = sstart + slist->msgh_descriptor_count;
 3898 
 3899         while (gstart < gend) {
 3900             mach_msg_descriptor_type_t  g_type;
 3901 
 3902             /*
 3903              * Skip port descriptors in gather list.
 3904              */
 3905             g_type = gstart->type.type;
 3906 
 3907             if (g_type != MACH_MSG_PORT_DESCRIPTOR) {
 3908 
 3909               /*
 3910                * A scatter list with a 0 descriptor count is treated as an
 3911                * automatic size mismatch.
 3912                */
 3913               if (slist->msgh_descriptor_count == 0) {
 3914                         kfree(slist, slist_size);
 3915                         return MACH_MSG_BODY_NULL;
 3916               }
 3917 
 3918               /*
 3919                * Skip port descriptors in  scatter list.
 3920                */
 3921               while (sstart < send) {
 3922                     if (sstart->type.type != MACH_MSG_PORT_DESCRIPTOR)
 3923                         break;
 3924                     sstart++;
 3925               }
 3926 
 3927               /*
 3928                * No more scatter descriptors, we're done
 3929                */
 3930               if (sstart >= send) {
 3931                     break;
 3932               }
 3933 
 3934               /*
 3935                * Check type, copy and size fields
 3936                */
 3937                 if (g_type == MACH_MSG_OOL_DESCRIPTOR ||
 3938                     g_type == MACH_MSG_OOL_VOLATILE_DESCRIPTOR) {
 3939                     if (sstart->type.type != MACH_MSG_OOL_DESCRIPTOR &&
 3940                         sstart->type.type != MACH_MSG_OOL_VOLATILE_DESCRIPTOR) {
 3941                         kfree(slist, slist_size);
 3942                         return MACH_MSG_BODY_NULL;
 3943                     }
 3944                     if (sstart->out_of_line.copy == MACH_MSG_OVERWRITE &&
 3945                         gstart->out_of_line.size > sstart->out_of_line.size) {
 3946                         kfree(slist, slist_size);
 3947                         return MACH_MSG_BODY_NULL;
 3948                     }
 3949                 }
 3950                 else {
 3951                   if (sstart->type.type != MACH_MSG_OOL_PORTS_DESCRIPTOR) {
 3952                         kfree(slist, slist_size);
 3953                         return MACH_MSG_BODY_NULL;
 3954                   }
 3955                     if (sstart->ool_ports.copy == MACH_MSG_OVERWRITE &&
 3956                         gstart->ool_ports.count > sstart->ool_ports.count) {
 3957                         kfree(slist, slist_size);
 3958                         return MACH_MSG_BODY_NULL;
 3959                     }
 3960                 }
 3961                 sstart++;
 3962             }
 3963             gstart++;
 3964         }
 3965         return slist;
 3966 }
 3967 
 3968 
 3969 /*
 3970  *      Routine:        ipc_kmsg_free_scatter
 3971  *      Purpose:
 3972  *              Deallocate a scatter list.  Since we actually allocated
 3973  *              a body without a header, and since the header was originally
 3974  *              accounted for in slist_size, we have to ajust it down
 3975  *              before freeing the scatter list.
 3976  */
 3977 void
 3978 ipc_kmsg_free_scatter(
 3979         mach_msg_body_t *slist,
 3980         mach_msg_size_t slist_size)
 3981 {
 3982 #if defined(__LP64__)
 3983         panic("%s called; halting!", __func__);
 3984 #endif
 3985 
 3986         slist_size -= (mach_msg_size_t)sizeof(mach_msg_header_t);
 3987         kfree(slist, slist_size);
 3988 }
 3989 
 3990 
 3991 /*
 3992  *      Routine:        ipc_kmsg_copyout_to_kernel
 3993  *      Purpose:
 3994  *              Copies out the destination and reply ports in the message.
 3995  *              Leaves all other rights and memory in the message alone.
 3996  *      Conditions:
 3997  *              Nothing locked.
 3998  *
 3999  *      Derived from ipc_kmsg_copyout_dest.
 4000  *      Use by mach_msg_rpc_from_kernel (which used to use copyout_dest).
 4001  *      We really do want to save rights and memory.
 4002  */
 4003 
 4004 void
 4005 ipc_kmsg_copyout_to_kernel(
 4006         ipc_kmsg_t      kmsg,
 4007         ipc_space_t     space)
 4008 {
 4009         ipc_object_t dest;
 4010         ipc_object_t reply;
 4011         mach_msg_type_name_t dest_type;
 4012         mach_msg_type_name_t reply_type;
 4013         mach_port_name_t dest_name, reply_name;
 4014 
 4015         dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
 4016         reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
 4017         dest_type = MACH_MSGH_BITS_REMOTE(kmsg->ikm_header->msgh_bits);
 4018         reply_type = MACH_MSGH_BITS_LOCAL(kmsg->ikm_header->msgh_bits);
 4019 
 4020         assert(IO_VALID(dest));
 4021 
 4022         io_lock(dest);
 4023         if (io_active(dest)) {
 4024                 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
 4025                 /* dest is unlocked */
 4026         } else {
 4027                 io_release(dest);
 4028                 io_check_unlock(dest);
 4029                 dest_name = MACH_PORT_DEAD;
 4030         }
 4031 
 4032         reply_name = CAST_MACH_PORT_TO_NAME(reply);
 4033 
 4034         kmsg->ikm_header->msgh_bits =
 4035                 (MACH_MSGH_BITS_OTHER(kmsg->ikm_header->msgh_bits) |
 4036                                         MACH_MSGH_BITS(reply_type, dest_type));
 4037         kmsg->ikm_header->msgh_local_port =  CAST_MACH_NAME_TO_PORT(dest_name);
 4038         kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
 4039 }
 4040 
 4041 #if IKM_SUPPORT_LEGACY
 4042 void
 4043 ipc_kmsg_copyout_to_kernel_legacy(
 4044         ipc_kmsg_t      kmsg,
 4045         ipc_space_t     space)
 4046 {
 4047         ipc_object_t dest;
 4048         ipc_object_t reply;
 4049         mach_msg_type_name_t dest_type;
 4050         mach_msg_type_name_t reply_type;
 4051         mach_port_name_t dest_name, reply_name;
 4052 
 4053         dest = (ipc_object_t) kmsg->ikm_header->msgh_remote_port;
 4054         reply = (ipc_object_t) kmsg->ikm_header->msgh_local_port;
 4055         dest_type = MACH_MSGH_BITS_REMOTE(kmsg->ikm_header->msgh_bits);
 4056         reply_type = MACH_MSGH_BITS_LOCAL(kmsg->ikm_header->msgh_bits);
 4057 
 4058         assert(IO_VALID(dest));
 4059 
 4060         io_lock(dest);
 4061         if (io_active(dest)) {
 4062                 ipc_object_copyout_dest(space, dest, dest_type, &dest_name);
 4063                 /* dest is unlocked */
 4064         } else {
 4065                 io_release(dest);
 4066                 io_check_unlock(dest);
 4067                 dest_name = MACH_PORT_DEAD;
 4068         }
 4069 
 4070         reply_name = CAST_MACH_PORT_TO_NAME(reply);
 4071 
 4072         kmsg->ikm_header->msgh_bits =
 4073                 (MACH_MSGH_BITS_OTHER(kmsg->ikm_header->msgh_bits) |
 4074                                         MACH_MSGH_BITS(reply_type, dest_type));
 4075         kmsg->ikm_header->msgh_local_port =  CAST_MACH_NAME_TO_PORT(dest_name);
 4076         kmsg->ikm_header->msgh_remote_port = CAST_MACH_NAME_TO_PORT(reply_name);
 4077 
 4078     mach_msg_descriptor_t *saddr;
 4079     mach_msg_legacy_descriptor_t *daddr;
 4080     mach_msg_type_number_t i, count = ((mach_msg_base_t *)kmsg->ikm_header)->body.msgh_descriptor_count;
 4081     saddr = (mach_msg_descriptor_t *) (((mach_msg_base_t *)kmsg->ikm_header) + 1);
 4082     saddr = &saddr[count-1];
 4083     daddr = (mach_msg_legacy_descriptor_t *)&saddr[count];
 4084     daddr--;
 4085 
 4086     vm_offset_t dsc_adjust = 0;
 4087 
 4088     for (i = 0; i < count; i++, saddr--, daddr--) {
 4089     switch (saddr->type.type) {
 4090         case MACH_MSG_PORT_DESCRIPTOR: {
 4091         mach_msg_port_descriptor_t *dsc = &saddr->port;
 4092         mach_msg_legacy_port_descriptor_t *dest_dsc = &daddr->port;
 4093 
 4094         mach_port_t name = dsc->name;
 4095         mach_msg_type_name_t disposition = dsc->disposition;
 4096 
 4097         dest_dsc->name = CAST_MACH_PORT_TO_NAME(name);
 4098         dest_dsc->disposition = disposition;
 4099         dest_dsc->type = MACH_MSG_PORT_DESCRIPTOR;
 4100         break;
 4101         }
 4102     case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
 4103     case MACH_MSG_OOL_DESCRIPTOR: {
 4104         /* The sender should supply ready-made memory, i.e. a vm_map_copy_t
 4105          * so we don't need to do anything special. */
 4106 
 4107         mach_msg_ool_descriptor_t       *source_dsc = (typeof(source_dsc))&saddr->out_of_line;
 4108 
 4109             mach_msg_ool_descriptor32_t *dest_dsc = &daddr->out_of_line32;
 4110 
 4111         vm_offset_t                         address = (vm_offset_t)source_dsc->address;
 4112         vm_size_t                       size = source_dsc->size;
 4113         boolean_t                       deallocate = source_dsc->deallocate;
 4114         mach_msg_copy_options_t         copy = source_dsc->copy;
 4115         mach_msg_descriptor_type_t  type = source_dsc->type;
 4116 
 4117         dest_dsc->address = address;
 4118         dest_dsc->size = size;
 4119         dest_dsc->deallocate = deallocate;
 4120         dest_dsc->copy = copy;
 4121         dest_dsc->type = type;
 4122         break;
 4123         }
 4124     case MACH_MSG_OOL_PORTS_DESCRIPTOR: {
 4125         mach_msg_ool_ports_descriptor_t         *source_dsc = (typeof(source_dsc))&saddr->ool_ports;
 4126 
 4127             mach_msg_ool_ports_descriptor32_t   *dest_dsc = &daddr->ool_ports32;
 4128 
 4129         vm_offset_t                         address = (vm_offset_t)source_dsc->address;
 4130         vm_size_t                       port_count = source_dsc->count;
 4131         boolean_t                       deallocate = source_dsc->deallocate;
 4132         mach_msg_copy_options_t         copy = source_dsc->copy;
 4133         mach_msg_descriptor_type_t  type = source_dsc->type;
 4134 
 4135         dest_dsc->address = address;
 4136         dest_dsc->count = port_count;
 4137         dest_dsc->deallocate = deallocate;
 4138         dest_dsc->copy = copy;
 4139         dest_dsc->type = type;
 4140         break;
 4141         }
 4142         default: {
 4143 #if     MACH_ASSERT
 4144         panic("ipc_kmsg_copyin_from_kernel:  bad descriptor");
 4145 #endif  /* MACH_ASSERT */
 4146                  }
 4147     }
 4148     }
 4149 
 4150     if(count) {
 4151         dsc_adjust = 4*count;
 4152         memmove((char *)((vm_offset_t)kmsg->ikm_header + dsc_adjust), kmsg->ikm_header, sizeof(mach_msg_base_t));
 4153         kmsg->ikm_header = (mach_msg_header_t *)((vm_offset_t)kmsg->ikm_header + dsc_adjust);
 4154         /* Update the message size for the smaller user representation */
 4155         kmsg->ikm_header->msgh_size -= dsc_adjust;
 4156     }
 4157 }
 4158 #endif /* IKM_SUPPORT_LEGACY */
 4159 
 4160 
 4161 #include <mach_kdb.h>
 4162 #if     MACH_KDB
 4163 
 4164 #include <ddb/db_output.h>
 4165 #include <ipc/ipc_print.h>
 4166 /*
 4167  * Forward declarations
 4168  */
 4169 void ipc_msg_print_untyped(
 4170         mach_msg_body_t         *body);
 4171 
 4172 const char * ipc_type_name(
 4173         int             type_name,
 4174         boolean_t       received);
 4175 
 4176 const char *
 4177 msgh_bit_decode(
 4178         mach_msg_bits_t bit);
 4179 
 4180 const char *
 4181 mm_copy_options_string(
 4182         mach_msg_copy_options_t option);
 4183 
 4184 void db_print_msg_uid(mach_msg_header_t *);
 4185 
 4186 
 4187 const char *
 4188 ipc_type_name(
 4189         int             type_name,
 4190         boolean_t       received)
 4191 {
 4192         switch (type_name) {
 4193                 case MACH_MSG_TYPE_PORT_NAME:
 4194                 return "port_name";
 4195                 
 4196                 case MACH_MSG_TYPE_MOVE_RECEIVE:
 4197                 if (received) {
 4198                         return "port_receive";
 4199                 } else {
 4200                         return "move_receive";
 4201                 }
 4202                 
 4203                 case MACH_MSG_TYPE_MOVE_SEND:
 4204                 if (received) {
 4205                         return "port_send";
 4206                 } else {
 4207                         return "move_send";
 4208                 }
 4209                 
 4210                 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
 4211                 if (received) {
 4212                         return "port_send_once";
 4213                 } else {
 4214                         return "move_send_once";
 4215                 }
 4216                 
 4217                 case MACH_MSG_TYPE_COPY_SEND:
 4218                 return "copy_send";
 4219                 
 4220                 case MACH_MSG_TYPE_MAKE_SEND:
 4221                 return "make_send";
 4222                 
 4223                 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
 4224                 return "make_send_once";
 4225                 
 4226                 default:
 4227                 return (char *) 0;
 4228         }
 4229 }
 4230                 
 4231 void
 4232 ipc_print_type_name(
 4233         int     type_name)
 4234 {
 4235         const char *name = ipc_type_name(type_name, TRUE);
 4236         if (name) {
 4237                 printf("%s", name);
 4238         } else {
 4239                 printf("type%d", type_name);
 4240         }
 4241 }
 4242 
 4243 /*
 4244  * ipc_kmsg_print       [ debug ]
 4245  */
 4246 void
 4247 ipc_kmsg_print(
 4248         ipc_kmsg_t      kmsg)
 4249 {
 4250         iprintf("kmsg=0x%x\n", kmsg);
 4251         iprintf("ikm_next=0x%x, prev=0x%x, size=%d",
 4252                 kmsg->ikm_next,
 4253                 kmsg->ikm_prev,
 4254                 kmsg->ikm_size);
 4255         printf("\n");
 4256         ipc_msg_print(kmsg->ikm_header);
 4257 }
 4258 
 4259 const char *
 4260 msgh_bit_decode(
 4261         mach_msg_bits_t bit)
 4262 {
 4263         switch (bit) {
 4264             case MACH_MSGH_BITS_COMPLEX:        return "complex";
 4265             case MACH_MSGH_BITS_CIRCULAR:       return "circular";
 4266             default:                            return (char *) 0;
 4267         }
 4268 }
 4269 
 4270 /*
 4271  * ipc_msg_print        [ debug ]
 4272  */
 4273 void
 4274 ipc_msg_print(
 4275         mach_msg_header_t       *msgh)
 4276 {
 4277         mach_msg_bits_t mbits;
 4278         unsigned int    bit, i;
 4279         const char      *bit_name;
 4280         int             needs_comma;
 4281 
 4282         mbits = msgh->msgh_bits;
 4283         iprintf("msgh_bits=0x%x:  l=0x%x,r=0x%x\n",
 4284                 mbits,
 4285                 MACH_MSGH_BITS_LOCAL(msgh->msgh_bits),
 4286                 MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
 4287 
 4288         mbits = MACH_MSGH_BITS_OTHER(mbits) & MACH_MSGH_BITS_USED;
 4289         db_indent += 2;
 4290         if (mbits)
 4291                 iprintf("decoded bits:  ");
 4292         needs_comma = 0;
 4293         for (i = 0, bit = 1; i < sizeof(mbits) * 8; ++i, bit <<= 1) {
 4294                 if ((mbits & bit) == 0)
 4295                         continue;
 4296                 bit_name = msgh_bit_decode((mach_msg_bits_t)bit);
 4297                 if (bit_name)
 4298                         printf("%s%s", needs_comma ? "," : "", bit_name);
 4299                 else
 4300                         printf("%sunknown(0x%x),", needs_comma ? "," : "", bit);
 4301                 ++needs_comma;
 4302         }
 4303         if (msgh->msgh_bits & ~MACH_MSGH_BITS_USED) {
 4304                 printf("%sunused=0x%x,", needs_comma ? "," : "",
 4305                        msgh->msgh_bits & ~MACH_MSGH_BITS_USED);
 4306         }
 4307         printf("\n");
 4308         db_indent -= 2;
 4309 
 4310         needs_comma = 1;
 4311         if (msgh->msgh_remote_port) {
 4312                 iprintf("remote=0x%x(", msgh->msgh_remote_port);
 4313                 ipc_print_type_name(MACH_MSGH_BITS_REMOTE(msgh->msgh_bits));
 4314                 printf(")");
 4315         } else {
 4316                 iprintf("remote=null");
 4317         }
 4318 
 4319         if (msgh->msgh_local_port) {
 4320                 printf("%slocal=%p(", needs_comma ? "," : "",
 4321                        msgh->msgh_local_port);
 4322                 ipc_print_type_name(MACH_MSGH_BITS_LOCAL(msgh->msgh_bits));
 4323                 printf(")\n");
 4324         } else {
 4325                 printf("local=null\n");
 4326         }
 4327 
 4328         iprintf("msgh_id=%d, size=%d\n",
 4329                 msgh->msgh_id,
 4330                 msgh->msgh_size);
 4331 
 4332         if (mbits & MACH_MSGH_BITS_COMPLEX) {   
 4333                 ipc_msg_print_untyped((mach_msg_body_t *) (msgh + 1));
 4334         }
 4335 }
 4336 
 4337 
 4338 const char *
 4339 mm_copy_options_string(
 4340         mach_msg_copy_options_t option)
 4341 {
 4342         const char      *name;
 4343 
 4344         switch (option) {
 4345             case MACH_MSG_PHYSICAL_COPY:
 4346                 name = "PHYSICAL";
 4347                 break;
 4348             case MACH_MSG_VIRTUAL_COPY:
 4349                 name = "VIRTUAL";
 4350                 break;
 4351             case MACH_MSG_OVERWRITE:
 4352                 name = "OVERWRITE";
 4353                 break;
 4354             case MACH_MSG_ALLOCATE:
 4355                 name = "ALLOCATE";
 4356                 break;
 4357             case MACH_MSG_KALLOC_COPY_T:
 4358                 name = "KALLOC_COPY_T";
 4359                 break;
 4360             default:
 4361                 name = "unknown";
 4362                 break;
 4363         }
 4364         return name;
 4365 }
 4366 
 4367 void
 4368 ipc_msg_print_untyped(
 4369         mach_msg_body_t         *body)
 4370 {
 4371     mach_msg_descriptor_t       *saddr, *send;
 4372     mach_msg_descriptor_type_t  type;
 4373 
 4374     iprintf("%d descriptors %d: \n", body->msgh_descriptor_count);
 4375 
 4376     saddr = (mach_msg_descriptor_t *) (body + 1);
 4377     send = saddr + body->msgh_descriptor_count;
 4378 
 4379     for ( ; saddr < send; saddr++ ) {
 4380         
 4381         type = saddr->type.type;
 4382 
 4383         switch (type) {
 4384             
 4385             case MACH_MSG_PORT_DESCRIPTOR: {
 4386                 mach_msg_port_descriptor_t *dsc;
 4387 
 4388                 dsc = &saddr->port;
 4389                 iprintf("-- PORT name = 0x%x disp = ", dsc->name);
 4390                 ipc_print_type_name(dsc->disposition);
 4391                 printf("\n");
 4392                 break;
 4393             }
 4394             case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
 4395             case MACH_MSG_OOL_DESCRIPTOR: {
 4396                 mach_msg_ool_descriptor_t *dsc;
 4397                 
 4398                 dsc = &saddr->out_of_line;
 4399                 iprintf("-- OOL%s addr = 0x%x size = 0x%x copy = %s %s\n",
 4400                         type == MACH_MSG_OOL_DESCRIPTOR ? "" : " VOLATILE",
 4401                         dsc->address, dsc->size,
 4402                         mm_copy_options_string(dsc->copy),
 4403                         dsc->deallocate ? "DEALLOC" : "");
 4404                 break;
 4405             } 
 4406             case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
 4407                 mach_msg_ool_ports_descriptor_t *dsc;
 4408 
 4409                 dsc = &saddr->ool_ports;
 4410 
 4411                 iprintf("-- OOL_PORTS addr = 0x%x count = 0x%x ",
 4412                           dsc->address, dsc->count);
 4413                 printf("disp = ");
 4414                 ipc_print_type_name(dsc->disposition);
 4415                 printf(" copy = %s %s\n",
 4416                        mm_copy_options_string(dsc->copy),
 4417                        dsc->deallocate ? "DEALLOC" : "");
 4418                 break;
 4419             }
 4420 
 4421             default: {
 4422                 iprintf("-- UNKNOWN DESCRIPTOR 0x%x\n", type);
 4423                 break;
 4424             }
 4425         }
 4426     }
 4427 }
 4428 #endif  /* MACH_KDB */

Cache object: 84f4c321eeea09d58337d27eef9ca0a3


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