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

Cache object: 5e5d571db4161a7239b45f0d51ecc45b


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