diff --git a/palera1nLoader/Utilities/CommandRunner.swift b/palera1nLoader/Utilities/CommandRunner.swift index 834aa2d6..8cea52a6 100644 --- a/palera1nLoader/Utilities/CommandRunner.swift +++ b/palera1nLoader/Utilities/CommandRunner.swift @@ -1,138 +1,31 @@ -// -// CommandRunner.swift -// palera1nLoader -// -// Created by Lakhan Lothiyi on 12/11/2022. -// -// This code belongs to Amy While and is from https://github.com/elihwyma/Pogo/blob/main/Pogo/CommandRunner.swift - import Foundation import Darwin.POSIX import Bridge -@discardableResult func spawn(command: String, args: [String]) -> Int { - var pipestdout: [Int32] = [0, 0] - var pipestderr: [Int32] = [0, 0] - - let bufsiz = Int(BUFSIZ) - - pipe(&pipestdout) - pipe(&pipestderr) +let XPC_ARRAY_APPEND = -1; - guard fcntl(pipestdout[0], F_SETFL, O_NONBLOCK) != -1 else { - log(type: .error, msg: "Could not open stdout" ) - return -1 - } - guard fcntl(pipestderr[0], F_SETFL, O_NONBLOCK) != -1 else { - log(type: .error, msg: "Could not open stderr" ) - return -1 - } - - let args: [String] = [String(command.split(separator: "/").last!)] + args - let argv: [UnsafeMutablePointer?] = args.map { $0.withCString(strdup) } - defer { for case let arg? in argv { free(arg) } } - - var fileActions: posix_spawn_file_actions_t? - posix_spawn_file_actions_init(&fileActions) - posix_spawn_file_actions_addclose(&fileActions, pipestdout[0]) - posix_spawn_file_actions_addclose(&fileActions, pipestderr[0]) - posix_spawn_file_actions_adddup2(&fileActions, pipestdout[1], STDOUT_FILENO) - posix_spawn_file_actions_adddup2(&fileActions, pipestderr[1], STDERR_FILENO) - posix_spawn_file_actions_addclose(&fileActions, pipestdout[1]) - posix_spawn_file_actions_addclose(&fileActions, pipestderr[1]) +@discardableResult func spawn(command: String, args: [String]) -> Int { + var xdict = xpc_dictionary_create(nil, nil, 0); + var xargv = xpc_array_create(nil, 0); + var xenvp = xpc_array_create(nil, 0); + xpc_dictionary_set_uint64(xdict, "cmd", UInt64(JBD_CMD_RUN_AS_ROOT)); + xpc_dictionary_set_string(xdict, "path", command); - var attr: posix_spawnattr_t? - posix_spawnattr_init(&attr) - posix_spawnattr_set_persona_np(&attr, 99, UInt32(POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE)); - posix_spawnattr_set_persona_uid_np(&attr, 0); - posix_spawnattr_set_persona_gid_np(&attr, 0); + xpc_array_set_string(xargv, XPC_ARRAY_APPEND, command); + for arg in args { + xpc_array_set_string(xargv, XPC_ARRAY_APPEND, arg); + } + xpc_array_set_string(xenvp, XPC_ARRAY_APPEND, "PATH=/usr/local/sbin:/var/jb/usr/local/sbin:/usr/local/bin:/var/jb/usr/local/bin:/usr/sbin:/var/jb/usr/sbin:/usr/bin:/var/jb/usr/bin:/sbin:/var/jb/sbin:/bin:/var/jb/bin:/usr/bin/X11:/var/jb/usr/bin/X11:/usr/games:/var/jb/usr/games"); + xpc_array_set_string(xenvp, XPC_ARRAY_APPEND, "NO_PASSWORD_PROMPT=1"); + xpc_dictionary_set_value(xdict, "argv", xargv); + xpc_dictionary_set_value(xdict, "envp", xenvp); - let env = [ "PATH=/usr/local/sbin:/var/jb/usr/local/sbin:/usr/local/bin:/var/jb/usr/local/bin:/usr/sbin:/var/jb/usr/sbin:/usr/bin:/var/jb/usr/bin:/sbin:/var/jb/sbin:/bin:/var/jb/bin:/usr/bin/X11:/var/jb/usr/bin/X11:/usr/games:/var/jb/usr/games", "NO_PASSWORD_PROMPT=1"] - let proenv: [UnsafeMutablePointer?] = env.map { $0.withCString(strdup) } - defer { for case let pro? in proenv { free(pro) } } + var xreply = jailbreak_send_jailbreakd_message_with_reply_sync(xdict); + defer { xpc_release(xreply!); } - var pid: pid_t = 0 - let spawnStatus = posix_spawn(&pid, command, &fileActions, &attr, argv + [nil], proenv + [nil]) - if spawnStatus != 0 { - return Int(spawnStatus) + if (xpc_dictionary_get_int64(xdict, "error") != 0) { + return Int(xpc_dictionary_get_int64(xdict, "error")); } - close(pipestdout[1]) - close(pipestderr[1]) - - var stdoutStr = "" - var stderrStr = "" - - let mutex = DispatchSemaphore(value: 0) - let readQueue = DispatchQueue(label: "in.palera.loader.command", - qos: .userInitiated, - attributes: .concurrent, - autoreleaseFrequency: .inherit, - target: nil) - - let stdoutSource = DispatchSource.makeReadSource(fileDescriptor: pipestdout[0], queue: readQueue) - let stderrSource = DispatchSource.makeReadSource(fileDescriptor: pipestderr[0], queue: readQueue) - - stdoutSource.setCancelHandler { - close(pipestdout[0]) - mutex.signal() - } - stderrSource.setCancelHandler { - close(pipestderr[0]) - mutex.signal() - } - - stdoutSource.setEventHandler { - let buffer = UnsafeMutablePointer.allocate(capacity: bufsiz) - defer { buffer.deallocate() } - - let bytesRead = read(pipestdout[0], buffer, bufsiz) - guard bytesRead > 0 else { - if bytesRead == -1 && errno == EAGAIN { - return - } - - stdoutSource.cancel() - return - } - - let array = Array(UnsafeBufferPointer(start: buffer, count: bytesRead)) + [UInt8(0)] - array.withUnsafeBufferPointer { ptr in - let str = String(cString: unsafeBitCast(ptr.baseAddress, to: UnsafePointer.self)) - stdoutStr += str - } - } - stderrSource.setEventHandler { - let buffer = UnsafeMutablePointer.allocate(capacity: bufsiz) - defer { buffer.deallocate() } - - let bytesRead = read(pipestderr[0], buffer, bufsiz) - guard bytesRead > 0 else { - if bytesRead == -1 && errno == EAGAIN { - return - } - - stderrSource.cancel() - return - } - - let array = Array(UnsafeBufferPointer(start: buffer, count: bytesRead)) + [UInt8(0)] - array.withUnsafeBufferPointer { ptr in - let str = String(cString: unsafeBitCast(ptr.baseAddress, to: UnsafePointer.self)) - stderrStr += str - } - } - - stdoutSource.resume() - stderrSource.resume() - - mutex.wait() - mutex.wait() - var status: Int32 = 0 - waitpid(pid, &status, 0) - - NSLog("stdout = \n%@", stdoutStr); - NSLog("stderr = \n%@", stdoutStr); - - return Int(status) + return Int(xpc_dictionary_get_int64(xdict, "status")); } diff --git a/palera1nLoader/XPC/bridge.h b/palera1nLoader/XPC/bridge.h index 26eb244e..571c98f4 100644 --- a/palera1nLoader/XPC/bridge.h +++ b/palera1nLoader/XPC/bridge.h @@ -8,8 +8,10 @@ #include #include #include +#include #include "jailbreakd.h" const char* xpc_strerror(int err); +static xpc_object_t jailbreak_send_jailbreakd_message_with_reply_sync(xpc_object_t xdict); #endif /* bridge_h */ diff --git a/palera1nLoader/XPC/jailbreakd.c b/palera1nLoader/XPC/jailbreakd.c index c35519bd..b447c106 100644 --- a/palera1nLoader/XPC/jailbreakd.c +++ b/palera1nLoader/XPC/jailbreakd.c @@ -9,27 +9,9 @@ #if !TARGET_OS_SIMULATOR -enum { - JBD_CMD_GET_PINFO_FLAGS = 1, - JBD_CMD_GET_PREBOOTPATH, - JBD_CMD_GET_PINFO_KERNEL_INFO, - JBD_CMD_GET_PINFO_ROOTDEV, - JBD_CMD_DEPLOY_BOOTSTRAP, - JBD_CMD_OBLITERATE_JAILBREAK, - JBD_CMD_PERFORM_REBOOT3, - JBD_CMD_OVERWRITE_FILE_WITH_CONTENT, - JBD_CMD_INTERCEPT_USERSPACE_PANIC, - JBD_CMD_EXIT_SAFE_MODE -}; - -enum { - LAUNCHD_CMD_RELOAD_JB_ENV = 1, - LAUNCHD_CMD_SET_TWEAKLOADER_PATH, -}; - const char* xpc_strerror(int error); -static xpc_object_t jailbreak_send_jailbreakd_message_with_reply_sync(xpc_object_t xdict) { +xpc_object_t jailbreak_send_jailbreakd_message_with_reply_sync(xpc_object_t xdict) { xpc_connection_t connection = xpc_connection_create_mach_service("in.palera.palera1nd.systemwide", NULL, 0); if (xpc_get_type(connection) == XPC_TYPE_ERROR) { return connection; diff --git a/palera1nLoader/XPC/jailbreakd.h b/palera1nLoader/XPC/jailbreakd.h index 0004c16b..6e6bbd07 100644 --- a/palera1nLoader/XPC/jailbreakd.h +++ b/palera1nLoader/XPC/jailbreakd.h @@ -57,8 +57,27 @@ struct xpc_global_data { extern struct _os_alloc_once_s _os_alloc_once_table[]; -#define OS_ALLOC_ONCE_KEY_LIBXPC 1 +enum { + JBD_CMD_GET_PINFO_FLAGS = 1, + JBD_CMD_GET_PREBOOTPATH, + JBD_CMD_GET_PINFO_KERNEL_INFO, + JBD_CMD_GET_PINFO_ROOTDEV, + JBD_CMD_DEPLOY_BOOTSTRAP, + JBD_CMD_OBLITERATE_JAILBREAK, + JBD_CMD_PERFORM_REBOOT3, + JBD_CMD_OVERWRITE_FILE_WITH_CONTENT, + JBD_CMD_INTERCEPT_USERSPACE_PANIC, + JBD_CMD_EXIT_SAFE_MODE, + JBD_CMD_RUN_AS_ROOT +}; + +enum { + LAUNCHD_CMD_RELOAD_JB_ENV = 1, + LAUNCHD_CMD_SET_TWEAKLOADER_PATH, +}; + +#define OS_ALLOC_ONCE_KEY_LIBXPC 1 uint64_t GetPinfoFlags_impl(void);