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


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

FreeBSD/Linux Kernel Cross Reference
sys/compat/mach/mach_message.c

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

    1 /*      $NetBSD: mach_message.c,v 1.45 2005/02/26 23:10:19 perry Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Emmanuel Dreyfus
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.45 2005/02/26 23:10:19 perry Exp $");
   41 
   42 #include "opt_ktrace.h"
   43 #include "opt_compat_mach.h" /* For COMPAT_MACH in <sys/ktrace.h> */
   44 #include "opt_compat_darwin.h"
   45 
   46 #include <sys/types.h>
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/signal.h>
   50 #include <sys/proc.h>
   51 #include <sys/kernel.h>
   52 #include <sys/queue.h>
   53 #include <sys/malloc.h>
   54 #include <sys/pool.h>
   55 #ifdef KTRACE
   56 #include <sys/ktrace.h>
   57 #endif
   58 
   59 #include <uvm/uvm_extern.h>
   60 #include <uvm/uvm_map.h>
   61 
   62 #include <compat/mach/mach_types.h>
   63 #include <compat/mach/mach_message.h>
   64 #include <compat/mach/mach_port.h>
   65 #include <compat/mach/mach_exec.h>
   66 #include <compat/mach/mach_clock.h>
   67 #include <compat/mach/mach_syscallargs.h>
   68 
   69 #ifdef COMPAT_DARWIN
   70 #include <compat/darwin/darwin_exec.h>
   71 #endif
   72 
   73 /* Mach message pool */
   74 static struct pool mach_message_pool;
   75 
   76 static inline
   77     int mach_msg_send(struct lwp *, mach_msg_header_t *, int *, size_t);
   78 static inline int mach_msg_recv(struct lwp *, mach_msg_header_t *,
   79     int, size_t, unsigned int, mach_port_t);
   80 static inline
   81     struct lwp *mach_get_target_task(struct lwp *, struct mach_port *);
   82 static inline void mach_drop_rights(struct mach_right *, int);
   83 static inline
   84     void mach_trade_rights(struct lwp *, struct lwp *, mach_port_t *, int);
   85 static inline
   86     int mach_trade_rights_complex(struct lwp *, struct mach_message *);
   87 
   88 int
   89 mach_sys_msg_overwrite_trap(l, v, retval)
   90         struct lwp *l;
   91         void *v;
   92         register_t *retval;
   93 {
   94         struct mach_sys_msg_overwrite_trap_args /* {
   95                 syscallarg(mach_msg_header_t *) msg;
   96                 syscallarg(mach_msg_option_t) option;
   97                 syscallarg(mach_msg_size_t) send_size;
   98                 syscallarg(mach_msg_size_t) rcv_size;
   99                 syscallarg(mach_port_name_t) rcv_name;
  100                 syscallarg(mach_msg_timeout_t) timeout;
  101                 syscallarg(mach_port_name_t) notify;
  102                 syscallarg(mach_msg_header_t *) rcv_msg;
  103                 syscallarg(mach_msg_size_t) scatter_list_size;
  104         } */ *uap = v;
  105         size_t send_size, recv_size;
  106         mach_msg_header_t *msg;
  107         int opt;
  108 
  109         *retval = MACH_MSG_SUCCESS;
  110         send_size = SCARG(uap, send_size);
  111         recv_size = SCARG(uap, rcv_size);
  112         opt = SCARG(uap, option);
  113 
  114         /* XXX not safe enough: lots of big messages will kill us */
  115         if (send_size > MACH_MAX_MSG_LEN) {
  116                 *retval = MACH_SEND_TOO_LARGE;
  117                 return 0;
  118         }
  119         if (recv_size > MACH_MAX_MSG_LEN) {
  120                 *retval = MACH_RCV_TOO_LARGE;
  121                 return 0;
  122         }
  123 
  124         /*
  125          * Two options: receive or send. If both are
  126          * set, we must send, and then receive. If
  127          * send fail, then we skip recieve.
  128          */
  129         msg = SCARG(uap, msg);
  130         if (opt & MACH_SEND_MSG)
  131                 *retval = mach_msg_send(l, msg, &opt, send_size);
  132 
  133         if ((opt & MACH_RCV_MSG) && (*retval == MACH_MSG_SUCCESS)) {
  134                 /*
  135                  * Find a buffer for the reply.
  136                  */
  137                 if (SCARG(uap, rcv_msg) != NULL)
  138                         msg = SCARG(uap, rcv_msg);
  139                 else if (SCARG(uap, msg) != NULL)
  140                         msg = SCARG(uap, msg);
  141                 else {
  142                         *retval = MACH_RCV_INVALID_DATA;
  143                         return 0;
  144                 }
  145 
  146                 *retval = mach_msg_recv(l, msg, opt, recv_size,
  147                     SCARG(uap, timeout), SCARG(uap, rcv_name));
  148         }
  149 
  150         return 0;
  151 }
  152 
  153 /*
  154  * Send a Mach message. This returns a Mach message error code.
  155  */
  156 static inline int
  157 mach_msg_send(l, msg, option, send_size)
  158         struct lwp *l;
  159         mach_msg_header_t *msg;
  160         int *option;
  161         size_t send_size;
  162 {
  163         struct mach_emuldata *med;
  164         struct mach_port *mp;
  165         struct proc *p = l->l_proc;
  166         mach_msg_header_t *sm;
  167         struct mach_service *srv;
  168         mach_port_t ln;
  169         mach_port_t rn;
  170         struct mach_right *lr = NULL;
  171         struct mach_right *rr;
  172         int rights;
  173         int bits;
  174         int ret;
  175         size_t reply_size;
  176         int error = 0;
  177 
  178         if (msg == NULL)
  179                 return MACH_SEND_INVALID_DATA;
  180 
  181         /*
  182          * Allocate memory for the message and its reply,
  183          * and copy the whole message in the kernel.
  184          */
  185         sm = malloc(send_size, M_EMULDATA, M_WAITOK);
  186         if ((error = copyin(msg, sm, send_size)) != 0) {
  187                 ret = MACH_SEND_INVALID_DATA;
  188                 goto out1;
  189         }
  190 
  191 #ifdef KTRACE
  192         /* Dump the Mach message */
  193         if (KTRPOINT(p, KTR_MMSG))
  194                 ktrmmsg(p, (char *)sm, send_size);
  195 #endif
  196         /*
  197          * Handle rights in the message
  198          */
  199         ln = sm->msgh_local_port;
  200         rn = sm->msgh_remote_port;
  201 
  202         lr = mach_right_check(ln, l, MACH_PORT_TYPE_ALL_RIGHTS);
  203         rr = mach_right_check(rn, l, MACH_PORT_TYPE_ALL_RIGHTS);
  204         if ((rr == NULL) || (rr->mr_port == NULL)) {
  205 #ifdef DEBUG_MACH
  206                 printf("msg id %d: invalid dest\n", sm->msgh_id);
  207 #endif
  208                 ret = MACH_SEND_INVALID_DEST;
  209                 goto out1;
  210         }
  211 
  212         /*
  213          * Check that the process has a send right on
  214          * the remote port.
  215          */
  216         rights = (MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_SEND_ONCE);
  217         if (mach_right_check(rn, l, rights) == NULL) {
  218                 ret = MACH_SEND_INVALID_RIGHT;
  219                 goto out1;
  220         }
  221 
  222         /*
  223          * If the remote port is a special port (host, kernel,
  224          * clock, or io_master), the message will be handled
  225          * by the kernel.
  226          */
  227         med = (struct mach_emuldata *)p->p_emuldata;
  228         mp = rr->mr_port;
  229         if (mp->mp_flags & MACH_MP_INKERNEL) {
  230                 struct mach_trap_args args;
  231                 mach_msg_header_t *rm;
  232                 size_t min_reqlen, max_replen;
  233 
  234                 /*
  235                  * Look for the function that will handle it,
  236                  * using the message id.
  237                  */
  238                 for (srv = mach_services_table; srv->srv_id; srv++)
  239                         if (srv->srv_id == sm->msgh_id)
  240                                 break;
  241 
  242                 /*
  243                  * If no match, give up, and display a warning.
  244                  */
  245                 if (srv->srv_handler == NULL) {
  246                         uprintf("No mach server for id = %d\n",
  247                             sm->msgh_id);
  248                         ret = MACH_SEND_INVALID_DEST;
  249                         goto out1;
  250                 }
  251                 min_reqlen = srv->srv_reqlen;
  252                 max_replen = srv->srv_replen;
  253 
  254                 /*
  255                  * Special case when the kernel behaves as
  256                  * the client: replies to exceptions and
  257                  * notifications. There will be no reply,
  258                  * as we already receive a reply.
  259                  * - request and reply are swapped
  260                  * - there will be no reply, so set lr to NULL.
  261                  * - skip the lr == NULL tests
  262                  * XXX This is inelegant.
  263                  */
  264                 if ((sm->msgh_id >= 2501) && (sm->msgh_id <= 2503)) {
  265                         min_reqlen = srv->srv_replen;
  266                         max_replen = srv->srv_reqlen;
  267                         lr = NULL;
  268                         goto skip_null_lr;
  269                 }
  270 
  271                 /*
  272                  * Check that the local port is valid, else
  273                  * we will not be able to send the reply
  274                  */
  275                 if ((lr == NULL) ||
  276                     (lr->mr_port == NULL) ||
  277                     (lr->mr_port->mp_recv == NULL)) {
  278 #ifdef DEBUG_MACH
  279                         printf("msg id %d: invalid src\n", sm->msgh_id);
  280 #endif
  281                         ret = MACH_SEND_INVALID_REPLY;
  282                         goto out1;
  283                 }
  284 skip_null_lr:
  285 
  286                 /*
  287                  * Sanity check message length. We do not want the
  288                  * server to:
  289                  * 1) use kernel memory located after
  290                  *    the end of the request message.
  291                  */
  292                 if (send_size < min_reqlen) {
  293 #ifdef DEBUG_MACH
  294                         printf("mach server %s: smsg overflow: "
  295                             "send = %d, min = %d\n",
  296                             srv->srv_name, send_size, min_reqlen);
  297 #endif
  298                         ret = MACH_SEND_MSG_TOO_SMALL;
  299                         goto out1;
  300                 }
  301 
  302                 /*
  303                  * 2) Overwrite kernel memory after the end of the
  304                  *    reply message buffer. This check is the
  305                  *    responsibility of the server.
  306                  */
  307 
  308 
  309                 /*
  310                  * Invoke the server. We give it the opportunity
  311                  * to shorten recv_size if there is less data in
  312                  * the reply than what the sender expected.
  313                  * If lr is NULL, this is a no reply operation.
  314                  */
  315                 reply_size = max_replen;
  316                 if (lr != NULL)
  317                         rm = malloc(reply_size, M_EMULDATA, M_WAITOK | M_ZERO);
  318                 else
  319                         rm = NULL;
  320 
  321                 args.l = l;
  322                 args.tl = mach_get_target_task(l, mp);
  323                 args.smsg = sm;
  324                 args.rmsg = rm;
  325                 args.rsize = &reply_size;
  326                 args.ssize = send_size;
  327                 if ((ret = (*srv->srv_handler)(&args)) != 0)
  328                         goto out1;
  329 
  330                 /*
  331                  * No-reply opration: everything is done.
  332                  * Change option so that we skip the
  333                  * receive stage.
  334                  */
  335                 if (lr == NULL) {
  336                         *option &= ~MACH_RCV_MSG;
  337                         return MACH_MSG_SUCCESS;
  338                 }
  339 
  340 #ifdef DIAGNOSTIC
  341                 /*
  342                  * Catch potential bug in the server (sanity
  343                  * check #2): did it output a larger message
  344                  * then the one that was allocated?
  345                  */
  346                 if ((*option & MACH_RCV_MSG) && (reply_size > max_replen)) {
  347                         uprintf("mach_msg: reply too big in %s\n",
  348                             srv->srv_name);
  349                 }
  350 #endif
  351 
  352                 /*
  353                  * Queue the reply.
  354                  */
  355                 mp = lr->mr_port;
  356                 (void)mach_message_get(rm, reply_size, mp, NULL);
  357 #ifdef DEBUG_MACH_MSG
  358                 printf("pid %d: message queued on port %p (%d) [%p]\n",
  359                     p->p_pid, mp, rm->msgh_id,
  360                     mp->mp_recv->mr_sethead);
  361                 if (sm->msgh_id == 404)
  362                         printf("*** msg to bootstrap. port = %p, "
  363                             "recv = %p [%p]\n", mach_bootstrap_port,
  364                             mach_bootstrap_port->mp_recv,
  365                             mach_bootstrap_port->mp_recv->mr_sethead);
  366 #endif
  367                 wakeup(mp->mp_recv->mr_sethead);
  368                 ret = MACH_MSG_SUCCESS;
  369 out1:
  370                 free(sm, M_EMULDATA);
  371 
  372                 return ret;
  373         }
  374 
  375         /*
  376          * The message is not to be handled by the kernel.
  377          * Check that there is a valid receiver, and
  378          * queue the message in the remote port.
  379          */
  380         mp = rr->mr_port; /* (mp != NULL) already checked */
  381         if (mp->mp_recv == NULL) {
  382 #ifdef DEBUG_MACH
  383                 printf("msg id %d: invalid dst\n", sm->msgh_id);
  384 #endif
  385                 free(sm, M_EMULDATA);
  386                 return MACH_SEND_INVALID_DEST;
  387         }
  388 
  389         (void)mach_message_get(sm, send_size, mp, l);
  390 #ifdef DEBUG_MACH_MSG
  391         printf("pid %d: message queued on port %p (%d) [%p]\n",
  392             p->p_pid, mp, sm->msgh_id,
  393             mp->mp_recv->mr_sethead);
  394 #endif
  395         /*
  396          * Drop any right carried by the message.
  397          */
  398         if (lr != NULL) {
  399                 bits = MACH_MSGH_LOCAL_BITS(sm->msgh_bits);
  400                 mach_drop_rights(lr, bits);
  401         }
  402 
  403         if (rr != NULL) {
  404                 bits = MACH_MSGH_REMOTE_BITS(sm->msgh_bits);
  405                 mach_drop_rights(rr, bits);
  406         }
  407 
  408         /*
  409          * Wakeup any process awaiting for this message.
  410          */
  411         wakeup(mp->mp_recv->mr_sethead);
  412 
  413         return MACH_MSG_SUCCESS;
  414 }
  415 
  416 /*
  417  * Receive a Mach message. This returns a Mach message error code.
  418  */
  419 static inline int
  420 mach_msg_recv(l, urm, option, recv_size, timeout, mn)
  421         struct lwp *l;
  422         mach_msg_header_t *urm;
  423         int option;
  424         size_t recv_size;
  425         unsigned int timeout;
  426         mach_port_t mn;
  427 {
  428         struct mach_port *mp;
  429         struct proc *p = l->l_proc;
  430         struct mach_message *mm;
  431         mach_port_t tmp;
  432         struct mach_right *cmr;
  433         struct mach_right *mr;
  434         int bits;
  435         int ret;
  436         int error = 0;
  437 
  438 
  439         if (option & MACH_RCV_TIMEOUT)
  440                 timeout = timeout * hz / 1000;
  441         else
  442                 timeout = 0;
  443 
  444         /*
  445          * Check for receive right on the port.
  446          */
  447         mr = mach_right_check(mn, l, MACH_PORT_TYPE_RECEIVE);
  448         if (mr == NULL) {
  449 
  450                 /*
  451                  * Is it a port set?
  452                  */
  453                 mr = mach_right_check(mn, l, MACH_PORT_TYPE_PORT_SET);
  454                 if (mr == NULL)
  455                         return MACH_RCV_INVALID_NAME;
  456 
  457                 /*
  458                  * This is a port set. For each port in the
  459                  * port set, check we have receive right, and
  460                  * and check if we have some message.
  461                  */
  462                 LIST_FOREACH(cmr, &mr->mr_set, mr_setlist) {
  463                         if ((mach_right_check(cmr->mr_name, l,
  464                             MACH_PORT_TYPE_RECEIVE)) == NULL)
  465                                 return MACH_RCV_INVALID_NAME;
  466 
  467                         mp = cmr->mr_port;
  468 #ifdef DEBUG_MACH
  469                         if (mp->mp_recv != cmr)
  470                                 uprintf("mach_msg_trap: bad receive "
  471                                     "port/right\n");
  472 #endif
  473                         if (mp->mp_count != 0)
  474                                 break;
  475                 }
  476 
  477                 /*
  478                  * If cmr is NULL then we found no message on
  479                  * any port. Sleep on the port set until we get
  480                  * some or until we get a timeout.
  481                  */
  482                 if (cmr == NULL) {
  483 #ifdef DEBUG_MACH_MSG
  484                         printf("pid %d: wait on port %p [%p]\n",
  485                             p->p_pid, mp, mr->mr_sethead);
  486 #endif
  487                         error = tsleep(mr->mr_sethead, PZERO|PCATCH,
  488                             "mach_msg", timeout);
  489                         if ((error == ERESTART) || (error == EINTR))
  490                                 return MACH_RCV_INTERRUPTED;
  491 
  492                         /*
  493                          * Check we did not loose the receive right
  494                          * while we were sleeping.
  495                          */
  496                         if ((mach_right_check(mn, l,
  497                              MACH_PORT_TYPE_PORT_SET)) == NULL)
  498                                 return  MACH_RCV_PORT_DIED;
  499 
  500                         /*
  501                          * Is there any pending message for
  502                          * a port in the port set?
  503                          */
  504                         LIST_FOREACH(cmr, &mr->mr_set, mr_setlist) {
  505                                 mp = cmr->mr_port;
  506                                 if (mp->mp_count != 0)
  507                                         break;
  508                         }
  509 
  510                         if (cmr == NULL)
  511                                 return MACH_RCV_TIMED_OUT;
  512                 }
  513 
  514                 /*
  515                  * We found a port with a pending message.
  516                  */
  517                 mp = cmr->mr_port;
  518 
  519         } else {
  520                 /*
  521                  * This is a receive on a simple port (no port set).
  522                  * If there is no message queued on the port,
  523                  * block until we get some.
  524                  */
  525                 mp = mr->mr_port;
  526 
  527 #ifdef DEBUG_MACH
  528                 if (mp->mp_recv != mr)
  529                         uprintf("mach_msg_trap: bad receive "
  530                             "port/right\n");
  531 #endif
  532 #ifdef DEBUG_MACH_MSG
  533                 printf("pid %d: wait on port %p [%p]\n",
  534                     p->p_pid, mp, mr->mr_sethead);
  535 #endif
  536                 if (mp->mp_count == 0) {
  537                         error = tsleep(mr->mr_sethead, PZERO|PCATCH,
  538                             "mach_msg", timeout);
  539                         if ((error == ERESTART) || (error == EINTR))
  540                                 return MACH_RCV_INTERRUPTED;
  541 
  542                         /*
  543                          * Check we did not lose the receive right
  544                          * while we were sleeping.
  545                          */
  546                         if ((mach_right_check(mn, l,
  547                              MACH_PORT_TYPE_RECEIVE)) == NULL)
  548                                 return MACH_RCV_PORT_DIED;
  549 
  550                         if (mp->mp_count == 0)
  551                                 return MACH_RCV_TIMED_OUT;
  552                 }
  553         }
  554 
  555         /*
  556          * Dequeue the message.
  557          * XXX Do we really need to lock here? There could be
  558          * only one reader process, so mm will not disapear
  559          * except if there is a port refcount error in our code.
  560          */
  561         lockmgr(&mp->mp_msglock, LK_SHARED, NULL);
  562         mm = TAILQ_FIRST(&mp->mp_msglist);
  563 #ifdef DEBUG_MACH_MSG
  564         printf("pid %d: dequeue message on port %p (id %d)\n",
  565             p->p_pid, mp, mm->mm_msg->msgh_id);
  566 #endif
  567 
  568         ret = MACH_MSG_SUCCESS;
  569         if (mm->mm_size > recv_size) {
  570                 struct mach_short_reply sr;
  571 
  572                 ret = MACH_RCV_TOO_LARGE;
  573                 /*
  574                  * If MACH_RCV_LARGE was not set, destroy the message.
  575                  */
  576                 if ((option & MACH_RCV_LARGE) == 0) {
  577                         free(mm->mm_msg, M_EMULDATA);
  578                         mach_message_put_shlocked(mm);
  579                         goto unlock;
  580                 }
  581 
  582                 /*
  583                  * If MACH_RCV_TOO_LARGE is set, then return
  584                  * a message with just header and trailer. The
  585                  * size in the header should correspond to the
  586                  * whole message, so just copy the whole header.
  587                  */
  588                 memcpy(&sr, mm->mm_msg, sizeof(mach_msg_header_t));
  589                 mach_set_trailer(&sr, sizeof(sr));
  590 
  591                 if ((error = copyout(&sr, urm, sizeof(sr))) != 0) {
  592                         ret = MACH_RCV_INVALID_DATA;
  593                         goto unlock;
  594                 }
  595 #ifdef KTRACE
  596                 /* Dump the Mach message */
  597                 if (KTRPOINT(p, KTR_MMSG))
  598                         ktrmmsg(p, (char *)&sr, sizeof(sr));
  599 #endif
  600                 goto unlock;
  601         }
  602 
  603         /*
  604          * Get rights carried by the message if it is not a
  605          * reply from the kernel.
  606          * XXX mm->mm_l could contain stall data. Reference
  607          * the thread's kernel port instead?
  608          */
  609         if (mm->mm_l != NULL) {
  610                 mach_port_t *mnp;
  611 #ifdef DEBUG_MACH
  612                 printf("mach_msg: non kernel-reply message\n");
  613 #endif
  614                 /*
  615                  * Turn local and remote port names into
  616                  * names in the local process namespace.
  617                  */
  618                 bits = MACH_MSGH_LOCAL_BITS(mm->mm_msg->msgh_bits);
  619                 mnp = &mm->mm_msg->msgh_local_port;
  620                 mach_trade_rights(l, mm->mm_l, mnp, bits);
  621 
  622                 bits = MACH_MSGH_REMOTE_BITS(mm->mm_msg->msgh_bits);
  623                 mnp = &mm->mm_msg->msgh_remote_port;
  624                 mach_trade_rights(l, mm->mm_l, mnp, bits);
  625 
  626                 /*
  627                  * The same operation must be done to all
  628                  * port descriptors carried with the message.
  629                  */
  630                 if ((mm->mm_msg->msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
  631                     ((ret = mach_trade_rights_complex(l, mm)) != 0))
  632                         goto unlock;
  633 
  634                 /*
  635                  * swap local and remote ports, and
  636                  * corresponding bits as well.
  637                  */
  638                 bits = (bits & 0xffff0000) |
  639                     ((bits & 0xff00) >> 8) |
  640                     ((bits & 0x00ff) << 8);
  641                 tmp = mm->mm_msg->msgh_remote_port;
  642                 mm->mm_msg->msgh_remote_port =
  643                     mm->mm_msg->msgh_local_port;
  644                 mm->mm_msg->msgh_local_port = tmp;
  645         }
  646 
  647         /*
  648          * Copy the message to userland.
  649          */
  650         if ((error = copyout(mm->mm_msg, urm, mm->mm_size)) != 0) {
  651                 ret = MACH_RCV_INVALID_DATA;
  652                 goto unlock;
  653         }
  654 #ifdef KTRACE
  655         /* Dump the Mach message */
  656         if (KTRPOINT(p, KTR_MMSG))
  657                 ktrmmsg(p, (char *)mm->mm_msg, mm->mm_size);
  658 #endif
  659 
  660         free(mm->mm_msg, M_EMULDATA);
  661         mach_message_put_shlocked(mm); /* decrease mp_count */
  662 unlock:
  663         lockmgr(&mp->mp_msglock, LK_RELEASE, NULL);
  664 
  665         return ret;
  666 }
  667 
  668 
  669 int
  670 mach_sys_msg_trap(l, v, retval)
  671         struct lwp *l;
  672         void *v;
  673         register_t *retval;
  674 {
  675         struct mach_sys_msg_trap_args /* {
  676                 syscallarg(mach_msg_header_t *) msg;
  677                 syscallarg(mach_msg_option_t) option;
  678                 syscallarg(mach_msg_size_t) send_size;
  679                 syscallarg(mach_msg_size_t) rcv_size;
  680                 syscallarg(mach_port_name_t) rcv_name;
  681                 syscallarg(mach_msg_timeout_t) timeout;
  682                 syscallarg(mach_port_name_t) notify;
  683         } */ *uap = v;
  684         struct mach_sys_msg_overwrite_trap_args cup;
  685 
  686         SCARG(&cup, msg) = SCARG(uap, msg);
  687         SCARG(&cup, option) = SCARG(uap, option);
  688         SCARG(&cup, send_size) = SCARG(uap, send_size);
  689         SCARG(&cup, rcv_size) = SCARG(uap, rcv_size);
  690         SCARG(&cup, rcv_name) = SCARG(uap, rcv_name);
  691         SCARG(&cup, timeout) = SCARG(uap, timeout);
  692         SCARG(&cup, notify) = SCARG(uap, notify);
  693         SCARG(&cup, rcv_msg) = NULL;
  694         SCARG(&cup, scatter_list_size) = 0;
  695 
  696         return mach_sys_msg_overwrite_trap(l, &cup, retval);
  697 }
  698 
  699 static inline  struct lwp *
  700 mach_get_target_task(l, mp)
  701         struct lwp *l;
  702         struct mach_port *mp;
  703 {
  704         struct proc *tp;
  705         struct lwp *tl;
  706 
  707         switch (mp->mp_datatype) {
  708         case MACH_MP_PROC:
  709                 tp = (struct proc *)mp->mp_data;
  710                 tl = proc_representative_lwp(tp);
  711                 break;
  712 
  713         case MACH_MP_LWP:
  714                 tl = (struct lwp *)mp->mp_data;
  715                 break;
  716 
  717         default:
  718                 tl = l;
  719                 break;
  720         }
  721 
  722         return tl;
  723 }
  724 
  725 static inline void
  726 mach_drop_rights(mr, bits)
  727         struct mach_right *mr;
  728         int bits;
  729 {
  730         int rights;
  731 
  732         switch (bits) {
  733         case MACH_MSG_TYPE_MOVE_SEND:
  734                 rights = MACH_PORT_TYPE_SEND;
  735                 break;
  736         case MACH_MSG_TYPE_MOVE_SEND_ONCE:
  737                 rights = MACH_PORT_TYPE_SEND_ONCE;
  738                 break;
  739         case MACH_MSG_TYPE_MOVE_RECEIVE:
  740                 /* Recv. right is lost when msg is received */
  741         case MACH_MSG_TYPE_MAKE_SEND:
  742         case MACH_MSG_TYPE_COPY_SEND:
  743         case MACH_MSG_TYPE_MAKE_SEND_ONCE:
  744         default:
  745                 rights = 0;
  746                 break;
  747         }
  748 
  749         if (rights != 0)
  750                 mach_right_put(mr, rights);
  751 
  752         return;
  753 }
  754 
  755 /*
  756  * When a messages is transmitted from one process to another,
  757  * we need to make sure the port names are in the receiver process
  758  * namespace.
  759  */
  760 static inline void
  761 mach_trade_rights(ll, rl, mnp, bits)
  762         struct lwp *ll;         /* local lwp (receiver, current lwp) */
  763         struct lwp *rl;         /* remote lwp (sender) */
  764         mach_port_t *mnp;       /* pointer to the port name */
  765         int bits;               /* right bits */
  766 {
  767         int lr;                 /* local right type (to be added) */
  768         int rr;                 /* remote right type */
  769         struct mach_right *lmr; /* right in the local process */
  770         struct mach_right *rmr; /* right in the remote process */
  771 
  772         switch (bits) {
  773         case MACH_MSG_TYPE_MAKE_SEND:
  774                 rr = MACH_PORT_TYPE_RECEIVE;
  775                 lr = MACH_PORT_TYPE_SEND;
  776                 break;
  777 
  778         case MACH_MSG_TYPE_COPY_SEND:
  779         case MACH_MSG_TYPE_MOVE_SEND:
  780                 rr = MACH_PORT_TYPE_SEND;
  781                 lr = MACH_PORT_TYPE_SEND;
  782                 break;
  783 
  784         case MACH_MSG_TYPE_MAKE_SEND_ONCE:
  785                 rr = MACH_PORT_TYPE_RECEIVE;
  786                 lr = MACH_PORT_TYPE_SEND_ONCE;
  787                 break;
  788 
  789         case MACH_MSG_TYPE_MOVE_SEND_ONCE:
  790                 rr = MACH_PORT_TYPE_SEND_ONCE;
  791                 lr = MACH_PORT_TYPE_SEND_ONCE;
  792                 break;
  793 
  794         case MACH_MSG_TYPE_MOVE_RECEIVE:
  795                 rr = MACH_PORT_TYPE_RECEIVE;
  796                 lr = MACH_PORT_TYPE_RECEIVE;
  797                 break;
  798 
  799         default:
  800                 rr = 0;
  801                 lr = 0;
  802                 break;
  803         }
  804 
  805         /* Get the right in the remote process (sender) */
  806         rmr = NULL;
  807         if (lr != 0)
  808                 rmr = mach_right_check(*mnp, rl, rr);
  809 
  810         /* Translate it into a right in the local process (receiver) */
  811         if (rmr != NULL) {
  812                 lmr = mach_right_get(rmr->mr_port, ll, lr, 0);
  813                 *mnp = lmr->mr_name;
  814         } else {
  815                 *mnp = 0;
  816         }
  817 
  818         return;
  819 }
  820 
  821 /*
  822  * Turn rights carried by complex messages into rights in
  823  * the local namespace. Returns a Mach messsage error
  824  * XXX Nothing is there yet to remove the rights from the
  825  * sender namespace, it should be done at send time and it
  826  * is not done yet.
  827  */
  828 static inline int
  829 mach_trade_rights_complex(l, mm)
  830         struct lwp *l;
  831         struct mach_message *mm;
  832 {
  833         struct mach_complex_msg *mcm;
  834         unsigned int i, count;
  835         unsigned long begin, end;
  836 
  837         /*
  838          * Sanity check the descriptor count.
  839          * Note that all descriptor types
  840          * have the same size, hence it is
  841          * safe to not take the descriptor
  842          * type into account here.
  843          */
  844         mcm = (struct mach_complex_msg *)mm->mm_msg;
  845         count = mcm->mcm_body.msgh_descriptor_count;
  846         begin = (u_long)mcm;
  847         end = (u_long)&mcm->mcm_desc.gen[count];
  848 
  849         if ((end - begin) > mm->mm_size) {
  850 #ifdef DEBUG_MACH
  851                 printf("msg id %d: invalid count\n", mm->mm_msg->msgh_id);
  852 #endif
  853                 return MACH_SEND_INVALID_DATA;
  854         }
  855 
  856         for (i = 0; i < count; i++) {
  857                 switch (mcm->mcm_desc.gen[i].type) {
  858                 case MACH_MSG_PORT_DESCRIPTOR:
  859                         mach_trade_rights(l, mm->mm_l,
  860                             &mcm->mcm_desc.port[i].name,
  861                             mcm->mcm_desc.port[i].disposition);
  862                         break;
  863 
  864                 case MACH_MSG_OOL_PORTS_DESCRIPTOR: {   /* XXX untested */
  865                         struct proc *rp;        /* remote process */
  866                         struct proc *lp;        /* local process */
  867                         void *lumnp;            /* local user address */
  868                         void *rumnp;            /* remote user address */
  869                         int disp;               /* disposition*/
  870                         size_t size;            /* data size */
  871                         int count;              /* descriptor count */
  872                         mach_port_t *kmnp;
  873                         void *kaddr;
  874                         int error;
  875                         int j;
  876 
  877                         rp = mm->mm_l->l_proc;
  878                         lp = l->l_proc;
  879                         disp = mcm->mcm_desc.ool_ports[i].disposition;
  880                         rumnp = mcm->mcm_desc.ool_ports[i].address;
  881                         count = mcm->mcm_desc.ool_ports[i].count;
  882                         size = count * sizeof(*kmnp);
  883                         kaddr = NULL;
  884                         lumnp = NULL;
  885 
  886                         /* This allocates kmnp */
  887                         error = mach_ool_copyin(rp, rumnp, &kaddr, size, 0);
  888                         if (error != 0)
  889                                 return MACH_SEND_INVALID_DATA;
  890 
  891                         kmnp = (mach_port_t *)kaddr;
  892                         for (j = 0; j < count; j++)
  893                                 mach_trade_rights(l, mm->mm_l, &kmnp[j], disp);
  894 
  895                         /* This frees kmnp */
  896                         if ((error = mach_ool_copyout(lp, kmnp, &lumnp,
  897                             size, MACH_OOL_FREE|MACH_OOL_TRACE)) != 0)
  898                                 return MACH_SEND_INVALID_DATA;
  899 
  900                         mcm->mcm_desc.ool_ports[i].address = lumnp;
  901                         break;
  902                 }
  903 
  904                 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
  905 #ifdef DEBUG_MACH
  906                         printf("MACH_MSG_OOL_VOLATILE_DESCRIPTOR\n");
  907 #endif
  908                         /* FALLTHROUGH */
  909                 case MACH_MSG_OOL_DESCRIPTOR: { /* XXX untested */
  910                         struct proc *rp;        /* remote process */
  911                         struct proc *lp;        /* local process */
  912                         void *ludata;           /* local user address */
  913                         void *rudata;           /* remote user address */
  914                         size_t size;            /* data size */
  915                         void *kdata;
  916                         int error;
  917 
  918                         rp = mm->mm_l->l_proc;
  919                         lp = l->l_proc;
  920                         rudata = mcm->mcm_desc.ool[i].address;
  921                         size = mcm->mcm_desc.ool[i].size;
  922                         kdata = NULL;
  923                         ludata = NULL;
  924 
  925                         /*
  926                          * XXX This is inefficient for large chunk of OOL
  927                          * memory. Think about remapping COW when possible.
  928                          */
  929 
  930                         /* This allocates kdata */
  931                         error = mach_ool_copyin(rp, rudata, &kdata, size, 0);
  932                         if (error != 0)
  933                                 return MACH_SEND_INVALID_DATA;
  934 
  935                         /* This frees kdata */
  936                         if ((error = mach_ool_copyout(lp, kdata, &ludata,
  937                             size, MACH_OOL_FREE|MACH_OOL_TRACE)) != 0)
  938                                 return MACH_SEND_INVALID_DATA;
  939 
  940                         mcm->mcm_desc.ool_ports[i].address = ludata;
  941                         break;
  942                 }
  943                 default:
  944 #ifdef DEBUG_MACH
  945                         printf("unknown descriptor type %d\n",
  946                             mcm->mcm_desc.gen[i].type);
  947 #endif
  948                         break;
  949                 }
  950         }
  951 
  952         return MACH_MSG_SUCCESS;
  953 }
  954 
  955 inline int
  956 mach_ool_copyin(p, uaddr, kaddr, size, flags)
  957         struct proc *p;
  958         const void *uaddr;
  959         void **kaddr;
  960         size_t size;
  961         int flags;
  962 {
  963         int error;
  964         void *kbuf;
  965 
  966         /*
  967          * Sanity check OOL size to avoid DoS on malloc: useless once
  968          * we remap data instead of copying it. In the meantime,
  969          * disabled since it makes some OOL transfer fail.
  970          */
  971 #if 0
  972         if (size > MACH_MAX_OOL_LEN)
  973                 return ENOMEM;
  974 #endif
  975 
  976         if (*kaddr == NULL)
  977                 kbuf = malloc(size, M_EMULDATA, M_WAITOK);
  978         else
  979                 kbuf = *kaddr;
  980 
  981         if ((error = copyin_proc(p, (void *)uaddr, kbuf, size)) != 0) {
  982                 if (*kaddr == NULL)
  983                         free(kbuf, M_EMULDATA);
  984                 return error;
  985         }
  986 
  987 #ifdef KTRACE
  988         if (size > PAGE_SIZE)
  989                 size = PAGE_SIZE;
  990         if ((flags & MACH_OOL_TRACE) && KTRPOINT(p, KTR_MOOL))
  991                 ktrmool(p, kaddr, size, uaddr);
  992 #endif
  993 
  994         *kaddr = kbuf;
  995         return 0;
  996 }
  997 
  998 inline int
  999 mach_ool_copyout(p, kaddr, uaddr, size, flags)
 1000         struct proc *p;
 1001         void *kaddr;
 1002         void **uaddr;
 1003         size_t size;
 1004         int flags;
 1005 {
 1006         vaddr_t ubuf;
 1007         int error = 0;
 1008 
 1009         /*
 1010          * Sanity check OOL size to avoid DoS on malloc: useless once
 1011          * we remap data instead of copying it. In the meantime,
 1012          * disabled since it makes some OOL transfer fail.
 1013          */
 1014 #if 0
 1015         if (size > MACH_MAX_OOL_LEN) {
 1016                 error = ENOMEM;
 1017                 goto out;
 1018         }
 1019 #endif
 1020 
 1021         if (*uaddr == NULL)
 1022                 ubuf = (vaddr_t)vm_map_min(&p->p_vmspace->vm_map);
 1023         else
 1024                 ubuf = (vaddr_t)*uaddr;
 1025 
 1026         /* Never map anything at address zero: this is a red zone */
 1027         if (ubuf == (vaddr_t)NULL)
 1028                 ubuf += PAGE_SIZE;
 1029 
 1030         if ((error = uvm_map(&p->p_vmspace->vm_map, &ubuf,
 1031             round_page(size), NULL, UVM_UNKNOWN_OFFSET, 0,
 1032             UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_ALL,
 1033             UVM_INH_COPY, UVM_ADV_NORMAL, UVM_FLAG_COPYONW))) != 0)
 1034                 goto out;
 1035 
 1036         if ((error = copyout_proc(p, kaddr, (void *)ubuf, size)) != 0)
 1037                 goto out;
 1038 
 1039 #ifdef KTRACE
 1040         if (size > PAGE_SIZE)
 1041                 size = PAGE_SIZE;
 1042         if ((flags & MACH_OOL_TRACE) && KTRPOINT(p, KTR_MOOL))
 1043                 ktrmool(p, kaddr, size, (void *)ubuf);
 1044 #endif
 1045 
 1046 out:
 1047         if (flags & MACH_OOL_FREE)
 1048                 free(kaddr, M_EMULDATA);
 1049 
 1050         if (error == 0)
 1051                 *uaddr = (void *)ubuf;
 1052         return error;
 1053 }
 1054 
 1055 
 1056 inline void
 1057 mach_set_trailer(msgh, size)
 1058         void *msgh;
 1059         size_t size;
 1060 {
 1061         mach_msg_trailer_t *trailer;
 1062         char *msg = (char *)msgh;
 1063 
 1064         trailer = (mach_msg_trailer_t *)&msg[size - sizeof(*trailer)];
 1065         trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
 1066         trailer->msgh_trailer_size = sizeof(*trailer);
 1067 
 1068         return;
 1069 }
 1070 
 1071 inline void
 1072 mach_set_header(rep, req, size)
 1073         void *rep;
 1074         void *req;
 1075         size_t size;
 1076 {
 1077         mach_msg_header_t *rephdr = rep;
 1078         mach_msg_header_t *reqhdr = req;
 1079 
 1080         rephdr->msgh_bits =
 1081                 MACH_MSGH_REPLY_LOCAL_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE);
 1082         rephdr->msgh_size = size - sizeof(mach_msg_trailer_t);
 1083         rephdr->msgh_local_port = reqhdr->msgh_local_port;
 1084         rephdr->msgh_remote_port = 0;
 1085         rephdr->msgh_id = reqhdr->msgh_id + 100;
 1086 
 1087         return;
 1088 }
 1089 
 1090 inline void
 1091 mach_add_port_desc(msg, name)
 1092         void *msg;
 1093         mach_port_name_t name;
 1094 {
 1095         struct mach_complex_msg *mcm = msg;
 1096         int i;
 1097 
 1098         if ((mcm->mcm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0) {
 1099                 mcm->mcm_header.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
 1100                 mcm->mcm_body.msgh_descriptor_count = 0;
 1101         }
 1102 
 1103         i = mcm->mcm_body.msgh_descriptor_count;
 1104 
 1105         mcm->mcm_desc.port[i].name = name;
 1106         mcm->mcm_desc.port[i].disposition = MACH_MSG_TYPE_MOVE_SEND;
 1107         mcm->mcm_desc.port[i].type = MACH_MSG_PORT_DESCRIPTOR;
 1108 
 1109         mcm->mcm_body.msgh_descriptor_count++;
 1110         return;
 1111 }
 1112 
 1113 inline void
 1114 mach_add_ool_ports_desc(msg, addr, count)
 1115         void *msg;
 1116         void *addr;
 1117         int count;
 1118 {
 1119         struct mach_complex_msg *mcm = msg;
 1120         int i;
 1121 
 1122         if ((mcm->mcm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0) {
 1123                 mcm->mcm_header.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
 1124                 mcm->mcm_body.msgh_descriptor_count = 0;
 1125         }
 1126 
 1127         i = mcm->mcm_body.msgh_descriptor_count;
 1128 
 1129         mcm->mcm_desc.ool_ports[i].address = addr;
 1130         mcm->mcm_desc.ool_ports[i].count = count;
 1131         mcm->mcm_desc.ool_ports[i].copy = MACH_MSG_ALLOCATE;
 1132         mcm->mcm_desc.ool_ports[i].disposition = MACH_MSG_TYPE_MOVE_SEND;
 1133         mcm->mcm_desc.ool_ports[i].type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
 1134 
 1135         mcm->mcm_body.msgh_descriptor_count++;
 1136         return;
 1137 }
 1138 
 1139 inline void mach_add_ool_desc(msg, addr, size)
 1140         void *msg;
 1141         void *addr;
 1142         size_t size;
 1143 {
 1144         struct mach_complex_msg *mcm = msg;
 1145         int i;
 1146 
 1147         if ((mcm->mcm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0) {
 1148                 mcm->mcm_header.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
 1149                 mcm->mcm_body.msgh_descriptor_count = 0;
 1150         }
 1151 
 1152         i = mcm->mcm_body.msgh_descriptor_count;
 1153 
 1154         mcm->mcm_desc.ool[i].address = addr;
 1155         mcm->mcm_desc.ool[i].size = size;
 1156         mcm->mcm_desc.ool[i].deallocate = 0;
 1157         mcm->mcm_desc.ool[i].copy = MACH_MSG_ALLOCATE;
 1158         mcm->mcm_desc.ool[i].type = MACH_MSG_OOL_DESCRIPTOR;
 1159 
 1160         mcm->mcm_body.msgh_descriptor_count++;
 1161         return;
 1162 }
 1163 
 1164 void
 1165 mach_message_init(void)
 1166 {
 1167         pool_init(&mach_message_pool, sizeof (struct mach_message),
 1168             0, 0, 0, "mach_message_pool", NULL);
 1169         return;
 1170 }
 1171 
 1172 struct mach_message *
 1173 mach_message_get(msgh, size, mp, l)
 1174         mach_msg_header_t *msgh;
 1175         size_t size;
 1176         struct mach_port *mp;
 1177         struct lwp *l;
 1178 {
 1179         struct mach_message *mm;
 1180 
 1181         mm = (struct mach_message *)pool_get(&mach_message_pool, PR_WAITOK);
 1182         bzero(mm, sizeof(*mm));
 1183         mm->mm_msg = msgh;
 1184         mm->mm_size = size;
 1185         mm->mm_port = mp;
 1186         mm->mm_l = l;
 1187 
 1188         lockmgr(&mp->mp_msglock, LK_EXCLUSIVE, NULL);
 1189         TAILQ_INSERT_TAIL(&mp->mp_msglist, mm, mm_list);
 1190         mp->mp_count++;
 1191         lockmgr(&mp->mp_msglock, LK_RELEASE, NULL);
 1192 
 1193         return mm;
 1194 }
 1195 
 1196 void
 1197 mach_message_put(mm)
 1198         struct mach_message *mm;
 1199 {
 1200         struct mach_port *mp;
 1201 
 1202         mp = mm->mm_port;
 1203 
 1204         lockmgr(&mp->mp_msglock, LK_EXCLUSIVE, NULL);
 1205         mach_message_put_exclocked(mm);
 1206         lockmgr(&mp->mp_msglock, LK_RELEASE, NULL);
 1207 
 1208         return;
 1209 }
 1210 
 1211 void
 1212 mach_message_put_shlocked(mm)
 1213         struct mach_message *mm;
 1214 {
 1215         struct mach_port *mp;
 1216 
 1217         mp = mm->mm_port;
 1218 
 1219         lockmgr(&mp->mp_msglock, LK_UPGRADE, NULL);
 1220         mach_message_put_exclocked(mm);
 1221         lockmgr(&mp->mp_msglock, LK_DOWNGRADE, NULL);
 1222 
 1223         return;
 1224 }
 1225 
 1226 void
 1227 mach_message_put_exclocked(mm)
 1228         struct mach_message *mm;
 1229 {
 1230         struct mach_port *mp;
 1231 
 1232         mp = mm->mm_port;
 1233 
 1234         TAILQ_REMOVE(&mp->mp_msglist, mm, mm_list);
 1235         mp->mp_count--;
 1236 
 1237         pool_put(&mach_message_pool, mm);
 1238 
 1239         return;
 1240 }
 1241 
 1242 #ifdef DEBUG_MACH
 1243 void
 1244 mach_debug_message(void)
 1245 {
 1246         struct lwp *l;
 1247         struct mach_emuldata *med;
 1248         struct mach_right *mr;
 1249         struct mach_right *mrs;
 1250         struct mach_port *mp;
 1251         struct mach_message *mm;
 1252 
 1253         LIST_FOREACH(l, &alllwp, l_list) {
 1254                 if ((l->l_proc->p_emul != &emul_mach) &&
 1255 #ifdef COMPAT_DARWIN
 1256                     (l->l_proc->p_emul != &emul_darwin) &&
 1257 #endif
 1258                     1)
 1259                         continue;
 1260 
 1261                 med = l->l_proc->p_emuldata;
 1262                 LIST_FOREACH(mr, &med->med_right, mr_list)
 1263                         if ((mr->mr_type & MACH_PORT_TYPE_PORT_SET) == 0) {
 1264                                 mp = mr->mr_port;
 1265                                 if (mp == NULL)
 1266                                         continue;
 1267 
 1268                                 printf("port %p(%d) ", mp, mp->mp_count);
 1269 
 1270                                 TAILQ_FOREACH(mm, &mp->mp_msglist, mm_list)
 1271                                         printf("%d ", mm->mm_msg->msgh_id);
 1272 
 1273                                 printf("\n");
 1274                                 continue;
 1275                         }
 1276                         /* Port set... */
 1277                         LIST_FOREACH(mrs, &mr->mr_set, mr_setlist) {
 1278                                 mp = mrs->mr_port;
 1279                                 if (mp == NULL)
 1280                                         continue;
 1281 
 1282                                 printf("port %p(%d) ", mp, mp->mp_count);
 1283 
 1284                                 TAILQ_FOREACH(mm, &mp->mp_msglist, mm_list)
 1285                                         printf("%d ", mm->mm_msg->msgh_id);
 1286 
 1287                                 printf("\n");
 1288                         }
 1289         }
 1290         return;
 1291 }
 1292 
 1293 #endif /* DEBUG_MACH */

Cache object: 7a12ed73c5948bb9984993d8ff726520


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