Skip to content

Commit

Permalink
Stability improvements, always use launchd as fallback, block tweak i…
Browse files Browse the repository at this point in the history
…njection into bootstrap processes
  • Loading branch information
opa334 committed Apr 12, 2023
1 parent c88afa0 commit a9752a6
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 114 deletions.
16 changes: 1 addition & 15 deletions BaseBin/jailbreakd/src/server.m
Original file line number Diff line number Diff line change
Expand Up @@ -438,21 +438,7 @@ void jailbreakd_received_message(mach_port_t machPort, bool systemwide)
case JBD_MSG_SETUID_FIX: {
int64_t result = 0;
if (gPPLRWStatus == kPPLRWStatusInitialized) {
NSString *clientPath = [procPath(clientPid) stringByResolvingSymlinksInPath];
struct stat sb;
if(stat(clientPath.fileSystemRepresentation, &sb) == 0) {
if (S_ISREG(sb.st_mode) && (sb.st_mode & S_ISUID)) {
uint64_t proc = proc_for_pid(clientPid);
uint64_t ucred = proc_get_ucred(proc);
ucred_set_svuid(ucred, 0);
}
else {
result = 10;
}
}
else {
result = 5;
}
proc_fix_setuid(clientPid);
}
else {
result = JBD_ERR_PRIMITIVE_NOT_INITIALIZED;
Expand Down
54 changes: 31 additions & 23 deletions BaseBin/launchdhook/src/xpc_hook.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@
#import <sandbox.h>
#import "substrate.h"

NSString *procPath(pid_t pid)
{
char pathbuf[4*MAXPATHLEN];
int ret = proc_pidpath(pid, pathbuf, sizeof(pathbuf));
if (ret <= 0) return nil;
return [NSString stringWithUTF8String:pathbuf];
}

// Server routine to make jailbreakd able to get back primitives when it restarts
void (*xpc_handler_orig)(uint64_t a1, uint64_t a2, xpc_object_t xdict);
void xpc_handler_hook(uint64_t a1, uint64_t a2, xpc_object_t xdict)
Expand All @@ -28,24 +20,40 @@ void xpc_handler_hook(uint64_t a1, uint64_t a2, xpc_object_t xdict)
audit_token_t auditToken = {};
xpc_dictionary_get_audit_token(xdict, &auditToken);
pid_t clientPid = audit_token_to_pid(auditToken);
NSString *clientPath = [[procPath(clientPid) stringByResolvingSymlinksInPath] stringByStandardizingPath];
NSString *clientPath = proc_get_path(clientPid);
NSString *jailbreakdPath = [[@"/var/jb/basebin/jailbreakd" stringByResolvingSymlinksInPath] stringByStandardizingPath];
if (xpc_dictionary_get_bool(xdict, "sw-fallback")) {
int sbc = sandbox_check(clientPid, "mach-lookup", SANDBOX_FILTER_GLOBAL_NAME | SANDBOX_CHECK_NO_REPORT, "com.opa334.jailbreakd.systemwide");
// Fallback API is only accessible if systemwide jailbreakd is not accessible
if (sbc != 0) {
uint64_t msgId = xpc_dictionary_get_uint64(xdict, "id");
xpc_object_t xreply = xpc_dictionary_create_reply(xdict);
switch (msgId) {
case JBD_MSG_DEBUG_ME: {
proc_set_debugged(clientPid);
xpc_dictionary_set_int64(xreply, "result", 0);
break;
}
if (xpc_dictionary_get_bool(xdict, "jailbreak-systemwide")) {
uint64_t msgId = xpc_dictionary_get_uint64(xdict, "id");
xpc_object_t xreply = xpc_dictionary_create_reply(xdict);
switch (msgId) {
case JBD_MSG_DEBUG_ME: {
proc_set_debugged(clientPid);
xpc_dictionary_set_int64(xreply, "result", 0);
break;
}
case JBD_MSG_PROCESS_BINARY: {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// downcall to jailbreakd asynchronously
// async because jbd might be upcalling to get primitives back
// which would cause an infinite hang if we're sync here
int64_t result = 0;
const char* filePath = xpc_dictionary_get_string(xdict, "filePath");
if (filePath) {
result = jbdProcessBinary(filePath);
}
xpc_dictionary_set_uint64(xreply, "result", result);
xpc_pipe_routine_reply(xreply);
});
return;
}
case JBD_MSG_SETUID_FIX: {
proc_fix_setuid(clientPid);
xpc_dictionary_set_int64(xreply, "result", 0);
break;
}
xpc_pipe_routine_reply(xreply);
return;
}
xpc_pipe_routine_reply(xreply);
return;
}
else {
char *xdictDescription = xpc_copy_description(xdict);
Expand Down
1 change: 1 addition & 0 deletions BaseBin/libjailbreak/src/jailbreakd.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,5 @@ int64_t jbdUpdateFromTIPA(NSString *pathToTIPA);
int64_t jbdUpdateFromBasebinTar(NSString *pathToBasebinTar);

int64_t jbdRebuildTrustCache(void);
int64_t jbdProcessBinary(const char *filePath);
int64_t jbdProcSetDebugged(pid_t pid);
55 changes: 44 additions & 11 deletions BaseBin/libjailbreak/src/jailbreakd.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#import <unistd.h>
#import <xpc/xpc.h>
#import <bsm/libbsm.h>
#include <sys/param.h>
#include <sys/mount.h>
#import "log.h"
#import "pplrw.h"

Expand All @@ -27,20 +29,22 @@ mach_port_t jbdMachPort(void)
return outPort;
}

xpc_object_t sendJBDMessage(xpc_object_t message)
xpc_object_t sendJBDMessage(xpc_object_t xdict)
{
xpc_object_t xreply = nil;
mach_port_t jbdPort = jbdMachPort();
xpc_object_t pipe = xpc_pipe_create_from_port(jbdPort, 0);

xpc_object_t reply = nil;
int err = xpc_pipe_routine(pipe, message, &reply);
mach_port_deallocate(mach_task_self(), jbdPort);
if (err != 0) {
JBLogError("xpc_pipe_routine error on sending message to jailbreakd: %d", err);
return nil;
if (jbdPort != -1) {
xpc_object_t pipe = xpc_pipe_create_from_port(jbdPort, 0);
if (pipe) {
int err = xpc_pipe_routine(pipe, xdict, &xreply);
if (err != 0) {
JBLogError("xpc_pipe_routine error on sending message to jailbreakd: %d / %s", err, xpc_strerror(err));
xreply = nil;
};
}
mach_port_deallocate(mach_task_self(), jbdPort);
}

return reply;
return xreply;
}

void jbdGetStatus(uint64_t *PPLRWStatus, uint64_t *kcallStatus, pid_t *pid)
Expand Down Expand Up @@ -195,6 +199,35 @@ int64_t jbdRebuildTrustCache(void)
return xpc_dictionary_get_int64(reply, "result");
}

int64_t jbdProcessBinary(const char *filePath)
{
// if file doesn't exist, bail out
if (access(filePath, F_OK) != 0) return 0;

// if file is on rootfs mount point, it doesn't need to be
// processed as it's guaranteed to be in static trust cache
// same goes for our /usr/lib bind mount
struct statfs fs;
int sfsret = statfs(filePath, &fs);
if (sfsret == 0) {
if (!strcmp(fs.f_mntonname, "/") || !strcmp(fs.f_mntonname, "/usr/lib")) return -1;
}

char absolutePath[PATH_MAX];
if (realpath(filePath, absolutePath) == NULL) return -1;

xpc_object_t message = xpc_dictionary_create_empty();
xpc_dictionary_set_uint64(message, "id", JBD_MSG_PROCESS_BINARY);
xpc_dictionary_set_string(message, "filePath", absolutePath);

xpc_object_t reply = sendJBDMessage(message);
int64_t result = -1;
if (reply) {
result = xpc_dictionary_get_int64(reply, "result");
}
return result;
}

int64_t jbdProcSetDebugged(pid_t pid)
{
xpc_object_t message = xpc_dictionary_create_empty();
Expand Down
16 changes: 11 additions & 5 deletions BaseBin/libjailbreak/src/launchd.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@ xpc_object_t launchd_xpc_send_message(xpc_object_t xdict)
if (!pipePtr) _os_alloc_once_table[1].once = -1;
}

struct xpc_global_data* globalData = pipePtr;
xpc_object_t pipe = globalData->xpc_bootstrap_pipe;

xpc_object_t xreply;
xpc_pipe_routine_with_flags(pipe, xdict, &xreply, 0);
xpc_object_t xreply = nil;
if (pipePtr) {
struct xpc_global_data* globalData = pipePtr;
xpc_object_t pipe = globalData->xpc_bootstrap_pipe;
if (pipe) {
int err = xpc_pipe_routine_with_flags(pipe, xdict, &xreply, 0);
if (err != 0) {
return nil;
}
}
}
return xreply;
}
4 changes: 3 additions & 1 deletion BaseBin/libjailbreak/src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,6 @@ void vnode_replace_entitlements(uint64_t vnode_ptr, NSDictionary *newEntitlement
NSMutableDictionary *proc_dump_entitlements(uint64_t proc_ptr);
void proc_replace_entitlements(uint64_t proc_ptr, NSDictionary *entitlements);

bool proc_set_debugged(pid_t pid);
bool proc_set_debugged(pid_t pid);
NSString *proc_get_path(pid_t pid);
int64_t proc_fix_setuid(pid_t pid);
29 changes: 29 additions & 0 deletions BaseBin/libjailbreak/src/util.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#import "boot_info.h"
#import "signatures.h"
#import "log.h"
#import <libproc.h>

extern const uint8_t *der_decode_plist(CFAllocatorRef allocator, CFTypeRef* output, CFErrorRef *error, const uint8_t *der_start, const uint8_t *der_end);
extern const uint8_t *der_encode_plist(CFTypeRef input, CFErrorRef *error, const uint8_t *der_start, const uint8_t *der_end);
Expand Down Expand Up @@ -626,4 +627,32 @@ bool proc_set_debugged(pid_t pid)
}
}
return 0;
}

