From 6191d8419240197495c037e8bc7952c998374f56 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 20 Dec 2024 18:55:03 +0800 Subject: [PATCH] Add resolveport --- Makefile | 2 +- TODO.md | 2 +- launchctl.c | 2 +- launchctl.h | 7 +-- os_alloc_once.h | 1 + procinfo.c | 12 ++--- resolveport.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ xpc_private.h | 23 ++++----- 8 files changed, 151 insertions(+), 26 deletions(-) create mode 100644 resolveport.c diff --git a/Makefile b/Makefile index ff2f349..fe4afa7 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ DESTDIR ?= SRC := attach.c blame.c bootstrap.c enable.c env.c error.c examine.c kickstart.c SRC += kill.c launchctl.c limit.c list.c load.c manager.c plist.c print.c reboot.c SRC += remove.c runstats.c start_stop.c userswitch.c version.c xpc_helper.c -SRC += dumpjpcategory.c procinfo.c +SRC += dumpjpcategory.c procinfo.c resolveport.c ifeq ($(DEBUG),1) CFLAGS += -O0 -g -fsanitize=address,undefined -fno-omit-frame-pointer diff --git a/TODO.md b/TODO.md index 6f1bc1b..25ab02d 100644 --- a/TODO.md +++ b/TODO.md @@ -14,7 +14,7 @@ 1. [x] plist 1. [x] procinfo 1. [x] hostinfo -1. [ ] resolveport +1. [x] resolveport 1. [x] limit 1. [x] runstats 1. [x] examine diff --git a/launchctl.c b/launchctl.c index 80399a0..22dc42f 100644 --- a/launchctl.c +++ b/launchctl.c @@ -73,7 +73,7 @@ static const struct { { "plist", "Prints a property list embedded in a binary (targets the Info.plist by default).", "[segment,section] ", plist_cmd }, { "procinfo", "Prints port information about a process.", "", procinfo_cmd }, { "hostinfo", "Prints port information about the host.", NULL, hostinfo_cmd }, - { "resolveport", "Resolves a port name from a process to an endpoint in launchd.", " ", todo_cmd }, + { "resolveport", "Resolves a port name from a process to an endpoint in launchd.", " ", resolveport_cmd }, { "limit", "Reads or modifies launchd's resource limits.", "[ [ | ]", limit_cmd }, { "runstats", "Prints performance statistics for a service.", "", runstats_cmd }, { "examine", "Runs the specified analysis tool against launchd in a non-reentrant manner.", "[ [arg0, arg1, ... , @PID, ...]]", examine_cmd }, diff --git a/launchctl.h b/launchctl.h index c8827cd..b2ef185 100644 --- a/launchctl.h +++ b/launchctl.h @@ -25,11 +25,9 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include - -#include - #include #ifndef _LAUNCHCTL_H_ @@ -122,6 +120,9 @@ cmd_main dumpjpcategory_cmd; cmd_main procinfo_cmd; cmd_main hostinfo_cmd; +// resolveport.c +cmd_main resolveport_cmd; + void launchctl_xpc_object_print(xpc_object_t, const char *name, int level); int launchctl_send_xpc_to_launchd(uint64_t routine, xpc_object_t msg, xpc_object_t *reply); void launchctl_setup_xpc_dict(xpc_object_t dict); diff --git a/os_alloc_once.h b/os_alloc_once.h index e79fe8c..11db6f1 100644 --- a/os_alloc_once.h +++ b/os_alloc_once.h @@ -26,6 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include + #include #define OS_ALLOC_ONCE_KEY_LIBXPC 1 diff --git a/procinfo.c b/procinfo.c index 2a05595..8369a72 100644 --- a/procinfo.c +++ b/procinfo.c @@ -152,7 +152,7 @@ get_port_type(mach_port_t port) launchctl_setup_xpc_dict_for_service_name("system", dict, NULL); xpc_dictionary_set_int64(dict, "process", getpid()); xpc_dictionary_set_uint64(dict, "name", port); - int retval = launchctl_send_xpc_to_launchd(XPC_ROUTINE_PORT_INFO, dict, &reply); + int retval = launchctl_send_xpc_to_launchd(XPC_ROUTINE_RESOLVE_PORT, dict, &reply); if (retval) { type = "unknown"; goto port_type_end; @@ -389,7 +389,7 @@ procinfo_cmd(xpc_object_t *msg, int argc, char **argv, char **envp, char **apple print_exception_port_info(1, masks, masksCnt, old_handlers); printf("}\n"); -procinfo_proc_info: { +procinfo_proc_info : { } if (task) mach_port_deallocate(mach_task_self(), task); @@ -531,7 +531,7 @@ procinfo_proc_info: { procinfo.pbsd.pbi_svgid, procinfo.pbsd.pbi_rgid, procinfo.pbsd.pbi_comm, procinfo.pbsd.pbi_name, procinfo.pbsd.e_tdev, procinfo.pbsd.e_tpgid); -procinfo_pressured_exit_info: { +procinfo_pressured_exit_info : { } free(procargs); uint32_t dflags; @@ -548,7 +548,7 @@ procinfo_pressured_exit_info: { !!(dflags & PROC_DIRTY_TRACKED), !!(dflags & PROC_DIRTY_IS_DIRTY), !!(dflags & PROC_DIRTY_ALLOWS_IDLE_EXIT)); -procinfo_entitlements: { +procinfo_entitlements : { } xpc_object_t xents = get_entitlements(pid, NULL); if (!xents) { @@ -559,7 +559,7 @@ procinfo_entitlements: { launchctl_xpc_object_print(xents, NULL, 0); xpc_release(xents); printf("\n"); -procinfo_cs_info: { +procinfo_cs_info : { } uint32_t csflags; retval = csops(pid, CS_OPS_STATUS, &csflags, sizeof(uint32_t)); @@ -604,7 +604,7 @@ procinfo_cs_info: { printf("code signing info = %s\n", cs_info_str); -procinfo_launchd_info: { +procinfo_launchd_info : { } printf("\n"); xpc_object_t dict, reply; diff --git a/resolveport.c b/resolveport.c new file mode 100644 index 0000000..95c1089 --- /dev/null +++ b/resolveport.c @@ -0,0 +1,128 @@ +/*- + * SPDX-License-Identifier: BSD 2-Clause License + * + * Copyright (c) 2024 Procursus Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include "launchctl.h" +#include "xpc_private.h" + +int +resolveport_cmd(xpc_object_t *msg, int argc, char **argv, char **envp, char **apple) +{ + if (argc < 3) + return EUSAGE; + + pid_t pid = strtol(argv[1], NULL, 0); + mach_port_t port = strtol(argv[2], NULL, 0); + + mach_port_t task = 0; + kern_return_t kr = task_for_pid(mach_task_self(), pid, &task); + + if (kr) { + fprintf(stderr, "task_for_pid(): 0x%x\n", kr); + return kr; + } + + mach_port_type_t type; + + kr = mach_port_type(task, port, &type); + + if (kr) { + if (kr == KERN_INVALID_NAME) + fprintf(stderr, "Right name does not exist in task.\n"); + else + fprintf(stderr, "task_for_pid(): 0x%x\n", kr); + + return kr; + } + + char rights[256] = { 0 }; + +#define RIGHT_DESCRIPTION(desc, bit) \ + if (type & bit) { \ + if (rights[0]) \ + strlcat(rights, "/", 256); \ + strlcat(rights, desc, 256); \ + } + + RIGHT_DESCRIPTION("receive", MACH_PORT_TYPE_RECEIVE); + RIGHT_DESCRIPTION("send", MACH_PORT_TYPE_SEND); + RIGHT_DESCRIPTION("send-once", MACH_PORT_TYPE_SEND_ONCE); + RIGHT_DESCRIPTION("dead name", MACH_PORT_TYPE_DEAD_NAME); + RIGHT_DESCRIPTION("port set", MACH_PORT_RIGHT_PORT_SET); + RIGHT_DESCRIPTION("mac label", MACH_PORT_RIGHT_LABELH); + RIGHT_DESCRIPTION("dead-name request", MACH_PORT_TYPE_DNREQUEST); + RIGHT_DESCRIPTION("send-possible request", MACH_PORT_TYPE_SPREQUEST); + RIGHT_DESCRIPTION("delayed send-possible request", MACH_PORT_TYPE_SPREQUEST_DELAYED); + + xpc_object_t dict = xpc_dictionary_create(NULL, NULL, 0), reply; + *msg = dict; + + launchctl_setup_xpc_dict_for_service_name("system", dict, NULL); + xpc_dictionary_set_int64(dict, "process", pid); + xpc_dictionary_set_uint64(dict, "name", port); + + int retval = launchctl_send_xpc_to_launchd(XPC_ROUTINE_RESOLVE_PORT, dict, &reply); + if (retval == ESRCH) { + fprintf(stderr, "Could not find name 0x%x in %d\n", port, pid); + return ESRCH; + } else if (retval == ENOSERVICE) { + fprintf(stderr, "Could not obtain task port for PID: %d\n", pid); + return ESRCH; + } else if (retval) { + return retval; + } + + if (xpc_dictionary_get_uint64(reply, "kern-error")) { + fprintf(stderr, "Could not obtain right for port: 0x%x\n", port); + return 0; + } + + const char *domain = xpc_dictionary_get_string(reply, "domain"); + if (!domain) + return EBADRESP; + + printf("domain = %s\n", domain); + + const char *service = xpc_dictionary_get_string(reply, "service"); + const char *endpoint = xpc_dictionary_get_string(reply, "endpoint"); + + if (service) + printf("service = %s\n", service); + + if (endpoint) + printf("endpoint = %s\n", endpoint); + + printf("task rights = %s\n", rights); + + return 0; +} diff --git a/xpc_private.h b/xpc_private.h index 68bbcd7..c67bbb9 100644 --- a/xpc_private.h +++ b/xpc_private.h @@ -27,7 +27,6 @@ */ #include #include - #include #ifndef _LAUNCHCTL_XPC_PRIVATE_H_ @@ -51,7 +50,7 @@ enum { XPC_ROUTINE_REMOVE = 816, XPC_ROUTINE_SETENV = 819, XPC_ROUTINE_GETENV = 820, - XPC_ROUTINE_PORT_INFO = 822, + XPC_ROUTINE_RESOLVE_PORT = 822, XPC_ROUTINE_LIMIT = 825, XPC_ROUTINE_EXAMINE = 826, XPC_ROUTINE_PRINT = 828, @@ -61,24 +60,20 @@ enum { XPC_DECL(xpc_pipe); -XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1 XPC_NONNULL2 XPC_NONNULL3 -int -xpc_pipe_routine(xpc_pipe_t pipe, xpc_object_t message, - xpc_object_t XPC_GIVES_REFERENCE *reply); +XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1 XPC_NONNULL2 XPC_NONNULL3 int xpc_pipe_routine(xpc_pipe_t pipe, + xpc_object_t message, xpc_object_t XPC_GIVES_REFERENCE *reply); -XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1 XPC_NONNULL3 XPC_NONNULL4 -int -_xpc_pipe_interface_routine(xpc_pipe_t pipe, uint64_t routine, - xpc_object_t message, xpc_object_t XPC_GIVES_REFERENCE *reply, - uint64_t flags) __API_AVAILABLE(ios(15.0)); +XPC_EXPORT XPC_WARN_RESULT XPC_NONNULL1 XPC_NONNULL3 XPC_NONNULL4 int _xpc_pipe_interface_routine(xpc_pipe_t pipe, + uint64_t routine, xpc_object_t message, xpc_object_t XPC_GIVES_REFERENCE *reply, uint64_t flags) + __API_AVAILABLE(ios(15.0)); int launch_active_user_switch(long, long) __API_AVAILABLE(ios(15.0)); int64_t xpc_user_sessions_enabled(void) __API_AVAILABLE(ios(16.0)); uint64_t xpc_user_sessions_get_foreground_uid(uint64_t) __API_AVAILABLE(ios(16.0)); -XPC_EXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT XPC_NONNULL1 -xpc_object_t xpc_create_from_plist(const void * data, size_t length); +XPC_EXPORT XPC_RETURNS_RETAINED XPC_WARN_RESULT XPC_NONNULL1 xpc_object_t xpc_create_from_plist(const void *data, + size_t length); const char *xpc_strerror(int); @@ -89,7 +84,7 @@ XPC_TYPE(_xpc_type_mach_send); typedef void (*xpc_dictionary_applier_f)(const char *key, xpc_object_t val, void *ctx); void xpc_dictionary_apply_f(xpc_object_t xdict, void *ctx, xpc_dictionary_applier_f applier); -typedef void (*xpc_array_applier_f)(size_t index, xpc_object_t value, void* context); +typedef void (*xpc_array_applier_f)(size_t index, xpc_object_t value, void *context); void xpc_array_apply_f(xpc_object_t xarray, void *context, xpc_array_applier_f applier); enum {