Exemplo n.º 1
0
void ExceptionThread(mach_port_t port)
{
	Common::SetCurrentThreadName("Mach exception thread");
	#pragma pack(4)
	struct
	{
		mach_msg_header_t Head;
		NDR_record_t NDR;
		exception_type_t exception;
		mach_msg_type_number_t codeCnt;
		int64_t code[2];
		int flavor;
		mach_msg_type_number_t old_stateCnt;
		natural_t old_state[x86_THREAD_STATE64_COUNT];
		mach_msg_trailer_t trailer;
	} msg_in;

	struct
	{
		mach_msg_header_t Head;
		NDR_record_t NDR;
		kern_return_t RetCode;
		int flavor;
		mach_msg_type_number_t new_stateCnt;
		natural_t new_state[x86_THREAD_STATE64_COUNT];
	} msg_out;
	#pragma pack()
	memset(&msg_in, 0xee, sizeof(msg_in));
	memset(&msg_out, 0xee, sizeof(msg_out));
	mach_msg_header_t *send_msg = NULL;
	mach_msg_size_t send_size = 0;
	mach_msg_option_t option = MACH_RCV_MSG;
	while (1)
	{
		// If this isn't the first run, send the reply message.  Then, receive
		// a message: either a mach_exception_raise_state RPC due to
		// thread_set_exception_ports, or MACH_NOTIFY_NO_SENDERS due to
		// mach_port_request_notification.
		CheckKR("mach_msg_overwrite", mach_msg_overwrite(send_msg, option, send_size, sizeof(msg_in), port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL, &msg_in.Head, 0));

		if (msg_in.Head.msgh_id == MACH_NOTIFY_NO_SENDERS)
		{
			// the other thread exited
			mach_port_destroy(mach_task_self(), port);
			return;
		}

		if (msg_in.Head.msgh_id != 2406)
		{
			PanicAlertT("unknown message received");
			return;
		}

		if (msg_in.flavor != x86_THREAD_STATE64)
		{
			PanicAlertT("unknown flavor %d (expected %d)", msg_in.flavor, x86_THREAD_STATE64);
			return;
		}

		x86_thread_state64_t *state = (x86_thread_state64_t *) msg_in.old_state;

		bool ok = DoFault(msg_in.code[1], state);

		// Set up the reply.
		msg_out.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(msg_in.Head.msgh_bits), 0);
		msg_out.Head.msgh_remote_port = msg_in.Head.msgh_remote_port;
		msg_out.Head.msgh_local_port = MACH_PORT_NULL;
		msg_out.Head.msgh_id = msg_in.Head.msgh_id + 100;
		msg_out.NDR = msg_in.NDR;
		if (ok)
		{
			msg_out.RetCode = KERN_SUCCESS;
			msg_out.flavor = x86_THREAD_STATE64;
			msg_out.new_stateCnt = x86_THREAD_STATE64_COUNT;
			memcpy(msg_out.new_state, msg_in.old_state, x86_THREAD_STATE64_COUNT * sizeof(natural_t));
		}
		else
		{
			// Pass the exception to the next handler (debugger or crash).
			msg_out.RetCode = KERN_FAILURE;
			msg_out.flavor = 0;
			msg_out.new_stateCnt = 0;
		}
		msg_out.Head.msgh_size = offsetof(typeof(msg_out), new_state) + msg_out.new_stateCnt * sizeof(natural_t);

		send_msg = &msg_out.Head;
		send_size = msg_out.Head.msgh_size;
		option |= MACH_SEND_MSG;
	}
}
Exemplo n.º 2
0
ipc_kmsg_t
ipc_kobject_server(
	ipc_kmsg_t	request)
{
	mach_msg_size_t reply_size;
	ipc_kmsg_t reply;
	kern_return_t kr;
	ipc_port_t *destp;
	mach_msg_format_0_trailer_t *trailer;
	register mig_hash_t *ptr;

	/*
	 * Find out corresponding mig_hash entry if any
	 */
	{
	    register int key = request->ikm_header->msgh_id;
	    register int i = MIG_HASH(key);
	    register int max_iter = mig_table_max_displ;
	
	    do
		ptr = &mig_buckets[i++ % MAX_MIG_ENTRIES];
	    while (key != ptr->num && ptr->num && --max_iter);

	    if (!ptr->routine || key != ptr->num) {
	        ptr = (mig_hash_t *)0;
		reply_size = mig_reply_size;
	    } else {
		reply_size = ptr->size;
#if	MACH_COUNTER
		ptr->callcount++;
#endif
	    }
	}

	/* round up for trailer size */
        reply_size += MAX_TRAILER_SIZE;
	reply = ipc_kmsg_alloc(reply_size);

	if (reply == IKM_NULL) {
		printf("ipc_kobject_server: dropping request\n");
		ipc_kmsg_destroy(request);
		return IKM_NULL;
	}

	/*
	 * Initialize reply message.
	 */
	{
#define	InP	((mach_msg_header_t *) request->ikm_header)
#define	OutP	((mig_reply_error_t *) reply->ikm_header)

	    /* 
	     * MIG should really assure no data leakage -
	     * but until it does, pessimistically zero the
	     * whole reply buffer.
	     */
	    bzero((void *)OutP, reply_size);

	    OutP->NDR = NDR_record;
	    OutP->Head.msgh_size = sizeof(mig_reply_error_t);

	    OutP->Head.msgh_bits =
		MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
	    OutP->Head.msgh_remote_port = InP->msgh_local_port;
	    OutP->Head.msgh_local_port  = MACH_PORT_NULL;
	    OutP->Head.msgh_reserved = (mach_msg_size_t)InP->msgh_id; /* useful for debug */
	    OutP->Head.msgh_id = InP->msgh_id + 100;

#undef	InP
#undef	OutP
	}

	/*
	 * Find the routine to call, and call it
	 * to perform the kernel function
	 */
	{
	    if (ptr) {	
		(*ptr->routine)(request->ikm_header, reply->ikm_header);
		kernel_task->messages_received++;
	    }
	    else {
		if (!ipc_kobject_notify(request->ikm_header, reply->ikm_header)){
#if	MACH_IPC_TEST
		    printf("ipc_kobject_server: bogus kernel message, id=%d\n",
			request->ikm_header->msgh_id);
#endif	/* MACH_IPC_TEST */
		    _MIG_MSGID_INVALID(request->ikm_header->msgh_id);

		    ((mig_reply_error_t *) reply->ikm_header)->RetCode
			= MIG_BAD_ID;
		}
		else
		  kernel_task->messages_received++;
	    }
	    kernel_task->messages_sent++;
	}

	/*
	 *	Destroy destination. The following code differs from
	 *	ipc_object_destroy in that we release the send-once
	 *	right instead of generating a send-once notification
	 * 	(which would bring us here again, creating a loop).
	 *	It also differs in that we only expect send or
	 *	send-once rights, never receive rights.
	 *
	 *	We set msgh_remote_port to IP_NULL so that the kmsg
	 *	destroy routines don't try to destroy the port twice.
	 */
	destp = (ipc_port_t *) &request->ikm_header->msgh_remote_port;
	switch (MACH_MSGH_BITS_REMOTE(request->ikm_header->msgh_bits)) {
		case MACH_MSG_TYPE_PORT_SEND:
		    ipc_port_release_send(*destp);
		    break;
		
		case MACH_MSG_TYPE_PORT_SEND_ONCE:
		    ipc_port_release_sonce(*destp);
		    break;
		
		default:
		    panic("ipc_kobject_server: strange destination rights");
	}
	*destp = IP_NULL;

        if (!(reply->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
           ((mig_reply_error_t *) reply->ikm_header)->RetCode != KERN_SUCCESS)
	 	kr = ((mig_reply_error_t *) reply->ikm_header)->RetCode;
	else
		kr = KERN_SUCCESS;

	if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
		/*
		 *	The server function is responsible for the contents
		 *	of the message.  The reply port right is moved
		 *	to the reply message, and we have deallocated
		 *	the destination port right, so we just need
		 *	to free the kmsg.
		 */
		ipc_kmsg_free(request);

	} else {
		/*
		 *	The message contents of the request are intact.
		 *	Destroy everthing except the reply port right,
		 *	which is needed in the reply message.
		 */
		request->ikm_header->msgh_local_port = MACH_PORT_NULL;
		ipc_kmsg_destroy(request);
	}

	if (kr == MIG_NO_REPLY) {
		/*
		 *	The server function will send a reply message
		 *	using the reply port right, which it has saved.
		 */

		ipc_kmsg_free(reply);

		return IKM_NULL;
	} else if (!IP_VALID((ipc_port_t)reply->ikm_header->msgh_remote_port)) {
		/*
		 *	Can't queue the reply message if the destination
		 *	(the reply port) isn't valid.
		 */

		ipc_kmsg_destroy(reply);

		return IKM_NULL;
	}

 	trailer = (mach_msg_format_0_trailer_t *)
		((vm_offset_t)reply->ikm_header + (int)reply->ikm_header->msgh_size);

 	trailer->msgh_sender = KERNEL_SECURITY_TOKEN;
 	trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
 	trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;

	return reply;
}
Exemplo n.º 3
0
/* Routine substrated_mark */
mig_external kern_return_t substrated_mark
(
	mach_port_t server,
	vm_map_t task,
	mach_vm_address_t source_address,
	mach_vm_size_t source_size,
	mach_vm_address_t *target_address
)
{

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
	typedef struct {
		mach_msg_header_t Head;
		/* start of the kernel processed data */
		mach_msg_body_t msgh_body;
		mach_msg_port_descriptor_t task;
		/* end of the kernel processed data */
		NDR_record_t NDR;
		mach_vm_address_t source_address;
		mach_vm_size_t source_size;
		mach_vm_address_t target_address;
	} Request __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
	typedef struct {
		mach_msg_header_t Head;
		NDR_record_t NDR;
		kern_return_t RetCode;
		mach_vm_address_t target_address;
		mach_msg_trailer_t trailer;
	} Reply __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
	typedef struct {
		mach_msg_header_t Head;
		NDR_record_t NDR;
		kern_return_t RetCode;
		mach_vm_address_t target_address;
	} __Reply __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif
	/*
	 * typedef struct {
	 * 	mach_msg_header_t Head;
	 * 	NDR_record_t NDR;
	 * 	kern_return_t RetCode;
	 * } mig_reply_error_t;
	 */

	union {
		Request In;
		Reply Out;
	} Mess;

	Request *InP = &Mess.In;
	Reply *Out0P = &Mess.Out;

	mach_msg_return_t msg_result;

#ifdef	__MIG_check__Reply__substrated_mark_t__defined
	kern_return_t check_result;
#endif	/* __MIG_check__Reply__substrated_mark_t__defined */

	__DeclareSendRpc(9000, "substrated_mark")

#if	UseStaticTemplates
	const static mach_msg_port_descriptor_t taskTemplate = {
		/* name = */		MACH_PORT_NULL,
		/* pad1 = */		0,
		/* pad2 = */		0,
		/* disp = */		19,
		/* type = */		MACH_MSG_PORT_DESCRIPTOR,
	};
#endif	/* UseStaticTemplates */

	InP->msgh_body.msgh_descriptor_count = 1;
#if	UseStaticTemplates
	InP->task = taskTemplate;
	InP->task.name = task;
#else	/* UseStaticTemplates */
	InP->task.name = task;
	InP->task.disposition = 19;
	InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
#endif	/* UseStaticTemplates */

	InP->NDR = NDR_record;

	InP->source_address = source_address;

	InP->source_size = source_size;

	InP->target_address = *target_address;

	InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
		MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
	/* msgh_size passed as argument */
	InP->Head.msgh_request_port = server;
	InP->Head.msgh_reply_port = mig_get_reply_port();
	InP->Head.msgh_id = 9000;
	InP->Head.msgh_reserved = 0;
	
/* BEGIN VOUCHER CODE */

#ifdef USING_VOUCHERS
	if (voucher_mach_msg_set != NULL) {
		voucher_mach_msg_set(&InP->Head);
	}
#endif // USING_VOUCHERS
	
/* END VOUCHER CODE */

	__BeforeSendRpc(9000, "substrated_mark")
	msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request), (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
	__AfterSendRpc(9000, "substrated_mark")
	if (msg_result != MACH_MSG_SUCCESS) {
		__MachMsgErrorWithoutTimeout(msg_result);
		{ return msg_result; }
	}


#if	defined(__MIG_check__Reply__substrated_mark_t__defined)
	check_result = __MIG_check__Reply__substrated_mark_t((__Reply__substrated_mark_t *)Out0P);
	if (check_result != MACH_MSG_SUCCESS)
		{ return check_result; }
#endif	/* defined(__MIG_check__Reply__substrated_mark_t__defined) */

	*target_address = Out0P->target_address;

	return KERN_SUCCESS;
}
Exemplo n.º 4
0
/* Routine mach_exception_raise_state */
mig_external kern_return_t mach_exception_raise_state
(
	mach_port_t exception_port,
	exception_type_t exception,
	const mach_exception_data_t code,
	mach_msg_type_number_t codeCnt,
	int *flavor,
	const thread_state_t old_state,
	mach_msg_type_number_t old_stateCnt,
	thread_state_t new_state,
	mach_msg_type_number_t *new_stateCnt
)
{

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
	typedef struct {
		mach_msg_header_t Head;
		NDR_record_t NDR;
		exception_type_t exception;
		mach_msg_type_number_t codeCnt;
		int64_t code[2];
		int flavor;
		mach_msg_type_number_t old_stateCnt;
		natural_t old_state[224];
	} Request __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
	typedef struct {
		mach_msg_header_t Head;
		NDR_record_t NDR;
		kern_return_t RetCode;
		int flavor;
		mach_msg_type_number_t new_stateCnt;
		natural_t new_state[224];
		mach_msg_trailer_t trailer;
	} Reply __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
	typedef struct {
		mach_msg_header_t Head;
		NDR_record_t NDR;
		kern_return_t RetCode;
		int flavor;
		mach_msg_type_number_t new_stateCnt;
		natural_t new_state[224];
	} __Reply __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif
	/*
	 * typedef struct {
	 * 	mach_msg_header_t Head;
	 * 	NDR_record_t NDR;
	 * 	kern_return_t RetCode;
	 * } mig_reply_error_t;
	 */

	union {
		Request In;
		Reply Out;
	} Mess;

	Request *InP = &Mess.In;
	Reply *Out0P = &Mess.Out;

	mach_msg_return_t msg_result;
	unsigned int msgh_size;
	unsigned int msgh_size_delta;


#ifdef	__MIG_check__Reply__mach_exception_raise_state_t__defined
	kern_return_t check_result;
#endif	/* __MIG_check__Reply__mach_exception_raise_state_t__defined */

	__DeclareSendRpc(2406, "mach_exception_raise_state")

	InP->NDR = NDR_record;

	InP->exception = exception;

	if (codeCnt > 2) {
		{ return MIG_ARRAY_TOO_LARGE; }
	}
	(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);

	InP->codeCnt = codeCnt;

	msgh_size_delta = (8 * codeCnt);
	msgh_size = (mach_msg_size_t)(sizeof(Request) - 912) + msgh_size_delta;
	InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16);

	InP->flavor = *flavor;

	if (old_stateCnt > 224) {
		{ return MIG_ARRAY_TOO_LARGE; }
	}
	(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);

	InP->old_stateCnt = old_stateCnt;

	msgh_size += (4 * old_stateCnt);
	InP = &Mess.In;
	InP->Head.msgh_bits =
		MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
	/* msgh_size passed as argument */
	InP->Head.msgh_request_port = exception_port;
	InP->Head.msgh_reply_port = mig_get_reply_port();
	InP->Head.msgh_id = 2406;
	
