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_entry_num_t maxnames, 118 mach_port_name_t *names, 119 ipc_entry_num_t *actualp); 120 121 122kern_return_t 123mach_port_guard_exception( 124 mach_port_name_t name, 125 uint64_t inguard, 126 uint64_t portguard, 127 unsigned reason); 128 129/* Needs port locked */ 130void mach_port_get_status_helper( 131 ipc_port_t port, 132 mach_port_status_t *status); 133 134/* Zeroed template of qos flags */ 135 136static mach_port_qos_t qos_template; 137 138/* 139 * Routine: mach_port_names_helper 140 * Purpose: 141 * A helper function for mach_port_names. 142 * 143 * Conditions: 144 * Space containing entry is [at least] read-locked. 145 */ 146 147void 148mach_port_names_helper( 149 ipc_port_timestamp_t timestamp, 150 ipc_entry_t entry, 151 mach_port_name_t name, 152 mach_port_name_t *names, 153 mach_port_type_t *types, 154 ipc_entry_num_t *actualp) 155{ 156 ipc_entry_bits_t bits; 157 ipc_port_request_index_t request; 158 mach_port_type_t type = 0; 159 ipc_entry_num_t actual; 160 ipc_port_t port; 161 162 bits = entry->ie_bits; 163 request = entry->ie_request; 164 port = (ipc_port_t) entry->ie_object; 165 166 if (bits & MACH_PORT_TYPE_RECEIVE) { 167 assert(IP_VALID(port)); 168 169 if (request != IE_REQ_NONE) { 170 ip_lock(port); 171 assert(ip_active(port)); 172 type |= ipc_port_request_type(port, name, request); 173 ip_unlock(port); 174 } 175 176 } else if (bits & MACH_PORT_TYPE_SEND_RIGHTS) { 177 mach_port_type_t reqtype; 178 179 assert(IP_VALID(port)); 180 ip_lock(port); 181 182 reqtype = (request != IE_REQ_NONE) ? 183 ipc_port_request_type(port, name, request) : 0; 184 185 /* 186 * If the port is alive, or was alive when the mach_port_names 187 * started, then return that fact. Otherwise, pretend we found 188 * a dead name entry. 189 */ 190 if (ip_active(port) || IP_TIMESTAMP_ORDER(timestamp, port->ip_timestamp)) { 191 type |= reqtype; 192 } else { 193 bits &= ~(IE_BITS_TYPE_MASK); 194 bits |= MACH_PORT_TYPE_DEAD_NAME; 195 /* account for additional reference for dead-name notification */ 196 if (reqtype != 0) 197 bits++; 198 } 199 ip_unlock(port); 200 } 201 202 type |= IE_BITS_TYPE(bits); 203 204 actual = *actualp; 205 names[actual] = name; 206 types[actual] = type; 207 *actualp = actual+1; 208} 209 210/* 211 * Routine: mach_port_names [kernel call] 212 * Purpose: 213 * Retrieves a list of the rights present in the space, 214 * along with type information. (Same as returned 215 * by mach_port_type.) The names are returned in 216 * no particular order, but they (and the type info) 217 * are an accurate snapshot of the space. 218 * Conditions: 219 * Nothing locked. 220 * Returns: 221 * KERN_SUCCESS Arrays of names and types returned. 222 * KERN_INVALID_TASK The space is null. 223 * KERN_INVALID_TASK The space is dead. 224 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 225 */ 226 227kern_return_t 228mach_port_names( 229 ipc_space_t space, 230 mach_port_name_t **namesp, 231 mach_msg_type_number_t *namesCnt, 232 mach_port_type_t **typesp, 233 mach_msg_type_number_t *typesCnt) 234{ 235 ipc_entry_t table; 236 ipc_entry_num_t tsize; 237 mach_port_index_t index; 238 ipc_entry_num_t actual; /* this many names */ 239 ipc_port_timestamp_t timestamp; /* logical time of this operation */ 240 mach_port_name_t *names; 241 mach_port_type_t *types; 242 kern_return_t kr; 243 244 vm_size_t size; /* size of allocated memory */ 245 vm_offset_t addr1; /* allocated memory, for names */ 246 vm_offset_t addr2; /* allocated memory, for types */ 247 vm_map_copy_t memory1; /* copied-in memory, for names */ 248 vm_map_copy_t memory2; /* copied-in memory, for types */ 249 250 /* safe simplifying assumption */ 251 assert_static(sizeof(mach_port_name_t) == sizeof(mach_port_type_t)); 252 253 if (space == IS_NULL) 254 return KERN_INVALID_TASK; 255 256 size = 0; 257 258 for (;;) { 259 ipc_entry_num_t bound; 260 vm_size_t size_needed; 261 262 is_read_lock(space); 263 if (!is_active(space)) { 264 is_read_unlock(space); 265 if (size != 0) { 266 kmem_free(ipc_kernel_map, addr1, size); 267 kmem_free(ipc_kernel_map, addr2, size); 268 } 269 return KERN_INVALID_TASK; 270 } 271 272 /* upper bound on number of names in the space */ 273 bound = space->is_table_size; 274 size_needed = vm_map_round_page( 275 (bound * sizeof(mach_port_name_t)), 276 VM_MAP_PAGE_MASK(ipc_kernel_map)); 277 278 if (size_needed <= size) 279 break; 280 281 is_read_unlock(space); 282 283 if (size != 0) { 284 kmem_free(ipc_kernel_map, addr1, size); 285 kmem_free(ipc_kernel_map, addr2, size); 286 } 287 size = size_needed; 288 289 kr = vm_allocate(ipc_kernel_map, &addr1, size, VM_FLAGS_ANYWHERE); 290 if (kr != KERN_SUCCESS) 291 return KERN_RESOURCE_SHORTAGE; 292 293 kr = vm_allocate(ipc_kernel_map, &addr2, size, VM_FLAGS_ANYWHERE); 294 if (kr != KERN_SUCCESS) { 295 kmem_free(ipc_kernel_map, addr1, size); 296 return KERN_RESOURCE_SHORTAGE; 297 } 298 299 /* can't fault while we hold locks */ 300 301 kr = vm_map_wire( 302 ipc_kernel_map, 303 vm_map_trunc_page(addr1, 304 VM_MAP_PAGE_MASK(ipc_kernel_map)), 305 vm_map_round_page(addr1 + size, 306 VM_MAP_PAGE_MASK(ipc_kernel_map)), 307 VM_PROT_READ|VM_PROT_WRITE, 308 FALSE); 309 if (kr != KERN_SUCCESS) { 310 kmem_free(ipc_kernel_map, addr1, size); 311 kmem_free(ipc_kernel_map, addr2, size); 312 return KERN_RESOURCE_SHORTAGE; 313 } 314 315 kr = vm_map_wire( 316 ipc_kernel_map, 317 vm_map_trunc_page(addr2, 318 VM_MAP_PAGE_MASK(ipc_kernel_map)), 319 vm_map_round_page(addr2 + size, 320 VM_MAP_PAGE_MASK(ipc_kernel_map)), 321 VM_PROT_READ|VM_PROT_WRITE, 322 FALSE); 323 if (kr != KERN_SUCCESS) { 324 kmem_free(ipc_kernel_map, addr1, size); 325 kmem_free(ipc_kernel_map, addr2, size); 326 return KERN_RESOURCE_SHORTAGE; 327 } 328 329 } 330 /* space is read-locked and active */ 331 332 names = (mach_port_name_t *) addr1; 333 types = (mach_port_type_t *) addr2; 334 actual = 0; 335 336 timestamp = ipc_port_timestamp(); 337 338 table = space->is_table; 339 tsize = space->is_table_size; 340 341 for (index = 0; index < tsize; index++) { 342 ipc_entry_t entry = &table[index]; 343 ipc_entry_bits_t bits = entry->ie_bits; 344 345 if (IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE) { 346 mach_port_name_t name; 347 348 name = MACH_PORT_MAKE(index, IE_BITS_GEN(bits)); 349 mach_port_names_helper(timestamp, entry, name, names, 350 types, &actual); 351 } 352 } 353 354 is_read_unlock(space); 355 356 if (actual == 0) { 357 memory1 = VM_MAP_COPY_NULL; 358 memory2 = VM_MAP_COPY_NULL; 359 360 if (size != 0) { 361 kmem_free(ipc_kernel_map, addr1, size); 362 kmem_free(ipc_kernel_map, addr2, size); 363 } 364 } else { 365 vm_size_t size_used; 366 vm_size_t vm_size_used; 367 368 size_used = actual * sizeof(mach_port_name_t); 369 vm_size_used = 370 vm_map_round_page(size_used, 371 VM_MAP_PAGE_MASK(ipc_kernel_map)); 372 373 /* 374 * Make used memory pageable and get it into 375 * copied-in form. Free any unused memory. 376 */ 377 378 kr = vm_map_unwire( 379 ipc_kernel_map, 380 vm_map_trunc_page(addr1, 381 VM_MAP_PAGE_MASK(ipc_kernel_map)), 382 vm_map_round_page(addr1 + vm_size_used, 383 VM_MAP_PAGE_MASK(ipc_kernel_map)), 384 FALSE); 385 assert(kr == KERN_SUCCESS); 386 387 kr = vm_map_unwire( 388 ipc_kernel_map, 389 vm_map_trunc_page(addr2, 390 VM_MAP_PAGE_MASK(ipc_kernel_map)), 391 vm_map_round_page(addr2 + vm_size_used, 392 VM_MAP_PAGE_MASK(ipc_kernel_map)), 393 FALSE); 394 assert(kr == KERN_SUCCESS); 395 396 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr1, 397 (vm_map_size_t)size_used, TRUE, &memory1); 398 assert(kr == KERN_SUCCESS); 399 400 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr2, 401 (vm_map_size_t)size_used, TRUE, &memory2); 402 assert(kr == KERN_SUCCESS); 403 404 if (vm_size_used != size) { 405 kmem_free(ipc_kernel_map, 406 addr1 + vm_size_used, size - vm_size_used); 407 kmem_free(ipc_kernel_map, 408 addr2 + vm_size_used, size - vm_size_used); 409 } 410 } 411 412 *namesp = (mach_port_name_t *) memory1; 413 *namesCnt = actual; 414 *typesp = (mach_port_type_t *) memory2; 415 *typesCnt = actual; 416 return KERN_SUCCESS; 417} 418 419/* 420 * Routine: mach_port_type [kernel call] 421 * Purpose: 422 * Retrieves the type of a right in the space. 423 * The type is a bitwise combination of one or more 424 * of the following type bits: 425 * MACH_PORT_TYPE_SEND 426 * MACH_PORT_TYPE_RECEIVE 427 * MACH_PORT_TYPE_SEND_ONCE 428 * MACH_PORT_TYPE_PORT_SET 429 * MACH_PORT_TYPE_DEAD_NAME 430 * In addition, the following pseudo-type bits may be present: 431 * MACH_PORT_TYPE_DNREQUEST 432 * A dead-name notification is requested. 433 * Conditions: 434 * Nothing locked. 435 * Returns: 436 * KERN_SUCCESS Type is returned. 437 * KERN_INVALID_TASK The space is null. 438 * KERN_INVALID_TASK The space is dead. 439 * KERN_INVALID_NAME The name doesn't denote a right. 440 */ 441 442kern_return_t 443mach_port_type( 444 ipc_space_t space, 445 mach_port_name_t name, 446 mach_port_type_t *typep) 447{ 448 mach_port_urefs_t urefs; 449 ipc_entry_t entry; 450 kern_return_t kr; 451 452 if (space == IS_NULL) 453 return KERN_INVALID_TASK; 454 455 if (name == MACH_PORT_NULL) 456 return KERN_INVALID_NAME; 457 458 if (name == MACH_PORT_DEAD) { 459 *typep = MACH_PORT_TYPE_DEAD_NAME; 460 return KERN_SUCCESS; 461 } 462 463 kr = ipc_right_lookup_write(space, name, &entry); 464 if (kr != KERN_SUCCESS) 465 return kr; 466 467 /* space is write-locked and active */ 468 kr = ipc_right_info(space, name, entry, typep, &urefs); 469 /* space is unlocked */ 470 471#if 1 472 /* JMM - workaround rdar://problem/9121297 (CF being too picky on these bits). */ 473 *typep &= ~(MACH_PORT_TYPE_SPREQUEST | MACH_PORT_TYPE_SPREQUEST_DELAYED); 474#endif 475 476 return kr; 477} 478 479/* 480 * Routine: mach_port_rename [kernel call] 481 * Purpose: 482 * Changes the name denoting a right, 483 * from oname to nname. 484 * Conditions: 485 * Nothing locked. 486 * Returns: 487 * KERN_SUCCESS The right is renamed. 488 * KERN_INVALID_TASK The space is null. 489 * KERN_INVALID_TASK The space is dead. 490 * KERN_INVALID_NAME The oname doesn't denote a right. 491 * KERN_INVALID_VALUE The nname isn't a legal name. 492 * KERN_NAME_EXISTS The nname already denotes a right. 493 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 494 * 495 * This interface is obsolete and always returns 496 * KERN_NOT_SUPPORTED. 497 */ 498 499kern_return_t 500mach_port_rename( 501 __unused ipc_space_t space, 502 __unused mach_port_name_t oname, 503 __unused mach_port_name_t nname) 504{ 505 return KERN_NOT_SUPPORTED; 506} 507 508 509/* 510 * Routine: mach_port_allocate_name [kernel call] 511 * Purpose: 512 * Allocates a right in a space, using a specific name 513 * for the new right. Possible rights: 514 * MACH_PORT_RIGHT_RECEIVE 515 * MACH_PORT_RIGHT_PORT_SET 516 * MACH_PORT_RIGHT_DEAD_NAME 517 * 518 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE) 519 * has no extant send or send-once rights and no queued 520 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT 521 * and its make-send count is 0. It is not a member of 522 * a port set. It has no registered no-senders or 523 * port-destroyed notification requests. 524 * 525 * A new port set has no members. 526 * 527 * A new dead name has one user reference. 528 * Conditions: 529 * Nothing locked. 530 * Returns: 531 * KERN_SUCCESS The right is allocated. 532 * KERN_INVALID_TASK The space is null. 533 * KERN_INVALID_TASK The space is dead. 534 * KERN_INVALID_VALUE The name isn't a legal name. 535 * KERN_INVALID_VALUE "right" isn't a legal kind of right. 536 * KERN_NAME_EXISTS The name already denotes a right. 537 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 538 * 539 * Restrictions on name allocation: NT bits are reserved by kernel, 540 * must be set on any chosen name. Can't do this at all in kernel 541 * loaded server. 542 */ 543 544kern_return_t 545mach_port_allocate_name( 546 ipc_space_t space, 547 mach_port_right_t right, 548 mach_port_name_t name) 549{ 550 kern_return_t kr; 551 mach_port_qos_t qos = qos_template; 552 553 qos.name = TRUE; 554 555 if (!MACH_PORT_VALID(name)) 556 return KERN_INVALID_VALUE; 557 558 kr = mach_port_allocate_full (space, right, MACH_PORT_NULL, 559 &qos, &name); 560 return (kr); 561} 562 563/* 564 * Routine: mach_port_allocate [kernel call] 565 * Purpose: 566 * Allocates a right in a space. Like mach_port_allocate_name, 567 * except that the implementation picks a name for the right. 568 * The name may be any legal name in the space that doesn't 569 * currently denote a right. 570 * Conditions: 571 * Nothing locked. 572 * Returns: 573 * KERN_SUCCESS The right is allocated. 574 * KERN_INVALID_TASK The space is null. 575 * KERN_INVALID_TASK The space is dead. 576 * KERN_INVALID_VALUE "right" isn't a legal kind of right. 577 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 578 * KERN_NO_SPACE No room in space for another right. 579 */ 580 581kern_return_t 582mach_port_allocate( 583 ipc_space_t space, 584 mach_port_right_t right, 585 mach_port_name_t *namep) 586{ 587 kern_return_t kr; 588 mach_port_qos_t qos = qos_template; 589 590 kr = mach_port_allocate_full (space, right, MACH_PORT_NULL, 591 &qos, namep); 592 return (kr); 593} 594 595/* 596 * Routine: mach_port_allocate_qos [kernel call] 597 * Purpose: 598 * Allocates a right, with qos options, in a space. Like 599 * mach_port_allocate_name, except that the implementation 600 * picks a name for the right. The name may be any legal name 601 * in the space that doesn't currently denote a right. 602 * Conditions: 603 * Nothing locked. 604 * Returns: 605 * KERN_SUCCESS The right is allocated. 606 * KERN_INVALID_TASK The space is null. 607 * KERN_INVALID_TASK The space is dead. 608 * KERN_INVALID_VALUE "right" isn't a legal kind of right. 609 * KERN_INVALID_ARGUMENT The qos request was invalid. 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_qos( 616 ipc_space_t space, 617 mach_port_right_t right, 618 mach_port_qos_t *qosp, 619 mach_port_name_t *namep) 620{ 621 kern_return_t kr; 622 623 if (qosp->name) 624 return KERN_INVALID_ARGUMENT; 625 kr = mach_port_allocate_full (space, right, MACH_PORT_NULL, 626 qosp, namep); 627 return (kr); 628} 629 630/* 631 * Routine: mach_port_allocate_full [kernel call] 632 * Purpose: 633 * Allocates a right in a space. Supports all of the 634 * special cases, such as specifying a subsystem, 635 * a specific name, a real-time port, etc. 636 * The name may be any legal name in the space that doesn't 637 * currently denote a right. 638 * Conditions: 639 * Nothing locked. 640 * Returns: 641 * KERN_SUCCESS The right is allocated. 642 * KERN_INVALID_TASK The space is null. 643 * KERN_INVALID_TASK The space is dead. 644 * KERN_INVALID_VALUE "right" isn't a legal kind of right. 645 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 646 * KERN_NO_SPACE No room in space for another right. 647 */ 648 649kern_return_t 650mach_port_allocate_full( 651 ipc_space_t space, 652 mach_port_right_t right, 653 mach_port_t proto, 654 mach_port_qos_t *qosp, 655 mach_port_name_t *namep) 656{ 657 ipc_kmsg_t kmsg = IKM_NULL; 658 kern_return_t kr; 659 660 if (space == IS_NULL) 661 return (KERN_INVALID_TASK); 662 663 if (proto != MACH_PORT_NULL) 664 return (KERN_INVALID_VALUE); 665 666 if (qosp->name) { 667 if (!MACH_PORT_VALID (*namep)) 668 return (KERN_INVALID_VALUE); 669 } 670 671 if (qosp->prealloc) { 672 if (qosp->len > MACH_MSG_SIZE_MAX - MAX_TRAILER_SIZE) { 673 return KERN_RESOURCE_SHORTAGE; 674 } else { 675 mach_msg_size_t size = qosp->len + MAX_TRAILER_SIZE; 676 677 if (right != MACH_PORT_RIGHT_RECEIVE) 678 return (KERN_INVALID_VALUE); 679 680 kmsg = (ipc_kmsg_t)ipc_kmsg_prealloc(size); 681 if (kmsg == IKM_NULL) 682 return (KERN_RESOURCE_SHORTAGE); 683 } 684 } 685 686 switch (right) { 687 case MACH_PORT_RIGHT_RECEIVE: 688 { 689 ipc_port_t port; 690 691 if (qosp->name) 692 kr = ipc_port_alloc_name(space, *namep, &port); 693 else 694 kr = ipc_port_alloc(space, namep, &port); 695 if (kr == KERN_SUCCESS) { 696 if (kmsg != IKM_NULL) 697 ipc_kmsg_set_prealloc(kmsg, port); 698 699 ip_unlock(port); 700 701 } else if (kmsg != IKM_NULL) 702 ipc_kmsg_free(kmsg); 703 break; 704 } 705 706 case MACH_PORT_RIGHT_PORT_SET: 707 { 708 ipc_pset_t pset; 709 710 if (qosp->name) 711 kr = ipc_pset_alloc_name(space, *namep, &pset); 712 else 713 kr = ipc_pset_alloc(space, namep, &pset); 714 if (kr == KERN_SUCCESS) 715 ips_unlock(pset); 716 break; 717 } 718 719 case MACH_PORT_RIGHT_DEAD_NAME: 720 kr = ipc_object_alloc_dead(space, namep); 721 break; 722 723 default: 724 kr = KERN_INVALID_VALUE; 725 break; 726 } 727 728 return (kr); 729} 730 731/* 732 * Routine: mach_port_destroy [kernel call] 733 * Purpose: 734 * Cleans up and destroys all rights denoted by a name 735 * in a space. The destruction of a receive right 736 * destroys the port, unless a port-destroyed request 737 * has been made for it; the destruction of a port-set right 738 * destroys the port set. 739 * Conditions: 740 * Nothing locked. 741 * Returns: 742 * KERN_SUCCESS The name is destroyed. 743 * KERN_INVALID_TASK The space is null. 744 * KERN_INVALID_TASK The space is dead. 745 * KERN_INVALID_NAME The name doesn't denote a right. 746 */ 747 748kern_return_t 749mach_port_destroy( 750 ipc_space_t space, 751 mach_port_name_t name) 752{ 753 ipc_entry_t entry; 754 kern_return_t kr; 755 756 if (space == IS_NULL) 757 return KERN_INVALID_TASK; 758 759 if (!MACH_PORT_VALID(name)) 760 return KERN_SUCCESS; 761 762 kr = ipc_right_lookup_write(space, name, &entry); 763 if (kr != KERN_SUCCESS) 764 return kr; 765 /* space is write-locked and active */ 766 767 kr = ipc_right_destroy(space, name, entry, TRUE, 0); /* unlocks space */ 768 return kr; 769} 770 771/* 772 * Routine: mach_port_deallocate [kernel call] 773 * Purpose: 774 * Deallocates a user reference from a send right, 775 * send-once right, or a dead-name right. May 776 * deallocate the right, if this is the last uref, 777 * and destroy the name, if it doesn't denote 778 * other rights. 779 * Conditions: 780 * Nothing locked. 781 * Returns: 782 * KERN_SUCCESS The uref is deallocated. 783 * KERN_INVALID_TASK The space is null. 784 * KERN_INVALID_TASK The space is dead. 785 * KERN_INVALID_NAME The name doesn't denote a right. 786 * KERN_INVALID_RIGHT The right isn't correct. 787 */ 788 789kern_return_t 790mach_port_deallocate( 791 ipc_space_t space, 792 mach_port_name_t name) 793{ 794 ipc_entry_t entry; 795 kern_return_t kr; 796 797 if (space == IS_NULL) 798 return KERN_INVALID_TASK; 799 800 if (!MACH_PORT_VALID(name)) 801 return KERN_SUCCESS; 802 803 kr = ipc_right_lookup_write(space, name, &entry); 804 if (kr != KERN_SUCCESS) 805 return kr; 806 /* space is write-locked */ 807 808 kr = ipc_right_dealloc(space, name, entry); /* unlocks space */ 809 return kr; 810} 811 812/* 813 * Routine: mach_port_get_refs [kernel call] 814 * Purpose: 815 * Retrieves the number of user references held by a right. 816 * Receive rights, port-set rights, and send-once rights 817 * always have one user reference. Returns zero if the 818 * name denotes a right, but not the queried right. 819 * Conditions: 820 * Nothing locked. 821 * Returns: 822 * KERN_SUCCESS Number of urefs returned. 823 * KERN_INVALID_TASK The space is null. 824 * KERN_INVALID_TASK The space is dead. 825 * KERN_INVALID_VALUE "right" isn't a legal value. 826 * KERN_INVALID_NAME The name doesn't denote a right. 827 */ 828 829kern_return_t 830mach_port_get_refs( 831 ipc_space_t space, 832 mach_port_name_t name, 833 mach_port_right_t right, 834 mach_port_urefs_t *urefsp) 835{ 836 mach_port_type_t type; 837 mach_port_urefs_t urefs; 838 ipc_entry_t entry; 839 kern_return_t kr; 840 841 if (space == IS_NULL) 842 return KERN_INVALID_TASK; 843 844 if (right >= MACH_PORT_RIGHT_NUMBER) 845 return KERN_INVALID_VALUE; 846 847 if (!MACH_PORT_VALID(name)) { 848 if (right == MACH_PORT_RIGHT_SEND || 849 right == MACH_PORT_RIGHT_SEND_ONCE) { 850 *urefsp = 1; 851 return KERN_SUCCESS; 852 } 853 return KERN_INVALID_NAME; 854 } 855 856 kr = ipc_right_lookup_write(space, name, &entry); 857 if (kr != KERN_SUCCESS) 858 return kr; 859 860 /* space is write-locked and active */ 861 kr = ipc_right_info(space, name, entry, &type, &urefs); 862 /* space is unlocked */ 863 864 if (kr != KERN_SUCCESS) 865 return kr; 866 867 if (type & MACH_PORT_TYPE(right)) 868 switch (right) { 869 case MACH_PORT_RIGHT_SEND_ONCE: 870 assert(urefs == 1); 871 /* fall-through */ 872 873 case MACH_PORT_RIGHT_PORT_SET: 874 case MACH_PORT_RIGHT_RECEIVE: 875 *urefsp = 1; 876 break; 877 878 case MACH_PORT_RIGHT_DEAD_NAME: 879 case MACH_PORT_RIGHT_SEND: 880 assert(urefs > 0); 881 *urefsp = urefs; 882 break; 883 884 default: 885 panic("mach_port_get_refs: strange rights"); 886 } 887 else 888 *urefsp = 0; 889 890 return kr; 891} 892 893/* 894 * Routine: mach_port_mod_refs 895 * Purpose: 896 * Modifies the number of user references held by a right. 897 * The resulting number of user references must be non-negative. 898 * If it is zero, the right is deallocated. If the name 899 * doesn't denote other rights, it is destroyed. 900 * Conditions: 901 * Nothing locked. 902 * Returns: 903 * KERN_SUCCESS Modified number of urefs. 904 * KERN_INVALID_TASK The space is null. 905 * KERN_INVALID_TASK The space is dead. 906 * KERN_INVALID_VALUE "right" isn't a legal value. 907 * KERN_INVALID_NAME The name doesn't denote a right. 908 * KERN_INVALID_RIGHT Name doesn't denote specified right. 909 * KERN_INVALID_VALUE Impossible modification to urefs. 910 * KERN_UREFS_OVERFLOW Urefs would overflow. 911 */ 912 913kern_return_t 914mach_port_mod_refs( 915 ipc_space_t space, 916 mach_port_name_t name, 917 mach_port_right_t right, 918 mach_port_delta_t delta) 919{ 920 ipc_entry_t entry; 921 kern_return_t kr; 922 923 if (space == IS_NULL) 924 return KERN_INVALID_TASK; 925 926 if (right >= MACH_PORT_RIGHT_NUMBER) 927 return KERN_INVALID_VALUE; 928 929 if (!MACH_PORT_VALID(name)) { 930 if (right == MACH_PORT_RIGHT_SEND || 931 right == MACH_PORT_RIGHT_SEND_ONCE) 932 return KERN_SUCCESS; 933 return KERN_INVALID_NAME; 934 } 935 936 kr = ipc_right_lookup_write(space, name, &entry); 937 if (kr != KERN_SUCCESS) 938 return kr; 939 /* space is write-locked and active */ 940 941 kr = ipc_right_delta(space, name, entry, right, delta); /* unlocks */ 942 return kr; 943} 944 945 946/* 947 * Routine: mach_port_peek [kernel call] 948 * Purpose: 949 * Peek at the message queue for the specified receive 950 * right and return info about a message in the queue. 951 * 952 * On input, seqnop points to a sequence number value 953 * to match the message being peeked. If zero is specified 954 * as the seqno, the first message in the queue will be 955 * peeked. 956 * 957 * Only the following trailer types are currently supported: 958 * MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) 959 * 960 * or'ed with one of these element types: 961 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_NULL) 962 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SEQNO) 963 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SENDER) 964 * MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) 965 * 966 * On input, the value pointed to by trailer_sizep must be 967 * large enough to hold the requested trailer size. 968 * 969 * The message sequence number, id, size, requested trailer info 970 * and requested trailer size are returned in their respective 971 * output parameters upon success. 972 * 973 * Conditions: 974 * Nothing locked. 975 * Returns: 976 * KERN_SUCCESS Matching message found, out parameters set. 977 * KERN_INVALID_TASK The space is null or dead. 978 * KERN_INVALID_NAME The name doesn't denote a right. 979 * KERN_INVALID_RIGHT Name doesn't denote receive rights. 980 * KERN_INVALID_VALUE The input parameter values are out of bounds. 981 * KERN_FAILURE The requested message was not found. 982 */ 983 984kern_return_t 985mach_port_peek( 986 ipc_space_t space, 987 mach_port_name_t name, 988 mach_msg_trailer_type_t trailer_type, 989 mach_port_seqno_t *seqnop, 990 mach_msg_size_t *msg_sizep, 991 mach_msg_id_t *msg_idp, 992 mach_msg_trailer_info_t trailer_infop, 993 mach_msg_type_number_t *trailer_sizep) 994{ 995 ipc_port_t port; 996 kern_return_t kr; 997 boolean_t found; 998 mach_msg_max_trailer_t max_trailer; 999 1000 if (space == IS_NULL) 1001 return KERN_INVALID_TASK; 1002 1003 if (!MACH_PORT_VALID(name)) 1004 return KERN_INVALID_RIGHT; 1005 1006 /* 1007 * We don't allow anything greater than the audit trailer - to avoid 1008 * leaking the context pointer and to avoid variable-sized context issues. 1009 */ 1010 if (GET_RCV_ELEMENTS(trailer_type) > MACH_RCV_TRAILER_AUDIT || 1011 REQUESTED_TRAILER_SIZE(TRUE, trailer_type) > *trailer_sizep) 1012 return KERN_INVALID_VALUE; 1013 1014 *trailer_sizep = REQUESTED_TRAILER_SIZE(TRUE, trailer_type); 1015 1016 kr = ipc_port_translate_receive(space, name, &port); 1017 if (kr != KERN_SUCCESS) 1018 return kr; 1019 1020 /* Port locked and active */ 1021 1022 found = ipc_mqueue_peek(&port->ip_messages, seqnop, 1023 msg_sizep, msg_idp, &max_trailer); 1024 ip_unlock(port); 1025 1026 if (found != TRUE) 1027 return KERN_FAILURE; 1028 1029 max_trailer.msgh_seqno = *seqnop; 1030 memcpy(trailer_infop, &max_trailer, *trailer_sizep); 1031 1032 return KERN_SUCCESS; 1033} 1034 1035/* 1036 * Routine: mach_port_set_mscount [kernel call] 1037 * Purpose: 1038 * Changes a receive right's make-send count. 1039 * Conditions: 1040 * Nothing locked. 1041 * Returns: 1042 * KERN_SUCCESS Set make-send count. 1043 * KERN_INVALID_TASK The space is null. 1044 * KERN_INVALID_TASK The space is dead. 1045 * KERN_INVALID_NAME The name doesn't denote a right. 1046 * KERN_INVALID_RIGHT Name doesn't denote receive rights. 1047 */ 1048 1049kern_return_t 1050mach_port_set_mscount( 1051 ipc_space_t space, 1052 mach_port_name_t name, 1053 mach_port_mscount_t mscount) 1054{ 1055 ipc_port_t port; 1056 kern_return_t kr; 1057 1058 if (space == IS_NULL) 1059 return KERN_INVALID_TASK; 1060 1061 if (!MACH_PORT_VALID(name)) 1062 return KERN_INVALID_RIGHT; 1063 1064 kr = ipc_port_translate_receive(space, name, &port); 1065 if (kr != KERN_SUCCESS) 1066 return kr; 1067 /* port is locked and active */ 1068 1069 ipc_port_set_mscount(port, mscount); 1070 1071 ip_unlock(port); 1072 return KERN_SUCCESS; 1073} 1074 1075/* 1076 * Routine: mach_port_set_seqno [kernel call] 1077 * Purpose: 1078 * Changes a receive right's sequence number. 1079 * Conditions: 1080 * Nothing locked. 1081 * Returns: 1082 * KERN_SUCCESS Set sequence number. 1083 * KERN_INVALID_TASK The space is null. 1084 * KERN_INVALID_TASK The space is dead. 1085 * KERN_INVALID_NAME The name doesn't denote a right. 1086 * KERN_INVALID_RIGHT Name doesn't denote receive rights. 1087 */ 1088 1089kern_return_t 1090mach_port_set_seqno( 1091 ipc_space_t space, 1092 mach_port_name_t name, 1093 mach_port_seqno_t seqno) 1094{ 1095 ipc_port_t port; 1096 kern_return_t kr; 1097 1098 if (space == IS_NULL) 1099 return KERN_INVALID_TASK; 1100 1101 if (!MACH_PORT_VALID(name)) 1102 return KERN_INVALID_RIGHT; 1103 1104 kr = ipc_port_translate_receive(space, name, &port); 1105 if (kr != KERN_SUCCESS) 1106 return kr; 1107 /* port is locked and active */ 1108 1109 ipc_mqueue_set_seqno(&port->ip_messages, seqno); 1110 1111 ip_unlock(port); 1112 return KERN_SUCCESS; 1113} 1114 1115/* 1116 * Routine: mach_port_get_context [kernel call] 1117 * Purpose: 1118 * Returns a receive right's context pointer. 1119 * Conditions: 1120 * Nothing locked. 1121 * Returns: 1122 * KERN_SUCCESS Set context pointer. 1123 * KERN_INVALID_TASK The space is null. 1124 * KERN_INVALID_TASK The space is dead. 1125 * KERN_INVALID_NAME The name doesn't denote a right. 1126 * KERN_INVALID_RIGHT Name doesn't denote receive rights. 1127 */ 1128 1129kern_return_t 1130mach_port_get_context( 1131 ipc_space_t space, 1132 mach_port_name_t name, 1133 mach_vm_address_t *context) 1134{ 1135 ipc_port_t port; 1136 kern_return_t kr; 1137 1138 if (space == IS_NULL) 1139 return KERN_INVALID_TASK; 1140 1141 if (!MACH_PORT_VALID(name)) 1142 return KERN_INVALID_RIGHT; 1143 1144 kr = ipc_port_translate_receive(space, name, &port); 1145 if (kr != KERN_SUCCESS) 1146 return kr; 1147 1148 /* Port locked and active */ 1149 1150 /* For strictly guarded ports, return empty context (which acts as guard) */ 1151 if (port->ip_strict_guard) 1152 *context = 0; 1153 else 1154 *context = port->ip_context; 1155 1156 ip_unlock(port); 1157 return KERN_SUCCESS; 1158} 1159 1160 1161/* 1162 * Routine: mach_port_set_context [kernel call] 1163 * Purpose: 1164 * Changes a receive right's context pointer. 1165 * Conditions: 1166 * Nothing locked. 1167 * Returns: 1168 * KERN_SUCCESS Set context pointer. 1169 * KERN_INVALID_TASK The space is null. 1170 * KERN_INVALID_TASK The space is dead. 1171 * KERN_INVALID_NAME The name doesn't denote a right. 1172 * KERN_INVALID_RIGHT Name doesn't denote receive rights. 1173 */ 1174 1175kern_return_t 1176mach_port_set_context( 1177 ipc_space_t space, 1178 mach_port_name_t name, 1179 mach_vm_address_t context) 1180{ 1181 ipc_port_t port; 1182 kern_return_t kr; 1183 1184 if (space == IS_NULL) 1185 return KERN_INVALID_TASK; 1186 1187 if (!MACH_PORT_VALID(name)) 1188 return KERN_INVALID_RIGHT; 1189 1190 kr = ipc_port_translate_receive(space, name, &port); 1191 if (kr != KERN_SUCCESS) 1192 return kr; 1193 1194 /* port is locked and active */ 1195 if(port->ip_strict_guard) { 1196 uint64_t portguard = port->ip_context; 1197 ip_unlock(port); 1198 /* For strictly guarded ports, disallow overwriting context; Raise Exception */ 1199 mach_port_guard_exception(name, context, portguard, kGUARD_EXC_SET_CONTEXT); 1200 return KERN_INVALID_ARGUMENT; 1201 } 1202 1203 port->ip_context = context; 1204 1205 ip_unlock(port); 1206 return KERN_SUCCESS; 1207} 1208 1209 1210/* 1211 * Routine: mach_port_get_set_status [kernel call] 1212 * Purpose: 1213 * Retrieves a list of members in a port set. 1214 * Returns the space's name for each receive right member. 1215 * Conditions: 1216 * Nothing locked. 1217 * Returns: 1218 * KERN_SUCCESS Retrieved list of members. 1219 * KERN_INVALID_TASK The space is null. 1220 * KERN_INVALID_TASK The space is dead. 1221 * KERN_INVALID_NAME The name doesn't denote a right. 1222 * KERN_INVALID_RIGHT Name doesn't denote a port set. 1223 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 1224 */ 1225 1226kern_return_t 1227mach_port_get_set_status( 1228 ipc_space_t space, 1229 mach_port_name_t name, 1230 mach_port_name_t **members, 1231 mach_msg_type_number_t *membersCnt) 1232{ 1233 ipc_entry_num_t actual; /* this many members */ 1234 ipc_entry_num_t maxnames; /* space for this many members */ 1235 kern_return_t kr; 1236 1237 vm_size_t size; /* size of allocated memory */ 1238 vm_offset_t addr; /* allocated memory */ 1239 vm_map_copy_t memory; /* copied-in memory */ 1240 1241 if (space == IS_NULL) 1242 return KERN_INVALID_TASK; 1243 1244 if (!MACH_PORT_VALID(name)) 1245 return KERN_INVALID_RIGHT; 1246 1247 size = VM_MAP_PAGE_SIZE(ipc_kernel_map); /* initial guess */ 1248 1249 for (;;) { 1250 mach_port_name_t *names; 1251 ipc_object_t psobj; 1252 ipc_pset_t pset; 1253 1254 kr = vm_allocate(ipc_kernel_map, &addr, size, VM_FLAGS_ANYWHERE); 1255 if (kr != KERN_SUCCESS) 1256 return KERN_RESOURCE_SHORTAGE; 1257 1258 /* can't fault while we hold locks */ 1259 1260 kr = vm_map_wire(ipc_kernel_map, addr, addr + size, 1261 VM_PROT_READ|VM_PROT_WRITE, FALSE); 1262 assert(kr == KERN_SUCCESS); 1263 1264 kr = ipc_object_translate(space, name, MACH_PORT_RIGHT_PORT_SET, &psobj); 1265 if (kr != KERN_SUCCESS) { 1266 kmem_free(ipc_kernel_map, addr, size); 1267 return kr; 1268 } 1269 1270 /* just use a portset reference from here on out */ 1271 pset = (ipc_pset_t) psobj; 1272 ips_reference(pset); 1273 ips_unlock(pset); 1274 1275 names = (mach_port_name_t *) addr; 1276 maxnames = (ipc_entry_num_t)(size / sizeof(mach_port_name_t)); 1277 1278 ipc_mqueue_set_gather_member_names(&pset->ips_messages, maxnames, names, &actual); 1279 1280 /* release the portset reference */ 1281 ips_release(pset); 1282 1283 if (actual <= maxnames) 1284 break; 1285 1286 /* didn't have enough memory; allocate more */ 1287 kmem_free(ipc_kernel_map, addr, size); 1288 size = vm_map_round_page( 1289 (actual * sizeof(mach_port_name_t)), 1290 VM_MAP_PAGE_MASK(ipc_kernel_map)) + 1291 VM_MAP_PAGE_SIZE(ipc_kernel_map); 1292 } 1293 1294 if (actual == 0) { 1295 memory = VM_MAP_COPY_NULL; 1296 1297 kmem_free(ipc_kernel_map, addr, size); 1298 } else { 1299 vm_size_t size_used; 1300 vm_size_t vm_size_used; 1301 1302 size_used = actual * sizeof(mach_port_name_t); 1303 vm_size_used = vm_map_round_page( 1304 size_used, 1305 VM_MAP_PAGE_MASK(ipc_kernel_map)); 1306 1307 /* 1308 * Make used memory pageable and get it into 1309 * copied-in form. Free any unused memory. 1310 */ 1311 1312 kr = vm_map_unwire( 1313 ipc_kernel_map, 1314 vm_map_trunc_page(addr, 1315 VM_MAP_PAGE_MASK(ipc_kernel_map)), 1316 vm_map_round_page(addr + vm_size_used, 1317 VM_MAP_PAGE_MASK(ipc_kernel_map)), 1318 FALSE); 1319 assert(kr == KERN_SUCCESS); 1320 1321 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr, 1322 (vm_map_size_t)size_used, TRUE, &memory); 1323 assert(kr == KERN_SUCCESS); 1324 1325 if (vm_size_used != size) 1326 kmem_free(ipc_kernel_map, 1327 addr + vm_size_used, size - vm_size_used); 1328 } 1329 1330 *members = (mach_port_name_t *) memory; 1331 *membersCnt = actual; 1332 return KERN_SUCCESS; 1333} 1334 1335/* 1336 * Routine: mach_port_move_member [kernel call] 1337 * Purpose: 1338 * If after is MACH_PORT_NULL, removes member 1339 * from the port set it is in. Otherwise, adds 1340 * member to after, removing it from any set 1341 * it might already be in. 1342 * Conditions: 1343 * Nothing locked. 1344 * Returns: 1345 * KERN_SUCCESS Moved the port. 1346 * KERN_INVALID_TASK The space is null. 1347 * KERN_INVALID_TASK The space is dead. 1348 * KERN_INVALID_NAME Member didn't denote a right. 1349 * KERN_INVALID_RIGHT Member didn't denote a receive right. 1350 * KERN_INVALID_NAME After didn't denote a right. 1351 * KERN_INVALID_RIGHT After didn't denote a port set right. 1352 * KERN_NOT_IN_SET 1353 * After is MACH_PORT_NULL and Member isn't in a port set. 1354 */ 1355 1356kern_return_t 1357mach_port_move_member( 1358 ipc_space_t space, 1359 mach_port_name_t member, 1360 mach_port_name_t after) 1361{ 1362 ipc_entry_t entry; 1363 ipc_port_t port; 1364 ipc_pset_t nset; 1365 kern_return_t kr; 1366 wait_queue_link_t wql; 1367 queue_head_t links_data; 1368 queue_t links = &links_data; 1369 1370 if (space == IS_NULL) 1371 return KERN_INVALID_TASK; 1372 1373 if (!MACH_PORT_VALID(member)) 1374 return KERN_INVALID_RIGHT; 1375 1376 if (after == MACH_PORT_DEAD) 1377 return KERN_INVALID_RIGHT; 1378 else if (after == MACH_PORT_NULL) 1379 wql = WAIT_QUEUE_LINK_NULL; 1380 else 1381 wql = wait_queue_link_allocate(); 1382 1383 queue_init(links); 1384 1385 kr = ipc_right_lookup_read(space, member, &entry); 1386 if (kr != KERN_SUCCESS) 1387 goto done; 1388 /* space is read-locked and active */ 1389 1390 if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) { 1391 is_read_unlock(space); 1392 kr = KERN_INVALID_RIGHT; 1393 goto done; 1394 } 1395 1396 port = (ipc_port_t) entry->ie_object; 1397 assert(port != IP_NULL); 1398 1399 if (after == MACH_PORT_NULL) 1400 nset = IPS_NULL; 1401 else { 1402 entry = ipc_entry_lookup(space, after); 1403 if (entry == IE_NULL) { 1404 is_read_unlock(space); 1405 kr = KERN_INVALID_NAME; 1406 goto done; 1407 } 1408 1409 if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) { 1410 is_read_unlock(space); 1411 kr = KERN_INVALID_RIGHT; 1412 goto done; 1413 } 1414 1415 nset = (ipc_pset_t) entry->ie_object; 1416 assert(nset != IPS_NULL); 1417 } 1418 ip_lock(port); 1419 ipc_pset_remove_from_all(port, links); 1420 1421 if (nset != IPS_NULL) { 1422 ips_lock(nset); 1423 kr = ipc_pset_add(nset, port, wql); 1424 ips_unlock(nset); 1425 } 1426 ip_unlock(port); 1427 is_read_unlock(space); 1428 1429 done: 1430 if (kr != KERN_SUCCESS && wql != WAIT_QUEUE_LINK_NULL) 1431 wait_queue_link_free(wql); 1432 while(!queue_empty(links)) { 1433 wql = (wait_queue_link_t) dequeue(links); 1434 wait_queue_link_free(wql); 1435 } 1436 1437 return kr; 1438} 1439 1440/* 1441 * Routine: mach_port_request_notification [kernel call] 1442 * Purpose: 1443 * Requests a notification. The caller supplies 1444 * a send-once right for the notification to use, 1445 * and the call returns the previously registered 1446 * send-once right, if any. Possible types: 1447 * 1448 * MACH_NOTIFY_PORT_DESTROYED 1449 * Requests a port-destroyed notification 1450 * for a receive right. Sync should be zero. 1451 * MACH_NOTIFY_NO_SENDERS 1452 * Requests a no-senders notification for a 1453 * receive right. If there are currently no 1454 * senders, sync is less than or equal to the 1455 * current make-send count, and a send-once right 1456 * is supplied, then an immediate no-senders 1457 * notification is generated. 1458 * MACH_NOTIFY_DEAD_NAME 1459 * Requests a dead-name notification for a send 1460 * or receive right. If the name is already a 1461 * dead name, sync is non-zero, and a send-once 1462 * right is supplied, then an immediate dead-name 1463 * notification is generated. 1464 * Conditions: 1465 * Nothing locked. 1466 * Returns: 1467 * KERN_SUCCESS Requested a notification. 1468 * KERN_INVALID_TASK The space is null. 1469 * KERN_INVALID_TASK The space is dead. 1470 * KERN_INVALID_VALUE Bad id value. 1471 * KERN_INVALID_NAME Name doesn't denote a right. 1472 * KERN_INVALID_RIGHT Name doesn't denote appropriate right. 1473 * KERN_INVALID_CAPABILITY The notify port is dead. 1474 * MACH_NOTIFY_PORT_DESTROYED: 1475 * KERN_INVALID_VALUE Sync isn't zero. 1476 * MACH_NOTIFY_DEAD_NAME: 1477 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 1478 * KERN_INVALID_ARGUMENT Name denotes dead name, but 1479 * sync is zero or notify is IP_NULL. 1480 * KERN_UREFS_OVERFLOW Name denotes dead name, but 1481 * generating immediate notif. would overflow urefs. 1482 */ 1483 1484kern_return_t 1485mach_port_request_notification( 1486 ipc_space_t space, 1487 mach_port_name_t name, 1488 mach_msg_id_t id, 1489 mach_port_mscount_t sync, 1490 ipc_port_t notify, 1491 ipc_port_t *previousp) 1492{ 1493 kern_return_t kr; 1494 1495 if (space == IS_NULL) 1496 return KERN_INVALID_TASK; 1497 1498 if (notify == IP_DEAD) 1499 return KERN_INVALID_CAPABILITY; 1500 1501#if NOTYET 1502 /* 1503 * Requesting notifications on RPC ports is an error. 1504 */ 1505 { 1506 ipc_port_t port; 1507 ipc_entry_t entry; 1508 1509 kr = ipc_right_lookup_write(space, name, &entry); 1510 if (kr != KERN_SUCCESS) 1511 return kr; 1512 1513 port = (ipc_port_t) entry->ie_object; 1514 1515 if (port->ip_subsystem != NULL) { 1516 is_write_unlock(space); 1517 panic("mach_port_request_notification: on RPC port!!"); 1518 return KERN_INVALID_CAPABILITY; 1519 } 1520 is_write_unlock(space); 1521 } 1522#endif /* NOTYET */ 1523 1524 1525 switch (id) { 1526 case MACH_NOTIFY_PORT_DESTROYED: { 1527 ipc_port_t port, previous; 1528 1529 if (sync != 0) 1530 return KERN_INVALID_VALUE; 1531 1532 if (!MACH_PORT_VALID(name)) 1533 return KERN_INVALID_RIGHT; 1534 1535 kr = ipc_port_translate_receive(space, name, &port); 1536 if (kr != KERN_SUCCESS) 1537 return kr; 1538 /* port is locked and active */ 1539 1540 ipc_port_pdrequest(port, notify, &previous); 1541 /* port is unlocked */ 1542 1543 *previousp = previous; 1544 break; 1545 } 1546 1547 case MACH_NOTIFY_NO_SENDERS: { 1548 ipc_port_t port; 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 ipc_port_nsrequest(port, sync, notify, previousp); 1559 /* port is unlocked */ 1560 break; 1561 } 1562 1563 case MACH_NOTIFY_SEND_POSSIBLE: 1564 1565 if (!MACH_PORT_VALID(name)) { 1566 return KERN_INVALID_ARGUMENT; 1567 } 1568 1569 kr = ipc_right_request_alloc(space, name, sync != 0, 1570 TRUE, notify, previousp); 1571 if (kr != KERN_SUCCESS) 1572 return kr; 1573 break; 1574 1575 case MACH_NOTIFY_DEAD_NAME: 1576 1577 if (!MACH_PORT_VALID(name)) { 1578 /* 1579 * Already dead. 1580 * Should do immediate delivery check - 1581 * will do that in the near future. 1582 */ 1583 return KERN_INVALID_ARGUMENT; 1584 } 1585 1586 kr = ipc_right_request_alloc(space, name, sync != 0, 1587 FALSE, notify, previousp); 1588 if (kr != KERN_SUCCESS) 1589 return kr; 1590 break; 1591 1592 default: 1593 return KERN_INVALID_VALUE; 1594 } 1595 1596 return KERN_SUCCESS; 1597} 1598 1599/* 1600 * Routine: mach_port_insert_right [kernel call] 1601 * Purpose: 1602 * Inserts a right into a space, as if the space 1603 * voluntarily received the right in a message, 1604 * except that the right gets the specified name. 1605 * Conditions: 1606 * Nothing locked. 1607 * Returns: 1608 * KERN_SUCCESS Inserted the right. 1609 * KERN_INVALID_TASK The space is null. 1610 * KERN_INVALID_TASK The space is dead. 1611 * KERN_INVALID_VALUE The name isn't a legal name. 1612 * KERN_NAME_EXISTS The name already denotes a right. 1613 * KERN_INVALID_VALUE Message doesn't carry a port right. 1614 * KERN_INVALID_CAPABILITY Port is null or dead. 1615 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded. 1616 * KERN_RIGHT_EXISTS Space has rights under another name. 1617 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 1618 */ 1619 1620kern_return_t 1621mach_port_insert_right( 1622 ipc_space_t space, 1623 mach_port_name_t name, 1624 ipc_port_t poly, 1625 mach_msg_type_name_t polyPoly) 1626{ 1627 if (space == IS_NULL) 1628 return KERN_INVALID_TASK; 1629 1630 if (!MACH_PORT_VALID(name) || 1631 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly)) 1632 return KERN_INVALID_VALUE; 1633 1634 if (!IO_VALID((ipc_object_t) poly)) 1635 return KERN_INVALID_CAPABILITY; 1636 1637 return ipc_object_copyout_name(space, (ipc_object_t) poly, 1638 polyPoly, FALSE, name); 1639} 1640 1641/* 1642 * Routine: mach_port_extract_right [kernel call] 1643 * Purpose: 1644 * Extracts a right from a space, as if the space 1645 * voluntarily sent the right to the caller. 1646 * Conditions: 1647 * Nothing locked. 1648 * Returns: 1649 * KERN_SUCCESS Extracted the right. 1650 * KERN_INVALID_TASK The space is null. 1651 * KERN_INVALID_TASK The space is dead. 1652 * KERN_INVALID_VALUE Requested type isn't a port right. 1653 * KERN_INVALID_NAME Name doesn't denote a right. 1654 * KERN_INVALID_RIGHT Name doesn't denote appropriate right. 1655 */ 1656 1657kern_return_t 1658mach_port_extract_right( 1659 ipc_space_t space, 1660 mach_port_name_t name, 1661 mach_msg_type_name_t msgt_name, 1662 ipc_port_t *poly, 1663 mach_msg_type_name_t *polyPoly) 1664{ 1665 kern_return_t kr; 1666 1667 if (space == IS_NULL) 1668 return KERN_INVALID_TASK; 1669 1670 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name)) 1671 return KERN_INVALID_VALUE; 1672 1673 if (!MACH_PORT_VALID(name)) { 1674 /* 1675 * really should copy out a dead name, if it is a send or 1676 * send-once right being copied, but instead return an 1677 * error for now. 1678 */ 1679 return KERN_INVALID_RIGHT; 1680 } 1681 1682 kr = ipc_object_copyin(space, name, msgt_name, (ipc_object_t *) poly); 1683 1684 if (kr == KERN_SUCCESS) 1685 *polyPoly = ipc_object_copyin_type(msgt_name); 1686 return kr; 1687} 1688 1689/* 1690 * Routine: mach_port_get_status_helper [helper] 1691 * Purpose: 1692 * Populates a mach_port_status_t structure with 1693 * port information. 1694 * Conditions: 1695 * Port needs to be locked 1696 * Returns: 1697 * None. 1698 */ 1699void mach_port_get_status_helper( 1700 ipc_port_t port, 1701 mach_port_status_t *statusp) 1702{ 1703 spl_t s; 1704 statusp->mps_pset = port->ip_pset_count; 1705 1706 s = splsched(); 1707 imq_lock(&port->ip_messages); 1708 statusp->mps_seqno = port->ip_messages.imq_seqno; 1709 statusp->mps_qlimit = port->ip_messages.imq_qlimit; 1710 statusp->mps_msgcount = port->ip_messages.imq_msgcount; 1711 imq_unlock(&port->ip_messages); 1712 splx(s); 1713 1714 statusp->mps_mscount = port->ip_mscount; 1715 statusp->mps_sorights = port->ip_sorights; 1716 statusp->mps_srights = port->ip_srights > 0; 1717 statusp->mps_pdrequest = port->ip_pdrequest != IP_NULL; 1718 statusp->mps_nsrequest = port->ip_nsrequest != IP_NULL; 1719 statusp->mps_flags = 0; 1720 statusp->mps_flags |= ((port->ip_impdonation) ? MACH_PORT_STATUS_FLAG_IMP_DONATION:0); 1721 statusp->mps_flags |= ((port->ip_tempowner) ? MACH_PORT_STATUS_FLAG_TEMPOWNER:0); 1722 statusp->mps_flags |= ((port->ip_taskptr) ? MACH_PORT_STATUS_FLAG_TASKPTR:0); 1723 statusp->mps_flags |= ((port->ip_guarded) ? MACH_PORT_STATUS_FLAG_GUARDED:0); 1724 statusp->mps_flags |= ((port->ip_strict_guard) ? MACH_PORT_STATUS_FLAG_STRICT_GUARD:0); 1725 return; 1726} 1727 1728 1729 1730kern_return_t 1731mach_port_get_attributes( 1732 ipc_space_t space, 1733 mach_port_name_t name, 1734 int flavor, 1735 mach_port_info_t info, 1736 mach_msg_type_number_t *count) 1737{ 1738 ipc_port_t port; 1739 kern_return_t kr; 1740 1741 if (space == IS_NULL) 1742 return KERN_INVALID_TASK; 1743 1744 switch (flavor) { 1745 case MACH_PORT_LIMITS_INFO: { 1746 mach_port_limits_t *lp = (mach_port_limits_t *)info; 1747 1748 if (*count < MACH_PORT_LIMITS_INFO_COUNT) 1749 return KERN_FAILURE; 1750 1751 if (!MACH_PORT_VALID(name)) { 1752 *count = 0; 1753 break; 1754 } 1755 1756 kr = ipc_port_translate_receive(space, name, &port); 1757 if (kr != KERN_SUCCESS) 1758 return kr; 1759 /* port is locked and active */ 1760 1761 lp->mpl_qlimit = port->ip_messages.imq_qlimit; 1762 *count = MACH_PORT_LIMITS_INFO_COUNT; 1763 ip_unlock(port); 1764 break; 1765 } 1766 1767 case MACH_PORT_RECEIVE_STATUS: { 1768 mach_port_status_t *statusp = (mach_port_status_t *)info; 1769 1770 if (*count < MACH_PORT_RECEIVE_STATUS_COUNT) 1771 return KERN_FAILURE; 1772 1773 if (!MACH_PORT_VALID(name)) 1774 return KERN_INVALID_RIGHT; 1775 1776 kr = ipc_port_translate_receive(space, name, &port); 1777 if (kr != KERN_SUCCESS) 1778 return kr; 1779 /* port is locked and active */ 1780 mach_port_get_status_helper(port, statusp); 1781 *count = MACH_PORT_RECEIVE_STATUS_COUNT; 1782 ip_unlock(port); 1783 break; 1784 } 1785 1786 case MACH_PORT_DNREQUESTS_SIZE: { 1787 ipc_port_request_t table; 1788 1789 if (*count < MACH_PORT_DNREQUESTS_SIZE_COUNT) 1790 return KERN_FAILURE; 1791 1792 if (!MACH_PORT_VALID(name)) { 1793 *(int *)info = 0; 1794 break; 1795 } 1796 1797 kr = ipc_port_translate_receive(space, name, &port); 1798 if (kr != KERN_SUCCESS) 1799 return kr; 1800 /* port is locked and active */ 1801 1802 table = port->ip_requests; 1803 if (table == IPR_NULL) 1804 *(int *)info = 0; 1805 else 1806 *(int *)info = table->ipr_size->its_size; 1807 *count = MACH_PORT_DNREQUESTS_SIZE_COUNT; 1808 ip_unlock(port); 1809 break; 1810 } 1811 1812 case MACH_PORT_INFO_EXT: { 1813 mach_port_info_ext_t *mp_info = (mach_port_info_ext_t *)info; 1814 if (*count < MACH_PORT_INFO_EXT_COUNT) 1815 return KERN_FAILURE; 1816 1817 if (!MACH_PORT_VALID(name)) 1818 return KERN_INVALID_RIGHT; 1819 1820 kr = ipc_port_translate_receive(space, name, &port); 1821 if (kr != KERN_SUCCESS) 1822 return kr; 1823 /* port is locked and active */ 1824 mach_port_get_status_helper(port, &mp_info->mpie_status); 1825 mp_info->mpie_boost_cnt = port->ip_impcount; 1826 *count = MACH_PORT_INFO_EXT_COUNT; 1827 ip_unlock(port); 1828 break; 1829 } 1830 1831 default: 1832 return KERN_INVALID_ARGUMENT; 1833 /*NOTREACHED*/ 1834 } 1835 1836 return KERN_SUCCESS; 1837} 1838 1839kern_return_t 1840mach_port_set_attributes( 1841 ipc_space_t space, 1842 mach_port_name_t name, 1843 int flavor, 1844 mach_port_info_t info, 1845 mach_msg_type_number_t count) 1846{ 1847 ipc_port_t port; 1848 kern_return_t kr; 1849 1850 if (space == IS_NULL) 1851 return KERN_INVALID_TASK; 1852 1853 switch (flavor) { 1854 1855 case MACH_PORT_LIMITS_INFO: { 1856 mach_port_limits_t *mplp = (mach_port_limits_t *)info; 1857 1858 if (count < MACH_PORT_LIMITS_INFO_COUNT) 1859 return KERN_FAILURE; 1860 1861 if (mplp->mpl_qlimit > MACH_PORT_QLIMIT_MAX) 1862 return KERN_INVALID_VALUE; 1863 1864 if (!MACH_PORT_VALID(name)) 1865 return KERN_INVALID_RIGHT; 1866 1867 kr = ipc_port_translate_receive(space, name, &port); 1868 if (kr != KERN_SUCCESS) 1869 return kr; 1870 /* port is locked and active */ 1871 1872 ipc_mqueue_set_qlimit(&port->ip_messages, mplp->mpl_qlimit); 1873 ip_unlock(port); 1874 break; 1875 } 1876 case MACH_PORT_DNREQUESTS_SIZE: { 1877 if (count < MACH_PORT_DNREQUESTS_SIZE_COUNT) 1878 return KERN_FAILURE; 1879 1880 if (!MACH_PORT_VALID(name)) 1881 return KERN_INVALID_RIGHT; 1882 1883 kr = ipc_port_translate_receive(space, name, &port); 1884 if (kr != KERN_SUCCESS) 1885 return kr; 1886 /* port is locked and active */ 1887 1888 kr = ipc_port_request_grow(port, *(int *)info); 1889 if (kr != KERN_SUCCESS) 1890 return kr; 1891 break; 1892 } 1893 case MACH_PORT_TEMPOWNER: 1894 if (!MACH_PORT_VALID(name)) 1895 return KERN_INVALID_RIGHT; 1896 1897 task_t release_imp_task = TASK_NULL; 1898 natural_t assertcnt = 0; 1899 1900 kr = ipc_port_translate_receive(space, name, &port); 1901 if (kr != KERN_SUCCESS) 1902 return kr; 1903 1904 /* port is locked and active */ 1905 1906 if (port->ip_tempowner != 0) { 1907 if (port->ip_taskptr != 0) { 1908 release_imp_task = port->ip_imp_task; 1909 port->ip_taskptr = 0; 1910 port->ip_imp_task = TASK_NULL; 1911 assertcnt = port->ip_impcount; 1912 } 1913 } else { 1914 assertcnt = port->ip_impcount; 1915 } 1916 1917 port->ip_impdonation = 1; 1918 port->ip_tempowner = 1; 1919 ip_unlock(port); 1920 1921#if IMPORTANCE_INHERITANCE 1922 /* drop assertions from previous destination task */ 1923 if (release_imp_task != TASK_NULL) { 1924 assert(release_imp_task->imp_receiver != 0); 1925 if (assertcnt > 0) 1926 task_importance_drop_internal_assertion(release_imp_task, assertcnt); 1927 task_deallocate(release_imp_task); 1928 } else if (assertcnt > 0) { 1929 release_imp_task = current_task(); 1930 if (release_imp_task->imp_receiver != 0) 1931 task_importance_drop_internal_assertion(release_imp_task, assertcnt); 1932 } 1933#else 1934 if (release_imp_task != TASK_NULL) 1935 task_deallocate(release_imp_task); 1936#endif /* IMPORTANCE_INHERITANCE */ 1937 1938 break; 1939#if IMPORTANCE_INHERITANCE 1940 case MACH_PORT_IMPORTANCE_RECEIVER: 1941 if (!MACH_PORT_VALID(name)) 1942 return KERN_INVALID_RIGHT; 1943 1944 kr = ipc_port_translate_receive(space, name, &port); 1945 if (kr != KERN_SUCCESS) 1946 return kr; 1947 /* port is locked and active */ 1948 1949 port->ip_impdonation = 1; 1950 ip_unlock(port); 1951 1952 break; 1953#endif /* IMPORTANCE_INHERITANCE */ 1954 1955 default: 1956 return KERN_INVALID_ARGUMENT; 1957 /*NOTREACHED*/ 1958 } 1959 return KERN_SUCCESS; 1960} 1961 1962/* 1963 * Routine: mach_port_insert_member [kernel call] 1964 * Purpose: 1965 * Add the receive right, specified by name, to 1966 * a portset. 1967 * The port cannot already be a member of the set. 1968 * Conditions: 1969 * Nothing locked. 1970 * Returns: 1971 * KERN_SUCCESS Moved the port. 1972 * KERN_INVALID_TASK The space is null. 1973 * KERN_INVALID_TASK The space is dead. 1974 * KERN_INVALID_NAME name didn't denote a right. 1975 * KERN_INVALID_RIGHT name didn't denote a receive right. 1976 * KERN_INVALID_NAME pset_name didn't denote a right. 1977 * KERN_INVALID_RIGHT pset_name didn't denote a portset right. 1978 * KERN_ALREADY_IN_SET name was already a member of pset. 1979 */ 1980 1981kern_return_t 1982mach_port_insert_member( 1983 ipc_space_t space, 1984 mach_port_name_t name, 1985 mach_port_name_t psname) 1986{ 1987 ipc_object_t obj; 1988 ipc_object_t psobj; 1989 kern_return_t kr; 1990 wait_queue_link_t wql; 1991 1992 if (space == IS_NULL) 1993 return KERN_INVALID_TASK; 1994 1995 if (!MACH_PORT_VALID(name) || !MACH_PORT_VALID(psname)) 1996 return KERN_INVALID_RIGHT; 1997 1998 wql = wait_queue_link_allocate(); 1999 2000 kr = ipc_object_translate_two(space, 2001 name, MACH_PORT_RIGHT_RECEIVE, &obj, 2002 psname, MACH_PORT_RIGHT_PORT_SET, &psobj); 2003 if (kr != KERN_SUCCESS) 2004 goto done; 2005 2006 /* obj and psobj are locked (and were locked in that order) */ 2007 assert(psobj != IO_NULL); 2008 assert(obj != IO_NULL); 2009 2010 kr = ipc_pset_add((ipc_pset_t)psobj, (ipc_port_t)obj, wql); 2011 io_unlock(psobj); 2012 io_unlock(obj); 2013 2014 done: 2015 if (kr != KERN_SUCCESS) 2016 wait_queue_link_free(wql); 2017 2018 return kr; 2019} 2020 2021/* 2022 * Routine: mach_port_extract_member [kernel call] 2023 * Purpose: 2024 * Remove a port from one portset that it is a member of. 2025 * Conditions: 2026 * Nothing locked. 2027 * Returns: 2028 * KERN_SUCCESS Moved the port. 2029 * KERN_INVALID_TASK The space is null. 2030 * KERN_INVALID_TASK The space is dead. 2031 * KERN_INVALID_NAME Member didn't denote a right. 2032 * KERN_INVALID_RIGHT Member didn't denote a receive right. 2033 * KERN_INVALID_NAME After didn't denote a right. 2034 * KERN_INVALID_RIGHT After didn't denote a port set right. 2035 * KERN_NOT_IN_SET 2036 * After is MACH_PORT_NULL and Member isn't in a port set. 2037 */ 2038 2039kern_return_t 2040mach_port_extract_member( 2041 ipc_space_t space, 2042 mach_port_name_t name, 2043 mach_port_name_t psname) 2044{ 2045 ipc_object_t psobj; 2046 ipc_object_t obj; 2047 kern_return_t kr; 2048 wait_queue_link_t wql = WAIT_QUEUE_LINK_NULL; 2049 2050 if (space == IS_NULL) 2051 return KERN_INVALID_TASK; 2052 2053 if (!MACH_PORT_VALID(name) || !MACH_PORT_VALID(psname)) 2054 return KERN_INVALID_RIGHT; 2055 2056 kr = ipc_object_translate_two(space, 2057 name, MACH_PORT_RIGHT_RECEIVE, &obj, 2058 psname, MACH_PORT_RIGHT_PORT_SET, &psobj); 2059 if (kr != KERN_SUCCESS) 2060 return kr; 2061 2062 /* obj and psobj are both locked (and were locked in that order) */ 2063 assert(psobj != IO_NULL); 2064 assert(obj != IO_NULL); 2065 2066 kr = ipc_pset_remove((ipc_pset_t)psobj, (ipc_port_t)obj, &wql); 2067 io_unlock(psobj); 2068 io_unlock(obj); 2069 2070 if (wql != WAIT_QUEUE_LINK_NULL) 2071 wait_queue_link_free(wql); 2072 2073 return kr; 2074} 2075 2076/* 2077 * task_set_port_space: 2078 * 2079 * Set port name space of task to specified size. 2080 */ 2081kern_return_t 2082task_set_port_space( 2083 ipc_space_t space, 2084 int table_entries) 2085{ 2086 kern_return_t kr; 2087 2088 is_write_lock(space); 2089 2090 if (!is_active(space)) { 2091 is_write_unlock(space); 2092 return KERN_INVALID_TASK; 2093 } 2094 2095 kr = ipc_entry_grow_table(space, table_entries); 2096 if (kr == KERN_SUCCESS) 2097 is_write_unlock(space); 2098 return kr; 2099} 2100 2101/* 2102 * Routine: mach_port_guard_locked [helper routine] 2103 * Purpose: 2104 * Sets a new guard for a locked port. 2105 * Conditions: 2106 * Port Locked. 2107 * Returns: 2108 * KERN_SUCCESS Port Guarded. 2109 * KERN_INVALID_ARGUMENT Port already contains a context/guard. 2110 */ 2111static kern_return_t 2112mach_port_guard_locked( 2113 ipc_port_t port, 2114 uint64_t guard, 2115 boolean_t strict) 2116{ 2117 if (port->ip_context) 2118 return KERN_INVALID_ARGUMENT; 2119 2120 port->ip_context = guard; 2121 port->ip_guarded = 1; 2122 port->ip_strict_guard = (strict)?1:0; 2123 return KERN_SUCCESS; 2124} 2125 2126/* 2127 * Routine: mach_port_unguard_locked [helper routine] 2128 * Purpose: 2129 * Removes guard for a locked port. 2130 * Conditions: 2131 * Port Locked. 2132 * Returns: 2133 * KERN_SUCCESS Port Unguarded. 2134 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch. 2135 * This also raises a EXC_GUARD exception. 2136 */ 2137static kern_return_t 2138mach_port_unguard_locked( 2139 ipc_port_t port, 2140 mach_port_name_t name, 2141 uint64_t guard) 2142{ 2143 /* Port locked and active */ 2144 if (!port->ip_guarded) { 2145 /* Port already unguarded; Raise exception */ 2146 mach_port_guard_exception(name, guard, 0, kGUARD_EXC_UNGUARDED); 2147 return KERN_INVALID_ARGUMENT; 2148 } 2149 2150 if (port->ip_context != guard) { 2151 /* Incorrect guard; Raise exception */ 2152 mach_port_guard_exception(name, guard, port->ip_context, kGUARD_EXC_INCORRECT_GUARD); 2153 return KERN_INVALID_ARGUMENT; 2154 } 2155 2156 port->ip_context = 0; 2157 port->ip_guarded = port->ip_strict_guard = 0; 2158 return KERN_SUCCESS; 2159} 2160 2161 2162/* 2163 * Routine: mach_port_guard_exception [helper routine] 2164 * Purpose: 2165 * Marks the thread with AST_GUARD for mach port guard violation. 2166 * Also saves exception info in thread structure. 2167 * Conditions: 2168 * None. 2169 * Returns: 2170 * KERN_FAILURE Thread marked with AST_GUARD. 2171 */ 2172kern_return_t 2173mach_port_guard_exception( 2174 mach_port_name_t name, 2175 uint64_t inguard, 2176 uint64_t portguard, 2177 unsigned reason) 2178{ 2179 thread_t t = current_thread(); 2180 uint64_t code, subcode; 2181 2182 /* Log exception info to syslog */ 2183 printf( "Mach Port Guard Exception - " 2184 "Thread: 0x%x, " 2185 "Port Name: 0x%x, " 2186 "Expected Guard: 0x%x, " 2187 "Received Guard: 0x%x\n", 2188 (unsigned)t, 2189 (unsigned)name, 2190 (unsigned)portguard, 2191 (unsigned)inguard); 2192 2193 /* 2194 * EXC_GUARD namespace for mach ports 2195 * 2196 * 2197 * Mach Port guards use the exception codes like 2198 * 2199 * code: 2200 * +----------------------------------------------------------------+ 2201 * |[63:61] GUARD_TYPE_MACH_PORT | [60:32] flavor | [31:0] port name| 2202 * +----------------------------------------------------------------+ 2203 * 2204 * subcode: 2205 * +----------------------------------------------------------------+ 2206 * | [63:0] guard value | 2207 * +----------------------------------------------------------------+ 2208 */ 2209 2210 code = (((uint64_t)GUARD_TYPE_MACH_PORT) << 61) | 2211 (((uint64_t)reason) << 32) | 2212 ((uint64_t)name); 2213 subcode = (uint64_t)(portguard); 2214 2215 t->guard_exc_info.code = code; 2216 t->guard_exc_info.subcode = subcode; 2217 2218 /* Mark thread with AST_GUARD */ 2219 thread_guard_violation(t, GUARD_TYPE_MACH_PORT); 2220 return KERN_FAILURE; 2221} 2222 2223 2224/* 2225 * Routine: mach_port_guard_ast 2226 * Purpose: 2227 * Raises an exception for mach port guard violation. 2228 * Conditions: 2229 * None. 2230 * Returns: 2231 * None. 2232 */ 2233 2234void 2235mach_port_guard_ast(thread_t t) 2236{ 2237 mach_exception_data_type_t code[EXCEPTION_CODE_MAX]; 2238 2239 code[0] = t->guard_exc_info.code; 2240 code[1] = t->guard_exc_info.subcode; 2241 2242 /* Raise an EXC_GUARD exception */ 2243 exception_triage(EXC_GUARD, code, EXCEPTION_CODE_MAX); 2244 2245 /* Terminate task which caused the exception */ 2246 (void) task_terminate_internal(current_task()); 2247 return; 2248} 2249 2250/* 2251 * Routine: mach_port_construct [kernel call] 2252 * Purpose: 2253 * Constructs a mach port with the provided set of options. 2254 * Conditions: 2255 * None. 2256 * Returns: 2257 * KERN_SUCCESS The right is allocated. 2258 * KERN_INVALID_TASK The space is null. 2259 * KERN_INVALID_TASK The space is dead. 2260 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory. 2261 * KERN_NO_SPACE No room in space for another right. 2262 * KERN_FAILURE Illegal option values requested. 2263 */ 2264 2265kern_return_t 2266mach_port_construct( 2267 ipc_space_t space, 2268 mach_port_options_t *options, 2269 uint64_t context, 2270 mach_port_name_t *name) 2271{ 2272 kern_return_t kr; 2273 ipc_port_t port; 2274 2275 if (space == IS_NULL) 2276 return (KERN_INVALID_TASK); 2277 2278 /* Allocate a new port in the IPC space */ 2279 kr = ipc_port_alloc(space, name, &port); 2280 if (kr != KERN_SUCCESS) 2281 return kr; 2282 2283 /* Port locked and active */ 2284 if (options->flags & MPO_CONTEXT_AS_GUARD) { 2285 kr = mach_port_guard_locked(port, (uint64_t) context, (options->flags & MPO_STRICT)); 2286 /* A newly allocated and locked port should always be guarded successfully */ 2287 assert(kr == KERN_SUCCESS); 2288 } else { 2289 port->ip_context = context; 2290 } 2291 2292 /* Unlock port */ 2293 ip_unlock(port); 2294 2295 /* Set port attributes as requested */ 2296 2297 if (options->flags & MPO_QLIMIT) { 2298 kr = mach_port_set_attributes(space, *name, MACH_PORT_LIMITS_INFO, 2299 (mach_port_info_t)&options->mpl, sizeof(options->mpl)/sizeof(int)); 2300 if (kr != KERN_SUCCESS) 2301 goto cleanup; 2302 } 2303 2304 if (options->flags & MPO_TEMPOWNER) { 2305 kr = mach_port_set_attributes(space, *name, MACH_PORT_TEMPOWNER, NULL, 0); 2306 if (kr != KERN_SUCCESS) 2307 goto cleanup; 2308 } 2309 2310 if (options->flags & MPO_IMPORTANCE_RECEIVER) { 2311 kr = mach_port_set_attributes(space, *name, MACH_PORT_IMPORTANCE_RECEIVER, NULL, 0); 2312 if (kr != KERN_SUCCESS) 2313 goto cleanup; 2314 } 2315 2316 if (options->flags & MPO_INSERT_SEND_RIGHT) { 2317 kr = ipc_object_copyin(space, *name, MACH_MSG_TYPE_MAKE_SEND, (ipc_object_t *)&port); 2318 if (kr != KERN_SUCCESS) 2319 goto cleanup; 2320 2321 kr = mach_port_insert_right(space, *name, port, MACH_MSG_TYPE_PORT_SEND); 2322 if (kr != KERN_SUCCESS) 2323 goto cleanup; 2324 } 2325 2326 return KERN_SUCCESS; 2327 2328cleanup: 2329 /* Attempt to destroy port. If its already destroyed by some other thread, we're done */ 2330 (void) mach_port_destruct(space, *name, 0, context); 2331 return kr; 2332} 2333 2334/* 2335 * Routine: mach_port_destruct [kernel call] 2336 * Purpose: 2337 * Destroys a mach port with appropriate guard 2338 * Conditions: 2339 * None. 2340 * Returns: 2341 * KERN_SUCCESS The name is destroyed. 2342 * KERN_INVALID_TASK The space is null. 2343 * KERN_INVALID_TASK The space is dead. 2344 * KERN_INVALID_NAME The name doesn't denote a right. 2345 * KERN_INVALID_RIGHT The right isn't correct. 2346 * KERN_INVALID_VALUE The delta for send right is incorrect. 2347 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch. 2348 * This also raises a EXC_GUARD exception. 2349 */ 2350 2351kern_return_t 2352mach_port_destruct( 2353 ipc_space_t space, 2354 mach_port_name_t name, 2355 mach_port_delta_t srdelta, 2356 uint64_t guard) 2357{ 2358 kern_return_t kr; 2359 ipc_entry_t entry; 2360 2361 if (space == IS_NULL) 2362 return KERN_INVALID_TASK; 2363 2364 if (!MACH_PORT_VALID(name)) 2365 return KERN_INVALID_NAME; 2366 2367 /* Remove reference for receive right */ 2368 kr = ipc_right_lookup_write(space, name, &entry); 2369 if (kr != KERN_SUCCESS) 2370 return kr; 2371 /* space is write-locked and active */ 2372 kr = ipc_right_destruct(space, name, entry, srdelta, guard); /* unlocks */ 2373 2374 return kr; 2375} 2376 2377/* 2378 * Routine: mach_port_guard [kernel call] 2379 * Purpose: 2380 * Guard a mach port with specified guard value. 2381 * The context field of the port is used as the guard. 2382 * Conditions: 2383 * None. 2384 * Returns: 2385 * KERN_SUCCESS The name is destroyed. 2386 * KERN_INVALID_TASK The space is null. 2387 * KERN_INVALID_TASK The space is dead. 2388 * KERN_INVALID_NAME The name doesn't denote a right. 2389 * KERN_INVALID_RIGHT The right isn't correct. 2390 * KERN_INVALID_ARGUMENT Port already contains a context/guard. 2391 */ 2392kern_return_t 2393mach_port_guard( 2394 ipc_space_t space, 2395 mach_port_name_t name, 2396 uint64_t guard, 2397 boolean_t strict) 2398{ 2399 kern_return_t kr; 2400 ipc_port_t port; 2401 2402 if (space == IS_NULL) 2403 return KERN_INVALID_TASK; 2404 2405 if (!MACH_PORT_VALID(name)) 2406 return KERN_INVALID_NAME; 2407 2408 /* Guard can be applied only to receive rights */ 2409 kr = ipc_port_translate_receive(space, name, &port); 2410 if (kr != KERN_SUCCESS) 2411 return kr; 2412 2413 /* Port locked and active */ 2414 kr = mach_port_guard_locked(port, guard, strict); 2415 ip_unlock(port); 2416 2417 return kr; 2418 2419} 2420 2421/* 2422 * Routine: mach_port_unguard [kernel call] 2423 * Purpose: 2424 * Unguard a mach port with specified guard value. 2425 * Conditions: 2426 * None. 2427 * Returns: 2428 * KERN_SUCCESS The name is destroyed. 2429 * KERN_INVALID_TASK The space is null. 2430 * KERN_INVALID_TASK The space is dead. 2431 * KERN_INVALID_NAME The name doesn't denote a right. 2432 * KERN_INVALID_RIGHT The right isn't correct. 2433 * KERN_INVALID_ARGUMENT Port is either unguarded already or guard mismatch. 2434 * This also raises a EXC_GUARD exception. 2435 */ 2436kern_return_t 2437mach_port_unguard( 2438 ipc_space_t space, 2439 mach_port_name_t name, 2440 uint64_t guard) 2441{ 2442 2443 kern_return_t kr; 2444 ipc_port_t port; 2445 2446 if (space == IS_NULL) 2447 return KERN_INVALID_TASK; 2448 2449 if (!MACH_PORT_VALID(name)) 2450 return KERN_INVALID_NAME; 2451 2452 kr = ipc_port_translate_receive(space, name, &port); 2453 if (kr != KERN_SUCCESS) 2454 return kr; 2455 2456 /* Port locked and active */ 2457 kr = mach_port_unguard_locked(port, name, guard); 2458 ip_unlock(port); 2459 return kr; 2460} 2461 2462/* 2463 * Get a (new) label handle representing the given port's port label. 2464 */ 2465#if CONFIG_MACF_MACH 2466kern_return_t 2467mach_get_label( 2468 ipc_space_t space, 2469 mach_port_name_t name, 2470 mach_port_name_t *outlabel) 2471{ 2472 ipc_entry_t entry; 2473 ipc_port_t port; 2474 struct label outl; 2475 kern_return_t kr; 2476 int dead; 2477 2478 if (!MACH_PORT_VALID(name)) 2479 return KERN_INVALID_NAME; 2480 2481 /* Lookup the port name in the task's space. */ 2482 kr = ipc_right_lookup_write(space, name, &entry); 2483 if (kr != KERN_SUCCESS) 2484 return kr; 2485 2486 port = (ipc_port_t) entry->ie_object; 2487 dead = ipc_right_check(space, port, name, entry); 2488 if (dead) { 2489 is_write_unlock(space); 2490 ip_release(port); 2491 return KERN_INVALID_RIGHT; 2492 } 2493 /* port is now locked */ 2494 2495 is_write_unlock(space); 2496 /* Make sure we are not dealing with a label handle. */ 2497 if (ip_kotype(port) == IKOT_LABELH) { 2498 /* already is a label handle! */ 2499 ip_unlock(port); 2500 return KERN_INVALID_ARGUMENT; 2501 } 2502 2503 /* Copy the port label and stash it in a new label handle. */ 2504 mac_port_label_init(&outl); 2505 mac_port_label_copy(&port->ip_label, &outl); 2506 kr = labelh_new_user(space, &outl, outlabel); 2507 ip_unlock(port); 2508 2509 return KERN_SUCCESS; 2510} 2511#else 2512kern_return_t 2513mach_get_label( 2514 __unused ipc_space_t space, 2515 __unused mach_port_name_t name, 2516 __unused mach_port_name_t *outlabel) 2517{ 2518 return KERN_INVALID_ARGUMENT; 2519} 2520#endif 2521 2522/* 2523 * also works on label handles 2524 */ 2525#if CONFIG_MACF_MACH 2526kern_return_t 2527mach_get_label_text( 2528 ipc_space_t space, 2529 mach_port_name_t name, 2530 labelstr_t policies, 2531 labelstr_t outlabel) 2532{ 2533 ipc_entry_t entry; 2534 ipc_port_t port; 2535 kern_return_t kr; 2536 struct label *l; 2537 int dead; 2538 2539 if (space == IS_NULL || space->is_task == NULL) 2540 return KERN_INVALID_TASK; 2541 2542 if (!MACH_PORT_VALID(name)) 2543 return KERN_INVALID_NAME; 2544 2545 kr = ipc_right_lookup_write(space, name, &entry); 2546 if (kr != KERN_SUCCESS) 2547 return kr; 2548 2549 port = (ipc_port_t)entry->ie_object; 2550 dead = ipc_right_check(space, port, name, entry); 2551 if (dead) { 2552 is_write_unlock(space); 2553 ip_release(port); 2554 return KERN_INVALID_RIGHT; 2555 } 2556 /* object (port) is now locked */ 2557 2558 is_write_unlock (space); 2559 l = io_getlabel(entry->ie_object); 2560 2561 mac_port_label_externalize(l, policies, outlabel, 512, 0); 2562 2563 io_unlocklabel(entry->ie_object); 2564 io_unlock(entry->ie_object); 2565 return KERN_SUCCESS; 2566} 2567#else 2568kern_return_t 2569mach_get_label_text( 2570 __unused ipc_space_t space, 2571 __unused mach_port_name_t name, 2572 __unused labelstr_t policies, 2573 __unused labelstr_t outlabel) 2574{ 2575 return KERN_INVALID_ARGUMENT; 2576} 2577#endif 2578 2579 2580#if CONFIG_MACF_MACH 2581kern_return_t 2582mach_set_port_label( 2583 ipc_space_t space, 2584 mach_port_name_t name, 2585 labelstr_t labelstr) 2586{ 2587 ipc_entry_t entry; 2588 kern_return_t kr; 2589 struct label inl; 2590 ipc_port_t port; 2591 int rc; 2592 2593 if (space == IS_NULL || space->is_task == NULL) 2594 return KERN_INVALID_TASK; 2595 2596 if (!MACH_PORT_VALID(name)) 2597 return KERN_INVALID_NAME; 2598 2599 mac_port_label_init(&inl); 2600 rc = mac_port_label_internalize(&inl, labelstr); 2601 if (rc) 2602 return KERN_INVALID_ARGUMENT; 2603 2604 kr = ipc_right_lookup_write(space, name, &entry); 2605 if (kr != KERN_SUCCESS) 2606 return kr; 2607 2608 if (io_otype(entMACry->ie_object) != IOT_PORT) { 2609 is_write_unlock(space); 2610 return KERN_INVALID_RIGHT; 2611 } 2612 2613 port = (ipc_port_t) entry->ie_object; 2614 ip_lock(port); 2615 2616 tasklabel_lock(space->is_task); 2617 rc = mac_port_check_label_update(&space->is_task->maclabel, 2618 &port->ip_label, &inl); 2619 tasklabel_unlock(space->is_task); 2620 if (rc) 2621 kr = KERN_NO_ACCESS; 2622 else 2623 mac_port_label_copy(&inl, &port->ip_label); 2624 2625 ip_unlock(port); 2626 is_write_unlock(space); 2627 return kr; 2628} 2629#else 2630kern_return_t 2631mach_set_port_label( 2632 ipc_space_t space __unused, 2633 mach_port_name_t name __unused, 2634 labelstr_t labelstr __unused) 2635{ 2636 return KERN_INVALID_ARGUMENT; 2637} 2638#endif 2639