/* * Routine: ipc_mqueue_peek * Purpose: * Peek at a (non-set) message queue to see if it has a message * matching the sequence number provided (if zero, then the * first message in the queue) and return vital info about the * message. * * Conditions: * Locks may be held by callers, so this routine cannot block. * Caller holds reference on the message queue. */ unsigned ipc_mqueue_peek(ipc_mqueue_t mq, mach_port_seqno_t *seqnop, mach_msg_size_t *msg_sizep, mach_msg_id_t *msg_idp, mach_msg_max_trailer_t *msg_trailerp) { ipc_kmsg_queue_t kmsgq; ipc_kmsg_t kmsg; mach_port_seqno_t seqno, msgoff; int res = 0; spl_t s; assert(!imq_is_set(mq)); s = splsched(); imq_lock(mq); seqno = (seqnop != NULL) ? seqno = *seqnop : 0; if (seqno == 0) { seqno = mq->imq_seqno; msgoff = 0; } else if (seqno >= mq->imq_seqno && seqno < mq->imq_seqno + mq->imq_msgcount) { msgoff = seqno - mq->imq_seqno; } else goto out; /* look for the message that would match that seqno */ kmsgq = &mq->imq_messages; kmsg = ipc_kmsg_queue_first(kmsgq); while (msgoff-- && kmsg != IKM_NULL) { kmsg = ipc_kmsg_queue_next(kmsgq, kmsg); } if (kmsg == IKM_NULL) goto out; /* found one - return the requested info */ if (seqnop != NULL) *seqnop = seqno; if (msg_sizep != NULL) *msg_sizep = kmsg->ikm_header->msgh_size; if (msg_idp != NULL) *msg_idp = kmsg->ikm_header->msgh_id; if (msg_trailerp != NULL) memcpy(msg_trailerp, (mach_msg_max_trailer_t *)((vm_offset_t)kmsg->ikm_header + round_msg(kmsg->ikm_header->msgh_size)), sizeof(mach_msg_max_trailer_t)); res = 1; out: imq_unlock(mq); splx(s); return res; }
static inline size_t machMessageSize(size_t bodySize, size_t numberOfPortDescriptors = 0, size_t numberOfOOLMemoryDescriptors = 0) { size_t size = sizeof(mach_msg_header_t) + bodySize; if (numberOfPortDescriptors || numberOfOOLMemoryDescriptors) { size += sizeof(mach_msg_body_t); if (numberOfPortDescriptors) size += (numberOfPortDescriptors * sizeof(mach_msg_port_descriptor_t)); if (numberOfOOLMemoryDescriptors) size += (numberOfOOLMemoryDescriptors * sizeof(mach_msg_ool_ports_descriptor_t)); } return round_msg(size); }
size_t MachMessage::messageSize(size_t bodySize, size_t portDescriptorCount, size_t memoryDescriptorCount) { size_t messageSize = sizeof(mach_msg_header_t) + bodySize; if (portDescriptorCount || memoryDescriptorCount) { messageSize += sizeof(mach_msg_body_t); if (portDescriptorCount) messageSize += (portDescriptorCount * sizeof(mach_msg_port_descriptor_t)); if (memoryDescriptorCount) messageSize += (memoryDescriptorCount * sizeof(mach_msg_ool_descriptor_t)); } return round_msg(messageSize); }
mach_msg_return_t msg_receive_error( ipc_kmsg_t kmsg, mach_vm_address_t msg_addr, mach_msg_option_t option, mach_port_seqno_t seqno, ipc_space_t space) { mach_vm_address_t context; mach_msg_trailer_size_t trailer_size; mach_msg_max_trailer_t *trailer; context = kmsg->ikm_header->msgh_remote_port->ip_context; /* * Copy out the destination port in the message. * Destroy all other rights and memory in the message. */ ipc_kmsg_copyout_dest(kmsg, space); /* * Build a minimal message with the requested trailer. */ trailer = (mach_msg_max_trailer_t *) ((vm_offset_t)kmsg->ikm_header + round_msg(sizeof(mach_msg_header_t))); kmsg->ikm_header->msgh_size = sizeof(mach_msg_header_t); bcopy( (char *)&trailer_template, (char *)trailer, sizeof(trailer_template)); trailer_size = ipc_kmsg_add_trailer(kmsg, space, option, current_thread(), seqno, TRUE, context); /* * Copy the message to user space */ if (ipc_kmsg_put(msg_addr, kmsg, kmsg->ikm_header->msgh_size + trailer_size) == MACH_RCV_INVALID_DATA) return(MACH_RCV_INVALID_DATA); else return(MACH_MSG_SUCCESS); }
/* Routine Query */ mig_external kern_return_t libinfoDSmig_Query ( mach_port_t server, int32_t proc, inline_data_t request, mach_msg_type_number_t requestCnt, inline_data_t reply, mach_msg_type_number_t *replyCnt, vm_offset_t *ooreply, mach_msg_type_number_t *ooreplyCnt, security_token_t *usertoken ) { #ifdef __MigPackStructs #pragma pack(4) #endif typedef struct { mach_msg_header_t Head; NDR_record_t NDR; int32_t proc; mach_msg_type_number_t requestCnt; char request[16384]; } Request; #ifdef __MigPackStructs #pragma pack() #endif #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_ool_descriptor_t ooreply; /* end of the kernel processed data */ NDR_record_t NDR; mach_msg_type_number_t replyCnt; char reply[16384]; mach_msg_type_number_t ooreplyCnt; mach_msg_max_trailer_t trailer; } Reply; #ifdef __MigPackStructs #pragma pack() #endif #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_ool_descriptor_t ooreply; /* end of the kernel processed data */ NDR_record_t NDR; mach_msg_type_number_t replyCnt; char reply[16384]; mach_msg_type_number_t ooreplyCnt; } __Reply; #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; Reply *Out1P = NULL; mach_msg_return_t msg_result; unsigned int msgh_size; mach_msg_max_trailer_t *TrailerP; #if __MigTypeCheck unsigned int trailer_size; #endif /* __MigTypeCheck */ #ifdef __MIG_check__Reply__Query_t__defined kern_return_t check_result; #endif /* __MIG_check__Reply__Query_t__defined */ __DeclareSendRpc(50001, "Query") InP->NDR = NDR_record; InP->proc = proc; if (requestCnt > 16384) { { return MIG_ARRAY_TOO_LARGE; } } (void)memcpy((char *) InP->request, (const char *) request, requestCnt); InP->requestCnt = requestCnt; msgh_size = (mach_msg_size_t)(sizeof(Request) - 16384) + (_WALIGN_(requestCnt)); InP->Head.msgh_bits = 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 = 50001; __BeforeSendRpc(50001, "Query") msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_MSG_OPTION_NONE|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SENDER), msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); __AfterSendRpc(50001, "Query") if (msg_result != MACH_MSG_SUCCESS) { __MachMsgErrorWithoutTimeout(msg_result); { return msg_result; } } #if defined(__MIG_check__Reply__Query_t__defined) check_result = __MIG_check__Reply__Query_t((__Reply__Query_t *)Out0P, (__Reply__Query_t **)&Out1P); if (check_result != MACH_MSG_SUCCESS) { return check_result; } #endif /* defined(__MIG_check__Reply__Query_t__defined) */ TrailerP = (mach_msg_max_trailer_t *)((vm_offset_t)Out0P + round_msg(Out0P->Head.msgh_size)); if (TrailerP->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0) { return MIG_TRAILER_ERROR ; } #if __MigTypeCheck trailer_size = TrailerP->msgh_trailer_size - (mach_msg_size_t)(sizeof(mach_msg_trailer_type_t) - sizeof(mach_msg_trailer_size_t)); #endif /* __MigTypeCheck */ #if __MigTypeCheck if (trailer_size < (mach_msg_size_t)sizeof(security_token_t)) { return MIG_TRAILER_ERROR ; } trailer_size -= (mach_msg_size_t)sizeof(security_token_t); #endif /* __MigTypeCheck */ if (Out0P->replyCnt > 16384) { (void)memcpy((char *) reply, (const char *) Out0P->reply, 16384); *replyCnt = Out0P->replyCnt; { return MIG_ARRAY_TOO_LARGE; } } (void)memcpy((char *) reply, (const char *) Out0P->reply, Out0P->replyCnt); *replyCnt = Out0P->replyCnt; *ooreply = (vm_offset_t)(Out0P->ooreply.address); *ooreplyCnt = Out1P->ooreplyCnt; *usertoken = TrailerP->msgh_sender; return KERN_SUCCESS; }
/* Routine GetProcedureNumber */ mig_external kern_return_t libinfoDSmig_GetProcedureNumber ( mach_port_t server, proc_name_t name, int32_t *procno, security_token_t *usertoken ) { #ifdef __MigPackStructs #pragma pack(4) #endif typedef struct { mach_msg_header_t Head; NDR_record_t NDR; mach_msg_type_number_t nameOffset; /* MiG doesn't use it */ mach_msg_type_number_t nameCnt; char name[256]; } Request; #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; int32_t procno; mach_msg_max_trailer_t trailer; } Reply; #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; int32_t procno; } __Reply; #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; mach_msg_max_trailer_t *TrailerP; #if __MigTypeCheck unsigned int trailer_size; #endif /* __MigTypeCheck */ #ifdef __MIG_check__Reply__GetProcedureNumber_t__defined kern_return_t check_result; #endif /* __MIG_check__Reply__GetProcedureNumber_t__defined */ __DeclareSendRpc(50000, "GetProcedureNumber") InP->NDR = NDR_record; InP->nameCnt = mig_strncpy(InP->name, name, 256); msgh_size = (mach_msg_size_t)(sizeof(Request) - 256) + (_WALIGN_(InP->nameCnt)); InP->Head.msgh_bits = 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 = 50000; __BeforeSendRpc(50000, "GetProcedureNumber") msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0)|MACH_MSG_OPTION_NONE|MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SENDER), msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); __AfterSendRpc(50000, "GetProcedureNumber") if (msg_result != MACH_MSG_SUCCESS) { __MachMsgErrorWithoutTimeout(msg_result); { return msg_result; } } #if defined(__MIG_check__Reply__GetProcedureNumber_t__defined) check_result = __MIG_check__Reply__GetProcedureNumber_t((__Reply__GetProcedureNumber_t *)Out0P); if (check_result != MACH_MSG_SUCCESS) { return check_result; } #endif /* defined(__MIG_check__Reply__GetProcedureNumber_t__defined) */ TrailerP = (mach_msg_max_trailer_t *)((vm_offset_t)Out0P + round_msg(Out0P->Head.msgh_size)); if (TrailerP->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0) { return MIG_TRAILER_ERROR ; } #if __MigTypeCheck trailer_size = TrailerP->msgh_trailer_size - (mach_msg_size_t)(sizeof(mach_msg_trailer_type_t) - sizeof(mach_msg_trailer_size_t)); #endif /* __MigTypeCheck */ #if __MigTypeCheck if (trailer_size < (mach_msg_size_t)sizeof(security_token_t)) { return MIG_TRAILER_ERROR ; } trailer_size -= (mach_msg_size_t)sizeof(security_token_t); #endif /* __MigTypeCheck */ *procno = Out0P->procno; *usertoken = TrailerP->msgh_sender; return KERN_SUCCESS; }
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; }