/* BEGIN VOUCHER CODE */

#ifdef USING_VOUCHERS
	if (voucher_mach_msg_set != NULL) {
		voucher_mach_msg_set(&InP->Head);
	}
#endif // USING_VOUCHERS
	
/* END VOUCHER CODE */

	__BeforeSendRpc(2406, "mach_exception_raise_state")
	msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
	__AfterSendRpc(2406, "mach_exception_raise_state")
	if (msg_result != MACH_MSG_SUCCESS) {
		__MachMsgErrorWithoutTimeout(msg_result);
		{ return msg_result; }
	}


#if	defined(__MIG_check__Reply__mach_exception_raise_state_t__defined)
	check_result = __MIG_check__Reply__mach_exception_raise_state_t((__Reply__mach_exception_raise_state_t *)Out0P);
	if (check_result != MACH_MSG_SUCCESS)
		{ return check_result; }
#endif	/* defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */

	*flavor = Out0P->flavor;

	if (Out0P->new_stateCnt > 224) {
		(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 *  224);
		*new_stateCnt = Out0P->new_stateCnt;
		{ return MIG_ARRAY_TOO_LARGE; }
	}
	(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);

	*new_stateCnt = Out0P->new_stateCnt;

	return KERN_SUCCESS;
}
Exemplo n.º 5
0
/* Routine mach_exception_raise_state_identity */
mig_external kern_return_t mach_exception_raise_state_identity
(
	mach_port_t exception_port,
	mach_port_t thread,
	mach_port_t task,
	exception_type_t exception,
	mach_exception_data_t code,
	mach_msg_type_number_t codeCnt,
	int *flavor,
	thread_state_t old_state,
	mach_msg_type_number_t old_stateCnt,
	thread_state_t new_state,
	mach_msg_type_number_t *new_stateCnt
)
{

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
	typedef struct {
		mach_msg_header_t Head;
		/* start of the kernel processed data */
		mach_msg_body_t msgh_body;
		mach_msg_port_descriptor_t thread;
		mach_msg_port_descriptor_t task;
		/* end of the kernel processed data */
		NDR_record_t NDR;
		exception_type_t exception;
		mach_msg_type_number_t codeCnt;
		int64_t code[2];
		int flavor;
		mach_msg_type_number_t old_stateCnt;
		natural_t old_state[224];
	} Request __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
	typedef struct {
		mach_msg_header_t Head;
		NDR_record_t NDR;
		kern_return_t RetCode;
		int flavor;
		mach_msg_type_number_t new_stateCnt;
		natural_t new_state[224];
		mach_msg_trailer_t trailer;
	} Reply __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
	typedef struct {
		mach_msg_header_t Head;
		NDR_record_t NDR;
		kern_return_t RetCode;
		int flavor;
		mach_msg_type_number_t new_stateCnt;
		natural_t new_state[224];
	} __Reply __attribute__((unused));
#ifdef  __MigPackStructs
#pragma pack()
#endif
	/*
	 * typedef struct {
	 * 	mach_msg_header_t Head;
	 * 	NDR_record_t NDR;
	 * 	kern_return_t RetCode;
	 * } mig_reply_error_t;
	 */

	union {
		Request In;
		Reply Out;
	} Mess;

	Request *InP = &Mess.In;
	Reply *Out0P = &Mess.Out;

	mach_msg_return_t msg_result;
	unsigned int msgh_size;
	unsigned int msgh_size_delta;


#ifdef	__MIG_check__Reply__mach_exception_raise_state_identity_t__defined
	kern_return_t check_result;
#endif	/* __MIG_check__Reply__mach_exception_raise_state_identity_t__defined */

	__DeclareSendRpc(2407, "mach_exception_raise_state_identity")

#if	UseStaticTemplates
	const static mach_msg_port_descriptor_t threadTemplate = {
		/* name = */		MACH_PORT_NULL,
		/* pad1 = */		0,
		/* pad2 = */		0,
		/* disp = */		19,
		/* type = */		MACH_MSG_PORT_DESCRIPTOR,
	};
#endif	/* UseStaticTemplates */

#if	UseStaticTemplates
	const static mach_msg_port_descriptor_t taskTemplate = {
		/* name = */		MACH_PORT_NULL,
		/* pad1 = */		0,
		/* pad2 = */		0,
		/* disp = */		19,
		/* type = */		MACH_MSG_PORT_DESCRIPTOR,
	};
#endif	/* UseStaticTemplates */

	InP->msgh_body.msgh_descriptor_count = 2;
#if	UseStaticTemplates
	InP->thread = threadTemplate;
	InP->thread.name = thread;
#else	/* UseStaticTemplates */
	InP->thread.name = thread;
	InP->thread.disposition = 19;
	InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
#endif	/* UseStaticTemplates */

#if	UseStaticTemplates
	InP->task = taskTemplate;
	InP->task.name = task;
#else	/* UseStaticTemplates */
	InP->task.name = task;
	InP->task.disposition = 19;
	InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
#endif	/* UseStaticTemplates */

	InP->NDR = NDR_record;

	InP->exception = exception;

	if (codeCnt > 2) {
		{ return MIG_ARRAY_TOO_LARGE; }
	}
	(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);

	InP->codeCnt = codeCnt;

	msgh_size_delta = (8 * codeCnt);
	msgh_size = (mach_msg_size_t)(sizeof(Request) - 912) + msgh_size_delta;
	InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16);

	InP->flavor = *flavor;

	if (old_stateCnt > 224) {
		{ return MIG_ARRAY_TOO_LARGE; }
	}
	(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);

	InP->old_stateCnt = old_stateCnt;

	msgh_size += (4 * old_stateCnt);
	InP = &Mess.In;
	InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
		MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
	/* msgh_size passed as argument */
	InP->Head.msgh_request_port = exception_port;
	InP->Head.msgh_reply_port = mig_get_reply_port();
	InP->Head.msgh_id = 2407;
	
