Skip to content

Commit

Permalink
Use jailbreakd to spawn root processes
Browse files Browse the repository at this point in the history
  • Loading branch information
asdfugil committed Jun 13, 2024
1 parent 55b7c51 commit 2658623
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 147 deletions.
147 changes: 20 additions & 127 deletions palera1nLoader/Utilities/CommandRunner.swift
Original file line number Diff line number Diff line change
@@ -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<CChar>?] = 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<CChar>?] = 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<UInt8>.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<CChar>.self))
stdoutStr += str
}
}
stderrSource.setEventHandler {
let buffer = UnsafeMutablePointer<UInt8>.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<CChar>.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"));
}
2 changes: 2 additions & 0 deletions palera1nLoader/XPC/bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
#include <spawn.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <xpc/xpc.h>
#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 */
20 changes: 1 addition & 19 deletions palera1nLoader/XPC/jailbreakd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
21 changes: 20 additions & 1 deletion palera1nLoader/XPC/jailbreakd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 2658623

Please sign in to comment.