Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion launchctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static const struct {
{ "plist", "Prints a property list embedded in a binary (targets the Info.plist by default).", "[segment,section] <path>", plist_cmd },
{ "procinfo", "Prints port information about a process.", "<pid>", 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.", "<owner-pid> <port-name>", todo_cmd },
{ "resolveport", "Resolves a port name from a process to an endpoint in launchd.", "<owner-pid> <port-name>", resolveport_cmd },
{ "limit", "Reads or modifies launchd's resource limits.", "[<limit-name> [<both-limits> | <soft-limit> <hard-limit>]", limit_cmd },
{ "runstats", "Prints performance statistics for a service.", "<service-target>", runstats_cmd },
{ "examine", "Runs the specified analysis tool against launchd in a non-reentrant manner.", "[<tool> [arg0, arg1, ... , @PID, ...]]", examine_cmd },
Expand Down
7 changes: 4 additions & 3 deletions launchctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <mach/mach.h>
#include <stdint.h>
#include <stdio.h>

#include <mach/mach.h>

#include <xpc/xpc.h>

#ifndef _LAUNCHCTL_H_
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions os_alloc_once.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>

#include <xpc/xpc.h>

#define OS_ALLOC_ONCE_KEY_LIBXPC 1
Expand Down
12 changes: 6 additions & 6 deletions procinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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));
Expand Down Expand Up @@ -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;
Expand Down
128 changes: 128 additions & 0 deletions resolveport.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*-
* SPDX-License-Identifier: BSD 2-Clause License
*
* Copyright (c) 2024 Procursus Team <team@procurs.us>
* 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 <errno.h>
#include <inttypes.h>
#include <mach/mach.h>
#include <stdio.h>
#include <xpc/xpc.h>

#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;
}
23 changes: 9 additions & 14 deletions xpc_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
*/
#include <stddef.h>
#include <stdint.h>

#include <xpc/xpc.h>

#ifndef _LAUNCHCTL_XPC_PRIVATE_H_
Expand All @@ -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,
Expand All @@ -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);

Expand All @@ -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 {
Expand Down
Loading