kextd_mig_server.c [plain text]
#include <CoreFoundation/CoreFoundation.h>
#include <mach/mach.h>
#include <mach/mach_port.h>
#include <servers/bootstrap.h>
#include <sysexits.h>
#include <IOKit/kext/OSKext.h>
#include "kext_tools_util.h"
#include "kextd_globals.h"
#include "kextd_mig_server.h"
extern struct mig_subsystem _kextmanager_subsystem;
extern boolean_t kextmanager_server(mach_msg_header_t *, mach_msg_header_t *);
extern struct mig_subsystem svc_kextd_kernel_request_subsystem;
extern boolean_t kextd_kernel_request_server(
mach_msg_header_t *InHeadP,
mach_msg_header_t *OutHeadP);
uid_t gClientUID = -1;
boolean_t kextd_demux(
mach_msg_header_t * request,
mach_msg_header_t * reply)
{
boolean_t processed = FALSE;
mach_msg_format_0_trailer_t * trailer;
if (!processed) {
if (request->msgh_id >= _kextmanager_subsystem.start &&
request->msgh_id < _kextmanager_subsystem.end) {
trailer = (mach_msg_security_trailer_t *)((vm_offset_t)request +
round_msg(request->msgh_size));
if ((trailer->msgh_trailer_type == MACH_MSG_TRAILER_FORMAT_0) &&
(trailer->msgh_trailer_size >= MACH_MSG_TRAILER_FORMAT_0_SIZE)) {
gClientUID = trailer->msgh_sender.val[0];
OSKextLog( NULL,
kOSKextLogDebugLevel | kOSKextLogIPCFlag,
"MIG message received: caller has eUID = %d, eGID = %d.",
trailer->msgh_sender.val[0],
trailer->msgh_sender.val[1]);
} else {
OSKextLog( NULL,
kOSKextLogWarningLevel | kOSKextLogIPCFlag,
"Caller's credentials not available.");
gClientUID = -1;
}
processed = kextmanager_server(request, reply);
} else if (request->msgh_id >= svc_kextd_kernel_request_subsystem.start &&
request->msgh_id < svc_kextd_kernel_request_subsystem.end) {
processed = kextd_kernel_request_server(request, reply);
}
}
if (!processed) {
if (request->msgh_id >= MACH_NOTIFY_FIRST &&
request->msgh_id < MACH_NOTIFY_LAST) {
OSKextLog( NULL,
kOSKextLogErrorLevel | kOSKextLogIPCFlag,
"Failed to process MIG message.");
} else {
OSKextLog( NULL,
kOSKextLogErrorLevel | kOSKextLogIPCFlag,
"Unknown MIG message received.");
}
}
gClientUID = (uid_t)-1;
return processed;
}
void kextd_mach_port_callback(
CFMachPortRef port,
void *msg,
CFIndex size,
void *info)
{
mig_reply_error_t * bufRequest = msg;
mig_reply_error_t * bufReply = CFAllocatorAllocate(
NULL, _kextmanager_subsystem.maxsize, 0);
mach_msg_return_t mr;
int options;
(void) kextd_demux(&bufRequest->Head, &bufReply->Head);
if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
(bufReply->RetCode != KERN_SUCCESS)) {
if (bufReply->RetCode == MIG_NO_REPLY) {
CFAllocatorDeallocate(NULL, bufReply);
return;
}
bufRequest->Head.msgh_remote_port = MACH_PORT_NULL;
mach_msg_destroy(&bufRequest->Head);
}
if (bufReply->Head.msgh_remote_port == MACH_PORT_NULL) {
if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
mach_msg_destroy(&bufReply->Head);
}
CFAllocatorDeallocate(NULL, bufReply);
return;
}
options = MACH_SEND_MSG;
if (MACH_MSGH_BITS_REMOTE(bufReply->Head.msgh_bits) == MACH_MSG_TYPE_MOVE_SEND_ONCE) {
options |= MACH_SEND_TIMEOUT;
}
mr = mach_msg(&bufReply->Head,
options,
bufReply->Head.msgh_size,
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
switch (mr) {
case MACH_SEND_INVALID_DEST:
case MACH_SEND_TIMED_OUT:
mach_msg_destroy(&bufReply->Head);
break;
default :
break;
}
CFAllocatorDeallocate(NULL, bufReply);
}