/* BEGIN VOUCHER CODE */

#ifdef USING_VOUCHERS
	if (voucher_mach_msg_set != NULL) {
		voucher_mach_msg_set(&InP->Head);
	}
#endif // USING_VOUCHERS
	
/* END VOUCHER CODE */

	__BeforeSendRpc(2407, "mach_exception_raise_state_identity")
	msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
	__AfterSendRpc(2407, "mach_exception_raise_state_identity")
	if (msg_result != MACH_MSG_SUCCESS) {
		__MachMsgErrorWithoutTimeout(msg_result);
		{ return msg_result; }
	}


#if	defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined)
	check_result = __MIG_check__Reply__mach_exception_raise_state_identity_t((__Reply__mach_exception_raise_state_identity_t *)Out0P);
	if (check_result != MACH_MSG_SUCCESS)
		{ return check_result; }
#endif	/* defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */

	*flavor = Out0P->flavor;

	if (Out0P->new_stateCnt > 224) {
		(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 *  224);
		*new_stateCnt = Out0P->new_stateCnt;
		{ return MIG_ARRAY_TOO_LARGE; }
	}
	(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);

	*new_stateCnt = Out0P->new_stateCnt;

	return KERN_SUCCESS;
}
Exemplo n.º 6
0
/* Send signal SIGNO to MSGPORT with REFPORT as reference.  Don't
   block in any fashion.  */
