I'm trying to understand the low-level mechanism of IPC using Mach messages between a launch daemon (running as root) and another process, running in a user-content.
Assuming the following data structs:
struct MACH_MSG_BASE
{
mach_msg_header_t hdr;
mach_msg_body_t body;
};
struct MACH_MSG_UINT32
{
MACH_MSG_BASE base;
unsigned int val; //Sending this value as a test
};
So I'm running the following code in the daemon:
//Server:
//No error checks for brevity
mach_port_t port = MACH_PORT_NULL;
mach_port_t task = mach_task_self();
mach_port_allocate(task,
MACH_PORT_RIGHT_RECEIVE,
&port);
mach_port_insert_right(task,
port,
port,
MACH_MSG_TYPE_MAKE_SEND);
MACH_MSG_UINT32 msg = {};
msg.base.hdr.msgh_local_port = port;
msg.base.hdr.msgh_size = sizeof(msg.base);
mach_msg(&msg.base.hdr,
MACH_RCV_MSG,
0,
sizeof(msg),
port,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
When I run the code above, it goes into a waiting mode at the mach_msg
call, as I would expect.
But then, the first issue - how do you get the port number of the daemon from another process? I'm assuming using task_for_pid
, as such:
//Client(s):
//No error checks for brevity
mach_port_t port = MACH_PORT_NULL;
mach_port_t task;
task_for_pid(mach_task_self(), server_pid, &task); //I guess we get server_pid by daemon process name?
mach_port_allocate(task,
MACH_PORT_RIGHT_RECEIVE,
&port);
MACH_MSG_UINT32 msg = {};
msg.base.hdr.msgh_remote_port = _port;
msg.base.hdr.msgh_local_port = MACH_PORT_NULL;
msg.base.hdr.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MAKE_SEND);
msg.base.hdr.msgh_size = sizeof(msg.base);
msg.val = 0x12345678;
mach_msg(&msg.base.hdr,
MACH_SEND_MSG,
sizeof(msg),
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
But when I run the code above, the mach_msg
returns 0x10000003 or MACH_SEND_INVALID_DEST
.
What am I doing wrong?