X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/0a7de7458d150b5d4dffc935ba399be265ef0a1a..ea3f04195ba4a5034c9c8e9b726d4f7ce96f1832:/osfmk/ipc/ipc_port.h diff --git a/osfmk/ipc/ipc_port.h b/osfmk/ipc/ipc_port.h index 971f77821..b9acef764 100644 --- a/osfmk/ipc/ipc_port.h +++ b/osfmk/ipc/ipc_port.h @@ -108,6 +108,8 @@ * taken when the port was destroyed. */ +struct task_watchport_elem; + typedef unsigned int ipc_port_timestamp_t; struct ipc_port { @@ -127,6 +129,7 @@ struct ipc_port { union { ipc_kobject_t kobject; + ipc_kobject_label_t kolabel; ipc_importance_task_t imp_task; ipc_port_t sync_inheritor_port; struct knote *sync_inheritor_knote; @@ -139,7 +142,6 @@ struct ipc_port { union { struct ipc_kmsg *premsg; struct turnstile *send_turnstile; - SLIST_ENTRY(ipc_port) dealloc_elm; } kdata2; mach_vm_address_t ip_context; @@ -151,8 +153,12 @@ struct ipc_port { ip_guarded:1, /* port guarded (use context value as guard) */ ip_strict_guard:1, /* Strict guarding; Prevents user manipulation of context values directly */ ip_specialreply:1, /* port is a special reply port */ - ip_sync_link_state:3, /* link the special reply port to destination port/ Workloop */ - ip_impcount:22; /* number of importance donations in nested queue */ + ip_sync_link_state:3, /* link the port to destination port/ Workloop */ + ip_sync_bootstrap_checkin:1,/* port part of sync bootstrap checkin, push on thread doing the checkin */ + ip_immovable_receive:1, /* the receive right cannot be moved out of a space, until it is destroyed */ + ip_no_grant:1, /* Port wont accept complex messages containing (ool) port descriptors */ + ip_immovable_send:1, /* No send(once) rights to this port can be moved out of a space */ + ip_impcount:18; /* number of importance donations in nested queue */ mach_port_mscount_t ip_mscount; mach_port_rights_t ip_srights; @@ -175,16 +181,17 @@ struct ipc_port { #define ip_references ip_object.io_references -#define ip_bits ip_object.io_bits #define ip_receiver_name ip_messages.imq_receiver_name #define ip_in_pset ip_messages.imq_in_pset +#define ip_reply_context ip_messages.imq_context #define ip_receiver data.receiver #define ip_destination data.destination #define ip_timestamp data.timestamp #define ip_kobject kdata.kobject +#define ip_kolabel kdata.kolabel #define ip_imp_task kdata.imp_task #define ip_sync_inheritor_port kdata.sync_inheritor_port #define ip_sync_inheritor_knote kdata.sync_inheritor_knote @@ -192,7 +199,6 @@ struct ipc_port { #define ip_premsg kdata2.premsg #define ip_send_turnstile kdata2.send_turnstile -#define ip_dealloc_elm kdata2.dealloc_elm #define port_send_turnstile(port) (IP_PREALLOC(port) ? (port)->ip_premsg->ikm_turnstile : (port)->ip_send_turnstile) @@ -208,11 +214,12 @@ MACRO_END #define port_send_turnstile_address(port) \ (IP_PREALLOC(port) ? &((port)->ip_premsg->ikm_turnstile) : &((port)->ip_send_turnstile)) -#define port_rcv_turnstile_address(port) (NULL) +#define port_rcv_turnstile_address(port) \ + &(port)->ip_messages.imq_wait_queue.waitq_ts /* - * SYNC IPC state flags for special reply port. + * SYNC IPC state flags for special reply port/ rcv right. * * PORT_SYNC_LINK_ANY * Special reply port is not linked to any other port @@ -237,26 +244,34 @@ MACRO_END * Message sent to special reply port, do * not allow any linkages till receive is * complete. + * + * PORT_SYNC_LINK_RCV_THREAD + * Receive right copied out as a part of bootstrap check in, + * push on the thread which copied out the port. */ #define PORT_SYNC_LINK_ANY (0) #define PORT_SYNC_LINK_PORT (0x1) #define PORT_SYNC_LINK_WORKLOOP_KNOTE (0x2) #define PORT_SYNC_LINK_WORKLOOP_STASH (0x3) #define PORT_SYNC_LINK_NO_LINKAGE (0x4) +#define PORT_SYNC_LINK_RCV_THREAD (0x5) #define IP_NULL IPC_PORT_NULL #define IP_DEAD IPC_PORT_DEAD #define IP_VALID(port) IPC_PORT_VALID(port) -#define ip_active(port) io_active(&(port)->ip_object) -#define ip_lock_init(port) io_lock_init(&(port)->ip_object) -#define ip_lock(port) io_lock(&(port)->ip_object) -#define ip_lock_try(port) io_lock_try(&(port)->ip_object) -#define ip_lock_held_kdp(port) io_lock_held_kdp(&(port)->ip_object) -#define ip_unlock(port) io_unlock(&(port)->ip_object) +#define ip_object_to_port(io) __container_of(io, struct ipc_port, ip_object) +#define ip_to_object(port) (&(port)->ip_object) +#define ip_active(port) io_active(ip_to_object(port)) +#define ip_lock_init(port) io_lock_init(ip_to_object(port)) +#define ip_lock_held(port) io_lock_held(ip_to_object(port)) +#define ip_lock(port) io_lock(ip_to_object(port)) +#define ip_lock_try(port) io_lock_try(ip_to_object(port)) +#define ip_lock_held_kdp(port) io_lock_held_kdp(ip_to_object(port)) +#define ip_unlock(port) io_unlock(ip_to_object(port)) -#define ip_reference(port) io_reference(&(port)->ip_object) -#define ip_release(port) io_release(&(port)->ip_object) +#define ip_reference(port) io_reference(ip_to_object(port)) +#define ip_release(port) io_release(ip_to_object(port)) /* get an ipc_port pointer from an ipc_mqueue pointer */ #define ip_from_mq(mq) \ @@ -265,7 +280,12 @@ MACRO_END #define ip_reference_mq(mq) ip_reference(ip_from_mq(mq)) #define ip_release_mq(mq) ip_release(ip_from_mq(mq)) -#define ip_kotype(port) io_kotype(&(port)->ip_object) +#define ip_kotype(port) io_kotype(ip_to_object(port)) +#define ip_is_kobject(port) io_is_kobject(ip_to_object(port)) +#define ip_is_kolabeled(port) io_is_kolabeled(ip_to_object(port)) +#define ip_get_kobject(port) ipc_kobject_get(port) +#define ip_label_check(space, port, msgt_name) \ + (!ip_is_kolabeled(port) || ipc_kobject_label_check((space), (port), (msgt_name))) #define ip_full_kernel(port) imq_full_kernel(&(port)->ip_messages) #define ip_full(port) imq_full(&(port)->ip_messages) @@ -279,18 +299,18 @@ MACRO_END * therefore cannot be blocked waiting for memory themselves). */ #define IP_BIT_PREALLOC 0x00008000 /* preallocated mesg */ -#define IP_PREALLOC(port) ((port)->ip_bits & IP_BIT_PREALLOC) +#define IP_PREALLOC(port) ((port)->ip_object.io_bits & IP_BIT_PREALLOC) #define IP_SET_PREALLOC(port, kmsg) \ MACRO_BEGIN \ - (port)->ip_bits |= IP_BIT_PREALLOC; \ + (port)->ip_object.io_bits |= IP_BIT_PREALLOC; \ (port)->ip_premsg = (kmsg); \ MACRO_END #define IP_CLEAR_PREALLOC(port, kmsg) \ MACRO_BEGIN \ assert((port)->ip_premsg == kmsg); \ - (port)->ip_bits &= ~IP_BIT_PREALLOC; \ + (port)->ip_object.io_bits &= ~IP_BIT_PREALLOC; \ (port)->ip_premsg = IKM_NULL; \ MACRO_END @@ -364,15 +384,34 @@ extern ipc_port_timestamp_t ipc_port_timestamp(void); #define IP_TIMESTAMP_ORDER(one, two) ((int) ((one) - (two)) < 0) +static inline void +require_ip_active(ipc_port_t port) +{ + if (!ip_active(port)) { + panic("Using inactive port %p", port); + } +} + +static inline kern_return_t +ipc_port_translate( + ipc_space_t space, + mach_port_name_t name, + mach_port_right_t right, + ipc_port_t *portp) +{ + ipc_object_t object; + kern_return_t kr; + + kr = ipc_object_translate(space, name, right, &object); + *portp = (kr == KERN_SUCCESS) ? ip_object_to_port(object) : IP_NULL; + return kr; +} + #define ipc_port_translate_receive(space, name, portp) \ - ipc_object_translate((space), (name), \ - MACH_PORT_RIGHT_RECEIVE, \ - (ipc_object_t *) (portp)) + ipc_port_translate((space), (name), MACH_PORT_RIGHT_RECEIVE, portp) #define ipc_port_translate_send(space, name, portp) \ - ipc_object_translate((space), (name), \ - MACH_PORT_RIGHT_SEND, \ - (ipc_object_t *) (portp)) + ipc_port_translate((space), (name), MACH_PORT_RIGHT_SEND, portp) /* Allocate a notification request slot */ #if IMPORTANCE_INHERITANCE @@ -421,23 +460,6 @@ extern boolean_t ipc_port_request_sparm( mach_msg_option_t option, mach_msg_priority_t override); -/* 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_requests; \ - assert(table != IPR_NULL); \ - \ - ipr = &table[index]; \ - assert(ipr->ipr_name == oname); \ - \ - ipr->ipr_name = nname; \ -MACRO_END - - /* Make a port-deleted request */ extern void ipc_port_pdrequest( ipc_port_t port, @@ -451,33 +473,36 @@ extern void ipc_port_nsrequest( ipc_port_t notify, ipc_port_t *previousp); -#define ipc_port_set_mscount(port, mscount) \ -MACRO_BEGIN \ - assert(ip_active(port)); \ - \ - (port)->ip_mscount = (mscount); \ -MACRO_END - /* Prepare a receive right for transmission/destruction */ extern boolean_t ipc_port_clear_receiver( ipc_port_t port, boolean_t should_destroy); +__options_decl(ipc_port_init_flags_t, uint32_t, { + IPC_PORT_INIT_NONE = 0x00000000, + IPC_PORT_INIT_MAKE_SEND_RIGHT = 0x00000001, + IPC_PORT_INIT_MESSAGE_QUEUE = 0x00000002, + IPC_PORT_INIT_SPECIAL_REPLY = 0x00000004, +}); + /* Initialize a newly-allocated port */ extern void ipc_port_init( ipc_port_t port, ipc_space_t space, + ipc_port_init_flags_t flags, mach_port_name_t name); /* Allocate a port */ extern kern_return_t ipc_port_alloc( ipc_space_t space, + ipc_port_init_flags_t flags, mach_port_name_t *namep, ipc_port_t *portp); /* Allocate a port, with a specific name */ extern kern_return_t ipc_port_alloc_name( ipc_space_t space, + ipc_port_init_flags_t flags, mach_port_name_t name, ipc_port_t *portp); @@ -511,45 +536,76 @@ enum { void ipc_port_link_special_reply_port( ipc_port_t special_reply_port, - ipc_port_t dest_port); + ipc_port_t dest_port, + boolean_t sync_bootstrap_checkin); #define IPC_PORT_ADJUST_SR_NONE 0 -#define IPC_PORT_ADJUST_SR_CLEAR_SPECIAL_REPLY 0x1 -#define IPC_PORT_ADJUST_SR_ALLOW_SYNC_LINKAGE 0x2 -#define IPC_PORT_ADJUST_SR_LINK_WORKLOOP 0x4 - +#define IPC_PORT_ADJUST_SR_ALLOW_SYNC_LINKAGE 0x1 +#define IPC_PORT_ADJUST_SR_LINK_WORKLOOP 0x2 +#define IPC_PORT_ADJUST_UNLINK_THREAD 0x4 #define IPC_PORT_ADJUST_SR_RECEIVED_MSG 0x8 #define IPC_PORT_ADJUST_SR_ENABLE_EVENT 0x10 +#define IPC_PORT_ADJUST_RESET_BOOSTRAP_CHECKIN 0x20 void -reset_ip_srp_bits(ipc_port_t special_reply_port); - -void -reset_ip_srp_msg_sent(ipc_port_t special_reply_port); +ipc_special_reply_port_bits_reset(ipc_port_t special_reply_port); void -set_ip_srp_msg_sent(ipc_port_t special_reply_port); +ipc_special_reply_port_msg_sent(ipc_port_t special_reply_port); void -set_ip_srp_lost_link(ipc_port_t special_reply_port); +ipc_special_reply_port_msg_sent(ipc_port_t special_reply_port); /* Adjust special reply port linkage */ -void ipc_port_adjust_special_reply_port_locked( +void +ipc_port_adjust_special_reply_port_locked( ipc_port_t special_reply_port, struct knote *kn, uint8_t flags, boolean_t get_turnstile); +void +ipc_port_adjust_sync_link_state_locked( + ipc_port_t port, + int sync_link_state, + turnstile_inheritor_t inheritor); + /* Adjust special reply port linkage */ void ipc_port_adjust_special_reply_port( ipc_port_t special_reply_port, - uint8_t flags, - boolean_t get_turnstile); + uint8_t flags); -turnstile_inheritor_t -ipc_port_get_special_reply_port_inheritor( - ipc_port_t special_reply_port); +void +ipc_port_adjust_port_locked( + ipc_port_t port, + struct knote *kn, + boolean_t sync_bootstrap_checkin); + +void +ipc_port_clear_sync_rcv_thread_boost_locked( + ipc_port_t port); + +kern_return_t +ipc_port_add_watchport_elem_locked( + ipc_port_t port, + struct task_watchport_elem *watchport_elem, + struct task_watchport_elem **old_elem); + +kern_return_t +ipc_port_clear_watchport_elem_internal_conditional_locked( + ipc_port_t port, + struct task_watchport_elem *watchport_elem); + +kern_return_t +ipc_port_replace_watchport_elem_conditional_locked( + ipc_port_t port, + struct task_watchport_elem *old_watchport_elem, + struct task_watchport_elem *new_watchport_elem); + +struct task_watchport_elem * +ipc_port_clear_watchport_elem_internal( + ipc_port_t port); void ipc_port_send_turnstile_prepare(ipc_port_t port); @@ -560,9 +616,6 @@ ipc_port_send_turnstile_complete(ipc_port_t port); struct waitq * ipc_port_rcv_turnstile_waitq(struct waitq *waitq); -struct turnstile * -ipc_port_rcv_turnstile(ipc_port_t port); - /* apply importance delta to port only */ extern mach_port_delta_t ipc_port_impcount_delta( @@ -586,11 +639,6 @@ ipc_port_importance_delta( 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, - mach_port_name_t name); - /* Make a naked send right from a receive right - port locked and active */ extern ipc_port_t ipc_port_make_send_locked( ipc_port_t port); @@ -599,6 +647,10 @@ extern ipc_port_t ipc_port_make_send_locked( extern ipc_port_t ipc_port_make_send( ipc_port_t port); +/* Make a naked send right from another naked send right - port locked and active */ +extern void ipc_port_copy_send_locked( + ipc_port_t port); + /* Make a naked send right from another naked send right */ extern ipc_port_t ipc_port_copy_send( ipc_port_t port); @@ -608,12 +660,6 @@ extern mach_port_name_t ipc_port_copyout_send( ipc_port_t sright, ipc_space_t space); -/* Copyout a naked send right to given name */ -extern mach_port_name_t ipc_port_copyout_name_send( - ipc_port_t sright, - ipc_space_t space, - mach_port_name_t name); - #endif /* MACH_KERNEL_PRIVATE */ #if KERNEL_PRIVATE @@ -654,7 +700,8 @@ extern void ipc_port_finalize( /* Allocate a port in a special space */ extern ipc_port_t ipc_port_alloc_special( - ipc_space_t space); + ipc_space_t space, + ipc_port_init_flags_t flags); /* Deallocate a port in a special space */ extern void ipc_port_dealloc_special( @@ -670,16 +717,21 @@ extern void ipc_port_track_dealloc( extern void ipc_port_debug_init(void); #endif /* MACH_ASSERT */ -extern struct turnstile *ipc_port_get_inheritor( - ipc_port_t port); +extern void ipc_port_recv_update_inheritor(ipc_port_t port, + struct turnstile *turnstile, + turnstile_update_flags_t flags); + +extern void ipc_port_send_update_inheritor(ipc_port_t port, + struct turnstile *turnstile, + turnstile_update_flags_t flags); #define ipc_port_alloc_kernel() \ - ipc_port_alloc_special(ipc_space_kernel) + ipc_port_alloc_special(ipc_space_kernel, IPC_PORT_INIT_NONE) #define ipc_port_dealloc_kernel(port) \ ipc_port_dealloc_special((port), ipc_space_kernel) #define ipc_port_alloc_reply() \ - ipc_port_alloc_special(ipc_space_reply) + ipc_port_alloc_special(ipc_space_reply, IPC_PORT_INIT_MESSAGE_QUEUE) #define ipc_port_dealloc_reply(port) \ ipc_port_dealloc_special((port), ipc_space_reply)