1/* 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_COPYRIGHT@ 30 */ 31/* 32 * Mach Operating System 33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University 34 * All Rights Reserved. 35 * 36 * Permission to use, copy, modify and distribute this software and its 37 * documentation is hereby granted, provided that both the copyright 38 * notice and this permission notice appear in all copies of the 39 * software, derivative works or modified versions, and any portions 40 * thereof, and that both notices appear in supporting documentation. 41 * 42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 45 * 46 * Carnegie Mellon requests users of this software to return to 47 * 48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie Mellon 54 * the rights to redistribute these changes. 55 */ 56/* 57 * NOTICE: This file was modified by McAfee Research in 2004 to introduce 58 * support for mandatory and extensible security protections. This notice 59 * is included in support of clause 2.2 (b) of the Apple Public License, 60 * Version 2.0. 61 * Copyright (c) 2005-2006 SPARTA, Inc. 62 */ 63/* 64 */ 65/* 66 * File: ipc/mach_port.c 67 * Author: Rich Draves 68 * Date: 1989 69 * 70 * Exported kernel calls. See mach/mach_port.defs. 71 */ 72 73#include <mach_debug.h> 74#include <mach_rt.h> 75 76#include <mach/port.h> 77#include <mach/kern_return.h> 78#include <mach/notify.h> 79#include <mach/mach_param.h> 80#include <mach/vm_param.h> 81#include <mach/vm_prot.h> 82#include <mach/vm_map.h> 83#include <kern/task.h> 84#include <kern/counters.h> 85#include <kern/thread.h> 86#include <kern/kalloc.h> 87#include <mach/mach_port_server.h> 88#include <vm/vm_map.h> 89#include <vm/vm_kern.h> 90#include <ipc/ipc_entry.h> 91#include <ipc/ipc_space.h> 92#include <ipc/ipc_object.h> 93#include <ipc/ipc_notify.h> 94#include <ipc/ipc_port.h> 95#include <ipc/ipc_pset.h> 96#include <ipc/ipc_right.h> 97#include <ipc/ipc_kmsg.h> 98#include <ipc/ipc_labelh.h> 99#include <kern/misc_protos.h> 100#include <security/mac_mach_internal.h> 101 102#include <mach/security_server.h> 103 104/* 105 * Forward declarations 106 */ 107void mach_port_names_helper( 108 ipc_port_timestamp_t timestamp, 109 ipc_entry_t entry, 110 mach_port_name_t name, 111 mach_port_name_t *names, 112 mach_port_type_t *types, 113 ipc_entry_num_t *actualp); 114 115void mach_port_gst_helper( 116 ipc_pset_t pset, 117 ipc_port_t port, 118 ipc_entry_num_t maxnames, 119 mach_port_name_t *names, 120 ipc_entry_num_t *actualp); 121 122 123/* Zeroed template of qos flags */ 124 125static mach_port_qos_t qos_template; 126 127/* 128 * Routine: mach_port_names_helper 129 * Purpose: 130 * A helper function for mach_port_names. 131 * 132 * Conditions: 133 * Space containing entry is [at least] read-locked. 134 */ 135 136void 137mach_port_names_helper( 138 ipc_port_timestamp_t timestamp, 139 ipc_entry_t entry, 140 mach_port_name_t name, 141 mach_port_name_t *names, 142 mach_port_type_t *types, 143 ipc_entry_num_t *actualp) 144{ 145 ipc_entry_bits_t bits; 146 ipc_port_request_index_t request; 147 mach_port_type_t type = 0; 148 ipc_entry_num_t actual; 149 ipc_port_t port; 150 151 bits = entry->ie_bits; 152 request = entry->ie_request; 153 port = (ipc_port_t) entry->ie_object; 154 155 if (bits & MACH_PORT_TYPE_RECEIVE) { 156 assert(IP_VALID(port)); 157 158 if (request != IE_REQ_NONE) { 159 ip_lock(port); 160 assert(ip_active(port)); 161 type |= ipc_port_request_type(port, name, request); 162 ip_unlock(port); 163 } 164 165 } else if (bits & MACH_PORT_TYPE_SEND_RIGHTS) { 166 mach_port_type_t reqtype; 167 168 assert(IP_VALID(port)); 169 ip_lock(port); 170 171 reqtype = (request != IE_REQ_NONE) ? 172 ipc_port_request_type(port, name, request) : 0; 173 174 /* 175 * If the port is alive, or was alive when the mach_port_names 176 * started, then return that fact. Otherwise, pretend we found 177 * a dead name entry. 178 */ 179 if (ip_active(port) || IP_TIMESTAMP_ORDER(timestamp, port->ip_timestamp)) { 180 type |= reqtype; 181 } else { 182 bits &= ~(IE_BITS_TYPE_MASK); 183 bits |= MACH_PORT_TYPE_DEAD_NAME; 184 /* account for additional reference for dead-name notification */ 185 if (reqtype != 0) 186 bits++; 187 } 188 ip_unlock(port); 189 } 190 191 type |= IE_BITS_TYPE(bits); 192 193 actual = *actualp; 194 names[actual] = name; 195 types[actual] = type; 196 *actualp = actual+1; 197} 198 199/* 200 * Routine: mach_port_names [kernel call] 201 * Purpose: 202 * Retrieves a list of the rights present in the space, 203 * along with type information. (Same as returned 204 * by mach_port_type.) The names are returned in 205 * no particular order, but they (and the type info) 206 * are an accurate snapshot of the space. 207 * Conditions: 208 * Nothing locked. 209 * Returns: 210 * KERN_SUCCESS Arrays of names and types returned. 211 * KERN_INVALID_TASK The space is null. 212 * KERN_INVALID_TASK The space is dead. 213 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 214 */ 215 216kern_return_t 217mach_port_names( 218 ipc_space_t space, 219 mach_port_name_t **namesp, 220 mach_msg_type_number_t *namesCnt, 221 mach_port_type_t **typesp, 222 mach_msg_type_number_t *typesCnt) 223{ 224 ipc_entry_t table; 225 ipc_entry_num_t tsize; 226 mach_port_index_t index; 227 ipc_entry_num_t actual; /* this many names */ 228 ipc_port_timestamp_t timestamp; /* logical time of this operation */ 229 mach_port_name_t *names; 230 mach_port_type_t *types; 231 kern_return_t kr; 232 233 vm_size_t size; /* size of allocated memory */ 234 vm_offset_t addr1; /* allocated memory, for names */ 235 vm_offset_t addr2; /* allocated memory, for types */ 236 vm_map_copy_t memory1; /* copied-in memory, for names */ 237 vm_map_copy_t memory2; /* copied-in memory, for types */ 238 239 /* safe simplifying assumption */ 240 assert_static(sizeof(mach_port_name_t) == sizeof(mach_port_type_t)); 241 242 if (space == IS_NULL) 243 return KERN_INVALID_TASK; 244 245 size = 0; 246 247 for (;;) { 248 ipc_entry_num_t bound; 249 vm_size_t size_needed; 250 251 is_read_lock(space); 252 if (!is_active(space)) { 253 is_read_unlock(space); 254 if (size != 0) { 255 kmem_free(ipc_kernel_map, addr1, size); 256 kmem_free(ipc_kernel_map, addr2, size); 257 } 258 return KERN_INVALID_TASK; 259 } 260 261 /* upper bound on number of names in the space */ 262 bound = space->is_table_size; 263 size_needed = round_page(bound * sizeof(mach_port_name_t)); 264 265 if (size_needed <= size) 266 break; 267 268 is_read_unlock(space); 269 270 if (size != 0) { 271 kmem_free(ipc_kernel_map, addr1, size); 272 kmem_free(ipc_kernel_map, addr2, size); 273 } 274 size = size_needed; 275 276 kr = vm_allocate(ipc_kernel_map, &addr1, size, VM_FLAGS_ANYWHERE); 277 if (kr != KERN_SUCCESS) 278 return KERN_RESOURCE_SHORTAGE; 279 280 kr = vm_allocate(ipc_kernel_map, &addr2, size, VM_FLAGS_ANYWHERE); 281 if (kr != KERN_SUCCESS) { 282 kmem_free(ipc_kernel_map, addr1, size); 283 return KERN_RESOURCE_SHORTAGE; 284 } 285 286 /* can't fault while we hold locks */ 287 288 kr = vm_map_wire(ipc_kernel_map, vm_map_trunc_page(addr1), 289 vm_map_round_page(addr1 + size), 290 VM_PROT_READ|VM_PROT_WRITE, FALSE); 291 if (kr != KERN_SUCCESS) { 292 kmem_free(ipc_kernel_map, addr1, size); 293 kmem_free(ipc_kernel_map, addr2, size); 294 return KERN_RESOURCE_SHORTAGE; 295 } 296 297 kr = vm_map_wire(ipc_kernel_map, vm_map_trunc_page(addr2), 298 vm_map_round_page(addr2 + size), 299 VM_PROT_READ|VM_PROT_WRITE, FALSE); 300 if (kr != KERN_SUCCESS) { 301 kmem_free(ipc_kernel_map, addr1, size); 302 kmem_free(ipc_kernel_map, addr2, size); 303 return KERN_RESOURCE_SHORTAGE; 304 } 305 306 } 307 /* space is read-locked and active */ 308 309 names = (mach_port_name_t *) addr1; 310 types = (mach_port_type_t *) addr2; 311 actual = 0; 312 313 timestamp = ipc_port_timestamp(); 314 315 table = space->is_table; 316 tsize = space->is_table_size; 317 318 for (index = 0; index < tsize; index++) { 319 ipc_entry_t entry = &table[index]; 320 ipc_entry_bits_t bits = entry->ie_bits; 321 322 if (IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE) { 323 mach_port_name_t name; 324 325 name = MACH_PORT_MAKE(index, IE_BITS_GEN(bits)); 326 mach_port_names_helper(timestamp, entry, name, names, 327 types, &actual); 328 } 329 } 330 331 is_read_unlock(space); 332 333 if (actual == 0) { 334 memory1 = VM_MAP_COPY_NULL; 335 memory2 = VM_MAP_COPY_NULL; 336 337 if (size != 0) { 338 kmem_free(ipc_kernel_map, addr1, size); 339 kmem_free(ipc_kernel_map, addr2, size); 340 } 341 } else { 342 vm_size_t size_used; 343 vm_size_t vm_size_used; 344 345 size_used = actual * sizeof(mach_port_name_t); 346 vm_size_used = round_page(size_used); 347 348 /* 349 * Make used memory pageable and get it into 350 * copied-in form. Free any unused memory. 351 */ 352 353 kr = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(addr1), 354 vm_map_round_page(addr1 + vm_size_used), FALSE); 355 assert(kr == KERN_SUCCESS); 356 357 kr = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(addr2), 358 vm_map_round_page(addr2 + vm_size_used), FALSE); 359 assert(kr == KERN_SUCCESS); 360 361 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr1, 362 (vm_map_size_t)size_used, TRUE, &memory1); 363 assert(kr == KERN_SUCCESS); 364 365 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr2, 366 (vm_map_size_t)size_used, TRUE, &memory2); 367 assert(kr == KERN_SUCCESS); 368 369 if (vm_size_used != size) { 370 kmem_free(ipc_kernel_map, 371 addr1 + vm_size_used, size - vm_size_used); 372 kmem_free(ipc_kernel_map, 373 addr2 + vm_size_used, size - vm_size_used); 374 } 375 } 376 377 *namesp = (mach_port_name_t *) memory1; 378 *namesCnt = actual; 379 *typesp = (mach_port_type_t *) memory2; 380 *typesCnt = actual; 381 return KERN_SUCCESS; 382} 383 384/* 385 * Routine: mach_port_type [kernel call] 386 * Purpose: 387 * Retrieves the type of a right in the space. 388 * The type is a bitwise combination of one or more 389 * of the following type bits: 390 * MACH_PORT_TYPE_SEND 391 * MACH_PORT_TYPE_RECEIVE 392 * MACH_PORT_TYPE_SEND_ONCE 393 * MACH_PORT_TYPE_PORT_SET 394 * MACH_PORT_TYPE_DEAD_NAME 395 * In addition, the following pseudo-type bits may be present: 396 * MACH_PORT_TYPE_DNREQUEST 397 * A dead-name notification is requested. 398 * Conditions: 399 * Nothing locked. 400 * Returns: 401 * KERN_SUCCESS Type is returned. 402 * KERN_INVALID_TASK The space is null. 403 * KERN_INVALID_TASK The space is dead. 404 * KERN_INVALID_NAME The name doesn't denote a right. 405 */ 406 407kern_return_t 408mach_port_type( 409 ipc_space_t space, 410 mach_port_name_t name, 411 mach_port_type_t *typep) 412{ 413 mach_port_urefs_t urefs; 414 ipc_entry_t entry; 415 kern_return_t kr; 416 417 if (space == IS_NULL) 418 return KERN_INVALID_TASK; 419 420 if (name == MACH_PORT_NULL) 421 return KERN_INVALID_NAME; 422 423 if (name == MACH_PORT_DEAD) { 424 *typep = MACH_PORT_TYPE_DEAD_NAME; 425 return KERN_SUCCESS; 426 } 427 428 kr = ipc_right_lookup_write(space, name, &entry); 429 if (kr != KERN_SUCCESS) 430 return kr; 431 432 /* space is write-locked and active */ 433 kr = ipc_right_info(space, name, entry, typep, &urefs); 434 /* space is unlocked */ 435 436#if 1 437 /* JMM - workaround rdar://problem/9121297 (CF being too picky on these bits). */ 438 *typep &= ~(MACH_PORT_TYPE_SPREQUEST | MACH_PORT_TYPE_SPREQUEST_DELAYED); 439#endif 440 441 return kr; 442} 443 444/* 445 * Routine: mach_port_rename [kernel call] 446 * Purpose: 447 * Changes the name denoting a right, 448 * from oname to nname. 449 * Conditions: 450 * Nothing locked. 451 * Returns: 452 * KERN_SUCCESS The right is renamed. 453 * KERN_INVALID_TASK The space is null. 454 * KERN_INVALID_TASK The space is dead. 455 * KERN_INVALID_NAME The oname doesn't denote a right. 456 * KERN_INVALID_VALUE The nname isn't a legal name. 457 * KERN_NAME_EXISTS The nname already denotes a right. 458 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 459 * 460 * This interface is obsolete and always returns 461 * KERN_NOT_SUPPORTED. 462 */ 463 464kern_return_t 465mach_port_rename( 466 __unused ipc_space_t space, 467 __unused mach_port_name_t oname, 468 __unused mach_port_name_t nname) 469{ 470 return KERN_NOT_SUPPORTED; 471} 472 473 474/* 475 * Routine: mach_port_allocate_name [kernel call] 476 * Purpose: 477 * Allocates a right in a space, using a specific name 478 * for the new right. Possible rights: 479 * MACH_PORT_RIGHT_RECEIVE 480 * MACH_PORT_RIGHT_PORT_SET 481 * MACH_PORT_RIGHT_DEAD_NAME 482 * 483 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE) 484 * has no extant send or send-once rights and no queued 485 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT 486 * and its make-send count is 0. It is not a member of 487 * a port set. It has no registered no-senders or 488 * port-destroyed notification requests. 489 * 490 * A new port set has no members. 491 * 492 * A new dead name has one user reference. 493 * Conditions: 494 * Nothing locked. 495 * Returns: 496 * KERN_SUCCESS The right is allocated. 497 * KERN_INVALID_TASK The space is null. 498 * KERN_INVALID_TASK The space is dead. 499 * KERN_INVALID_VALUE The name isn't a legal name. 500 * KERN_INVALID_VALUE "right" isn't a legal kind of right. 501 * KERN_NAME_EXISTS The name already denotes a right. 502 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 503 * 504 * Restrictions on name allocation: NT bits are reserved by kernel, 505 * must be set on any chosen name. Can't do this at all in kernel 506 * loaded server. 507 */ 508 509kern_return_t 510mach_port_allocate_name( 511 ipc_space_t space, 512 mach_port_right_t right, 513 mach_port_name_t name) 514{ 515 kern_return_t kr; 516 mach_port_qos_t qos = qos_template; 517 518 qos.name = TRUE; 519 520 if (!MACH_PORT_VALID(name)) 521 return KERN_INVALID_VALUE; 522 523 kr = mach_port_allocate_full (space, right, MACH_PORT_NULL, 524 &qos, &name); 525 return (kr); 526} 527 528/* 529 * Routine: mach_port_allocate [kernel call] 530 * Purpose: 531 * Allocates a right in a space. Like mach_port_allocate_name, 532 * except that the implementation picks a name for the right. 533 * The name may be any legal name in the space that doesn't 534 * currently denote a right. 535 * Conditions: 536 * Nothing locked. 537 * Returns: 538 * KERN_SUCCESS The right is allocated. 539 * KERN_INVALID_TASK The space is null. 540 * KERN_INVALID_TASK The space is dead. 541 * KERN_INVALID_VALUE "right" isn't a legal kind of right. 542 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 543 * KERN_NO_SPACE No room in space for another right. 544 */ 545 546kern_return_t 547mach_port_allocate( 548 ipc_space_t space, 549 mach_port_right_t right, 550 mach_port_name_t *namep) 551{ 552 kern_return_t kr; 553 mach_port_qos_t qos = qos_template; 554 555 kr = mach_port_allocate_full (space, right, MACH_PORT_NULL, 556 &qos, namep); 557 return (kr); 558} 559 560/* 561 * Routine: mach_port_allocate_qos [kernel call] 562 * Purpose: 563 * Allocates a right, with qos options, in a space. Like 564 * mach_port_allocate_name, except that the implementation 565 * picks a name for the right. The name may be any legal name 566 * in the space that doesn't currently denote a right. 567 * Conditions: 568 * Nothing locked. 569 * Returns: 570 * KERN_SUCCESS The right is allocated. 571 * KERN_INVALID_TASK The space is null. 572 * KERN_INVALID_TASK The space is dead. 573 * KERN_INVALID_VALUE "right" isn't a legal kind of right. 574 * KERN_INVALID_ARGUMENT The qos request was invalid. 575 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 576 * KERN_NO_SPACE No room in space for another right. 577 */ 578 579kern_return_t 580mach_port_allocate_qos( 581 ipc_space_t space, 582 mach_port_right_t right, 583 mach_port_qos_t *qosp, 584 mach_port_name_t *namep) 585{ 586 kern_return_t kr; 587 588 if (qosp->name) 589 return KERN_INVALID_ARGUMENT; 590 kr = mach_port_allocate_full (space, right, MACH_PORT_NULL, 591 qosp, namep); 592 return (kr); 593} 594 595/* 596 * Routine: mach_port_allocate_full [kernel call] 597 * Purpose: 598 * Allocates a right in a space. Supports all of the 599 * special cases, such as specifying a subsystem, 600 * a specific name, a real-time port, etc. 601 * The name may be any legal name in the space that doesn't 602 * currently denote a right. 603 * Conditions: 604 * Nothing locked. 605 * Returns: 606 * KERN_SUCCESS The right is allocated. 607 * KERN_INVALID_TASK The space is null. 608 * KERN_INVALID_TASK The space is dead. 609 * KERN_INVALID_VALUE "right" isn't a legal kind of right. 610 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 611 * KERN_NO_SPACE No room in space for another right. 612 */ 613 614kern_return_t 615mach_port_allocate_full( 616 ipc_space_t space, 617 mach_port_right_t right, 618 mach_port_t proto, 619 mach_port_qos_t *qosp, 620 mach_port_name_t *namep) 621{ 622 ipc_kmsg_t kmsg = IKM_NULL; 623 kern_return_t kr; 624 625 if (space == IS_NULL) 626 return (KERN_INVALID_TASK); 627 628 if (proto != MACH_PORT_NULL) 629 return (KERN_INVALID_VALUE); 630 631 if (qosp->name) { 632 if (!MACH_PORT_VALID (*namep)) 633 return (KERN_INVALID_VALUE); 634 } 635 636 if (qosp->prealloc) { 637 if (qosp->len > MACH_MSG_SIZE_MAX - MAX_TRAILER_SIZE) { 638 return KERN_RESOURCE_SHORTAGE; 639 } else { 640 mach_msg_size_t size = qosp->len + MAX_TRAILER_SIZE; 641 642 if (right != MACH_PORT_RIGHT_RECEIVE) 643 return (KERN_INVALID_VALUE); 644 645 kmsg = (ipc_kmsg_t)ipc_kmsg_prealloc(size); 646 if (kmsg == IKM_NULL) 647 return (KERN_RESOURCE_SHORTAGE); 648 } 649 } 650 651 switch (right) { 652 case MACH_PORT_RIGHT_RECEIVE: 653 { 654 ipc_port_t port; 655 656 if (qosp->name) 657 kr = ipc_port_alloc_name(space, *namep, &port); 658 else 659 kr = ipc_port_alloc(space, namep, &port); 660 if (kr == KERN_SUCCESS) { 661 if (kmsg != IKM_NULL) 662 ipc_kmsg_set_prealloc(kmsg, port); 663 664 ip_unlock(port); 665 666 } else if (kmsg != IKM_NULL) 667 ipc_kmsg_free(kmsg); 668 break; 669 } 670 671 case MACH_PORT_RIGHT_PORT_SET: 672 { 673 ipc_pset_t pset; 674 675 if (qosp->name) 676 kr = ipc_pset_alloc_name(space, *namep, &pset); 677 else 678 kr = ipc_pset_alloc(space, namep, &pset); 679 if (kr == KERN_SUCCESS) 680 ips_unlock(pset); 681 break; 682 } 683 684 case MACH_PORT_RIGHT_DEAD_NAME: 685 kr = ipc_object_alloc_dead(space, namep); 686 break; 687 688 default: 689 kr = KERN_INVALID_VALUE; 690 break; 691 } 692 693 return (kr); 694} 695 696/* 697 * Routine: mach_port_destroy [kernel call] 698 * Purpose: 699 * Cleans up and destroys all rights denoted by a name 700 * in a space. The destruction of a receive right 701 * destroys the port, unless a port-destroyed request 702 * has been made for it; the destruction of a port-set right 703 * destroys the port set. 704 * Conditions: 705 * Nothing locked. 706 * Returns: 707 * KERN_SUCCESS The name is destroyed. 708 * KERN_INVALID_TASK The space is null. 709 * KERN_INVALID_TASK The space is dead. 710 * KERN_INVALID_NAME The name doesn't denote a right. 711 */ 712 713kern_return_t 714mach_port_destroy( 715 ipc_space_t space, 716 mach_port_name_t name) 717{ 718 ipc_entry_t entry; 719 kern_return_t kr; 720 721 if (space == IS_NULL) 722 return KERN_INVALID_TASK; 723 724 if (!MACH_PORT_VALID(name)) 725 return KERN_SUCCESS; 726 727 kr = ipc_right_lookup_write(space, name, &entry); 728 if (kr != KERN_SUCCESS) 729 return kr; 730 /* space is write-locked and active */ 731 732 kr = ipc_right_destroy(space, name, entry); /* unlocks space */ 733 return kr; 734} 735 736/* 737 * Routine: mach_port_deallocate [kernel call] 738 * Purpose: 739 * Deallocates a user reference from a send right, 740 * send-once right, or a dead-name right. May 741 * deallocate the right, if this is the last uref, 742 * and destroy the name, if it doesn't denote 743 * other rights. 744 * Conditions: 745 * Nothing locked. 746 * Returns: 747 * KERN_SUCCESS The uref is deallocated. 748 * KERN_INVALID_TASK The space is null. 749 * KERN_INVALID_TASK The space is dead. 750 * KERN_INVALID_NAME The name doesn't denote a right. 751 * KERN_INVALID_RIGHT The right isn't correct. 752 */ 753 754kern_return_t 755mach_port_deallocate( 756 ipc_space_t space, 757 mach_port_name_t name) 758{ 759 ipc_entry_t entry; 760 kern_return_t kr; 761 762 if (space == IS_NULL) 763 return KERN_INVALID_TASK; 764 765 if (!MACH_PORT_VALID(name)) 766 return KERN_SUCCESS; 767 768 kr = ipc_right_lookup_write(space, name, &entry); 769 if (kr != KERN_SUCCESS) 770 return kr; 771 /* space is write-locked */ 772 773 kr = ipc_right_dealloc(space, name, entry); /* unlocks space */ 774 return kr; 775} 776 777/* 778 * Routine: mach_port_get_refs [kernel call] 779 * Purpose: 780 * Retrieves the number of user references held by a right. 781 * Receive rights, port-set rights, and send-once rights 782 * always have one user reference. Returns zero if the 783 * name denotes a right, but not the queried right. 784 * Conditions: 785 * Nothing locked. 786 * Returns: 787 * KERN_SUCCESS Number of urefs returned. 788 * KERN_INVALID_TASK The space is null. 789 * KERN_INVALID_TASK The space is dead. 790 * KERN_INVALID_VALUE "right" isn't a legal value. 791 * KERN_INVALID_NAME The name doesn't denote a right. 792 */ 793 794kern_return_t 795mach_port_get_refs( 796 ipc_space_t space, 797 mach_port_name_t name, 798 mach_port_right_t right, 799 mach_port_urefs_t *urefsp) 800{ 801 mach_port_type_t type; 802 mach_port_urefs_t urefs; 803 ipc_entry_t entry; 804 kern_return_t kr; 805 806 if (space == IS_NULL) 807 return KERN_INVALID_TASK; 808 809 if (right >= MACH_PORT_RIGHT_NUMBER) 810 return KERN_INVALID_VALUE; 811 812 if (!MACH_PORT_VALID(name)) { 813 if (right == MACH_PORT_RIGHT_SEND || 814 right == MACH_PORT_RIGHT_SEND_ONCE) { 815 *urefsp = 1; 816 return KERN_SUCCESS; 817 } 818 return KERN_INVALID_NAME; 819 } 820 821 kr = ipc_right_lookup_write(space, name, &entry); 822 if (kr != KERN_SUCCESS) 823 return kr; 824 825 /* space is write-locked and active */ 826 kr = ipc_right_info(space, name, entry, &type, &urefs); 827 /* space is unlocked */ 828 829 if (kr != KERN_SUCCESS) 830 return kr; 831 832 if (type & MACH_PORT_TYPE(right)) 833 switch (right) { 834 case MACH_PORT_RIGHT_SEND_ONCE: 835 assert(urefs == 1); 836 /* fall-through */ 837 838 case MACH_PORT_RIGHT_PORT_SET: 839 case MACH_PORT_RIGHT_RECEIVE: 840 *urefsp = 1; 841 break; 842 843 case MACH_PORT_RIGHT_DEAD_NAME: 844 case MACH_PORT_RIGHT_SEND: 845 assert(urefs > 0); 846 *urefsp = urefs; 847 break; 848 849 default: 850 panic("mach_port_get_refs: strange rights"); 851 } 852 else 853 *urefsp = 0; 854 855 return kr; 856} 857 858/* 859 * Routine: mach_port_mod_refs 860 * Purpose: 861 * Modifies the number of user references held by a right. 862 * The resulting number of user references must be non-negative. 863 * If it is zero, the right is deallocated. If the name 864 * doesn't denote other rights, it is destroyed. 865 * Conditions: 866 * Nothing locked. 867 * Returns: 868 * KERN_SUCCESS Modified number of urefs. 869 * KERN_INVALID_TASK The space is null. 870 * KERN_INVALID_TASK The space is dead. 871 * KERN_INVALID_VALUE "right" isn't a legal value. 872 * KERN_INVALID_NAME The name doesn't denote a right. 873 * KERN_INVALID_RIGHT Name doesn't denote specified right. 874 * KERN_INVALID_VALUE Impossible modification to urefs. 875 * KERN_UREFS_OVERFLOW Urefs would overflow. 876 */ 877 878kern_return_t 879mach_port_mod_refs( 880 ipc_space_t space, 881 mach_port_name_t name, 882 mach_port_right_t right, 883 mach_port_delta_t delta) 884{ 885 ipc_entry_t entry; 886 kern_return_t kr; 887 888 if (space == IS_NULL) 889 return KERN_INVALID_TASK; 890 891 if (right >= MACH_PORT_RIGHT_NUMBER) 892 return KERN_INVALID_VALUE; 893 894 if (!MACH_PORT_VALID(name)) { 895 if (right == MACH_PORT_RIGHT_SEND || 896 right == MACH_PORT_RIGHT_SEND_ONCE) 897 return KERN_SUCCESS; 898 return KERN_INVALID_NAME; 899 } 900 901 kr = ipc_right_lookup_write(space, name, &entry); 902 if (kr != KERN_SUCCESS) 903 return kr; 904 /* space is write-locked and active */ 905 906 kr = ipc_right_delta(space, name, entry, right, delta); /* unlocks */ 907 return kr; 908} 909 910 911/* 912 * Routine: mach_port_set_mscount [kernel call] 913 * Purpose: 914 * Changes a receive right's make-send count. 915 * Conditions: 916 * Nothing locked. 917 * Returns: 918 * KERN_SUCCESS Set make-send count. 919 * KERN_INVALID_TASK The space is null. 920 * KERN_INVALID_TASK The space is dead. 921 * KERN_INVALID_NAME The name doesn't denote a right. 922 * KERN_INVALID_RIGHT Name doesn't denote receive rights. 923 */ 924 925kern_return_t 926mach_port_set_mscount( 927 ipc_space_t space, 928 mach_port_name_t name, 929 mach_port_mscount_t mscount) 930{ 931 ipc_port_t port; 932 kern_return_t kr; 933 934 if (space == IS_NULL) 935 return KERN_INVALID_TASK; 936 937 if (!MACH_PORT_VALID(name)) 938 return KERN_INVALID_RIGHT; 939 940 kr = ipc_port_translate_receive(space, name, &port); 941 if (kr != KERN_SUCCESS) 942 return kr; 943 /* port is locked and active */ 944 945 ipc_port_set_mscount(port, mscount); 946 947 ip_unlock(port); 948 return KERN_SUCCESS; 949} 950 951/* 952 * Routine: mach_port_set_seqno [kernel call] 953 * Purpose: 954 * Changes a receive right's sequence number. 955 * Conditions: 956 * Nothing locked. 957 * Returns: 958 * KERN_SUCCESS Set sequence number. 959 * KERN_INVALID_TASK The space is null. 960 * KERN_INVALID_TASK The space is dead. 961 * KERN_INVALID_NAME The name doesn't denote a right. 962 * KERN_INVALID_RIGHT Name doesn't denote receive rights. 963 */ 964 965kern_return_t 966mach_port_set_seqno( 967 ipc_space_t space, 968 mach_port_name_t name, 969 mach_port_seqno_t seqno) 970{ 971 ipc_port_t port; 972 kern_return_t kr; 973 974 if (space == IS_NULL) 975 return KERN_INVALID_TASK; 976 977 if (!MACH_PORT_VALID(name)) 978 return KERN_INVALID_RIGHT; 979 980 kr = ipc_port_translate_receive(space, name, &port); 981 if (kr != KERN_SUCCESS) 982 return kr; 983 /* port is locked and active */ 984 985 ipc_mqueue_set_seqno(&port->ip_messages, seqno); 986 987 ip_unlock(port); 988 return KERN_SUCCESS; 989} 990 991/* 992 * Routine: mach_port_get_context [kernel call] 993 * Purpose: 994 * Returns a receive right's context pointer. 995 * Conditions: 996 * Nothing locked. 997 * Returns: 998 * KERN_SUCCESS Set context pointer. 999 * KERN_INVALID_TASK The space is null. 1000 * KERN_INVALID_TASK The space is dead. 1001 * KERN_INVALID_NAME The name doesn't denote a right. 1002 * KERN_INVALID_RIGHT Name doesn't denote receive rights. 1003 */ 1004 1005kern_return_t 1006mach_port_get_context( 1007 ipc_space_t space, 1008 mach_port_name_t name, 1009 mach_vm_address_t *context) 1010{ 1011 ipc_port_t port; 1012 kern_return_t kr; 1013 1014 if (space == IS_NULL) 1015 return KERN_INVALID_TASK; 1016 1017 if (!MACH_PORT_VALID(name)) 1018 return KERN_INVALID_RIGHT; 1019 1020 kr = ipc_port_translate_receive(space, name, &port); 1021 if (kr != KERN_SUCCESS) 1022 return kr; 1023 1024 /* port is locked and active */ 1025 *context = port->ip_context; 1026 1027 ip_unlock(port); 1028 return KERN_SUCCESS; 1029} 1030 1031 1032/* 1033 * Routine: mach_port_set_context [kernel call] 1034 * Purpose: 1035 * Changes a receive right's context pointer. 1036 * Conditions: 1037 * Nothing locked. 1038 * Returns: 1039 * KERN_SUCCESS Set context pointer. 1040 * KERN_INVALID_TASK The space is null. 1041 * KERN_INVALID_TASK The space is dead. 1042 * KERN_INVALID_NAME The name doesn't denote a right. 1043 * KERN_INVALID_RIGHT Name doesn't denote receive rights. 1044 */ 1045 1046kern_return_t 1047mach_port_set_context( 1048 ipc_space_t space, 1049 mach_port_name_t name, 1050 mach_vm_address_t context) 1051{ 1052 ipc_port_t port; 1053 kern_return_t kr; 1054 1055 if (space == IS_NULL) 1056 return KERN_INVALID_TASK; 1057 1058 if (!MACH_PORT_VALID(name)) 1059 return KERN_INVALID_RIGHT; 1060 1061 kr = ipc_port_translate_receive(space, name, &port); 1062 if (kr != KERN_SUCCESS) 1063 return kr; 1064 1065 /* port is locked and active */ 1066 port->ip_context = context; 1067 1068 ip_unlock(port); 1069 return KERN_SUCCESS; 1070} 1071 1072 1073/* 1074 * Routine: mach_port_gst_helper 1075 * Conditions: 1076 * portspace is locked for both the recieve right and pset 1077 * under observation. 1078 * Purpose: 1079 * A helper function for mach_port_get_set_status. 1080 */ 1081 1082void 1083mach_port_gst_helper( 1084 ipc_pset_t pset, 1085 ipc_port_t port, 1086 ipc_entry_num_t maxnames, 1087 mach_port_name_t *names, 1088 ipc_entry_num_t *actualp) 1089{ 1090 mach_port_name_t name; 1091 1092 assert(port != IP_NULL); 1093 /* 1094 * The space lock is held by the calling function, 1095 * hence it is OK to read name without the port lock. 1096 */ 1097 assert(ip_active(port)); 1098 name = port->ip_receiver_name; 1099 assert(name != MACH_PORT_NULL); 1100 1101 if (ipc_pset_member(pset, port)) { 1102 ipc_entry_num_t actual = *actualp; 1103 1104 if (actual < maxnames) 1105 names[actual] = name; 1106 1107 *actualp = actual+1; 1108 } 1109} 1110 1111/* 1112 * Routine: mach_port_get_set_status [kernel call] 1113 * Purpose: 1114 * Retrieves a list of members in a port set. 1115 * Returns the space's name for each receive right member. 1116 * Conditions: 1117 * Nothing locked. 1118 * Returns: 1119 * KERN_SUCCESS Retrieved list of members. 1120 * KERN_INVALID_TASK The space is null. 1121 * KERN_INVALID_TASK The space is dead. 1122 * KERN_INVALID_NAME The name doesn't denote a right. 1123 * KERN_INVALID_RIGHT Name doesn't denote a port set. 1124 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 1125 */ 1126 1127kern_return_t 1128mach_port_get_set_status( 1129 ipc_space_t space, 1130 mach_port_name_t name, 1131 mach_port_name_t **members, 1132 mach_msg_type_number_t *membersCnt) 1133{ 1134 ipc_entry_num_t actual; /* this many members */ 1135 ipc_entry_num_t maxnames; /* space for this many members */ 1136 kern_return_t kr; 1137 1138 vm_size_t size; /* size of allocated memory */ 1139 vm_offset_t addr; /* allocated memory */ 1140 vm_map_copy_t memory; /* copied-in memory */ 1141 1142 if (space == IS_NULL) 1143 return KERN_INVALID_TASK; 1144 1145 if (!MACH_PORT_VALID(name)) 1146 return KERN_INVALID_RIGHT; 1147 1148 size = PAGE_SIZE; /* initial guess */ 1149 1150 for (;;) { 1151 ipc_entry_t entry, table; 1152 ipc_entry_num_t tsize; 1153 mach_port_index_t index; 1154 mach_port_name_t *names; 1155 ipc_pset_t pset; 1156 1157 kr = vm_allocate(ipc_kernel_map, &addr, size, VM_FLAGS_ANYWHERE); 1158 if (kr != KERN_SUCCESS) 1159 return KERN_RESOURCE_SHORTAGE; 1160 1161 /* can't fault while we hold locks */ 1162 1163 kr = vm_map_wire(ipc_kernel_map, addr, addr + size, 1164 VM_PROT_READ|VM_PROT_WRITE, FALSE); 1165 assert(kr == KERN_SUCCESS); 1166 1167 kr = ipc_right_lookup_read(space, name, &entry); 1168 if (kr != KERN_SUCCESS) { 1169 kmem_free(ipc_kernel_map, addr, size); 1170 return kr; 1171 } 1172 /* space is read-locked and active */ 1173 1174 if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_PORT_SET) { 1175 is_read_unlock(space); 1176 kmem_free(ipc_kernel_map, addr, size); 1177 return KERN_INVALID_RIGHT; 1178 } 1179 1180 pset = (ipc_pset_t) entry->ie_object; 1181 assert(pset != IPS_NULL); 1182 /* the port set must be active */ 1183 1184 names = (mach_port_name_t *) addr; 1185 maxnames = (ipc_entry_num_t)(size / sizeof(mach_port_name_t)); 1186 actual = 0; 1187 1188 table = space->is_table; 1189 tsize = space->is_table_size; 1190 1191 for (index = 0; index < tsize; index++) { 1192 ipc_entry_t ientry = &table[index]; 1193 ipc_port_t port = (ipc_port_t) ientry->ie_object; 1194 1195 if (ientry->ie_bits & MACH_PORT_TYPE_RECEIVE && 1196 port->ip_pset_count > 0) { 1197 mach_port_gst_helper(pset, port, 1198 maxnames, names, &actual); 1199 } 1200 } 1201 1202 is_read_unlock(space); 1203 1204 if (actual <= maxnames) 1205 break; 1206 1207 /* didn't have enough memory; allocate more */ 1208 1209 kmem_free(ipc_kernel_map, addr, size); 1210 size = round_page(actual * sizeof(mach_port_name_t)) + PAGE_SIZE; 1211 } 1212 1213 if (actual == 0) { 1214 memory = VM_MAP_COPY_NULL; 1215 1216 kmem_free(ipc_kernel_map, addr, size); 1217 } else { 1218 vm_size_t size_used; 1219 vm_size_t vm_size_used; 1220 1221 size_used = actual * sizeof(mach_port_name_t); 1222 vm_size_used = round_page(size_used); 1223 1224 /* 1225 * Make used memory pageable and get it into 1226 * copied-in form. Free any unused memory. 1227 */ 1228 1229 kr = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(addr), 1230 vm_map_round_page(addr + vm_size_used), FALSE); 1231 assert(kr == KERN_SUCCESS); 1232 1233 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr, 1234 (vm_map_size_t)size_used, TRUE, &memory); 1235 assert(kr == KERN_SUCCESS); 1236 1237 if (vm_size_used != size) 1238 kmem_free(ipc_kernel_map, 1239 addr + vm_size_used, size - vm_size_used); 1240 } 1241 1242 *members = (mach_port_name_t *) memory; 1243 *membersCnt = actual; 1244 return KERN_SUCCESS; 1245} 1246 1247/* 1248 * Routine: mach_port_move_member [kernel call] 1249 * Purpose: 1250 * If after is MACH_PORT_NULL, removes member 1251 * from the port set it is in. Otherwise, adds 1252 * member to after, removing it from any set 1253 * it might already be in. 1254 * Conditions: 1255 * Nothing locked. 1256 * Returns: 1257 * KERN_SUCCESS Moved the port. 1258 * KERN_INVALID_TASK The space is null. 1259 * KERN_INVALID_TASK The space is dead. 1260 * KERN_INVALID_NAME Member didn't denote a right. 1261 * KERN_INVALID_RIGHT Member didn't denote a receive right. 1262 * KERN_INVALID_NAME After didn't denote a right. 1263 * KERN_INVALID_RIGHT After didn't denote a port set right. 1264 * KERN_NOT_IN_SET 1265 * After is MACH_PORT_NULL and Member isn't in a port set. 1266 */ 1267 1268kern_return_t 1269mach_port_move_member( 1270 ipc_space_t space, 1271 mach_port_name_t member, 1272 mach_port_name_t after) 1273{ 1274 ipc_entry_t entry; 1275 ipc_port_t port; 1276 ipc_pset_t nset; 1277 kern_return_t kr; 1278 wait_queue_link_t wql; 1279 queue_head_t links_data; 1280 queue_t links = &links_data; 1281 1282 if (space == IS_NULL) 1283 return KERN_INVALID_TASK; 1284 1285 if (!MACH_PORT_VALID(member)) 1286 return KERN_INVALID_RIGHT; 1287 1288 if (after == MACH_PORT_DEAD) 1289 return KERN_INVALID_RIGHT; 1290 else if (after == MACH_PORT_NULL) 1291 wql = WAIT_QUEUE_LINK_NULL; 1292 else 1293 wql = wait_queue_link_allocate(); 1294 1295 queue_init(links); 1296 1297 kr = ipc_right_lookup_read(space, member, &entry); 1298 if (kr != KERN_SUCCESS) 1299 goto done; 1300 /* space is read-locked and active */ 1301 1302 if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) { 1303 is_read_unlock(space); 1304 kr = KERN_INVALID_RIGHT; 1305 goto done; 1306 } 1307 1308 port = (ipc_port_t) entry->ie_object; 1309 assert(port != IP_NULL); 1310 1311 if (after == MACH_PORT_NULL) 1312 nset = IPS_NULL; 1313 else { 1314 entry = ipc_entry_lookup(space, after); 1315 if (entry == IE_NULL) { 1316 is_read_unlock(space); 1317 kr = KERN_INVALID_NAME; 1318 goto done; 1319 } 1320 1321 if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) { 1322 is_read_unlock(space); 1323 kr = KERN_INVALID_RIGHT; 1324 goto done; 1325 } 1326 1327 nset = (ipc_pset_t) entry->ie_object; 1328 assert(nset != IPS_NULL); 1329 } 1330 ip_lock(port); 1331 ipc_pset_remove_from_all(port, links); 1332 1333 if (nset != IPS_NULL) { 1334 ips_lock(nset); 1335 kr = ipc_pset_add(nset, port, wql); 1336 ips_unlock(nset); 1337 } 1338 ip_unlock(port); 1339 is_read_unlock(space); 1340 1341 done: 1342 if (kr != KERN_SUCCESS && wql != WAIT_QUEUE_LINK_NULL) 1343 wait_queue_link_free(wql); 1344 while(!queue_empty(links)) { 1345 wql = (wait_queue_link_t) dequeue(links); 1346 wait_queue_link_free(wql); 1347 } 1348 1349 return kr; 1350} 1351 1352/* 1353 * Routine: mach_port_request_notification [kernel call] 1354 * Purpose: 1355 * Requests a notification. The caller supplies 1356 * a send-once right for the notification to use, 1357 * and the call returns the previously registered 1358 * send-once right, if any. Possible types: 1359 * 1360 * MACH_NOTIFY_PORT_DESTROYED 1361 * Requests a port-destroyed notification 1362 * for a receive right. Sync should be zero. 1363 * MACH_NOTIFY_NO_SENDERS 1364 * Requests a no-senders notification for a 1365 * receive right. If there are currently no 1366 * senders, sync is less than or equal to the 1367 * current make-send count, and a send-once right 1368 * is supplied, then an immediate no-senders 1369 * notification is generated. 1370 * MACH_NOTIFY_DEAD_NAME 1371 * Requests a dead-name notification for a send 1372 * or receive right. If the name is already a 1373 * dead name, sync is non-zero, and a send-once 1374 * right is supplied, then an immediate dead-name 1375 * notification is generated. 1376 * Conditions: 1377 * Nothing locked. 1378 * Returns: 1379 * KERN_SUCCESS Requested a notification. 1380 * KERN_INVALID_TASK The space is null. 1381 * KERN_INVALID_TASK The space is dead. 1382 * KERN_INVALID_VALUE Bad id value. 1383 * KERN_INVALID_NAME Name doesn't denote a right. 1384 * KERN_INVALID_RIGHT Name doesn't denote appropriate right. 1385 * KERN_INVALID_CAPABILITY The notify port is dead. 1386 * MACH_NOTIFY_PORT_DESTROYED: 1387 * KERN_INVALID_VALUE Sync isn't zero. 1388 * MACH_NOTIFY_DEAD_NAME: 1389 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 1390 * KERN_INVALID_ARGUMENT Name denotes dead name, but 1391 * sync is zero or notify is IP_NULL. 1392 * KERN_UREFS_OVERFLOW Name denotes dead name, but 1393 * generating immediate notif. would overflow urefs. 1394 */ 1395 1396kern_return_t 1397mach_port_request_notification( 1398 ipc_space_t space, 1399 mach_port_name_t name, 1400 mach_msg_id_t id, 1401 mach_port_mscount_t sync, 1402 ipc_port_t notify, 1403 ipc_port_t *previousp) 1404{ 1405 kern_return_t kr; 1406 1407 if (space == IS_NULL) 1408 return KERN_INVALID_TASK; 1409 1410 if (notify == IP_DEAD) 1411 return KERN_INVALID_CAPABILITY; 1412 1413#if NOTYET 1414 /* 1415 * Requesting notifications on RPC ports is an error. 1416 */ 1417 { 1418 ipc_port_t port; 1419 ipc_entry_t entry; 1420 1421 kr = ipc_right_lookup_write(space, name, &entry); 1422 if (kr != KERN_SUCCESS) 1423 return kr; 1424 1425 port = (ipc_port_t) entry->ie_object; 1426 1427 if (port->ip_subsystem != NULL) { 1428 is_write_unlock(space); 1429 panic("mach_port_request_notification: on RPC port!!"); 1430 return KERN_INVALID_CAPABILITY; 1431 } 1432 is_write_unlock(space); 1433 } 1434#endif /* NOTYET */ 1435 1436 1437 switch (id) { 1438 case MACH_NOTIFY_PORT_DESTROYED: { 1439 ipc_port_t port, previous; 1440 1441 if (sync != 0) 1442 return KERN_INVALID_VALUE; 1443 1444 if (!MACH_PORT_VALID(name)) 1445 return KERN_INVALID_RIGHT; 1446 1447 kr = ipc_port_translate_receive(space, name, &port); 1448 if (kr != KERN_SUCCESS) 1449 return kr; 1450 /* port is locked and active */ 1451 1452 ipc_port_pdrequest(port, notify, &previous); 1453 /* port is unlocked */ 1454 1455 *previousp = previous; 1456 break; 1457 } 1458 1459 case MACH_NOTIFY_NO_SENDERS: { 1460 ipc_port_t port; 1461 1462 if (!MACH_PORT_VALID(name)) 1463 return KERN_INVALID_RIGHT; 1464 1465 kr = ipc_port_translate_receive(space, name, &port); 1466 if (kr != KERN_SUCCESS) 1467 return kr; 1468 /* port is locked and active */ 1469 1470 ipc_port_nsrequest(port, sync, notify, previousp); 1471 /* port is unlocked */ 1472 break; 1473 } 1474 1475 case MACH_NOTIFY_SEND_POSSIBLE: 1476 1477 if (!MACH_PORT_VALID(name)) { 1478 return KERN_INVALID_ARGUMENT; 1479 } 1480 1481 kr = ipc_right_request_alloc(space, name, sync != 0, 1482 TRUE, notify, previousp); 1483 if (kr != KERN_SUCCESS) 1484 return kr; 1485 break; 1486 1487 case MACH_NOTIFY_DEAD_NAME: 1488 1489 if (!MACH_PORT_VALID(name)) { 1490 /* 1491 * Already dead. 1492 * Should do immediate delivery check - 1493 * will do that in the near future. 1494 */ 1495 return KERN_INVALID_ARGUMENT; 1496 } 1497 1498 kr = ipc_right_request_alloc(space, name, sync != 0, 1499 FALSE, notify, previousp); 1500 if (kr != KERN_SUCCESS) 1501 return kr; 1502 break; 1503 1504 default: 1505 return KERN_INVALID_VALUE; 1506 } 1507 1508 return KERN_SUCCESS; 1509} 1510 1511/* 1512 * Routine: mach_port_insert_right [kernel call] 1513 * Purpose: 1514 * Inserts a right into a space, as if the space 1515 * voluntarily received the right in a message, 1516 * except that the right gets the specified name. 1517 * Conditions: 1518 * Nothing locked. 1519 * Returns: 1520 * KERN_SUCCESS Inserted the right. 1521 * KERN_INVALID_TASK The space is null. 1522 * KERN_INVALID_TASK The space is dead. 1523 * KERN_INVALID_VALUE The name isn't a legal name. 1524 * KERN_NAME_EXISTS The name already denotes a right. 1525 * KERN_INVALID_VALUE Message doesn't carry a port right. 1526 * KERN_INVALID_CAPABILITY Port is null or dead. 1527 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded. 1528 * KERN_RIGHT_EXISTS Space has rights under another name. 1529 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 1530 */ 1531 1532kern_return_t 1533mach_port_insert_right( 1534 ipc_space_t space, 1535 mach_port_name_t name, 1536 ipc_port_t poly, 1537 mach_msg_type_name_t polyPoly) 1538{ 1539 if (space == IS_NULL) 1540 return KERN_INVALID_TASK; 1541 1542 if (!MACH_PORT_VALID(name) || 1543 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly)) 1544 return KERN_INVALID_VALUE; 1545 1546 if (!IO_VALID((ipc_object_t) poly)) 1547 return KERN_INVALID_CAPABILITY; 1548 1549 return ipc_object_copyout_name(space, (ipc_object_t) poly, 1550 polyPoly, FALSE, name); 1551} 1552 1553/* 1554 * Routine: mach_port_extract_right [kernel call] 1555 * Purpose: 1556 * Extracts a right from a space, as if the space 1557 * voluntarily sent the right to the caller. 1558 * Conditions: 1559 * Nothing locked. 1560 * Returns: 1561 * KERN_SUCCESS Extracted the right. 1562 * KERN_INVALID_TASK The space is null. 1563 * KERN_INVALID_TASK The space is dead. 1564 * KERN_INVALID_VALUE Requested type isn't a port right. 1565 * KERN_INVALID_NAME Name doesn't denote a right. 1566 * KERN_INVALID_RIGHT Name doesn't denote appropriate right. 1567 */ 1568 1569kern_return_t 1570mach_port_extract_right( 1571 ipc_space_t space, 1572 mach_port_name_t name, 1573 mach_msg_type_name_t msgt_name, 1574 ipc_port_t *poly, 1575 mach_msg_type_name_t *polyPoly) 1576{ 1577 kern_return_t kr; 1578 1579 if (space == IS_NULL) 1580 return KERN_INVALID_TASK; 1581 1582 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name)) 1583 return KERN_INVALID_VALUE; 1584 1585 if (!MACH_PORT_VALID(name)) { 1586 /* 1587 * really should copy out a dead name, if it is a send or 1588 * send-once right being copied, but instead return an 1589 * error for now. 1590 */ 1591 return KERN_INVALID_RIGHT; 1592 } 1593 1594 kr = ipc_object_copyin(space, name, msgt_name, (ipc_object_t *) poly); 1595 1596 if (kr == KERN_SUCCESS) 1597 *polyPoly = ipc_object_copyin_type(msgt_name); 1598 return kr; 1599} 1600 1601 1602kern_return_t 1603mach_port_get_attributes( 1604 ipc_space_t space, 1605 mach_port_name_t name, 1606 int flavor, 1607 mach_port_info_t info, 1608 mach_msg_type_number_t *count) 1609{ 1610 ipc_port_t port; 1611 kern_return_t kr; 1612 1613 if (space == IS_NULL) 1614 return KERN_INVALID_TASK; 1615 1616 switch (flavor) { 1617 case MACH_PORT_LIMITS_INFO: { 1618 mach_port_limits_t *lp = (mach_port_limits_t *)info; 1619 1620 if (*count < MACH_PORT_LIMITS_INFO_COUNT) 1621 return KERN_FAILURE; 1622 1623 if (!MACH_PORT_VALID(name)) { 1624 *count = 0; 1625 break; 1626 } 1627 1628 kr = ipc_port_translate_receive(space, name, &port); 1629 if (kr != KERN_SUCCESS) 1630 return kr; 1631 /* port is locked and active */ 1632 1633 lp->mpl_qlimit = port->ip_messages.imq_qlimit; 1634 *count = MACH_PORT_LIMITS_INFO_COUNT; 1635 ip_unlock(port); 1636 break; 1637 } 1638 1639 case MACH_PORT_RECEIVE_STATUS: { 1640 mach_port_status_t *statusp = (mach_port_status_t *)info; 1641 spl_t s; 1642 1643 if (*count < MACH_PORT_RECEIVE_STATUS_COUNT) 1644 return KERN_FAILURE; 1645 1646 if (!MACH_PORT_VALID(name)) 1647 return KERN_INVALID_RIGHT; 1648 1649 kr = ipc_port_translate_receive(space, name, &port); 1650 if (kr != KERN_SUCCESS) 1651 return kr; 1652 /* port is locked and active */ 1653 1654 statusp->mps_pset = port->ip_pset_count; 1655 1656 s = splsched(); 1657 imq_lock(&port->ip_messages); 1658 statusp->mps_seqno = port->ip_messages.imq_seqno; 1659 statusp->mps_qlimit = port->ip_messages.imq_qlimit; 1660 statusp->mps_msgcount = port->ip_messages.imq_msgcount; 1661 imq_unlock(&port->ip_messages); 1662 splx(s); 1663 1664 statusp->mps_mscount = port->ip_mscount; 1665 statusp->mps_sorights = port->ip_sorights; 1666 statusp->mps_srights = port->ip_srights > 0; 1667 statusp->mps_pdrequest = port->ip_pdrequest != IP_NULL; 1668 statusp->mps_nsrequest = port->ip_nsrequest != IP_NULL; 1669 statusp->mps_flags = 0; 1670 1671 *count = MACH_PORT_RECEIVE_STATUS_COUNT; 1672 ip_unlock(port); 1673 break; 1674 } 1675 1676 case MACH_PORT_DNREQUESTS_SIZE: { 1677 ipc_port_request_t table; 1678 1679 if (*count < MACH_PORT_DNREQUESTS_SIZE_COUNT) 1680 return KERN_FAILURE; 1681 1682 if (!MACH_PORT_VALID(name)) { 1683 *(int *)info = 0; 1684 break; 1685 } 1686 1687 kr = ipc_port_translate_receive(space, name, &port); 1688 if (kr != KERN_SUCCESS) 1689 return kr; 1690 /* port is locked and active */ 1691 1692 table = port->ip_requests; 1693 if (table == IPR_NULL) 1694 *(int *)info = 0; 1695 else 1696 *(int *)info = table->ipr_size->its_size; 1697 *count = MACH_PORT_DNREQUESTS_SIZE_COUNT; 1698 ip_unlock(port); 1699 break; 1700 } 1701 1702 default: 1703 return KERN_INVALID_ARGUMENT; 1704 /*NOTREACHED*/ 1705 } 1706 1707 return KERN_SUCCESS; 1708} 1709 1710kern_return_t 1711mach_port_set_attributes( 1712 ipc_space_t space, 1713 mach_port_name_t name, 1714 int flavor, 1715 mach_port_info_t info, 1716 mach_msg_type_number_t count) 1717{ 1718 ipc_port_t port; 1719 kern_return_t kr; 1720 1721 if (space == IS_NULL) 1722 return KERN_INVALID_TASK; 1723 1724 switch (flavor) { 1725 1726 case MACH_PORT_LIMITS_INFO: { 1727 mach_port_limits_t *mplp = (mach_port_limits_t *)info; 1728 1729 if (count < MACH_PORT_LIMITS_INFO_COUNT) 1730 return KERN_FAILURE; 1731 1732 if (mplp->mpl_qlimit > MACH_PORT_QLIMIT_MAX) 1733 return KERN_INVALID_VALUE; 1734 1735 if (!MACH_PORT_VALID(name)) 1736 return KERN_INVALID_RIGHT; 1737 1738 kr = ipc_port_translate_receive(space, name, &port); 1739 if (kr != KERN_SUCCESS) 1740 return kr; 1741 /* port is locked and active */ 1742 1743 ipc_mqueue_set_qlimit(&port->ip_messages, mplp->mpl_qlimit); 1744 ip_unlock(port); 1745 break; 1746 } 1747 case MACH_PORT_DNREQUESTS_SIZE: { 1748 if (count < MACH_PORT_DNREQUESTS_SIZE_COUNT) 1749 return KERN_FAILURE; 1750 1751 if (!MACH_PORT_VALID(name)) 1752 return KERN_INVALID_RIGHT; 1753 1754 kr = ipc_port_translate_receive(space, name, &port); 1755 if (kr != KERN_SUCCESS) 1756 return kr; 1757 /* port is locked and active */ 1758 1759 kr = ipc_port_request_grow(port, *(int *)info); 1760 if (kr != KERN_SUCCESS) 1761 return kr; 1762 break; 1763 } 1764 default: 1765 return KERN_INVALID_ARGUMENT; 1766 /*NOTREACHED*/ 1767 } 1768 return KERN_SUCCESS; 1769} 1770 1771/* 1772 * Routine: mach_port_insert_member [kernel call] 1773 * Purpose: 1774 * Add the receive right, specified by name, to 1775 * a portset. 1776 * The port cannot already be a member of the set. 1777 * Conditions: 1778 * Nothing locked. 1779 * Returns: 1780 * KERN_SUCCESS Moved the port. 1781 * KERN_INVALID_TASK The space is null. 1782 * KERN_INVALID_TASK The space is dead. 1783 * KERN_INVALID_NAME name didn't denote a right. 1784 * KERN_INVALID_RIGHT name didn't denote a receive right. 1785 * KERN_INVALID_NAME pset_name didn't denote a right. 1786 * KERN_INVALID_RIGHT pset_name didn't denote a portset right. 1787 * KERN_ALREADY_IN_SET name was already a member of pset. 1788 */ 1789 1790kern_return_t 1791mach_port_insert_member( 1792 ipc_space_t space, 1793 mach_port_name_t name, 1794 mach_port_name_t psname) 1795{ 1796 ipc_object_t obj; 1797 ipc_object_t psobj; 1798 kern_return_t kr; 1799 wait_queue_link_t wql; 1800 1801 if (space == IS_NULL) 1802 return KERN_INVALID_TASK; 1803 1804 if (!MACH_PORT_VALID(name) || !MACH_PORT_VALID(psname)) 1805 return KERN_INVALID_RIGHT; 1806 1807 wql = wait_queue_link_allocate(); 1808 1809 kr = ipc_object_translate_two(space, 1810 name, MACH_PORT_RIGHT_RECEIVE, &obj, 1811 psname, MACH_PORT_RIGHT_PORT_SET, &psobj); 1812 if (kr != KERN_SUCCESS) 1813 goto done; 1814 1815 /* obj and psobj are locked (and were locked in that order) */ 1816 assert(psobj != IO_NULL); 1817 assert(obj != IO_NULL); 1818 1819 kr = ipc_pset_add((ipc_pset_t)psobj, (ipc_port_t)obj, wql); 1820 io_unlock(psobj); 1821 io_unlock(obj); 1822 1823 done: 1824 if (kr != KERN_SUCCESS) 1825 wait_queue_link_free(wql); 1826 1827 return kr; 1828} 1829 1830/* 1831 * Routine: mach_port_extract_member [kernel call] 1832 * Purpose: 1833 * Remove a port from one portset that it is a member of. 1834 * Conditions: 1835 * Nothing locked. 1836 * Returns: 1837 * KERN_SUCCESS Moved the port. 1838 * KERN_INVALID_TASK The space is null. 1839 * KERN_INVALID_TASK The space is dead. 1840 * KERN_INVALID_NAME Member didn't denote a right. 1841 * KERN_INVALID_RIGHT Member didn't denote a receive right. 1842 * KERN_INVALID_NAME After didn't denote a right. 1843 * KERN_INVALID_RIGHT After didn't denote a port set right. 1844 * KERN_NOT_IN_SET 1845 * After is MACH_PORT_NULL and Member isn't in a port set. 1846 */ 1847 1848kern_return_t 1849mach_port_extract_member( 1850 ipc_space_t space, 1851 mach_port_name_t name, 1852 mach_port_name_t psname) 1853{ 1854 ipc_object_t psobj; 1855 ipc_object_t obj; 1856 kern_return_t kr; 1857 wait_queue_link_t wql = WAIT_QUEUE_LINK_NULL; 1858 1859 if (space == IS_NULL) 1860 return KERN_INVALID_TASK; 1861 1862 if (!MACH_PORT_VALID(name) || !MACH_PORT_VALID(psname)) 1863 return KERN_INVALID_RIGHT; 1864 1865 kr = ipc_object_translate_two(space, 1866 name, MACH_PORT_RIGHT_RECEIVE, &obj, 1867 psname, MACH_PORT_RIGHT_PORT_SET, &psobj); 1868 if (kr != KERN_SUCCESS) 1869 return kr; 1870 1871 /* obj and psobj are both locked (and were locked in that order) */ 1872 assert(psobj != IO_NULL); 1873 assert(obj != IO_NULL); 1874 1875 kr = ipc_pset_remove((ipc_pset_t)psobj, (ipc_port_t)obj, &wql); 1876 io_unlock(psobj); 1877 io_unlock(obj); 1878 1879 if (wql != WAIT_QUEUE_LINK_NULL) 1880 wait_queue_link_free(wql); 1881 1882 return kr; 1883} 1884 1885/* 1886 * task_set_port_space: 1887 * 1888 * Set port name space of task to specified size. 1889 */ 1890kern_return_t 1891task_set_port_space( 1892 ipc_space_t space, 1893 int table_entries) 1894{ 1895 kern_return_t kr; 1896 1897 is_write_lock(space); 1898 1899 if (!is_active(space)) { 1900 is_write_unlock(space); 1901 return KERN_INVALID_TASK; 1902 } 1903 1904 kr = ipc_entry_grow_table(space, table_entries); 1905 if (kr == KERN_SUCCESS) 1906 is_write_unlock(space); 1907 return kr; 1908} 1909 1910/* 1911 * Get a (new) label handle representing the given port's port label. 1912 */ 1913#if CONFIG_MACF_MACH 1914kern_return_t 1915mach_get_label( 1916 ipc_space_t space, 1917 mach_port_name_t name, 1918 mach_port_name_t *outlabel) 1919{ 1920 ipc_entry_t entry; 1921 ipc_port_t port; 1922 struct label outl; 1923 kern_return_t kr; 1924 int dead; 1925 1926 if (!MACH_PORT_VALID(name)) 1927 return KERN_INVALID_NAME; 1928 1929 /* Lookup the port name in the task's space. */ 1930 kr = ipc_right_lookup_write(space, name, &entry); 1931 if (kr != KERN_SUCCESS) 1932 return kr; 1933 1934 port = (ipc_port_t) entry->ie_object; 1935 dead = ipc_right_check(space, port, name, entry); 1936 if (dead) { 1937 is_write_unlock(space); 1938 ip_release(port); 1939 return KERN_INVALID_RIGHT; 1940 } 1941 /* port is now locked */ 1942 1943 is_write_unlock(space); 1944 /* Make sure we are not dealing with a label handle. */ 1945 if (ip_kotype(port) == IKOT_LABELH) { 1946 /* already is a label handle! */ 1947 ip_unlock(port); 1948 return KERN_INVALID_ARGUMENT; 1949 } 1950 1951 /* Copy the port label and stash it in a new label handle. */ 1952 mac_port_label_init(&outl); 1953 mac_port_label_copy(&port->ip_label, &outl); 1954 kr = labelh_new_user(space, &outl, outlabel); 1955 ip_unlock(port); 1956 1957 return KERN_SUCCESS; 1958} 1959#else 1960kern_return_t 1961mach_get_label( 1962 __unused ipc_space_t space, 1963 __unused mach_port_name_t name, 1964 __unused mach_port_name_t *outlabel) 1965{ 1966 return KERN_INVALID_ARGUMENT; 1967} 1968#endif 1969 1970/* 1971 * also works on label handles 1972 */ 1973#if CONFIG_MACF_MACH 1974kern_return_t 1975mach_get_label_text( 1976 ipc_space_t space, 1977 mach_port_name_t name, 1978 labelstr_t policies, 1979 labelstr_t outlabel) 1980{ 1981 ipc_entry_t entry; 1982 ipc_port_t port; 1983 kern_return_t kr; 1984 struct label *l; 1985 int dead; 1986 1987 if (space == IS_NULL || space->is_task == NULL) 1988 return KERN_INVALID_TASK; 1989 1990 if (!MACH_PORT_VALID(name)) 1991 return KERN_INVALID_NAME; 1992 1993 kr = ipc_right_lookup_write(space, name, &entry); 1994 if (kr != KERN_SUCCESS) 1995 return kr; 1996 1997 port = (ipc_port_t)entry->ie_object; 1998 dead = ipc_right_check(space, port, name, entry); 1999 if (dead) { 2000 is_write_unlock(space); 2001 ip_release(port); 2002 return KERN_INVALID_RIGHT; 2003 } 2004 /* object (port) is now locked */ 2005 2006 is_write_unlock (space); 2007 l = io_getlabel(entry->ie_object); 2008 2009 mac_port_label_externalize(l, policies, outlabel, 512, 0); 2010 2011 io_unlocklabel(entry->ie_object); 2012 io_unlock(entry->ie_object); 2013 return KERN_SUCCESS; 2014} 2015#else 2016kern_return_t 2017mach_get_label_text( 2018 __unused ipc_space_t space, 2019 __unused mach_port_name_t name, 2020 __unused labelstr_t policies, 2021 __unused labelstr_t outlabel) 2022{ 2023 return KERN_INVALID_ARGUMENT; 2024} 2025#endif 2026 2027 2028#if CONFIG_MACF_MACH 2029kern_return_t 2030mach_set_port_label( 2031 ipc_space_t space, 2032 mach_port_name_t name, 2033 labelstr_t labelstr) 2034{ 2035 ipc_entry_t entry; 2036 kern_return_t kr; 2037 struct label inl; 2038 ipc_port_t port; 2039 int rc; 2040 2041 if (space == IS_NULL || space->is_task == NULL) 2042 return KERN_INVALID_TASK; 2043 2044 if (!MACH_PORT_VALID(name)) 2045 return KERN_INVALID_NAME; 2046 2047 mac_port_label_init(&inl); 2048 rc = mac_port_label_internalize(&inl, labelstr); 2049 if (rc) 2050 return KERN_INVALID_ARGUMENT; 2051 2052 kr = ipc_right_lookup_write(space, name, &entry); 2053 if (kr != KERN_SUCCESS) 2054 return kr; 2055 2056 if (io_otype(entMACry->ie_object) != IOT_PORT) { 2057 is_write_unlock(space); 2058 return KERN_INVALID_RIGHT; 2059 } 2060 2061 port = (ipc_port_t) entry->ie_object; 2062 ip_lock(port); 2063 2064 tasklabel_lock(space->is_task); 2065 rc = mac_port_check_label_update(&space->is_task->maclabel, 2066 &port->ip_label, &inl); 2067 tasklabel_unlock(space->is_task); 2068 if (rc) 2069 kr = KERN_NO_ACCESS; 2070 else 2071 mac_port_label_copy(&inl, &port->ip_label); 2072 2073 ip_unlock(port); 2074 is_write_unlock(space); 2075 return kr; 2076} 2077#else 2078kern_return_t 2079mach_set_port_label( 2080 ipc_space_t space __unused, 2081 mach_port_name_t name __unused, 2082 labelstr_t labelstr __unused) 2083{ 2084 return KERN_INVALID_ARGUMENT; 2085} 2086#endif 2087