diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2013-11-21 16:50:49 +0100 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-10-01 09:03:51 +0200 |
commit | d565bf2f784ce1203e77306d05eade03933bc523 (patch) | |
tree | 1c30bed601834acd886b9dc4abcecb706349d8b6 | |
parent | 3a0fae39873c9c7d73dc978888e45b87ad27d44e (diff) |
ipc: add protected payload
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.
(ipc_port_set_protected_payload): Add function declaration.
(ipc_port_clear_protected_payload): Likewise.
(ipc_port_flag_protected_payload): Add accessor for the protected
payload flag.
(ipc_port_flag_protected_payload_set): Likewise.
(ipc_port_flag_protected_payload_clear): 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.h (IO_BITS_PROTECTED_PAYLOAD): New bitmask.
(IO_BITS_OTYPE): Adjust accordingly.
-rw-r--r-- | ipc/ipc_object.c | 1 | ||||
-rw-r--r-- | ipc/ipc_object.h | 4 | ||||
-rw-r--r-- | ipc/ipc_port.c | 48 | ||||
-rw-r--r-- | ipc/ipc_port.h | 27 | ||||
-rw-r--r-- | ipc/ipc_right.c | 12 |
5 files changed, 91 insertions, 1 deletions
diff --git a/ipc/ipc_object.c b/ipc/ipc_object.c index 982bd4e..db6ef01 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; + ipc_port_flag_protected_payload_clear(port); ip_unlock(port); break; } diff --git a/ipc/ipc_object.h b/ipc/ipc_object.h index adf5bca..b83bb5a 100644 --- a/ipc/ipc_object.h +++ b/ipc/ipc_object.h @@ -57,7 +57,9 @@ typedef struct ipc_object { #define IO_VALID(io) (((io) != IO_NULL) && ((io) != IO_DEAD)) #define IO_BITS_KOTYPE 0x0000ffff /* used by the object */ -#define IO_BITS_OTYPE 0x7fff0000 /* determines a cache */ +#define IO_BITS_OTYPE 0x3fff0000 /* determines a cache */ +/* The following masks are used to store attributes of ipc ports. */ +#define IO_BITS_PROTECTED_PAYLOAD 0x40000000 /* pp set? */ #define IO_BITS_ACTIVE 0x80000000U /* is object alive? */ #define io_active(io) ((int)(io)->io_bits < 0) /* hack */ diff --git a/ipc/ipc_port.c b/ipc/ipc_port.c index 78211e6..89a5d67 100644 --- a/ipc/ipc_port.c +++ b/ipc/ipc_port.c @@ -423,6 +423,44 @@ ipc_port_set_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; + ipc_port_flag_protected_payload_set(port); + 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); + ipc_port_flag_protected_payload_clear(port); + imq_unlock(mqueue); +} + + +/* * Routine: ipc_port_clear_receiver * Purpose: * Prepares a receive right for transmission/destruction. @@ -491,6 +529,8 @@ ipc_port_init( port->ip_seqno = 0; port->ip_msgcount = 0; port->ip_qlimit = MACH_PORT_QLIMIT_DEFAULT; + ipc_port_flag_protected_payload_clear(port); + port->ip_protected_payload = 0; ipc_mqueue_init(&port->ip_messages); ipc_thread_queue_init(&port->ip_blocked); @@ -613,6 +653,7 @@ ipc_port_destroy( /* make port be in limbo */ port->ip_receiver_name = MACH_PORT_NULL; port->ip_destination = IP_NULL; + ipc_port_flag_protected_payload_clear(port); ip_unlock(port); if (!ipc_port_check_circularity(port, pdrequest)) { @@ -1215,6 +1256,11 @@ ipc_port_print(port) indent += 2; + iprintf("flags "); + printf("has_protected_payload=%d", + ipc_port_flag_protected_payload(port)); + 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); @@ -1237,6 +1283,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..125fefc 100644 --- a/ipc/ipc_port.h +++ b/ipc/ipc_port.h @@ -48,6 +48,7 @@ #include <ipc/ipc_mqueue.h> #include <ipc/ipc_table.h> #include <ipc/ipc_thread.h> +#include <ipc/ipc_object.h> #include "ipc_target.h" #include <mach/rpc.h> @@ -96,6 +97,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 +264,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 @@ -325,4 +333,23 @@ ipc_port_dealloc_special(ipc_port_t, ipc_space_t); #define ipc_port_release(port) \ ipc_object_release(&(port)->ip_object) +extern inline boolean_t +ipc_port_flag_protected_payload(const struct ipc_port *port) +{ + return !! (port->ip_target.ipt_object.io_bits + & IO_BITS_PROTECTED_PAYLOAD); +} + +extern inline void +ipc_port_flag_protected_payload_set(struct ipc_port *port) +{ + port->ip_target.ipt_object.io_bits |= IO_BITS_PROTECTED_PAYLOAD; +} + +extern inline void +ipc_port_flag_protected_payload_clear(struct ipc_port *port) +{ + port->ip_target.ipt_object.io_bits &= ~IO_BITS_PROTECTED_PAYLOAD; +} + #endif /* _IPC_IPC_PORT_H_ */ diff --git a/ipc/ipc_right.c b/ipc/ipc_right.c index 77a68ce..503eb1f 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. + */ + ipc_port_flag_protected_payload_clear(port); 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. + */ + ipc_port_flag_protected_payload_clear(port); + assert((bits & MACH_PORT_TYPE_RECEIVE) == 0); if (bits & MACH_PORT_TYPE_SEND) { |