NSString *proc_get_path(pid_t pid)
{
char pathbuf[4*MAXPATHLEN];
int ret = proc_pidpath(pid, pathbuf, sizeof(pathbuf));
if (ret <= 0) return nil;
return [[[NSString stringWithUTF8String:pathbuf] stringByResolvingSymlinksInPath] stringByStandardizingPath];
}

int64_t proc_fix_setuid(pid_t pid)
{
NSString *procPath = proc_get_path(pid);
struct stat sb;
if(stat(procPath.fileSystemRepresentation, &sb) == 0) {
if (S_ISREG(sb.st_mode) && (sb.st_mode & S_ISUID)) {
uint64_t proc = proc_for_pid(pid);
uint64_t ucred = proc_get_ucred(proc);
ucred_set_svuid(ucred, 0);
return 0;
}
else {
return 10;
}
}
else {
return 5;
}
}
71 changes: 38 additions & 33 deletions BaseBin/systemhook/src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,28 +44,10 @@ mach_port_t jbdSystemWideMachPort(void)
return outPort;
}

xpc_object_t sendJBDMessageSystemWide(xpc_object_t message)
xpc_object_t sendLaunchdMessageFallback(xpc_object_t xdict)
{
mach_port_t jbdPort = jbdSystemWideMachPort();
if (jbdPort == -1) return nil;

xpc_object_t pipe = xpc_pipe_create_from_port(jbdPort, 0);

xpc_object_t xreply = nil;
int err = xpc_pipe_routine(pipe, message, &xreply);
xpc_release(pipe);
mach_port_deallocate(mach_task_self(), jbdPort);
if (err != 0) {
return nil;
}

return xreply;
}

