Initial iokitd daemon with stubs

This commit is contained in:
Lubos Dolezel 2020-02-10 10:59:45 +01:00
parent 9a89b4e25e
commit 0d64152ab8
6 changed files with 1174 additions and 34 deletions

View File

@ -2,13 +2,28 @@ project(iokitd)
add_compile_options(
-nostdinc
-nostdinc++
-Wno-gcc-compat
)
add_definitions(-DIOKIT=1 -DIOKIT_ALL_IPC=1)
include_directories(
${CMAKE_SOURCE_DIR}/src/launchd
${CMAKE_SOURCE_DIR}/src/lkm/osfmk
)
include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/libcxx/include ${CMAKE_CURRENT_BINARY_DIR})
mig(iokitmig.defs)
set(iokitd_sources
src/main.cpp
src/stubs.c
${CMAKE_CURRENT_BINARY_DIR}/iokitmigServer.c
)
add_darling_executable(iokitd ${iokitd_sources})
target_link_libraries(iokitd cxx)
install(TARGETS iokitd DESTINATION libexec/darling/usr/sbin)
install(FILES org.darlinghq.iokitd.plist DESTINATION libexec/darling/System/Library/LaunchDaemons)

1
iokitmig.defs Normal file
View File

@ -0,0 +1 @@
#include <device/device.defs>

View File

@ -13,7 +13,9 @@
<key>org.darlinghq.iokitd</key>
<true/>
</dict>
<key>EnableTransactions</key>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>

View File

@ -2,8 +2,6 @@
#define _IOKITD_H
#include <mach/mach.h>
extern mach_port_t g_machServerPort;
#define asldebug(...) os_log_debug(OS_LOG_DEFAULT, __VA_ARGS__)
#endif

View File

@ -1,54 +1,111 @@
#include <unistd.h>
#include <os/log.h>
#include <liblaunch/launch.h>
#include <liblaunch/bootstrap.h>
#include <dispatch/dispatch.h>
#include <cstdlib>
#include "iokitd.h"
#include "iokitmig.h"
extern "C" {
#include "iokitmigServer.h"
}
static const char* SERVICE_NAME = "org.darlinghq.iokitd";
mach_port_t g_machServerPort;
static void launch_config();
static void service_mach_message(mach_port_t serverPort);
int main(int argc, const char** argv)
{
launch_config();
mach_port_t bs, mp;
kern_return_t ret;
task_get_bootstrap_port(mach_task_self(), &bs);
ret = bootstrap_check_in(bs, SERVICE_NAME, &mp);
mach_port_destroy(mach_task_self(), bs);
if (ret != KERN_SUCCESS)
{
os_log_error(OS_LOG_DEFAULT, "%d bootstrap_check_in() failed with error %d", getpid(), ret);
return 1;
}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t portSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, mp, 0, queue);
if (!portSource)
{
os_log_error(OS_LOG_DEFAULT, "%d dispatch_source_create() failed", getpid());
return 1;
}
dispatch_source_set_event_handler(portSource, ^{
service_mach_message(mp);
});
dispatch_resume(portSource);
dispatch_main();
return 0;
}
static void launch_config()
typedef union
{
launch_data_t tmp, pdict;
kern_return_t status;
launch_data_t launch_dict;
mach_msg_header_t head;
union __RequestUnion__iokit_subsystem request;
} iokit_request_msg;
tmp = launch_data_new_string(LAUNCH_KEY_CHECKIN);
launch_dict = launch_msg(tmp);
launch_data_free(tmp);
typedef union
{
mach_msg_header_t head;
union __ReplyUnion__iokit_subsystem reply;
} iokit_reply_msg;
if (!launch_dict)
static void service_mach_message(mach_port_t serverPort)
{
__block kern_return_t status;
uint32_t rbits, sbits;
iokit_request_msg *request;
iokit_reply_msg *reply;
char rbuf[sizeof(iokit_request_msg) + MAX_TRAILER_SIZE];
char sbuf[sizeof(iokit_reply_msg) + MAX_TRAILER_SIZE];
while (true)
{
os_log_error(OS_LOG_DEFAULT, "%d launchd checkin failed\n", global.pid);
exit(1);
}
memset(rbuf, 0, sizeof(rbuf));
memset(sbuf, 0, sizeof(sbuf));
tmp = launch_data_dict_lookup(launch_dict, LAUNCH_JOBKEY_MACHSERVICES);
if (!tmp)
{
os_log_error(OS_LOG_DEFAULT, "%d launchd lookup of LAUNCH_JOBKEY_MACHSERVICES failed\n", getpid());
exit(1);
}
request = (iokit_request_msg *)rbuf;
reply = (iokit_reply_msg *)sbuf;
pdict = launch_data_dict_lookup(tmp, SERVICE_NAME);
if (!pdict)
{
os_log_error(OS_LOG_DEFAULT, "%d launchd lookup of SERVICE_NAME failed\n", getpid());
exit(1);
}
request->head.msgh_local_port = serverPort;
request->head.msgh_size = sizeof(iokit_request_msg) + MAX_TRAILER_SIZE;
g_machServerPort = launch_data_get_machport(pdict);
rbits = MACH_RCV_MSG | MACH_RCV_TIMEOUT | MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) | MACH_RCV_VOUCHER;
sbits = MACH_SEND_MSG;
status = mach_msg(&(request->head), rbits, 0, request->head.msgh_size, serverPort, 0, MACH_PORT_NULL);
if (status != KERN_SUCCESS) return;
voucher_mach_msg_state_t voucher = voucher_mach_msg_adopt(&(request->head));
status = iokit_server(&(request->head), &(reply->head));
if (!status && (request->head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
{
/* destroy the request - but not the reply port */
request->head.msgh_remote_port = MACH_PORT_NULL;
mach_msg_destroy(&(request->head));
}
if (reply->head.msgh_remote_port)
{
status = mach_msg(&(reply->head), sbits, reply->head.msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
if (status == MACH_SEND_INVALID_DEST || status == MACH_SEND_TIMED_OUT)
{
/* deallocate reply port rights not consumed by failed mach_msg() send */
mach_msg_destroy(&(reply->head));
}
}
voucher_mach_msg_revert(voucher);
}
}

1067
src/stubs.c Normal file

File diff suppressed because it is too large Load Diff