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_port.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_port.c,v 1.60 2006/11/16 01:32:44 christos 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 "opt_compat_darwin.h"
   40 
   41 #include <sys/cdefs.h>
   42 __KERNEL_RCSID(0, "$NetBSD: mach_port.c,v 1.60 2006/11/16 01:32:44 christos Exp $");
   43 
   44 #include <sys/types.h>
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/signal.h>
   48 #include <sys/pool.h>
   49 #include <sys/queue.h>
   50 #include <sys/malloc.h>
   51 #include <sys/proc.h>
   52 
   53 #include <compat/mach/mach_types.h>
   54 #include <compat/mach/mach_message.h>
   55 #include <compat/mach/mach_port.h>
   56 #include <compat/mach/mach_iokit.h>
   57 #include <compat/mach/mach_clock.h>
   58 #include <compat/mach/mach_exec.h>
   59 #include <compat/mach/mach_errno.h>
   60 #include <compat/mach/mach_notify.h>
   61 #include <compat/mach/mach_services.h>
   62 #include <compat/mach/mach_syscallargs.h>
   63 
   64 #ifdef COMPAT_DARWIN
   65 #include <compat/darwin/darwin_exec.h>
   66 #endif
   67 
   68 /* Right and port pools, list of all rights and its lock */
   69 static struct pool mach_port_pool;
   70 static struct pool mach_right_pool;
   71 
   72 struct mach_port *mach_bootstrap_port;
   73 struct mach_port *mach_clock_port;
   74 struct mach_port *mach_io_master_port;
   75 struct mach_port *mach_saved_bootstrap_port;
   76 
   77 int
   78 mach_sys_reply_port(struct lwp *l, void *v, register_t *retval)
   79 {
   80         struct mach_right *mr;
   81 
   82         mr = mach_right_get(mach_port_get(), l, MACH_PORT_TYPE_RECEIVE, 0);
   83         *retval = (register_t)mr->mr_name;
   84 
   85         return 0;
   86 }
   87 
   88 int
   89 mach_sys_thread_self_trap(struct lwp *l, void *v, register_t *retval)
   90 {
   91         struct mach_lwp_emuldata *mle;
   92         struct mach_right *mr;
   93 
   94         mle = l->l_emuldata;
   95         mr = mach_right_get(mle->mle_kernel, l, MACH_PORT_TYPE_SEND, 0);
   96         *retval = (register_t)mr->mr_name;
   97 
   98         return 0;
   99 }
  100 
  101 
  102 int
  103 mach_sys_task_self_trap(struct lwp *l, void *v, register_t *retval)
  104 {
  105         struct mach_emuldata *med;
  106         struct mach_right *mr;
  107 
  108         med = (struct mach_emuldata *)l->l_proc->p_emuldata;
  109         mr = mach_right_get(med->med_kernel, l, MACH_PORT_TYPE_SEND, 0);
  110         *retval = (register_t)mr->mr_name;
  111 
  112         return 0;
  113 }
  114 
  115 
  116 int
  117 mach_sys_host_self_trap(struct lwp *l, void *v, register_t *retval)
  118 {
  119         struct mach_emuldata *med;
  120         struct mach_right *mr;
  121 
  122         med = (struct mach_emuldata *)l->l_proc->p_emuldata;
  123         mr = mach_right_get(med->med_host, l, MACH_PORT_TYPE_SEND, 0);
  124         *retval = (register_t)mr->mr_name;
  125 
  126         return 0;
  127 }
  128 
  129 int
  130 mach_port_deallocate(args)
  131         struct mach_trap_args *args;
  132 {
  133         mach_port_deallocate_request_t *req = args->smsg;
  134         mach_port_deallocate_reply_t *rep = args->rmsg;
  135         size_t *msglen = args->rsize;
  136         struct lwp *l = args->l;
  137         mach_port_t mn;
  138         struct mach_right *mr;
  139 
  140         mn = req->req_name;
  141         if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_REF_RIGHTS)) != NULL)
  142                 mach_right_put(mr, MACH_PORT_TYPE_REF_RIGHTS);
  143 
  144         *msglen = sizeof(*rep);
  145         mach_set_header(rep, req, *msglen);
  146 
  147         rep->rep_retval = 0;
  148 
  149         mach_set_trailer(rep, *msglen);
  150 
  151         return 0;
  152 }
  153 
  154 int
  155 mach_port_destroy(args)
  156         struct mach_trap_args *args;
  157 {
  158         mach_port_destroy_request_t *req = args->smsg;
  159         mach_port_destroy_reply_t *rep = args->rmsg;
  160         size_t *msglen = args->rsize;
  161         struct lwp *l = args->l;
  162         mach_port_t mn;
  163         struct mach_right *mr;
  164 
  165 #ifdef DEBUG_MACH
  166         printf("mach_port_destroy mn = %x\n", req->req_name);
  167 #endif
  168         mn = req->req_name;
  169         if ((mr = mach_right_check(mn,
  170             l, MACH_PORT_TYPE_ALL_RIGHTS)) != NULL) {
  171                 MACH_PORT_UNREF(mr->mr_port);
  172                 mr->mr_port = NULL;
  173                 mach_right_put(mr, MACH_PORT_TYPE_ALL_RIGHTS);
  174         }
  175 
  176         *msglen = sizeof(*rep);
  177         mach_set_header(rep, req, *msglen);
  178 
  179         rep->rep_retval = 0;
  180 
  181         mach_set_trailer(rep, *msglen);
  182 
  183         return 0;
  184 }
  185 
  186 int
  187 mach_port_allocate(args)
  188         struct mach_trap_args *args;
  189 {
  190         mach_port_allocate_request_t *req = args->smsg;
  191         mach_port_allocate_reply_t *rep = args->rmsg;
  192         size_t *msglen = args->rsize;
  193         struct lwp *l = args->l;
  194         struct mach_right *mr;
  195         struct mach_port *mp;
  196 
  197         switch (req->req_right) {
  198         case MACH_PORT_RIGHT_RECEIVE:
  199                 mp = mach_port_get();
  200                 mr = mach_right_get(mp, l, MACH_PORT_TYPE_RECEIVE, 0);
  201                 break;
  202 
  203         case MACH_PORT_RIGHT_DEAD_NAME:
  204                 mr = mach_right_get(NULL, l, MACH_PORT_TYPE_DEAD_NAME, 0);
  205                 break;
  206 
  207         case MACH_PORT_RIGHT_PORT_SET:
  208                 mr = mach_right_get(NULL, l, MACH_PORT_TYPE_PORT_SET, 0);
  209                 break;
  210 
  211         default:
  212                 uprintf("mach_port_allocate: unknown right %x\n",
  213                     req->req_right);
  214                 return mach_msg_error(args, EINVAL);
  215                 break;
  216         }
  217 
  218         *msglen = sizeof(*rep);
  219         mach_set_header(rep, req, *msglen);
  220 
  221         rep->rep_retval = 0;
  222         rep->rep_name = (mach_port_name_t)mr->mr_name;
  223 
  224         mach_set_trailer(rep, *msglen);
  225 
  226         return 0;
  227 }
  228 
  229 int
  230 mach_port_insert_right(args)
  231         struct mach_trap_args *args;
  232 {
  233         mach_port_insert_right_request_t *req = args->smsg;
  234         mach_port_insert_right_reply_t *rep = args->rmsg;
  235         size_t *msglen = args->rsize;
  236         struct lwp *l = args->l;
  237         mach_port_t name;
  238         mach_port_t right;
  239         struct mach_right *mr;
  240         struct mach_right *nmr;
  241 
  242         name = req->req_name;
  243         right = req->req_poly.name;
  244         nmr = NULL;
  245 
  246         mr = mach_right_check(right, l, MACH_PORT_TYPE_ALL_RIGHTS);
  247         if (mr == NULL)
  248                 return mach_msg_error(args, EPERM);
  249 
  250         switch (req->req_poly.disposition) {
  251         case MACH_MSG_TYPE_MAKE_SEND:
  252         case MACH_MSG_TYPE_MOVE_SEND:
  253         case MACH_MSG_TYPE_COPY_SEND:
  254                 nmr = mach_right_get(mr->mr_port,
  255                     l, MACH_PORT_TYPE_SEND, name);
  256                 break;
  257 
  258         case MACH_MSG_TYPE_MAKE_SEND_ONCE:
  259         case MACH_MSG_TYPE_MOVE_SEND_ONCE:
  260                 nmr = mach_right_get(mr->mr_port,
  261                     l, MACH_PORT_TYPE_SEND_ONCE, name);
  262                 break;
  263 
  264         case MACH_MSG_TYPE_MOVE_RECEIVE:
  265                 nmr = mach_right_get(mr->mr_port,
  266                     l, MACH_PORT_TYPE_RECEIVE, name);
  267                 break;
  268 
  269         default:
  270                 uprintf("mach_port_insert_right: unknown right %x\n",
  271                     req->req_poly.disposition);
  272                 break;
  273         }
  274 
  275         *msglen = sizeof(*rep);
  276         mach_set_header(rep, req, *msglen);
  277 
  278         rep->rep_retval = 0;
  279 
  280         mach_set_trailer(rep, *msglen);
  281 
  282         return 0;
  283 }
  284 
  285 int
  286 mach_port_type(args)
  287         struct mach_trap_args *args;
  288 {
  289         mach_port_type_request_t *req = args->smsg;
  290         mach_port_type_reply_t *rep = args->rmsg;
  291         size_t *msglen = args->rsize;
  292         struct lwp *l = args->l;
  293         mach_port_t mn;
  294         struct mach_right *mr;
  295 
  296         mn = req->req_name;
  297         if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
  298                 return mach_msg_error(args, EPERM);
  299 
  300         *msglen = sizeof(*rep);
  301         mach_set_header(rep, req, *msglen);
  302 
  303         rep->rep_retval = 0;
  304         rep->rep_ptype = mr->mr_type;
  305 
  306         mach_set_trailer(rep, *msglen);
  307 
  308         return 0;
  309 }
  310 
  311 int
  312 mach_port_set_attributes(args)
  313         struct mach_trap_args *args;
  314 {
  315         mach_port_set_attributes_request_t *req = args->smsg;
  316         mach_port_set_attributes_reply_t *rep = args->rmsg;
  317         size_t *msglen = args->rsize;
  318         int end_offset;
  319 
  320         /* Sanity check req->req_count */
  321         end_offset = req->req_count;
  322         if (MACH_REQMSG_OVERFLOW(args, req->req_port_info[end_offset]))
  323                  return mach_msg_error(args, EINVAL);
  324 
  325         switch(req->req_flavor) {
  326         case MACH_PORT_LIMITS_INFO:
  327         case MACH_PORT_RECEIVE_STATUS:
  328         case MACH_PORT_DNREQUESTS_SIZE:
  329                 break;
  330         default:
  331                 uprintf("mach_port_set_attributes: unknown flavor %d\n",
  332                     req->req_flavor);
  333                 break;
  334         }
  335 
  336         *msglen = sizeof(*rep);
  337         mach_set_header(rep, req, *msglen);
  338 
  339         rep->rep_retval = 0;
  340 
  341         mach_set_trailer(rep, *msglen);
  342 
  343         return 0;
  344 }
  345 
  346 int
  347 mach_port_get_attributes(args)
  348         struct mach_trap_args *args;
  349 {
  350         mach_port_get_attributes_request_t *req = args->smsg;
  351         mach_port_get_attributes_reply_t *rep = args->rmsg;
  352         size_t *msglen = args->rsize;
  353         struct lwp *l = args->l;
  354         mach_port_t mn;
  355         struct mach_right *mr;
  356 
  357         /* Sanity check req_count */
  358         if (req->req_count > 10)
  359                 return mach_msg_error(args, EINVAL);
  360 
  361         mn = req->req_msgh.msgh_remote_port;
  362         if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
  363                 return mach_msg_error(args, EPERM);
  364 
  365         switch (req->req_flavor) {
  366         case MACH_PORT_LIMITS_INFO: {
  367                 struct mach_port_limits *mpl;
  368 
  369                 if (req->req_count < (sizeof(*mpl) / sizeof(rep->rep_info[0])))
  370                         return mach_msg_error(args, EINVAL);
  371 
  372                 mpl = (struct mach_port_limits *)&rep->rep_info[0];
  373                 mpl->mpl_qlimit = MACH_PORT_QLIMIT_DEFAULT; /* XXX fake limit */
  374 
  375                 rep->rep_count = sizeof(*mpl);
  376 
  377                 break;
  378         }
  379 
  380         case MACH_PORT_RECEIVE_STATUS: {
  381                 struct mach_port_status *mps;
  382                 struct mach_port *mp;
  383 
  384                 if (req->req_count < (sizeof(*mps) / sizeof(rep->rep_info[0])))
  385                         return mach_msg_error(args, EINVAL);
  386 
  387                 mps = (struct mach_port_status *)&rep->rep_info[0];
  388                 memset(mps, 0, sizeof(*mps));
  389 
  390                 if (mr->mr_sethead != NULL)
  391                         mps->mps_pset = mr->mr_sethead->mr_name;
  392                 mps->mps_seqno = 0; /* XXX */
  393                 mps->mps_qlimit = MACH_PORT_QLIMIT_DEFAULT; /* XXX fake limit */
  394                 if ((mp = mr->mr_port) != NULL) {
  395                         mps->mps_mscount = mp->mp_refcount; /* XXX */
  396                         mps->mps_msgcount = mp->mp_count;
  397                 } else {
  398                         mps->mps_mscount = 0;
  399                         mps->mps_msgcount = 0;
  400                 }
  401                 mps->mps_sorights = 0; /* XXX */
  402                 mps->mps_srights =  0; /* XXX */
  403                 if (mr->mr_notify_destroyed != NULL)
  404                         mps->mps_pdrequest = 1;
  405                 if (mr->mr_notify_no_senders != NULL)
  406                         mps->mps_nsrequest = 1;
  407                 mps->mps_flags = 0; /* XXX */
  408 
  409                 rep->rep_count = sizeof(*mps);
  410                 break;
  411         }
  412 
  413         default:
  414                 printf("mach_port_get_attributes: unknown flavor %d\n",
  415                     req->req_flavor);
  416                 return mach_msg_error(args, EINVAL);
  417 
  418                 break;
  419         };
  420 
  421         *msglen = sizeof(*rep) - 10 + rep->rep_count;
  422         mach_set_header(rep, req, *msglen);
  423 
  424         rep->rep_retval = 0;
  425 
  426         mach_set_trailer(rep, *msglen);
  427 
  428         return 0;
  429 }
  430 
  431 /* XXX insert a recv right into a port set without removing it from another */
  432 int
  433 mach_port_insert_member(args)
  434         struct mach_trap_args *args;
  435 {
  436         mach_port_insert_member_request_t *req = args->smsg;
  437         mach_port_insert_member_reply_t *rep = args->rmsg;
  438         size_t *msglen = args->rsize;
  439 
  440         uprintf("Unimplemented mach_port_insert_member\n");
  441 
  442         *msglen = sizeof(*rep);
  443         mach_set_header(rep, req, *msglen);
  444 
  445         rep->rep_retval = 0;
  446 
  447         mach_set_trailer(rep, *msglen);
  448 
  449         return 0;
  450 }
  451 
  452 int
  453 mach_port_move_member(args)
  454         struct mach_trap_args *args;
  455 {
  456         mach_port_move_member_request_t *req = args->smsg;
  457         mach_port_move_member_reply_t *rep = args->rmsg;
  458         size_t *msglen = args->rsize;
  459         struct lwp *l = args->l;
  460         struct mach_emuldata *med = l->l_proc->p_emuldata;
  461         mach_port_t member = req->req_member;
  462         mach_port_t after = req->req_after;
  463         struct mach_right *mrr;
  464         struct mach_right *mrs;
  465 
  466         mrr = mach_right_check(member, l, MACH_PORT_TYPE_RECEIVE);
  467         if (mrr == NULL)
  468                 return mach_msg_error(args, EPERM);
  469 
  470         mrs = mach_right_check(after, l, MACH_PORT_TYPE_PORT_SET);
  471         if (mrs == NULL)
  472                 return mach_msg_error(args, EPERM);
  473 
  474         lockmgr(&med->med_rightlock, LK_EXCLUSIVE, NULL);
  475 
  476         /* Remove it from an existing port set */
  477         if (mrr->mr_sethead != mrr)
  478                 LIST_REMOVE(mrr, mr_setlist);
  479 
  480         /* Insert it into the new port set */
  481         LIST_INSERT_HEAD(&mrs->mr_set, mrr, mr_setlist);
  482         mrr->mr_sethead = mrs;
  483 
  484         lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
  485 
  486         *msglen = sizeof(*rep);
  487         mach_set_header(rep, req, *msglen);
  488 
  489         rep->rep_retval = 0;
  490 
  491         mach_set_trailer(rep, *msglen);
  492 
  493         return 0;
  494 }
  495 
  496 int
  497 mach_port_request_notification(args)
  498         struct mach_trap_args *args;
  499 {
  500         mach_port_request_notification_request_t *req = args->smsg;
  501         mach_port_request_notification_reply_t *rep = args->rmsg;
  502         struct lwp *l = args->l;
  503         size_t *msglen = args->rsize;
  504         mach_port_t mn;
  505         struct mach_right *nmr;
  506         struct mach_right *tmr;
  507         struct mach_right *oldnmr;
  508         mach_port_t oldmn;
  509 
  510 #ifdef DEBUG_MACH
  511         printf("mach_port_request_notification, notify = %08x, target = %08x\n",
  512             req->req_notify.name, mn = req->req_name);
  513 #endif
  514         mn = req->req_notify.name;
  515         if ((nmr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
  516                 return mach_msg_error(args, EINVAL);
  517 
  518         mn = req->req_name;
  519         if ((tmr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == NULL)
  520                 return mach_msg_error(args, EINVAL);
  521 
  522 #ifdef DEBUG_MACH
  523         if (nmr->mr_port == NULL) {
  524                 printf("Notification right without a port\n");
  525                 printf("mr->mr_port = %p, mr = %08x\n", nmr->mr_port, nmr->mr_name);
  526                 return mach_msg_error(args, EINVAL);
  527         }
  528 #endif
  529 
  530 
  531         oldnmr = NULL;
  532         switch(req->req_msgid) {
  533         case MACH_NOTIFY_DESTROYED_MSGID:
  534                 oldnmr = tmr->mr_notify_destroyed;
  535                 tmr->mr_notify_destroyed = mach_right_get(nmr->mr_port,
  536                     l, MACH_PORT_TYPE_SEND_ONCE, req->req_notify.name);
  537                 break;
  538 
  539         case MACH_NOTIFY_NO_SENDERS_MSGID:
  540                 oldnmr = tmr->mr_notify_no_senders;
  541                 tmr->mr_notify_no_senders = mach_right_get(nmr->mr_port,
  542                     l, MACH_PORT_TYPE_SEND_ONCE, req->req_notify.name);
  543                 tmr->mr_notify_no_senders->mr_port->mp_datatype =
  544                     MACH_MP_NOTIFY_SYNC;
  545                 tmr->mr_notify_no_senders->mr_port->mp_data = (void *)
  546                     req->req_count;
  547                 break;
  548 
  549         case MACH_NOTIFY_DEAD_NAME_MSGID:
  550                 oldnmr = tmr->mr_notify_dead_name;
  551                 tmr->mr_notify_dead_name = mach_right_get(nmr->mr_port,
  552                     l, MACH_PORT_TYPE_SEND_ONCE, req->req_notify.name);
  553                 break;
  554 
  555         case MACH_NOTIFY_SEND_ONCE_MSGID:
  556         case MACH_NOTIFY_DELETED_MSGID:
  557         default:
  558 #ifdef DEBUG_MACH
  559                 printf("unsupported notify request %d\n", req->req_msgid);
  560                 return mach_msg_error(args, EINVAL);
  561 #endif
  562                 break;
  563         }
  564 
  565         if (oldnmr != NULL) {
  566                 oldnmr->mr_refcount++;
  567                 oldmn = oldnmr->mr_name;
  568         } else {
  569                 oldmn = (mach_port_t)MACH_PORT_NULL;
  570         }
  571 
  572         *msglen = sizeof(*rep);
  573         mach_set_header(rep, req, *msglen);
  574         mach_add_port_desc(rep, oldmn);
  575         mach_set_trailer(rep, *msglen);
  576 
  577         return 0;
  578 }
  579 
  580 int
  581 mach_port_get_refs(args)
  582         struct mach_trap_args *args;
  583 {
  584         mach_port_get_refs_request_t *req = args->smsg;
  585         mach_port_get_refs_reply_t *rep = args->rmsg;
  586         size_t *msglen = args->rsize;
  587         struct lwp *l = args->l;
  588         mach_port_t mn;
  589         struct mach_right *mr;
  590         mach_port_right_t right = req->req_right;
  591 
  592         mn = req->req_name;
  593         if ((mr = mach_right_check(mn, l, right)) == NULL)
  594                 return mach_msg_error(args, EINVAL);
  595 
  596         *msglen = sizeof(*rep);
  597         mach_set_header(rep, req, *msglen);
  598 
  599         rep->rep_retval = 0;
  600         rep->rep_refs = mr->mr_refcount;
  601 
  602         mach_set_trailer(rep, *msglen);
  603 
  604         return 0;
  605 }
  606 
  607 int
  608 mach_port_mod_refs(args)
  609         struct mach_trap_args *args;
  610 {
  611         mach_port_mod_refs_request_t *req = args->smsg;
  612         mach_port_mod_refs_reply_t *rep = args->rmsg;
  613         size_t *msglen = args->rsize;
  614 #if 0
  615         struct lwp *l = args->l;
  616         mach_port_t mn;
  617         struct mach_right *mr;
  618         mach_port_right_t right = req->req_right;
  619 
  620         mn = req->req_name;
  621         if ((mr = mach_right_check(mn, l, right)) == NULL)
  622                 return mach_msg_error(args, EINVAL);
  623 
  624         /*
  625          * Changing the refcount is likely to cause crashes,
  626          * as we will free a right which might still be referenced
  627          * within the kernel. Add a user refcount field?
  628          */
  629         mr->mr_refcount += req->req_delta;
  630         if (mr->mr_refcount <= 0)
  631                 mach_right_put(mr, right);
  632 #endif
  633 
  634         *msglen = sizeof(*rep);
  635         mach_set_header(rep, req, *msglen);
  636 
  637         rep->rep_retval = 0;
  638 
  639         mach_set_trailer(rep, *msglen);
  640 
  641         return 0;
  642 }
  643 
  644 void
  645 mach_port_init(void)
  646 {
  647         pool_init(&mach_port_pool, sizeof (struct mach_port),
  648             0, 0, 0, "mach_port_pool", NULL);
  649         pool_init(&mach_right_pool, sizeof (struct mach_right),
  650             0, 0, 0, "mach_right_pool", NULL);
  651 
  652         mach_bootstrap_port = mach_port_get();
  653         mach_clock_port = mach_port_get();
  654         mach_io_master_port = mach_port_get();
  655 
  656         mach_bootstrap_port->mp_flags |= MACH_MP_INKERNEL;
  657         mach_clock_port->mp_flags |= MACH_MP_INKERNEL;
  658         mach_io_master_port->mp_flags |= MACH_MP_INKERNEL;
  659 
  660         mach_saved_bootstrap_port = mach_bootstrap_port;
  661 
  662         return;
  663 }
  664 
  665 struct mach_port *
  666 mach_port_get(void)
  667 {
  668         struct mach_port *mp;
  669 
  670         mp = (struct mach_port *)pool_get(&mach_port_pool, PR_WAITOK);
  671         bzero(mp, sizeof(*mp));
  672         mp->mp_recv = NULL;
  673         mp->mp_count = 0;
  674         mp->mp_flags = 0;
  675         mp->mp_datatype = MACH_MP_NONE;
  676         mp->mp_data = NULL;
  677         TAILQ_INIT(&mp->mp_msglist);
  678         lockinit(&mp->mp_msglock, PZERO|PCATCH, "mach_port", 0, 0);
  679 
  680         return mp;
  681 }
  682 
  683 void
  684 mach_port_put(mp)
  685         struct mach_port *mp;
  686 {
  687         struct mach_message *mm;
  688 
  689 #ifdef DIAGNOSTIC
  690         if (mp->mp_refcount > 0) {
  691                 uprintf("mach_port_put: trying to free a referenced port\n");
  692                 return;
  693         }
  694 #endif
  695 
  696         lockmgr(&mp->mp_msglock, LK_EXCLUSIVE, NULL);
  697         while ((mm = TAILQ_FIRST(&mp->mp_msglist)) != NULL)
  698                 mach_message_put_exclocked(mm);
  699         lockmgr(&mp->mp_msglock, LK_RELEASE, NULL);
  700         lockmgr(&mp->mp_msglock, LK_DRAIN, NULL);
  701 
  702         if (mp->mp_flags & MACH_MP_DATA_ALLOCATED)
  703                 free(mp->mp_data, M_EMULDATA);
  704 
  705         pool_put(&mach_port_pool, mp);
  706 
  707         return;
  708 }
  709 
  710 struct mach_right *
  711 mach_right_get(mp, l, type, hint)
  712         struct mach_port *mp;
  713         struct lwp *l;
  714         int type;
  715         mach_port_t hint;
  716 {
  717         struct mach_right *mr;
  718         struct mach_emuldata *med;
  719         int rights;
  720 
  721 #ifdef DEBUG_MACH
  722         if (type == 0)
  723                 uprintf("mach_right_get: right = 0\n");
  724 #endif
  725         med = (struct mach_emuldata *)l->l_proc->p_emuldata;
  726 
  727         if (mp != NULL)
  728                 MACH_PORT_REF(mp);
  729 
  730         /* Send and receive right must return an existing right */
  731         rights = (MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_RECEIVE);
  732         if (type & rights) {
  733                 lockmgr(&med->med_rightlock, LK_SHARED, NULL);
  734                 LIST_FOREACH(mr, &med->med_right, mr_list) {
  735                         if ((mr->mr_port == mp) && (mr->mr_type & rights))
  736                                 break;
  737                 }
  738                 lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
  739 
  740                 if (mr != NULL) {
  741                         mr->mr_type |= type;
  742                         if (type & MACH_PORT_TYPE_SEND)
  743                                 mr->mr_refcount++;
  744                         goto rcvck;
  745                 }
  746         }
  747 
  748         mr = pool_get(&mach_right_pool, PR_WAITOK);
  749 
  750         mr->mr_port = mp;
  751         mr->mr_lwp = l;
  752         mr->mr_type = type;
  753         mr->mr_sethead = mr;
  754         mr->mr_refcount = 1;
  755         mr->mr_notify_destroyed = NULL;
  756         mr->mr_notify_dead_name = NULL;
  757         mr->mr_notify_no_senders = NULL;
  758 
  759         LIST_INIT(&mr->mr_set);
  760 
  761         /* Insert the right in the right lists */
  762         if (type & MACH_PORT_TYPE_ALL_RIGHTS) {
  763                 lockmgr(&med->med_rightlock, LK_EXCLUSIVE, NULL);
  764                 mr->mr_name = mach_right_newname(l, hint);
  765 #ifdef DEBUG_MACH_RIGHT
  766                 printf("mach_right_get: insert right %x(%x)\n",
  767                     mr->mr_name, mr->mr_type);
  768 #endif
  769                 LIST_INSERT_HEAD(&med->med_right, mr, mr_list);
  770                 lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
  771         }
  772 
  773 rcvck:
  774         if (type & MACH_PORT_TYPE_RECEIVE) {
  775                 /*
  776                  * Destroy the former receive right on this port, and
  777                  * register the new right.
  778                  */
  779                 if (mr->mr_port->mp_recv != NULL)
  780                         mach_right_put(mr->mr_port->mp_recv,
  781                             MACH_PORT_TYPE_RECEIVE);
  782                 mr->mr_port->mp_recv = mr;
  783         }
  784         return mr;
  785 }
  786 
  787 void
  788 mach_right_put(mr, right)
  789         struct mach_right *mr;
  790         int right;
  791 {
  792         struct mach_emuldata *med = mr->mr_lwp->l_proc->p_emuldata;
  793 
  794         lockmgr(&med->med_rightlock, LK_EXCLUSIVE, NULL);
  795         mach_right_put_exclocked(mr, right);
  796         lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
  797 
  798         return;
  799 }
  800 
  801 void
  802 mach_right_put_shlocked(mr, right)
  803         struct mach_right *mr;
  804         int right;
  805 {
  806         struct mach_emuldata *med = mr->mr_lwp->l_proc->p_emuldata;
  807 
  808         lockmgr(&med->med_rightlock, LK_UPGRADE, NULL);
  809         mach_right_put_exclocked(mr, right);
  810         lockmgr(&med->med_rightlock, LK_DOWNGRADE, NULL);
  811 
  812         return;
  813 }
  814 
  815 void
  816 mach_right_put_exclocked(mr, right)
  817         struct mach_right *mr;
  818         int right;
  819 {
  820         struct mach_right *cmr;
  821         struct mach_emuldata *med;
  822         int lright;
  823         int kill_right;
  824 
  825         med = mr->mr_lwp->l_proc->p_emuldata;
  826 
  827 #ifdef DEBUG_MACH_RIGHT
  828         printf("mach_right_put: mr = %p\n", mr);
  829         printf("right %x(%x) refcount %d, deallocate %x\n",
  830             mr->mr_name, mr->mr_type, mr->mr_refcount, right);
  831         if ((mr->mr_type & right) == 0)
  832                 printf("mach_right_put: dropping nonexistant right %x on %x\n",
  833                     right, mr->mr_name);
  834         LIST_FOREACH(cmr, &med->med_right, mr_list)
  835                 if (cmr == mr)
  836                         break;
  837         if (cmr == NULL) {
  838                 printf("mach_right_put: dropping already dropped right %x\n",
  839                     mr->mr_name);
  840                 return;
  841         }
  842 #endif
  843         kill_right = 0;
  844 
  845         /* When receive right is deallocated, the port should die */
  846         lright = (right & MACH_PORT_TYPE_RECEIVE);
  847 #ifdef DEBUG_MACH_RIGHT
  848         printf("mr->mr_type = %x, lright = %x, right = %x, refcount = %d\n",
  849             mr->mr_type, lright, right, mr->mr_refcount);
  850 #endif
  851         if (mr->mr_type & lright) {
  852                 if (mr->mr_refcount <= 0) {
  853                         mr->mr_type &= ~MACH_PORT_TYPE_RECEIVE;
  854                         kill_right = 1;
  855                 } else {
  856                         mr->mr_type &= ~MACH_PORT_TYPE_RECEIVE;
  857                         mr->mr_type |= MACH_PORT_TYPE_DEAD_NAME;
  858                         mach_notify_port_dead_name(mr->mr_lwp, mr);
  859                 }
  860                 if (mr->mr_port != NULL) {
  861                         /* There is no more receiver */
  862 #ifdef DIAGNOSTIC
  863                         if (mr->mr_port->mp_recv != mr)
  864                                 printf("several receiver on a single port\n");
  865 #endif
  866                         mr->mr_port->mp_recv = NULL;
  867 
  868                         MACH_PORT_UNREF(mr->mr_port);
  869                         mr->mr_port = NULL;
  870                 }
  871         }
  872 
  873         /* send, send_once and dead_name */
  874         lright = (right & MACH_PORT_TYPE_REF_RIGHTS);
  875         if (mr->mr_type & lright) {
  876                 mr->mr_refcount--;
  877 
  878                 mach_notify_port_no_senders(mr->mr_lwp, mr);
  879 
  880                 if (mr->mr_refcount <= 0) {
  881                         mr->mr_type &= ~MACH_PORT_TYPE_REF_RIGHTS;
  882                         if ((mr->mr_type & MACH_PORT_TYPE_RECEIVE) == 0)
  883                                 kill_right = 1;
  884                 }
  885         }
  886 
  887         lright = (right & MACH_PORT_TYPE_PORT_SET);
  888         if ((mr->mr_type & lright) || (kill_right == 1)) {
  889                 while ((cmr = LIST_FIRST(&mr->mr_set)) != NULL) {
  890                         LIST_REMOVE(cmr, mr_setlist);
  891                         cmr->mr_sethead = cmr;
  892                 }
  893                 mr->mr_type &= ~MACH_PORT_TYPE_PORT_SET;
  894                 if ((mr->mr_type & MACH_PORT_TYPE_RECEIVE) == 0)
  895                         kill_right = 1;
  896         }
  897 
  898         /* Should we kill it? */
  899         if (kill_right == 1) {
  900 #ifdef DEBUG_MACH_RIGHT
  901                 printf("mach_right_put: kill name %x\n", mr->mr_name);
  902 #endif
  903                 /* If the right is used for an IO notification, remove it */
  904                 mach_iokit_cleanup_notify(mr);
  905 
  906                 mach_notify_port_destroyed(mr->mr_lwp, mr);
  907                 LIST_REMOVE(mr, mr_list);
  908                 pool_put(&mach_right_pool, mr);
  909         }
  910         return;
  911 }
  912 
  913 /*
  914  * Check that a process has a given right.
  915  */
  916 struct mach_right *
  917 mach_right_check(mn, l, type)
  918         mach_port_t mn;
  919         struct lwp *l;
  920         int type;
  921 {
  922         struct mach_right *cmr;
  923         struct mach_emuldata *med;
  924 
  925         if ((mn == 0) || (mn == -1) || (l == NULL))
  926                 return NULL;
  927 
  928         med = (struct mach_emuldata *)l->l_proc->p_emuldata;
  929 
  930         lockmgr(&med->med_rightlock, LK_SHARED, NULL);
  931 
  932 #ifdef DEBUG_MACH_RIGHT
  933         printf("mach_right_check: type = %x, mn = %x\n", type, mn);
  934 #endif
  935         LIST_FOREACH(cmr, &med->med_right, mr_list) {
  936 #ifdef DEBUG_MACH_RIGHT
  937                 printf("cmr = %p, cmr->mr_name = %x, cmr->mr_type = %x\n",
  938                     cmr, cmr->mr_name, cmr->mr_type);
  939 #endif
  940                 if (cmr->mr_name != mn)
  941                         continue;
  942                 if (type & cmr->mr_type)
  943                         break;
  944         }
  945 
  946         lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
  947 
  948         return cmr;
  949 }
  950 
  951 
  952 /*
  953  * Find an usnused port name in a given lwp.
  954  * Right lists should be locked.
  955  */
  956 mach_port_t
  957 mach_right_newname(l, hint)
  958         struct lwp *l;
  959         mach_port_t hint;
  960 {
  961         struct mach_emuldata *med;
  962         struct mach_right *mr;
  963         mach_port_t newname = -1;
  964 
  965         med = l->l_proc->p_emuldata;
  966 
  967         if (hint == 0)
  968                 hint = med->med_nextright;
  969 
  970         while (newname == -1) {
  971                 LIST_FOREACH(mr, &med->med_right, mr_list)
  972                         if (mr->mr_name == hint)
  973                                 break;
  974                 if (mr == NULL)
  975                         newname = hint;
  976                 hint++;
  977         }
  978 
  979         med->med_nextright = hint;
  980 
  981         return newname;
  982 }
  983 
  984 #ifdef DEBUG_MACH
  985 void
  986 mach_debug_port(void)
  987 {
  988         struct mach_emuldata *med;
  989         struct mach_right *mr;
  990         struct mach_right *mrs;
  991         struct proc *p;
  992 
  993         PROCLIST_FOREACH(p, &allproc) {
  994                 if ((p->p_emul != &emul_mach) &&
  995 #ifdef COMPAT_DARWIN
  996                     (p->p_emul != &emul_darwin) &&
  997 #endif
  998                     1)
  999                         continue;
 1000 
 1001                 med = p->p_emuldata;
 1002                 LIST_FOREACH(mr, &med->med_right, mr_list) {
 1003                         if ((mr->mr_type & MACH_PORT_TYPE_PORT_SET) == 0) {
 1004                                 printf("pid %d: %p(%x)=>%p",
 1005                                     p->p_pid, mr, mr->mr_type, mr->mr_port);
 1006                                 if (mr->mr_port && mr->mr_port->mp_recv)
 1007                                         printf("[%p]\n",
 1008                                             mr->mr_port->mp_recv->mr_sethead);
 1009                                 else
 1010                                         printf("[NULL]\n");
 1011 
 1012                                 continue;
 1013                         }
 1014 
 1015                         /* Port set... */
 1016                         printf("pid %d: set %p(%x) ",
 1017                             p->p_pid, mr, mr->mr_type);
 1018                         LIST_FOREACH(mrs, &mr->mr_set, mr_setlist) {
 1019                                 printf("%p(%x)=>%p",
 1020                                     mrs, mrs->mr_type, mrs->mr_port);
 1021                                 if (mrs->mr_port && mrs->mr_port->mp_recv)
 1022                                         printf("[%p]",
 1023                                             mrs->mr_port->mp_recv->mr_sethead);
 1024                                 else
 1025                                         printf("[NULL]");
 1026 
 1027                                 printf(" ");
 1028                         }
 1029                         printf("\n");
 1030                 }
 1031         }
 1032         return;
 1033 }
 1034 
 1035 #endif /* DEBUG_MACH */

Cache object: 0985a0f0f45c2f39c11e5108fc3eb232


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