diff --git a/src/lkm/ipc_msg.c b/src/lkm/ipc_msg.c index ac0b4051e..a7fd80d95 100644 --- a/src/lkm/ipc_msg.c +++ b/src/lkm/ipc_msg.c @@ -320,6 +320,7 @@ mach_msg_return_t ipc_msg_invoke_server(struct ipc_kmsg* kmsg, mig_routine_t routine; mach_msg_header_t* reply_msg; mach_msg_return_t ret; + mach_port_t tmp; subsystem = kmsg->target->port->server_port.subsystem; @@ -382,8 +383,17 @@ mach_msg_return_t ipc_msg_invoke_server(struct ipc_kmsg* kmsg, kmsg->msg->msgh_id, kmsg->msg->msgh_size); reply_msg->msgh_size = sizeof(mig_reply_error_t); + + // MIG generated code expects local and remote ports to be swapped + tmp = kmsg->msg->msgh_local_port; + kmsg->msg->msgh_local_port = kmsg->msg->msgh_remote_port; + kmsg->msg->msgh_remote_port = tmp; routine(kmsg->msg, reply_msg); + + // Swap port numbers back, just to be consistent + kmsg->msg->msgh_remote_port = kmsg->msg->msgh_local_port; + kmsg->msg->msgh_local_port = tmp; debug_msg("ipc_msg_deliver(): reply size: %d, ret = 0x%x\n", reply_msg->msgh_size, diff --git a/src/lkm/ipc_space.c b/src/lkm/ipc_space.c index dc04cd065..b873fd71f 100644 --- a/src/lkm/ipc_space.c +++ b/src/lkm/ipc_space.c @@ -68,6 +68,9 @@ mach_msg_return_t ipc_space_make_receive(ipc_namespace_t* space, else right = ipc_right_new(port, MACH_PORT_RIGHT_RECEIVE); + // Replace with anon_inode_getfd(name, ops, priv, O_CLOEXEC) + // (..., fdget, fdput) + // for pollable fds (needed for kevent()) id = idr_alloc(&space->names, right, 1, -1, GFP_KERNEL); if (id < 0) { diff --git a/src/lkm/servers/thread_act.c b/src/lkm/servers/thread_act.c index 70cb1a8c3..45f5532c9 100644 --- a/src/lkm/servers/thread_act.c +++ b/src/lkm/servers/thread_act.c @@ -23,6 +23,7 @@ #include "../darling_task.h" #include "stub.h" #include +#include #include "thread_act.h" struct thread_private @@ -224,8 +225,56 @@ kern_return_t thread_info mach_msg_type_number_t *thread_info_outCnt ) { - UNIMPL_MIG_CALL(); - return KERN_NOT_SUPPORTED; + mach_task_t* task; + darling_mach_port_right_t* right = NULL; + struct task_struct* ltask = NULL; + pid_t pid; + kern_return_t ret = KERN_SUCCESS; + + task = darling_task_get_current(); + ipc_space_lock(&task->namespace); + + right = ipc_space_lookup_unlocked(&task->namespace, target_act); + if (right == NULL) + { + debug_msg("thread_info: right %d not found", target_act); + ret = KERN_INVALID_RIGHT; + goto err; + } + + pid = get_thread_pid(right->port); + ltask = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID); + + if (ltask == NULL) + { + ret = KERN_FAILURE; + goto err; + } + + if (flavor == THREAD_IDENTIFIER_INFO) + { + thread_identifier_info_data_t data; + + data.thread_handle = ltask->pid; + data.dispatch_qaddr = 0; + + data.thread_id = data.thread_handle; + data.thread_id |= (ltask->start_time & 0xffffffff) << 32; + + memcpy(thread_info_out, &data, sizeof(data)); + *thread_info_outCnt = THREAD_IDENTIFIER_INFO_COUNT; + } + else + { + debug_msg("Unsupported thread_info flavor: %d", flavor); + UNIMPL_MIG_CALL(); + ret = KERN_NOT_SUPPORTED; + } + +err: + ipc_space_unlock(&task->namespace); + + return ret; } kern_return_t thread_set_exception_ports