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