xpc_object_t sendLaunchdMessageFallback(xpc_object_t message)
{
xpc_dictionary_set_bool(message, "jailbreak", true);
xpc_dictionary_set_bool(message, "sw-fallback", true);
xpc_dictionary_set_bool(xdict, "jailbreak", true);
xpc_dictionary_set_bool(xdict, "jailbreak-systemwide", true);

void* pipePtr = NULL;
if(_os_alloc_once_table[1].once == -1)
Expand All @@ -78,14 +60,43 @@ xpc_object_t sendLaunchdMessageFallback(xpc_object_t message)
if (!pipePtr) _os_alloc_once_table[1].once = -1;
}

struct xpc_global_data* globalData = pipePtr;
xpc_object_t pipe = globalData->xpc_bootstrap_pipe;

xpc_object_t xreply;
xpc_pipe_routine_with_flags(pipe, message, &xreply, 0);
xpc_object_t xreply = nil;
if (pipePtr) {
struct xpc_global_data* globalData = pipePtr;
xpc_object_t pipe = globalData->xpc_bootstrap_pipe;
if (pipe) {
int err = xpc_pipe_routine_with_flags(pipe, xdict, &xreply, 0);
if (err != 0) {
return nil;
}
}
}
return xreply;
}

xpc_object_t sendJBDMessageSystemWide(xpc_object_t xdict)
{
xpc_object_t jbd_xreply = nil;
if (jbdSystemWideIsReachable()) {
mach_port_t jbdPort = jbdSystemWideMachPort();
if (jbdPort != -1) {
xpc_object_t pipe = xpc_pipe_create_from_port(jbdPort, 0);
if (pipe) {
int err = xpc_pipe_routine(pipe, xdict, &jbd_xreply);
if (err != 0) jbd_xreply = nil;
xpc_release(pipe);
}
mach_port_deallocate(mach_task_self(), jbdPort);
}
}

if (!jbd_xreply && getpid() != 1) {
return sendLaunchdMessageFallback(xdict);
}

return jbd_xreply;
}

int64_t jbdswFixSetuid(void)
{
xpc_object_t message = xpc_dictionary_create_empty();
Expand Down Expand Up @@ -139,13 +150,7 @@ int64_t jbdswDebugMe(void)
{
xpc_object_t message = xpc_dictionary_create_empty();
xpc_dictionary_set_uint64(message, "id", JBD_MSG_DEBUG_ME);
xpc_object_t reply;
if (jbdSystemWideIsReachable()) {
reply = sendJBDMessageSystemWide(message);
}
else {
reply = sendLaunchdMessageFallback(message);
}
xpc_object_t reply = sendJBDMessageSystemWide(message);
int64_t result = -1;
if (reply) {
result = xpc_dictionary_get_int64(reply, "result");
Expand Down
Loading

0 comments on commit a9752a6

Please sign in to comment.