Add a field ip_protected_payload and a flag ip_has_protected_payload to struct ipc_port.
Clear the protected payload when a receive port is moved from one ipc space to another. This is done to retain the old behavior of mach_msg, so that a port name is sent in the msgh_local_port field. If the new owner of that receive right wishes to use the protected payload mechanism, it has to be explicitly set again. * ipc/ipc_port.h (struct ipc_port): Add field ip_protected_payload and flag ip_has_protected_payload. (ipc_port_set_protected_payload): Add function declaration. (ipc_port_clear_protected_payload): Likewise. * ipc/ipc_port.c (ipc_port_init): Initialize protected payload. (ipc_port_print): Print protected_payload. (ipc_port_set_protected_payload): New function. (ipc_port_clear_protected_payload): Likewise. (ipc_port_destroy): Clear the payload when moving a receive port. * ipc/ipc_right.c (ipc_right_copyin): Likewise. (ipc_right_copyout): Likewise. * ipc/ipc_object.c (ipc_object_copyin_from_kernel): Likewise. --- ipc/ipc_object.c | 1 + ipc/ipc_port.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ ipc/ipc_port.h | 11 +++++++++++ ipc/ipc_right.c | 12 ++++++++++++ 4 files changed, 71 insertions(+) diff --git a/ipc/ipc_object.c b/ipc/ipc_object.c index 982bd4e..d9875d1 100644 --- a/ipc/ipc_object.c +++ b/ipc/ipc_object.c @@ -481,6 +481,7 @@ ipc_object_copyin_from_kernel( port->ip_receiver_name = MACH_PORT_NULL; port->ip_destination = IP_NULL; + port->ip_has_protected_payload = FALSE; ip_unlock(port); break; } diff --git a/ipc/ipc_port.c b/ipc/ipc_port.c index d4ade8e..0789296 100644 --- a/ipc/ipc_port.c +++ b/ipc/ipc_port.c @@ -425,6 +425,44 @@ ipc_port_set_seqno(port, seqno) } /* + * Routine: ipc_port_set_protected_payload + * Purpose: + * Changes a port's protected payload. + * Conditions: + * The port is locked and active. + */ + +void +ipc_port_set_protected_payload(ipc_port_t port, unsigned long payload) +{ + ipc_mqueue_t mqueue; + + mqueue = ipc_port_lock_mqueue(port); + port->ip_protected_payload = payload; + port->ip_has_protected_payload = TRUE; + imq_unlock(mqueue); +} + +/* + * Routine: ipc_port_clear_protected_payload + * Purpose: + * Clear a port's protected payload. + * Conditions: + * The port is locked and active. + */ + +void +ipc_port_clear_protected_payload(ipc_port_t port) +{ + ipc_mqueue_t mqueue; + + mqueue = ipc_port_lock_mqueue(port); + port->ip_has_protected_payload = FALSE; + imq_unlock(mqueue); +} + + +/* * Routine: ipc_port_clear_receiver * Purpose: * Prepares a receive right for transmission/destruction. @@ -493,6 +531,8 @@ ipc_port_init( port->ip_seqno = 0; port->ip_msgcount = 0; port->ip_qlimit = MACH_PORT_QLIMIT_DEFAULT; + port->ip_has_protected_payload = FALSE; + port->ip_protected_payload = 0; ipc_mqueue_init(&port->ip_messages); ipc_thread_queue_init(&port->ip_blocked); @@ -615,6 +655,7 @@ ipc_port_destroy( /* make port be in limbo */ port->ip_receiver_name = MACH_PORT_NULL; port->ip_destination = IP_NULL; + port->ip_has_protected_payload = FALSE; ip_unlock(port); if (!ipc_port_check_circularity(port, pdrequest)) { @@ -1218,6 +1259,10 @@ ipc_port_print(port) indent += 2; + iprintf("flags "); + printf("has_protected_payload=%d", port->ip_has_protected_payload); + printf("\n"); + ipc_object_print(&port->ip_object); iprintf("receiver=0x%x", port->ip_receiver); printf(", receiver_name=0x%x\n", port->ip_receiver_name); @@ -1240,6 +1285,8 @@ ipc_port_print(port) printf(", sndrs=0x%x", port->ip_blocked.ithq_base); printf(", kobj=0x%x\n", port->ip_kobject); + iprintf("protected_payload=%p\n", (void *) port->ip_protected_payload); + indent -= 2; } diff --git a/ipc/ipc_port.h b/ipc/ipc_port.h index 27d2e49..4c7c742 100644 --- a/ipc/ipc_port.h +++ b/ipc/ipc_port.h @@ -71,6 +71,10 @@ typedef unsigned int ipc_port_timestamp_t; struct ipc_port { struct ipc_target ip_target; + /* Flags. */ + unsigned int ip_has_protected_payload:1; /* A pp has + been set. */ + /* This points to the ip_target above if this port isn't on a port set; otherwise it points to the port set's ips_target. */ struct ipc_target *ip_cur_target; @@ -96,6 +100,7 @@ struct ipc_port { mach_port_msgcount_t ip_msgcount; mach_port_msgcount_t ip_qlimit; struct ipc_thread_queue ip_blocked; + unsigned long ip_protected_payload; }; #define ip_object ip_target.ipt_object @@ -262,6 +267,12 @@ extern void ipc_port_set_seqno(ipc_port_t, mach_port_seqno_t); extern void +ipc_port_set_protected_payload(ipc_port_t, unsigned long); + +extern void +ipc_port_clear_protected_payload(ipc_port_t); + +extern void ipc_port_clear_receiver(ipc_port_t); extern void diff --git a/ipc/ipc_right.c b/ipc/ipc_right.c index 41fe3de..6b6b590 100644 --- a/ipc/ipc_right.c +++ b/ipc/ipc_right.c @@ -1432,6 +1432,12 @@ ipc_right_copyin( port->ip_receiver_name = MACH_PORT_NULL; port->ip_destination = IP_NULL; + + /* + * Clear the protected payload field to retain + * the behavior of mach_msg. + */ + port->ip_has_protected_payload = FALSE; ip_unlock(port); *objectp = (ipc_object_t) port; @@ -1932,6 +1938,12 @@ ipc_right_copyout( port->ip_receiver_name = name; port->ip_receiver = space; + /* + * Clear the protected payload field to retain + * the behavior of mach_msg. + */ + port->ip_has_protected_payload = FALSE; + assert((bits & MACH_PORT_TYPE_RECEIVE) == 0); if (bits & MACH_PORT_TYPE_SEND) { -- 1.8.5.2