X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/9bccf70c0258c7cac2dcb80011b2a964d884c552..143464d58d2bd6378e74eec636961ceb0d32fb91:/osfmk/ipc/ipc_port.h diff --git a/osfmk/ipc/ipc_port.h b/osfmk/ipc/ipc_port.h index 50bc7ed87..169189f63 100644 --- a/osfmk/ipc/ipc_port.h +++ b/osfmk/ipc/ipc_port.h @@ -1,23 +1,29 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2008 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ @@ -47,6 +53,12 @@ * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ +/* + * NOTICE: This file was modified by McAfee Research in 2004 to introduce + * support for mandatory and extensible security protections. This notice + * is included in support of clause 2.2 (b) of the Apple Public License, + * Version 2.0. + */ /* */ /* @@ -60,26 +72,26 @@ #ifndef _IPC_IPC_PORT_H_ #define _IPC_IPC_PORT_H_ -#include +#if MACH_KERNEL_PRIVATE + #include #include #include +#include #include #include -#include #include -#include -#include -#include +#include + +#include #include #include -#include -#include -#include #include +#include + /* * A receive right (port) can be in four states: * 1) dead (not active, ip_timestamp has death time) @@ -97,15 +109,15 @@ typedef unsigned int ipc_port_timestamp_t; -typedef unsigned int ipc_port_flags_t; - struct ipc_port { /* - * Initial sub-structure in common with ipc_pset and rpc_port - * First element is an ipc_object + * Initial sub-structure in common with ipc_pset + * First element is an ipc_object second is a + * message queue */ struct ipc_object ip_object; + struct ipc_mqueue ip_messages; union { struct ipc_space *receiver; @@ -113,50 +125,64 @@ struct ipc_port { ipc_port_timestamp_t timestamp; } data; - ipc_kobject_t ip_kobject; + union { + ipc_kobject_t kobject; + task_t imp_task; + uintptr_t alias; + } kdata; + + struct ipc_port *ip_nsrequest; + struct ipc_port *ip_pdrequest; + struct ipc_port_request *ip_requests; + struct ipc_kmsg *ip_premsg; + mach_port_mscount_t ip_mscount; mach_port_rights_t ip_srights; mach_port_rights_t ip_sorights; - struct ipc_port *ip_nsrequest; - struct ipc_port *ip_pdrequest; - struct ipc_port_request *ip_dnrequests; + natural_t ip_sprequests:1, /* send-possible requests outstanding */ + ip_spimportant:1, /* ... at least one is importance donating */ + ip_impdonation:1, /* port supports importance donation */ + ip_tempowner:1, /* dont give donations to current receiver */ + ip_taskptr:1, /* ... instead give them to a specified task */ + ip_guarded:1, /* port guarded (use context value as guard) */ + ip_strict_guard:1, /* Strict guarding; Prevents user manipulation of context values directly */ + ip_reserved:1, + ip_impcount:24; /* number of importance donations in nested queue */ - unsigned int ip_pset_count; - struct ipc_mqueue ip_messages; - struct ipc_kmsg *ip_premsg; + mach_vm_address_t ip_context; -#if NORMA_VM - /* - * These fields are needed for the use of XMM. - * Few ports need this information; it should - * be kept in XMM instead (TBD). XXX - */ - long ip_norma_xmm_object_refs; - struct ipc_port *ip_norma_xmm_object; -#endif #if MACH_ASSERT -#define IP_NSPARES 10 -#define IP_CALLSTACK_MAX 10 +#define IP_NSPARES 4 +#define IP_CALLSTACK_MAX 16 queue_chain_t ip_port_links; /* all allocated ports */ - natural_t ip_thread; /* who made me? thread context */ + thread_t ip_thread; /* who made me? thread context */ unsigned long ip_timetrack; /* give an idea of "when" created */ - natural_t ip_callstack[IP_CALLSTACK_MAX]; /* stack trace */ + uintptr_t ip_callstack[IP_CALLSTACK_MAX]; /* stack trace */ unsigned long ip_spares[IP_NSPARES]; /* for debugging */ #endif /* MACH_ASSERT */ - int alias; + +#if CONFIG_MACF_MACH + struct label ip_label; +#endif }; #define ip_references ip_object.io_references #define ip_bits ip_object.io_bits -#define ip_receiver_name ip_object.io_receiver_name + +#define ip_receiver_name ip_messages.imq_receiver_name +#define ip_pset_count ip_messages.imq_pset_count #define ip_receiver data.receiver #define ip_destination data.destination #define ip_timestamp data.timestamp +#define ip_kobject kdata.kobject +#define ip_imp_task kdata.imp_task +#define ip_alias kdata.alias + #define IP_NULL IPC_PORT_NULL #define IP_DEAD IPC_PORT_DEAD #define IP_VALID(port) IPC_PORT_VALID(port) @@ -166,13 +192,15 @@ struct ipc_port { #define ip_lock(port) io_lock(&(port)->ip_object) #define ip_lock_try(port) io_lock_try(&(port)->ip_object) #define ip_unlock(port) io_unlock(&(port)->ip_object) -#define ip_check_unlock(port) io_check_unlock(&(port)->ip_object) #define ip_reference(port) io_reference(&(port)->ip_object) #define ip_release(port) io_release(&(port)->ip_object) #define ip_kotype(port) io_kotype(&(port)->ip_object) +#define ip_full_kernel(port) imq_full_kernel(&(port)->ip_messages) +#define ip_full(port) imq_full(&(port)->ip_messages) + /* * JMM - Preallocation flag * This flag indicates that there is a message buffer preallocated for this @@ -197,9 +225,8 @@ MACRO_BEGIN \ (port)->ip_premsg = IKM_NULL; \ MACRO_END -typedef ipc_table_index_t ipc_port_request_index_t; - -typedef struct ipc_port_request { +/* JMM - address alignment/packing for LP64 */ +struct ipc_port_request { union { struct ipc_port *port; ipc_port_request_index_t index; @@ -209,7 +236,7 @@ typedef struct ipc_port_request { mach_port_name_t name; struct ipc_table_size *size; } name; -} *ipc_port_request_t; +}; #define ipr_next notify.index #define ipr_size name.size @@ -217,7 +244,19 @@ typedef struct ipc_port_request { #define ipr_soright notify.port #define ipr_name name.name -#define IPR_NULL ((ipc_port_request_t) 0) +/* + * Use the low bits in the ipr_soright to specify the request type + */ +#define IPR_SOR_SPARM_MASK 1 /* send-possible armed */ +#define IPR_SOR_SPREQ_MASK 2 /* send-possible requested */ +#define IPR_SOR_SPBIT_MASK 3 /* combo */ +#define IPR_SOR_SPARMED(sor) (((uintptr_t)(sor) & IPR_SOR_SPARM_MASK) != 0) +#define IPR_SOR_SPREQ(sor) (((uintptr_t)(sor) & IPR_SOR_SPREQ_MASK) != 0) +#define IPR_SOR_PORT(sor) ((ipc_port_t)((uintptr_t)(sor) & ~IPR_SOR_SPBIT_MASK)) +#define IPR_SOR_MAKE(p,m) ((ipc_port_t)((uintptr_t)(p) | (m))) + +extern lck_grp_t ipc_lck_grp; +extern lck_attr_t ipc_lck_attr; /* * Taking the ipc_port_multiple lock grants the privilege @@ -225,16 +264,30 @@ typedef struct ipc_port_request { * when it is taken. */ -decl_mutex_data(extern,ipc_port_multiple_lock_data) +#if 1 +decl_lck_mtx_data(extern,ipc_port_multiple_lock_data) +extern lck_mtx_ext_t ipc_port_multiple_lock_data_ext; + +#define ipc_port_multiple_lock_init() \ + lck_mtx_init_ext(&ipc_port_multiple_lock_data, &ipc_port_multiple_lock_data_ext, &ipc_lck_grp, &ipc_lck_attr) + +#define ipc_port_multiple_lock() \ + lck_mtx_lock(&ipc_port_multiple_lock_data) + +#define ipc_port_multiple_unlock() \ + lck_mtx_unlock(&ipc_port_multiple_lock_data) +#else +lck_spin_t ipc_port_multiple_lock_data; #define ipc_port_multiple_lock_init() \ - mutex_init(&ipc_port_multiple_lock_data, ETAP_IPC_PORT_MULT) + lck_spin_init(&ipc_port_multiple_lock_data, &ipc_lck_grp, &ipc_lck_attr) #define ipc_port_multiple_lock() \ - mutex_lock(&ipc_port_multiple_lock_data) + lck_spin_lock(&ipc_port_multiple_lock_data) #define ipc_port_multiple_unlock() \ - mutex_unlock(&ipc_port_multiple_lock_data) + lck_spin_unlock(&ipc_port_multiple_lock_data) +#endif /* * The port timestamp facility provides timestamps @@ -242,18 +295,8 @@ decl_mutex_data(extern,ipc_port_multiple_lock_data) * mach_port_names with port death. */ -decl_mutex_data(extern,ipc_port_timestamp_lock_data) extern ipc_port_timestamp_t ipc_port_timestamp_data; -#define ipc_port_timestamp_lock_init() \ - mutex_init(&ipc_port_timestamp_lock_data, ETAP_IPC_PORT_TIME) - -#define ipc_port_timestamp_lock() \ - mutex_lock(&ipc_port_timestamp_lock_data) - -#define ipc_port_timestamp_unlock() \ - mutex_unlock(&ipc_port_timestamp_lock_data) - /* Retrieve a port timestamp value */ extern ipc_port_timestamp_t ipc_port_timestamp(void); @@ -276,32 +319,67 @@ extern ipc_port_timestamp_t ipc_port_timestamp(void); MACH_PORT_RIGHT_SEND, \ (ipc_object_t *) (portp)) -/* Allocate a dead-name request slot */ +/* Allocate a notification request slot */ +#if IMPORTANCE_INHERITANCE +extern kern_return_t +ipc_port_request_alloc( + ipc_port_t port, + mach_port_name_t name, + ipc_port_t soright, + boolean_t send_possible, + boolean_t immediate, + ipc_port_request_index_t *indexp, + boolean_t *importantp); +#else extern kern_return_t -ipc_port_dnrequest( +ipc_port_request_alloc( ipc_port_t port, mach_port_name_t name, ipc_port_t soright, + boolean_t send_possible, + boolean_t immediate, ipc_port_request_index_t *indexp); +#endif /* IMPORTANCE_INHERITANCE */ -/* Grow a port's table of dead-name requests */ -extern kern_return_t ipc_port_dngrow( - ipc_port_t port, - int target_size); +/* Grow one of a port's tables of notifcation requests */ +extern kern_return_t ipc_port_request_grow( + ipc_port_t port, + ipc_table_elems_t target_size); + +/* Return the type(s) of notification requests outstanding */ +extern mach_port_type_t ipc_port_request_type( + ipc_port_t port, + mach_port_name_t name, + ipc_port_request_index_t index); + +/* Cancel a notification request and return the send-once right */ +extern ipc_port_t ipc_port_request_cancel( + ipc_port_t port, + mach_port_name_t name, + ipc_port_request_index_t index); -/* Cancel a dead-name request and return the send-once right */ -extern ipc_port_t ipc_port_dncancel( +/* Arm any delayed send-possible notification */ +#if IMPORTANCE_INHERITANCE +extern boolean_t ipc_port_request_sparm( + ipc_port_t port, + mach_port_name_t name, + ipc_port_request_index_t index, + mach_msg_option_t option); +#else +extern boolean_t ipc_port_request_sparm( ipc_port_t port, mach_port_name_t name, ipc_port_request_index_t index); +#endif /* IMPORTANCE_INHERITANCE */ -#define ipc_port_dnrename(port, index, oname, nname) \ +/* Macros for manipulating a port's dead name notificaiton requests */ +#define ipc_port_request_rename(port, index, oname, nname) \ MACRO_BEGIN \ ipc_port_request_t ipr, table; \ \ assert(ip_active(port)); \ \ - table = port->ip_dnrequests; \ + table = port->ip_requests; \ assert(table != IPR_NULL); \ \ ipr = &table[index]; \ @@ -310,6 +388,7 @@ MACRO_BEGIN \ ipr->ipr_name = nname; \ MACRO_END + /* Make a port-deleted request */ extern void ipc_port_pdrequest( ipc_port_t port, @@ -332,7 +411,8 @@ MACRO_END /* Prepare a receive right for transmission/destruction */ extern void ipc_port_clear_receiver( - ipc_port_t port); + ipc_port_t port, + queue_t links); /* Initialize a newly-allocated port */ extern void ipc_port_init( @@ -354,8 +434,11 @@ extern kern_return_t ipc_port_alloc_name( /* Generate dead name notifications */ extern void ipc_port_dnnotify( - ipc_port_t port, - ipc_port_request_t dnrequests); + ipc_port_t port); + +/* Generate send-possible notifications */ +extern void ipc_port_spnotify( + ipc_port_t port); /* Destroy a port */ extern void ipc_port_destroy( @@ -368,6 +451,14 @@ ipc_port_check_circularity( ipc_port_t port, ipc_port_t dest); +#if IMPORTANCE_INHERITANCE +/* Apply an importance delta to a port */ +extern boolean_t +ipc_port_importance_delta( + ipc_port_t port, + mach_port_delta_t delta); +#endif /* IMPORTANCE_INHERITANCE */ + /* Make a send-once notify port from a receive right */ extern ipc_port_t ipc_port_lookup_notify( ipc_space_t space, @@ -390,10 +481,28 @@ extern mach_port_name_t ipc_port_copyout_send( ipc_port_t sright, ipc_space_t space); +#endif /* MACH_KERNEL_PRIVATE */ + +#if KERNEL_PRIVATE + /* Release a (valid) naked send right */ extern void ipc_port_release_send( ipc_port_t port); +extern void ipc_port_reference( + ipc_port_t port); + +extern void ipc_port_release( + ipc_port_t port); + +#endif /* KERNEL_PRIVATE */ + +#if MACH_KERNEL_PRIVATE + +/* Make a naked send-once right from a locked and active receive right */ +extern ipc_port_t ipc_port_make_sonce_locked( + ipc_port_t port); + /* Make a naked send-once right from a receive right */ extern ipc_port_t ipc_port_make_sonce( ipc_port_t port); @@ -406,6 +515,10 @@ extern void ipc_port_release_sonce( extern void ipc_port_release_receive( ipc_port_t port); +/* finalize the destruction of a port before it gets freed */ +extern void ipc_port_finalize( + ipc_port_t port); + /* Allocate a port in a special space */ extern ipc_port_t ipc_port_alloc_special( ipc_space_t space); @@ -434,10 +547,6 @@ extern void ipc_port_debug_init(void); #define ipc_port_dealloc_reply(port) \ ipc_port_dealloc_special((port), ipc_space_reply) -#define ipc_port_reference(port) \ - ipc_object_reference(&(port)->ip_object) - -#define ipc_port_release(port) \ - ipc_object_release(&(port)->ip_object) +#endif /* MACH_KERNEL_PRIVATE */ #endif /* _IPC_IPC_PORT_H_ */