void
send_signal (mach_port_t msgport,
	     int signal,
	     mach_port_t refport)
{
  error_t err;

  /* This message buffer might be modified by mach_msg in some error cases,
     so we cannot safely use a shared static buffer.  */
  struct msg_sig_post_request message =
  {
    {
      /* Message header: */
      (MACH_MSGH_BITS_COMPLEX
       | MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND,
			 MACH_MSG_TYPE_MAKE_SEND_ONCE)), /* msgh_bits */
      sizeof message,		/* msgh_size */
      msgport,			/* msgh_remote_port */
      MACH_PORT_NULL,		/* msgh_local_port */
      0,			/* msgh_seqno */
      RPCID_SIG_POST,		/* msgh_id */
    },
    {
      /* Type descriptor for signo */
      MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
      32,			/* msgt_size */
      1,			/* msgt_number */
      1,			/* msgt_inline */
      0,			/* msgt_longform */
      0,			/* msgt_deallocate */
      0,			/* msgt_unused */
    },
    /* Signal number */
    signal,
    /* Type descriptor for sigcode */
    {
      MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
      32,			/* msgt_size */
      1,			/* msgt_number */
      1,			/* msgt_inline */
      0,			/* msgt_longform */
      0,			/* msgt_deallocate */
      0,			/* msgt_unused */
    },
    /* Sigcode */
    0,
    {
      /* Type descriptor for refport */
      MACH_MSG_TYPE_COPY_SEND, /* msgt_name */
      32,			/* msgt_size */
      1,			/* msgt_number */
      1,			/* msgt_inline */
      0,			/* msgt_longform */
      0,			/* msgt_deallocate */
      0,			/* msgt_unused */
    },
    refport
  };

  err = mach_msg ((mach_msg_header_t *)&message,
		  MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof message, 0,
		  MACH_PORT_NULL, 0, MACH_PORT_NULL);
  switch (err)
    {
    case MACH_SEND_TIMED_OUT:
      /* The send could not complete immediately, and we do not want to
	 block.  We'll fork off another thread to do the blocking send.
	 The message buffer was modified by a pseudo-receive operation, so
	 we need to copy its modified contents into a malloc'd buffer.  */
      {
	struct msg_sig_post_request *copy = malloc (sizeof *copy);
	if (copy)
	  {
	    memcpy (copy, &message, sizeof message);
	    cthread_detach (cthread_fork (blocking_message_send, copy));
	  }
	break;
      }

      /* These are the other codes that mean a pseudo-receive modified
	 the message buffer and we might need to clean up the send rights.
	 None of them should be possible in our usage.  */
    case MACH_SEND_INTERRUPTED:
    case MACH_SEND_INVALID_NOTIFY:
    case MACH_SEND_NO_NOTIFY:
    case MACH_SEND_NOTIFY_IN_PROGRESS:
      assert_perror (err);
      break;

    default:			/* Other errors are safe to ignore.  */
      break;
    }
}
Exemplo n.º 7
0
Arquivo: IPC.c Projeto: aosm/Startup
static void* handleIPCMessage (void* aMsgParam, CFIndex aMessageSize, CFAllocatorRef anAllocator, void* aMachPort)
{
    SystemStarterIPCMessage*     aMessage = (SystemStarterIPCMessage*) aMsgParam;
    SystemStarterIPCMessage*     aReplyMessage = NULL;
    
    CFDataRef aResult = NULL;
    CFDataRef aData = NULL;

    if (aMessage->aHeader.msgh_bits & MACH_MSGH_BITS_COMPLEX)
      {
        warning(CFSTR("Ignoring out-of-line IPC message.\n"));
        return NULL;
      }
    else
      {
        mach_msg_security_trailer_t* aSecurityTrailer = (mach_msg_security_trailer_t*)
        ((uint8_t*)aMessage + round_msg(sizeof(SystemStarterIPCMessage) + aMessage->aByteLength));

        /* CFRunLoop includes the format 0 message trailer with the passed message. */
        if (aSecurityTrailer->msgh_trailer_type == MACH_MSG_TRAILER_FORMAT_0 &&
            aSecurityTrailer->msgh_sender.val[0] != 0)
          {
            warning(CFSTR("Ignoring IPC message sent from uid %d\n."), aSecurityTrailer->msgh_sender.val[0]);
            return NULL;
          }
      }

    if (aMessage->aProtocol != kIPCProtocolVersion)
      {
        warning(CFSTR("Unsupported IPC protocol version number: %d.  Message ignored.\n"), aMessage->aProtocol);
        return NULL;
      }

    aData = CFDataCreateWithBytesNoCopy(NULL,
                                        (uint8_t*)aMessage + sizeof(SystemStarterIPCMessage),
                                        aMessage->aByteLength,
                                        kCFAllocatorNull);
    /*
     * Dispatch the IPC message.
     */
    if (aData)
      {
        StartupContext	aStartupContext = NULL;
        CFStringRef	anErrorString   = NULL;
        CFDictionaryRef	anIPCMessage    = (CFDictionaryRef) CFPropertyListCreateFromXMLData(NULL, aData, kCFPropertyListImmutable, &anErrorString);
        
        if (gDebugFlag == 2) debug(CFSTR("\nIPC message = %@\n"), anIPCMessage);

        if (aMachPort)
          {
            CFMachPortContext aMachPortContext;
            CFMachPortGetContext((CFMachPortRef)aMachPort, &aMachPortContext);
            aStartupContext = (StartupContext)aMachPortContext.info;
          }
        
        if (anIPCMessage && CFGetTypeID(anIPCMessage) == CFDictionaryGetTypeID())
          {
            /* switch on the type of the IPC message */
            CFStringRef anIPCMessageType = CFDictionaryGetValue(anIPCMessage, kIPCMessageKey);
            if (anIPCMessageType && CFGetTypeID(anIPCMessageType) == CFStringGetTypeID())
              {
                if (CFEqual(anIPCMessageType, kIPCConsoleMessage))
                  {
                    consoleMessage(aStartupContext, anIPCMessage);
                  }
                else if (CFEqual(anIPCMessageType, kIPCStatusMessage))
                  {
                    statusMessage(aStartupContext, anIPCMessage);
                  }
                else if (CFEqual(anIPCMessageType, kIPCQueryMessage))
                  {
                    aResult = queryConfigSetting(aStartupContext, anIPCMessage);
                  }
                else if (CFEqual(anIPCMessageType, kIPCLoadDisplayBundleMessage))
                  {
                    loadDisplayBundle(aStartupContext, anIPCMessage);
                  }
                else if (CFEqual(anIPCMessageType, kIPCUnloadDisplayBundleMessage))
                  {
                    unloadDisplayBundle(aStartupContext, anIPCMessage);
                  }
              }
          }
        else
          {
            error(CFSTR("Unable to parse IPC message: %@\n"), anErrorString);
          }
        CFRelease(aData);
      }
    else
      {
        error(CFSTR("Out of memory.  Could not allocate space for IPC message.\n"));
      }

    /*
     * Generate a Mach message for the result data.
     */
    if (!aResult) aResult = CFDataCreateWithBytesNoCopy(NULL, "", 1, kCFAllocatorNull);
    if (aResult)
    {
        CFIndex aDataSize = CFDataGetLength(aResult);
        CFIndex aReplyMessageSize = round_msg(sizeof(SystemStarterIPCMessage) + aDataSize + 3);
        aReplyMessage = CFAllocatorAllocate(kCFAllocatorSystemDefault, aReplyMessageSize, 0);
        if (aReplyMessage)
          {
            aReplyMessage->aHeader.msgh_id = -1 * (SInt32)aMessage->aHeader.msgh_id;
            aReplyMessage->aHeader.msgh_size = aReplyMessageSize;
            aReplyMessage->aHeader.msgh_remote_port = aMessage->aHeader.msgh_remote_port;
            aReplyMessage->aHeader.msgh_local_port = MACH_PORT_NULL;
            aReplyMessage->aHeader.msgh_reserved = 0;
            aReplyMessage->aHeader.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0);
            aReplyMessage->aBody.msgh_descriptor_count = 0;
            aReplyMessage->aProtocol = kIPCProtocolVersion;
            aReplyMessage->aByteLength = CFDataGetLength(aResult);
            memmove((uint8_t*)aReplyMessage + sizeof(SystemStarterIPCMessage),
                    CFDataGetBytePtr(aResult),
                    CFDataGetLength(aResult));
          }
        CFRelease(aResult);
    }
    if (!aReplyMessage)
      {
        error(CFSTR("Out of memory.  Could not allocate IPC result.\n"));
      }
    return aReplyMessage;
}
Exemplo n.º 8
0
void profile_thread() 
{
	struct message {
		mach_msg_header_t	head;
		mach_msg_type_t		type;
		int			arg[SIZE_PROF_BUFFER+1];
	} msg;

	register spl_t	s;
	buf_to_send_t	buf_entry;
	queue_entry_t	prof_queue_entry;
	prof_data_t	pbuf;
	simple_lock_t 	lock;
	msg_return_t 	mr;
	int		j;

	/* Initialise the queue header for the prof_queue */
	mpqueue_init(&prof_queue);

	/* Template initialisation of header and type structures */
	msg.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
	msg.head.msgh_size = sizeof(msg); 
	msg.head.msgh_local_port = MACH_PORT_NULL;
	msg.head.msgh_kind = MACH_MSGH_KIND_NORMAL;
	msg.head.msgh_id = 666666;
	
	msg.type.msgt_name = MACH_MSG_TYPE_INTEGER_32;
	msg.type.msgt_size = 32;
	msg.type.msgt_number = SIZE_PROF_BUFFER+1;
	msg.type.msgt_inline = TRUE;
	msg.type.msgt_longform = FALSE;
	msg.type.msgt_deallocate = FALSE;
	msg.type.msgt_unused = 0;

	while (TRUE) {

	   /* Dequeue the first buffer. */
	   s = splsched();
	   mpdequeue_head(&prof_queue, &prof_queue_entry);
	   splx(s);

	   if ((buf_entry = (buf_to_send_t) prof_queue_entry) == NULLBTS)
                { 
		thread_sleep((event_t) profile_thread, lock, TRUE);
		if (current_thread()->wait_result != THREAD_AWAKENED)
			break;
                }
	   else {
		task_t		curr_task;
                thread_t	curr_th;
		register int 	*sample;
                int 		curr_buf;
		int 		imax;

                curr_th = (thread_t) buf_entry->thread;
                curr_buf = (int) buf_entry->number; 
		pbuf = curr_th->profil_buffer;

		/* Set the remote port */
		msg.head.msgh_remote_port = (mach_port_t) pbuf->prof_port;

                 
                sample = pbuf->prof_area[curr_buf].p_zone;
	        imax = pbuf->prof_area[curr_buf].p_index;
	        for(j=0 ;j<imax; j++,sample++)
		msg.arg[j] = *sample;	

	        /* Let hardclock() know you've finished the dirty job */
	        pbuf->prof_area[curr_buf].p_full = FALSE;

	        /*
		 * Store the number of samples actually sent 
	         * as the last element of the array.
		 */
	        msg.arg[SIZE_PROF_BUFFER] = imax;

	        mr = mach_msg(&(msg.head), MACH_SEND_MSG, 
			            sizeof(struct message), 0, 
				    MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, 
				    MACH_PORT_NULL);

		if (mr != MACH_MSG_SUCCESS) {
printf("profile_thread: mach_msg failed returned %x\n",(int)mr);
		}

		if (buf_entry->wakeme)
			thread_wakeup((event_t) &buf_entry->wakeme);
		kmem_free(kernel_map, (buf_to_send_t) buf_entry,
					sizeof(struct buf_to_send));

            }

        }
	/* The profile thread has been signalled to exit.  There may still
	   be sample data queued for us, which we must now throw away.
	   Once we set profile_thread_id to null, hardclock() will stop
	   queueing any additional samples, so we do not need to alter
	   the interrupt level.  */
	profile_thread_id = THREAD_NULL;
	while (1) {
		mpdequeue_head(&prof_queue, &prof_queue_entry);
		if ((buf_entry = (buf_to_send_t) prof_queue_entry) == NULLBTS)
			break;
		if (buf_entry->wakeme)
			thread_wakeup((event_t) &buf_entry->wakeme);
		kmem_free(kernel_map, (buf_to_send_t) buf_entry,
					sizeof(struct buf_to_send));
	}

	thread_halt_self();
}
Exemplo n.º 9
0
bool Connection::sendOutgoingMessage(MessageID messageID, PassOwnPtr<MessageEncoder> encoder)
{
    Vector<Attachment> attachments = encoder->releaseAttachments();

    size_t numberOfPortDescriptors = 0;
    size_t numberOfOOLMemoryDescriptors = 0;
    for (size_t i = 0; i < attachments.size(); ++i) {
        Attachment::Type type = attachments[i].type();
        if (type == Attachment::MachPortType)
            numberOfPortDescriptors++;
        else if (type == Attachment::MachOOLMemoryType)
            numberOfOOLMemoryDescriptors++;
    }

    size_t messageSize = machMessageSize(encoder->bufferSize(), numberOfPortDescriptors, numberOfOOLMemoryDescriptors);
    char buffer[inlineMessageMaxSize];

    bool messageBodyIsOOL = false;
    if (messageSize > sizeof(buffer)) {
        messageBodyIsOOL = true;

        attachments.append(Attachment(encoder->buffer(), encoder->bufferSize(), MACH_MSG_VIRTUAL_COPY, false));
        numberOfOOLMemoryDescriptors++;
        messageSize = machMessageSize(0, numberOfPortDescriptors, numberOfOOLMemoryDescriptors);
    }

    bool isComplex = (numberOfPortDescriptors + numberOfOOLMemoryDescriptors > 0);

    mach_msg_header_t* header = reinterpret_cast<mach_msg_header_t*>(&buffer);
    header->msgh_bits = isComplex ? MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND | MACH_MSGH_BITS_COMPLEX, 0) : MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
    header->msgh_size = messageSize;
    header->msgh_remote_port = m_sendPort;
    header->msgh_local_port = MACH_PORT_NULL;
    header->msgh_id = messageID.toInt();
    if (messageBodyIsOOL)
        header->msgh_id |= MessageBodyIsOOL;

    uint8_t* messageData;

    if (isComplex) {
        mach_msg_body_t* body = reinterpret_cast<mach_msg_body_t*>(header + 1);
        body->msgh_descriptor_count = numberOfPortDescriptors + numberOfOOLMemoryDescriptors;

        uint8_t* descriptorData = reinterpret_cast<uint8_t*>(body + 1);
        for (size_t i = 0; i < attachments.size(); ++i) {
            Attachment attachment = attachments[i];

            mach_msg_descriptor_t* descriptor = reinterpret_cast<mach_msg_descriptor_t*>(descriptorData);
            switch (attachment.type()) {
            case Attachment::MachPortType:
                descriptor->port.name = attachment.port();
                descriptor->port.disposition = attachment.disposition();
                descriptor->port.type = MACH_MSG_PORT_DESCRIPTOR;

                descriptorData += sizeof(mach_msg_port_descriptor_t);
                break;
            case Attachment::MachOOLMemoryType:
                descriptor->out_of_line.address = attachment.address();
                descriptor->out_of_line.size = attachment.size();
                descriptor->out_of_line.copy = attachment.copyOptions();
                descriptor->out_of_line.deallocate = attachment.deallocate();
                descriptor->out_of_line.type = MACH_MSG_OOL_DESCRIPTOR;

                descriptorData += sizeof(mach_msg_ool_descriptor_t);
                break;
            default:
                ASSERT_NOT_REACHED();
            }
        }

        messageData = descriptorData;
    } else
        messageData = (uint8_t*)(header + 1);

    // Copy the data if it is not being sent out-of-line.
    if (!messageBodyIsOOL)
        memcpy(messageData, encoder->buffer(), encoder->bufferSize());

    ASSERT(m_sendPort);

    // Send the message.
    kern_return_t kr = mach_msg(header, MACH_SEND_MSG, messageSize, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
    if (kr != KERN_SUCCESS) {
        // FIXME: What should we do here?
    }

    return true;
}
Exemplo n.º 10
0
/* SimpleRoutine mach_notify_port_destroyed */
mig_external kern_return_t _dispatch_send_mach_notify_port_destroyed
(
    mach_port_t _notify,
    mach_port_t _rights
)
{

#ifdef  __MigPackStructs
#pragma pack(4)
#endif
    typedef struct {
        mach_msg_header_t Head;
        /* start of the kernel processed data */
        mach_msg_body_t msgh_body;
        mach_msg_port_descriptor_t _rights;
        /* end of the kernel processed data */
    } Request;
#ifdef  __MigPackStructs
#pragma pack()
#endif
    /*
     * typedef struct {
     * 	mach_msg_header_t Head;
     * 	NDR_record_t NDR;
     * 	kern_return_t RetCode;
     * } mig_reply_error_t;
     */

    union {
        Request In;
    } Mess;

    Request *InP = &Mess.In;

    mach_msg_return_t msg_result;

#ifdef	__MIG_check__Reply__mach_notify_port_destroyed_t__defined
    kern_return_t check_result;
#endif	/* __MIG_check__Reply__mach_notify_port_destroyed_t__defined */

    __DeclareSendSimple(69, "mach_notify_port_destroyed")

#if	UseStaticTemplates
    const static mach_msg_port_descriptor_t _rightsTemplate = {
        /* name = */		MACH_PORT_NULL,
        /* pad1 = */		0,
        /* pad2 = */		0,
        /* disp = */		16,
        /* type = */		MACH_MSG_PORT_DESCRIPTOR,
    };
#endif	/* UseStaticTemplates */

    InP->msgh_body.msgh_descriptor_count = 1;
#if	UseStaticTemplates
    InP->_rights = _rightsTemplate;
    InP->_rights.name = _rights;
#else	/* UseStaticTemplates */
    InP->_rights.name = _rights;
    InP->_rights.disposition = 16;
    InP->_rights.type = MACH_MSG_PORT_DESCRIPTOR;
#endif	/* UseStaticTemplates */

    InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
        MACH_MSGH_BITS(18, 0);
    /* msgh_size passed as argument */
    InP->Head.msgh_request_port = _notify;
    InP->Head.msgh_reply_port = MACH_PORT_NULL;
    InP->Head.msgh_id = 69;

    __BeforeSendSimple(69, "mach_notify_port_destroyed")
    msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
    __AfterSendSimple(69, "mach_notify_port_destroyed")
    return msg_result;
}