├── .gitignore ├── .gitmodules ├── Makefile ├── Shims.x ├── Tweak.x ├── bootstrap.h ├── defaultheaders ├── launch.h └── xpc ├── dispatch └── mach_private.h ├── entitlements.xml ├── framework ├── fullheaders ├── launch.h └── xpc ├── layout ├── DEBIAN │ ├── control │ ├── postinst │ └── prerm └── Library │ ├── LaunchDaemons │ └── com.rpetrich.rocketbootstrapd.plist │ └── MobileSubstrate │ └── DynamicLibraries │ ├── RocketBootstrap.dylib │ └── RocketBootstrap.plist ├── libjailbreak_xpc.h ├── log.h ├── overlayheaders ├── rocketbootstrap.h ├── rocketbootstrap_dynamic.h ├── rocketbootstrap_internal.h ├── rocketd.c ├── rocketd_reenable.c ├── sandbox.h ├── tests ├── Makefile ├── control ├── framework └── tests.m └── unfair_lock.h /.gitignore: -------------------------------------------------------------------------------- 1 | ._* 2 | *.deb 3 | .debmake 4 | _ 5 | obj 6 | .theos 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "framework"] 2 | path = framework 3 | url = git://github.com/rpetrich/theos.git 4 | [submodule "LightMessaging"] 5 | path = LightMessaging 6 | url = git://github.com/rpetrich/LightMessaging.git 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LIBRARY_NAME = librocketbootstrap 2 | librocketbootstrap_FILES = Tweak.x Shims.x 3 | librocketbootstrap_LIBRARIES = substrate 4 | librocketbootstrap_FRAMEWORKS = Foundation 5 | librocketbootstrap_USE_MODULES = 0 6 | 7 | TOOL_NAME = rocketd _rocketd_reenable 8 | rocketd_FILES = rocketd.c 9 | rocketd_CFLAGS = -fblocks 10 | rocketd_FRAMEWORKS = CoreFoundation 11 | rocketd_INSTALL_PATH = /usr/libexec 12 | rocketd_USE_MODULES = 0 13 | rocketd_CODESIGN_FLAGS = -Sentitlements.xml 14 | 15 | _rocketd_reenable_FILES = rocketd_reenable.c 16 | _rocketd_reenable_INSTALL_PATH = /usr/libexec 17 | _rocketd_reenable_USE_MODULES = 0 18 | _rocketd_reenable_CODESIGN_FLAGS = -Sentitlements.xml 19 | 20 | ADDITIONAL_CFLAGS = -std=c99 -Ioverlayheaders 21 | 22 | # Support targeting 3.0 in packaged builds, but allow testing packages/builds to be missing support for old iOS versions 23 | XCODE4_PATH ?= /Applications/Xcode_Legacy.app 24 | XCODE6_PATH ?= /Volumes/Xcode/Xcode.app 25 | XCODE9_PATH ?= /Volumes/Xcode_9.4.1/Xcode.app 26 | 27 | ifeq ($(wildcard $(XCODE4_PATH)/.*),) 28 | ADDITIONAL_CFLAGS += -Idefaultheaders 29 | IPHONE_ARCHS = armv7 armv7s arm64 arm64e 30 | TARGET_IPHONEOS_DEPLOYMENT_VERSION = 8.4 31 | ifeq ($(FINALPACKAGE),1) 32 | $(error Building final package requires a legacy Xcode install!) 33 | endif 34 | else 35 | armv6_CFLAGS += -Ifullheaders 36 | armv7_CFLAGS += -Ifullheaders 37 | armv7s_CFLAGS += -Ifullheaders 38 | arm64_CFLAGS += -Idefaultheaders 39 | arm64e_CFLAGS += -Idefaultheaders 40 | rocketd_IPHONE_ARCHS = armv6 arm64 41 | _rocketd_reenable_IPHONE_ARCHS = armv6 arm64 42 | IPHONE_ARCHS = armv6 armv7 armv7s arm64 arm64e 43 | SDKVERSION_armv6 = 5.1 44 | INCLUDE_SDKVERSION_armv6 = 8.4 45 | TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv6 = 3.0 46 | TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv7 = 4.0 47 | TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv7s = 6.0 48 | TARGET_IPHONEOS_DEPLOYMENT_VERSION_arm64 = 7.0 49 | TARGET_IPHONEOS_DEPLOYMENT_VERSION_arm64e = 12.0 50 | TARGET_IPHONEOS_DEPLOYMENT_VERSION = 9.0 51 | THEOS_PLATFORM_SDK_ROOT_armv6 = $(XCODE4_PATH)/Contents/Developer 52 | THEOS_PLATFORM_SDK_ROOT_armv7 = $(XCODE6_PATH)/Contents/Developer 53 | THEOS_PLATFORM_SDK_ROOT_armv7s = $(XCODE6_PATH)/Contents/Developer 54 | THEOS_PLATFORM_SDK_ROOT_arm64 = $(XCODE9_PATH)/Contents/Developer 55 | endif 56 | 57 | include framework/makefiles/common.mk 58 | include framework/makefiles/library.mk 59 | include framework/makefiles/tool.mk 60 | 61 | stage:: 62 | mkdir -p "$(THEOS_STAGING_DIR)/usr/include" 63 | cp -a rocketbootstrap.h rocketbootstrap_dynamic.h "$(THEOS_STAGING_DIR)/usr/include" 64 | plutil -convert binary1 "$(THEOS_STAGING_DIR)/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.plist" 65 | plutil -convert binary1 "$(THEOS_STAGING_DIR)/Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist" 66 | -------------------------------------------------------------------------------- /Shims.x: -------------------------------------------------------------------------------- 1 | #import "log.h" 2 | #import "unfair_lock.h" 3 | #import "rocketbootstrap_internal.h" 4 | 5 | #import 6 | #import 7 | #import 8 | 9 | static unfair_lock shim_lock; 10 | 11 | kern_return_t bootstrap_look_up3(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, const uuid_t instance_id, uint64_t flags) __attribute__((weak_import)); 12 | static kern_return_t (*_bootstrap_look_up3)(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, const uuid_t instance_id, uint64_t flags); 13 | 14 | static kern_return_t $bootstrap_look_up3(mach_port_t bp, const name_t service_name, mach_port_t *sp, pid_t target_pid, const uuid_t instance_id, uint64_t flags) 15 | { 16 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 17 | NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary; 18 | id obj = [threadDictionary objectForKey:@"rocketbootstrap_intercept_next_lookup"]; 19 | if (obj) { 20 | [threadDictionary removeObjectForKey:@"rocketbootstrap_intercept_next_lookup"]; 21 | [pool drain]; 22 | return rocketbootstrap_look_up(bp, service_name, sp); 23 | } 24 | [pool drain]; 25 | return _bootstrap_look_up3(bp, service_name, sp, target_pid, instance_id, flags); 26 | } 27 | 28 | static void hook_bootstrap_lookup(void) 29 | { 30 | static bool hooked_bootstrap_look_up; 31 | unfair_lock_lock(&shim_lock); 32 | if (!hooked_bootstrap_look_up) { 33 | MSHookFunction(bootstrap_look_up3, $bootstrap_look_up3, (void **)&_bootstrap_look_up3); 34 | hooked_bootstrap_look_up = true; 35 | } 36 | unfair_lock_unlock(&shim_lock); 37 | } 38 | 39 | CFMessagePortRef rocketbootstrap_cfmessageportcreateremote(CFAllocatorRef allocator, CFStringRef name) 40 | { 41 | if (rocketbootstrap_is_passthrough()) 42 | return CFMessagePortCreateRemote(allocator, name); 43 | hook_bootstrap_lookup(); 44 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 45 | NSMutableDictionary *threadDictionary = [NSThread currentThread].threadDictionary; 46 | [threadDictionary setObject:(id)kCFBooleanTrue forKey:@"rocketbootstrap_intercept_next_lookup"]; 47 | CFMessagePortRef result = CFMessagePortCreateRemote(allocator, name); 48 | [threadDictionary removeObjectForKey:@"rocketbootstrap_intercept_next_lookup"]; 49 | [pool drain]; 50 | return result; 51 | } 52 | 53 | kern_return_t rocketbootstrap_cfmessageportexposelocal(CFMessagePortRef messagePort) 54 | { 55 | if (rocketbootstrap_is_passthrough()) 56 | return 0; 57 | CFStringRef name = CFMessagePortGetName(messagePort); 58 | if (!name) 59 | return -1; 60 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 61 | kern_return_t result = rocketbootstrap_unlock([(NSString *)name UTF8String]); 62 | [pool drain]; 63 | return result; 64 | } 65 | 66 | @interface CPDistributedMessagingCenter : NSObject 67 | - (void)_setupInvalidationSource; 68 | @end 69 | 70 | %group messaging_center 71 | 72 | static bool has_hooked_messaging_center; 73 | 74 | %hook CPDistributedMessagingCenter 75 | 76 | - (mach_port_t)_sendPort 77 | { 78 | if (objc_getAssociatedObject(self, &has_hooked_messaging_center)) { 79 | mach_port_t *_sendPort = CHIvarRef(self, _sendPort, mach_port_t); 80 | NSLock **_lock = CHIvarRef(self, _lock, NSLock *); 81 | if (_sendPort && _lock) { 82 | [*_lock lock]; 83 | mach_port_t result = *_sendPort; 84 | if (result == MACH_PORT_NULL) { 85 | NSString **_centerName = CHIvarRef(self, _centerName, NSString *); 86 | if (_centerName && *_centerName && [self respondsToSelector:@selector(_setupInvalidationSource)]) { 87 | mach_port_t bootstrap = MACH_PORT_NULL; 88 | task_get_bootstrap_port(mach_task_self(), &bootstrap); 89 | rocketbootstrap_look_up(bootstrap, [*_centerName UTF8String], _sendPort); 90 | [self _setupInvalidationSource]; 91 | result = *_sendPort; 92 | } 93 | } 94 | [*_lock unlock]; 95 | return result; 96 | } 97 | } 98 | return %orig(); 99 | } 100 | 101 | - (void)runServerOnCurrentThreadProtectedByEntitlement:(id)entitlement 102 | { 103 | if (objc_getAssociatedObject(self, &has_hooked_messaging_center)) { 104 | NSString **_centerName = CHIvarRef(self, _centerName, NSString *); 105 | if (_centerName && *_centerName) { 106 | rocketbootstrap_unlock([*_centerName UTF8String]); 107 | } 108 | } 109 | %orig(); 110 | } 111 | 112 | %end 113 | 114 | %end 115 | 116 | void rocketbootstrap_distributedmessagingcenter_apply(CPDistributedMessagingCenter *messaging_center) 117 | { 118 | if (rocketbootstrap_is_passthrough()) 119 | return; 120 | unfair_lock_lock(&shim_lock); 121 | if (!has_hooked_messaging_center) { 122 | has_hooked_messaging_center = true; 123 | %init(messaging_center); 124 | } 125 | unfair_lock_unlock(&shim_lock); 126 | objc_setAssociatedObject(messaging_center, &has_hooked_messaging_center, (id)kCFBooleanTrue, OBJC_ASSOCIATION_ASSIGN); 127 | } 128 | 129 | #ifdef __clang__ 130 | 131 | #ifndef __IPHONE_9_0 132 | #define __IPHONE_9_0 90000 133 | #define __AVAILABILITY_INTERNAL__IPHONE_9_0 134 | #endif 135 | 136 | #include 137 | 138 | static xpc_endpoint_t _xpc_endpoint_create(mach_port_t port) 139 | { 140 | static xpc_endpoint_t(*__xpc_endpoint_create)(mach_port_t); 141 | if (!__xpc_endpoint_create) { 142 | MSImageRef libxpc = MSGetImageByName("/usr/lib/system/libxpc.dylib"); 143 | if (!libxpc) { 144 | return NULL; 145 | } 146 | __xpc_endpoint_create = MSFindSymbol(libxpc, "__xpc_endpoint_create"); 147 | if (!__xpc_endpoint_create) { 148 | return NULL; 149 | } 150 | } 151 | return __xpc_endpoint_create(port); 152 | } 153 | 154 | static mach_port_t _xpc_connection_copy_listener_port(xpc_connection_t connection) 155 | { 156 | static mach_port_t(*__xpc_connection_copy_listener_port)(xpc_connection_t); 157 | if (!__xpc_connection_copy_listener_port) { 158 | MSImageRef libxpc = MSGetImageByName("/usr/lib/system/libxpc.dylib"); 159 | if (!libxpc) { 160 | return MACH_PORT_NULL; 161 | } 162 | __xpc_connection_copy_listener_port = MSFindSymbol(libxpc, "__xpc_connection_copy_listener_port"); 163 | if (!__xpc_connection_copy_listener_port) { 164 | return MACH_PORT_NULL; 165 | } 166 | } 167 | return __xpc_connection_copy_listener_port(connection); 168 | } 169 | 170 | xpc_object_t xpc_connection_copy_entitlement_value(xpc_connection_t, const char* entitlement); 171 | 172 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 173 | xpc_connection_t rocketbootstrap_xpc_connection_create(const char *name, dispatch_queue_t targetq, uint64_t flags) 174 | { 175 | mach_port_t bootstrap = MACH_PORT_NULL; 176 | if (task_get_bootstrap_port(mach_task_self(), &bootstrap) != 0) { 177 | return NULL; 178 | } 179 | if (flags & XPC_CONNECTION_MACH_SERVICE_LISTENER) { 180 | if (rocketbootstrap_unlock(name) != 0) { 181 | return NULL; 182 | } 183 | xpc_connection_t result = xpc_connection_create(NULL, targetq); 184 | mach_port_t port = _xpc_connection_copy_listener_port(result); 185 | if (bootstrap_register(bootstrap, (char *)name, port) != 0) { 186 | xpc_release(result); 187 | return NULL; 188 | } 189 | return result; 190 | } 191 | mach_port_t send_port = MACH_PORT_NULL; 192 | if (rocketbootstrap_look_up(bootstrap, name, &send_port) != 0) { 193 | return NULL; 194 | } 195 | xpc_endpoint_t endpoint = _xpc_endpoint_create(send_port); 196 | xpc_connection_t result = xpc_connection_create_from_endpoint(endpoint); 197 | xpc_release(endpoint); 198 | if (targetq != NULL) { 199 | xpc_connection_set_target_queue(result, targetq); 200 | } 201 | return result; 202 | } 203 | 204 | xpc_object_t rocketbootstrap_xpc_connection_copy_application_identifier(xpc_connection_t connection) 205 | { 206 | xpc_object_t application_id = xpc_connection_copy_entitlement_value(connection, "application-identifier"); 207 | if (!application_id) { 208 | return NULL; 209 | } 210 | if (xpc_get_type(application_id) != XPC_TYPE_STRING) { 211 | xpc_release(application_id); 212 | return NULL; 213 | } 214 | xpc_object_t team_id = xpc_connection_copy_entitlement_value(connection, "com.apple.developer.team-identifier"); 215 | if (!team_id) { 216 | return application_id; 217 | } 218 | if (xpc_get_type(team_id) != XPC_TYPE_STRING) { 219 | xpc_release(team_id); 220 | return application_id; 221 | } 222 | const char *application_id_str = xpc_string_get_string_ptr(application_id); 223 | const char *team_id_str = xpc_string_get_string_ptr(team_id); 224 | size_t team_id_length = xpc_string_get_length(team_id); 225 | if (memcmp(application_id_str, team_id_str, team_id_length) != 0 || application_id_str[team_id_length] != '.') { 226 | xpc_release(team_id); 227 | return application_id; 228 | } 229 | xpc_object_t trimmed_id = xpc_string_create(application_id_str + team_id_length + 1); 230 | xpc_release(team_id); 231 | xpc_release(application_id); 232 | return trimmed_id; 233 | } 234 | 235 | #endif 236 | -------------------------------------------------------------------------------- /Tweak.x: -------------------------------------------------------------------------------- 1 | #include 2 | #undef __IOS_PROHIBITED 3 | #define __IOS_PROHIBITED 4 | 5 | #include 6 | 7 | #define LIGHTMESSAGING_USE_ROCKETBOOTSTRAP 0 8 | #define LIGHTMESSAGING_TIMEOUT 300 9 | #import "LightMessaging/LightMessaging.h" 10 | #import "log.h" 11 | #import "unfair_lock.h" 12 | 13 | #import "rocketbootstrap_internal.h" 14 | 15 | #ifndef __APPLE_API_PRIVATE 16 | #define __APPLE_API_PRIVATE 17 | #include "sandbox.h" 18 | #undef __APPLE_API_PRIVATE 19 | #else 20 | #include "sandbox.h" 21 | #endif 22 | 23 | #import 24 | #import 25 | #import 26 | //#import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #define __DISPATCH_INDIRECT__ 32 | #define DISPATCH_MACH_SPI 1 33 | #import 34 | 35 | extern int *_NSGetArgc(void); 36 | extern const char ***_NSGetArgv(void); 37 | 38 | #define kUserAppsPath "/var/mobile/Applications/" 39 | #define kSystemAppsPath "/Applications/" 40 | 41 | static BOOL isDaemon; 42 | 43 | static kern_return_t rocketbootstrap_look_up_with_timeout(mach_port_t bp, const name_t service_name, mach_port_t *sp, mach_msg_timeout_t timeout) 44 | { 45 | #ifdef DEBUG 46 | NSLog(@"RocketBootstrap: rocketbootstrap_look_up(%llu, %s, %p)", (unsigned long long)bp, service_name, sp); 47 | #endif 48 | if (rocketbootstrap_is_passthrough() || isDaemon) { 49 | if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_5_0) { 50 | int sandbox_result = sandbox_check(getpid(), "mach-lookup", SANDBOX_FILTER_LOCAL_NAME | SANDBOX_CHECK_NO_REPORT, service_name); 51 | if (sandbox_result) { 52 | return sandbox_result; 53 | } 54 | } 55 | return bootstrap_look_up(bp, service_name, sp); 56 | } 57 | // Compatibility mode for Flex, limits it to only the processes in rbs 1.0.1 and earlier 58 | if (strcmp(service_name, "FLMessagingCenterSpringboard") == 0) { 59 | const char **argv = *_NSGetArgv(); 60 | size_t arg0len = strlen(argv[0]); 61 | bool allowed = false; 62 | if ((arg0len > sizeof(kUserAppsPath)) && (memcmp(argv[0], kUserAppsPath, sizeof(kUserAppsPath) - 1) == 0)) 63 | allowed = true; 64 | if ((arg0len > sizeof(kSystemAppsPath)) && (memcmp(argv[0], kSystemAppsPath, sizeof(kSystemAppsPath) - 1) == 0)) 65 | allowed = true; 66 | if (!allowed) 67 | return 1; 68 | } 69 | // Ask our service running inside of the com.apple.ReportCrash.SimulateCrash job 70 | mach_port_t servicesPort = MACH_PORT_NULL; 71 | kern_return_t err = bootstrap_look_up(bp, "com.apple.ReportCrash.SimulateCrash", &servicesPort); 72 | if (err) { 73 | #ifdef DEBUG 74 | NSLog(@"RocketBootstrap: = %lld (failed to lookup com.apple.ReportCrash.SimulateCrash)", (unsigned long long)err); 75 | #endif 76 | return err; 77 | } 78 | mach_port_t selfTask = mach_task_self(); 79 | // Create a reply port 80 | mach_port_name_t replyPort = MACH_PORT_NULL; 81 | err = mach_port_allocate(selfTask, MACH_PORT_RIGHT_RECEIVE, &replyPort); 82 | if (err) { 83 | #ifdef DEBUG 84 | NSLog(@"RocketBootstrap: = %lld (failed to allocate port)", (unsigned long long)err); 85 | #endif 86 | mach_port_deallocate(selfTask, servicesPort); 87 | return err; 88 | } 89 | // Send message 90 | size_t service_name_size = strlen(service_name); 91 | size_t size = (sizeof(_rocketbootstrap_lookup_query_t) + service_name_size + 3) & ~3; 92 | if (size < sizeof(_rocketbootstrap_lookup_response_t)) { 93 | size = sizeof(_rocketbootstrap_lookup_response_t); 94 | } 95 | char buffer[size]; 96 | _rocketbootstrap_lookup_query_t *message = (_rocketbootstrap_lookup_query_t *)&buffer[0]; 97 | memset(message, 0, sizeof(_rocketbootstrap_lookup_response_t)); 98 | message->head.msgh_id = ROCKETBOOTSTRAP_LOOKUP_ID; 99 | message->head.msgh_size = size; 100 | message->head.msgh_remote_port = servicesPort; 101 | message->head.msgh_local_port = replyPort; 102 | message->head.msgh_reserved = 0; 103 | message->head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); 104 | message->name_length = service_name_size; 105 | memcpy(&message->name[0], service_name, service_name_size); 106 | mach_msg_option_t options = MACH_SEND_MSG | MACH_RCV_MSG; 107 | if (timeout == 0) { 108 | timeout = MACH_MSG_TIMEOUT_NONE; 109 | } else { 110 | options |= MACH_SEND_TIMEOUT | MACH_RCV_TIMEOUT; 111 | } 112 | err = mach_msg(&message->head, options, size, size, replyPort, timeout, MACH_PORT_NULL); 113 | // Parse response 114 | if (!err) { 115 | _rocketbootstrap_lookup_response_t *response = (_rocketbootstrap_lookup_response_t *)message; 116 | if (response->body.msgh_descriptor_count) { 117 | *sp = response->response_port.name; 118 | #ifdef DEBUG 119 | NSLog(@"RocketBootstrap: = 0 (success)"); 120 | #endif 121 | } else { 122 | err = 1; 123 | #ifdef DEBUG 124 | NSLog(@"RocketBootstrap: = 1 (disallowed)"); 125 | #endif 126 | } 127 | } 128 | // Cleanup 129 | mach_port_deallocate(selfTask, servicesPort); 130 | mach_port_deallocate(selfTask, replyPort); 131 | return err; 132 | } 133 | 134 | kern_return_t rocketbootstrap_look_up(mach_port_t bp, const name_t service_name, mach_port_t *sp) 135 | { 136 | return rocketbootstrap_look_up_with_timeout(bp, service_name, sp, LIGHTMESSAGING_TIMEOUT); 137 | } 138 | 139 | static NSMutableSet *allowedNames; 140 | static unfair_lock namesLock; 141 | 142 | static void daemon_restarted_callback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) 143 | { 144 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 145 | unfair_lock_lock(&namesLock); 146 | NSSet *allNames = [allowedNames copy]; 147 | unfair_lock_unlock(&namesLock); 148 | for (NSString *name in allNames) { 149 | const char *service_name = [name UTF8String]; 150 | LMConnectionSendOneWay(&connection, 0, service_name, strlen(service_name)); 151 | } 152 | [allNames release]; 153 | [pool drain]; 154 | } 155 | 156 | kern_return_t rocketbootstrap_unlock(const name_t service_name) 157 | { 158 | #ifdef DEBUG 159 | NSLog(@"RocketBootstrap: rocketbootstrap_unlock(%s)", service_name); 160 | #endif 161 | if (rocketbootstrap_is_passthrough()) 162 | return 0; 163 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 164 | NSString *serviceNameString = [NSString stringWithUTF8String:service_name]; 165 | unfair_lock_lock(&namesLock); 166 | BOOL containedName; 167 | if (!allowedNames) { 168 | allowedNames = [[NSMutableSet alloc] init]; 169 | [allowedNames addObject:serviceNameString]; 170 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), &daemon_restarted_callback, daemon_restarted_callback, CFSTR("com.rpetrich.rocketd.started"), NULL, CFNotificationSuspensionBehaviorCoalesce); 171 | containedName = NO; 172 | } else { 173 | containedName = [allowedNames containsObject:serviceNameString]; 174 | if (!containedName) { 175 | [allowedNames addObject:serviceNameString]; 176 | } 177 | } 178 | unfair_lock_unlock(&namesLock); 179 | [pool drain]; 180 | if (containedName) { 181 | return 0; 182 | } 183 | // Ask rocketd to unlock it for us 184 | int sandbox_result = sandbox_check(getpid(), "mach-lookup", SANDBOX_FILTER_LOCAL_NAME | SANDBOX_CHECK_NO_REPORT, kRocketBootstrapUnlockService); 185 | if (sandbox_result) { 186 | return sandbox_result; 187 | } 188 | return LMConnectionSendOneWay(&connection, 0, service_name, strlen(service_name)); 189 | } 190 | 191 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 192 | kern_return_t rocketbootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp) 193 | { 194 | kern_return_t err = rocketbootstrap_unlock(service_name); 195 | if (err) 196 | return err; 197 | return bootstrap_register(bp, service_name, sp); 198 | } 199 | #pragma GCC diagnostic warning "-Wdeprecated-declarations" 200 | 201 | static kern_return_t handle_bootstrap_lookup_msg(mach_msg_header_t *request) 202 | { 203 | _rocketbootstrap_lookup_query_t *lookup_message = (_rocketbootstrap_lookup_query_t *)request; 204 | // Extract service name 205 | size_t length = request->msgh_size - offsetof(_rocketbootstrap_lookup_query_t, name); 206 | if (lookup_message->name_length <= length) { 207 | length = lookup_message->name_length; 208 | } 209 | #ifdef DEBUG 210 | NSLog(@"RocketBootstrap: handle_bootstrap_lookup_msg(%.*s)", (int)length, &lookup_message->name[0]); 211 | #endif 212 | // Ask rocketd if it's unlocked 213 | LMResponseBuffer buffer; 214 | if (LMConnectionSendTwoWay(&connection, 1, &lookup_message->name[0], length, &buffer)) 215 | return 1; 216 | BOOL nameIsAllowed = LMResponseConsumeInteger(&buffer) != 0; 217 | // Lookup service port 218 | mach_port_t servicePort = MACH_PORT_NULL; 219 | mach_port_t selfTask = mach_task_self(); 220 | kern_return_t err; 221 | if (nameIsAllowed) { 222 | mach_port_t bootstrap = MACH_PORT_NULL; 223 | err = task_get_bootstrap_port(selfTask, &bootstrap); 224 | if (!err) { 225 | char *buffer = malloc(length + 1); 226 | if (buffer) { 227 | memcpy(buffer, lookup_message->name, length); 228 | buffer[length] = '\0'; 229 | err = bootstrap_look_up(bootstrap, buffer, &servicePort); 230 | free(buffer); 231 | } 232 | } 233 | } 234 | // Generate response 235 | _rocketbootstrap_lookup_response_t response; 236 | response.head.msgh_id = 0; 237 | response.head.msgh_size = (sizeof(_rocketbootstrap_lookup_response_t) + 3) & ~3; 238 | response.head.msgh_remote_port = request->msgh_remote_port; 239 | response.head.msgh_local_port = MACH_PORT_NULL; 240 | response.head.msgh_reserved = 0; 241 | response.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0); 242 | if (servicePort != MACH_PORT_NULL) { 243 | response.head.msgh_bits |= MACH_MSGH_BITS_COMPLEX; 244 | response.body.msgh_descriptor_count = 1; 245 | response.response_port.name = servicePort; 246 | response.response_port.disposition = MACH_MSG_TYPE_COPY_SEND; 247 | response.response_port.type = MACH_MSG_PORT_DESCRIPTOR; 248 | } else { 249 | response.body.msgh_descriptor_count = 0; 250 | } 251 | // Send response 252 | err = mach_msg(&response.head, MACH_SEND_MSG, response.head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); 253 | if (err) { 254 | if (servicePort != MACH_PORT_NULL) { 255 | mach_port_mod_refs(selfTask, servicePort, MACH_PORT_RIGHT_SEND, -1); 256 | } 257 | } 258 | return err; 259 | } 260 | 261 | mach_msg_return_t mach_msg_server_once(boolean_t (*demux)(mach_msg_header_t *, mach_msg_header_t *), mach_msg_size_t max_size, mach_port_t rcv_name, mach_msg_options_t options); 262 | 263 | static mach_msg_return_t (*_mach_msg_server_once)(boolean_t (*demux)(mach_msg_header_t *, mach_msg_header_t *), mach_msg_size_t max_size, mach_port_t rcv_name, mach_msg_options_t options); 264 | 265 | static unfair_lock server_once_lock; 266 | static boolean_t (*server_once_demux_orig)(mach_msg_header_t *, mach_msg_header_t *); 267 | static bool continue_server_once; 268 | 269 | static boolean_t new_demux(mach_msg_header_t *request, mach_msg_header_t *reply) 270 | { 271 | #ifdef DEBUG 272 | NSLog(@"RocketBootstrap: new_demux(%lld)", (long long)request->msgh_id); 273 | #endif 274 | // Highjack ROCKETBOOTSTRAP_LOOKUP_ID from the com.apple.ReportCrash.SimulateCrash demuxer 275 | if (request->msgh_id == ROCKETBOOTSTRAP_LOOKUP_ID) { 276 | continue_server_once = true; 277 | kern_return_t err = handle_bootstrap_lookup_msg(request); 278 | if (err) { 279 | mach_port_mod_refs(mach_task_self(), reply->msgh_remote_port, MACH_PORT_RIGHT_SEND_ONCE, -1); 280 | } 281 | return true; 282 | } 283 | return server_once_demux_orig(request, reply); 284 | } 285 | 286 | static mach_msg_return_t $mach_msg_server_once(boolean_t (*demux)(mach_msg_header_t *, mach_msg_header_t *), mach_msg_size_t max_size, mach_port_t rcv_name, mach_msg_options_t options) 287 | { 288 | #ifdef DEBUG 289 | NSLog(@"RocketBootstrap: mach_msg_server_once(%p, %llu, %llu, 0x%llx)", demux, (unsigned long long)max_size, (unsigned long long)rcv_name, (long long)options); 290 | #endif 291 | // Highjack com.apple.ReportCrash.SimulateCrash's use of mach_msg_server_once 292 | unfair_lock_lock(&server_once_lock); 293 | if (!server_once_demux_orig) { 294 | server_once_demux_orig = demux; 295 | demux = new_demux; 296 | } else if (server_once_demux_orig == demux) { 297 | demux = new_demux; 298 | } else { 299 | unfair_lock_unlock(&server_once_lock); 300 | mach_msg_return_t result = _mach_msg_server_once(demux, max_size, rcv_name, options); 301 | return result; 302 | } 303 | unfair_lock_unlock(&server_once_lock); 304 | mach_msg_return_t result; 305 | do { 306 | continue_server_once = false; 307 | result = _mach_msg_server_once(demux, max_size, rcv_name, options); 308 | } while (continue_server_once); 309 | return result; 310 | } 311 | 312 | #ifdef __clang__ 313 | 314 | static void *interceptedConnection; 315 | 316 | static void *(*_xpc_connection_create_mach_service)(const char *name, dispatch_queue_t targetq, uint64_t flags); 317 | static void *$xpc_connection_create_mach_service(const char *name, dispatch_queue_t targetq, uint64_t flags) 318 | { 319 | #ifdef DEBUG 320 | NSLog(@"RocketBootstrap: xpc_connection_create_mach_service(%s, %p, %lld)", name, targetq, (unsigned long long)flags); 321 | #endif 322 | if (name && strcmp(name, "com.apple.ReportCrash.SimulateCrash") == 0) { 323 | void *result = _xpc_connection_create_mach_service(name, targetq, flags); 324 | interceptedConnection = result; 325 | return result; 326 | } 327 | return _xpc_connection_create_mach_service(name, targetq, flags); 328 | } 329 | 330 | static void (*__xpc_connection_mach_event)(void *context, dispatch_mach_reason_t reason, dispatch_mach_msg_t message, mach_error_t error); 331 | static void $_xpc_connection_mach_event(void *context, dispatch_mach_reason_t reason, dispatch_mach_msg_t message, mach_error_t error) 332 | { 333 | #ifdef DEBUG 334 | NSLog(@"RocketBootstrap: _xpc_connection_mach_event(%p, %lu, %p, 0x%x)", context, reason, message, error); 335 | #endif 336 | // Highjack ROCKETBOOTSTRAP_LOOKUP_ID from the com.apple.ReportCrash.SimulateCrash XPC service 337 | if ((reason == DISPATCH_MACH_MESSAGE_RECEIVED) && (context == interceptedConnection)) { 338 | size_t size; 339 | mach_msg_header_t *header = dispatch_mach_msg_get_msg(message, &size); 340 | if (header->msgh_id == ROCKETBOOTSTRAP_LOOKUP_ID) { 341 | handle_bootstrap_lookup_msg(header); 342 | return; 343 | } 344 | } 345 | return __xpc_connection_mach_event(context, reason, message, error); 346 | } 347 | 348 | #endif 349 | 350 | static pid_t pid_of_process(const char *process_name) 351 | { 352 | int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; 353 | size_t miblen = 4; 354 | 355 | size_t size; 356 | int st = sysctl(mib, miblen, NULL, &size, NULL, 0); 357 | 358 | struct kinfo_proc * process = NULL; 359 | struct kinfo_proc * newprocess = NULL; 360 | 361 | do { 362 | if (size == 0){ 363 | st = sysctl(mib, miblen, NULL, &size, NULL, 0); 364 | } 365 | 366 | size += size / 10; 367 | newprocess = (struct kinfo_proc *)realloc(process, size); 368 | 369 | if (!newprocess) { 370 | if (process) { 371 | free(process); 372 | } 373 | return 0; 374 | } 375 | 376 | process = newprocess; 377 | st = sysctl(mib, miblen, process, &size, NULL, 0); 378 | 379 | } while (st == -1 && errno == ENOMEM); 380 | 381 | if (st == 0) { 382 | if (size % sizeof(struct kinfo_proc) == 0) { 383 | int nprocess = size / sizeof(struct kinfo_proc); 384 | if (nprocess) { 385 | for (int i = nprocess - 1; i >= 0; i--) { 386 | if (strcmp(process[i].kp_proc.p_comm, process_name) == 0) { 387 | pid_t result = process[i].kp_proc.p_pid; 388 | free(process); 389 | return result; 390 | } 391 | } 392 | } 393 | } 394 | } 395 | 396 | free(process); 397 | return 0; 398 | } 399 | 400 | static int daemon_die_queue; 401 | static CFFileDescriptorRef daemon_die_fd; 402 | static CFRunLoopSourceRef daemon_die_source; 403 | 404 | static void process_terminate_callback(CFFileDescriptorRef fd, CFOptionFlags callBackTypes, void *info); 405 | 406 | static void observe_rocketd(void) 407 | { 408 | // Force the daemon to load 409 | mach_port_t bootstrap = MACH_PORT_NULL; 410 | mach_port_t self = mach_task_self(); 411 | task_get_bootstrap_port(self, &bootstrap); 412 | mach_port_t servicesPort = MACH_PORT_NULL; 413 | kern_return_t err = bootstrap_look_up(bootstrap, "com.rpetrich.rocketbootstrapd", &servicesPort); 414 | if (err) { 415 | #if __clang__ 416 | #pragma clang diagnostic push 417 | #pragma clang diagnostic ignored "-Wavailability" 418 | #endif 419 | pid_t pid; 420 | char *const argv[] = { "/usr/libexec/_rocketd_reenable", NULL }; 421 | if (posix_spawn(&pid, "/usr/libexec/_rocketd_reenable", NULL, NULL, argv, NULL) == 0) { 422 | waitpid(pid, NULL, 0); 423 | } 424 | #if __clang__ 425 | #pragma clang diagnostic pop 426 | #endif 427 | err = bootstrap_look_up(bootstrap, "com.rpetrich.rocketbootstrapd", &servicesPort); 428 | } 429 | if (err) { 430 | #ifdef DEBUG 431 | NSLog(@"RocketBootstrap: failed to launch rocketd!"); 432 | #endif 433 | } else { 434 | mach_port_name_t replyPort = MACH_PORT_NULL; 435 | err = mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, &replyPort); 436 | if (err == 0) { 437 | LMResponseBuffer buffer; 438 | uint32_t size = LMBufferSizeForLength(0); 439 | memset(&buffer.message, 0, sizeof(LMMessage)); 440 | buffer.message.head.msgh_id = 2; 441 | buffer.message.head.msgh_size = size; 442 | buffer.message.head.msgh_local_port = replyPort; 443 | buffer.message.head.msgh_reserved = 0; 444 | buffer.message.head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE); 445 | buffer.message.head.msgh_remote_port = servicesPort; 446 | buffer.message.body.msgh_descriptor_count = 0; 447 | buffer.message.data.in_line.length = 0; 448 | err = mach_msg(&buffer.message.head, MACH_SEND_MSG | MACH_RCV_MSG | _LIGHTMESSAGING_TIMEOUT_FLAGS, size, sizeof(LMResponseBuffer), replyPort, LIGHTMESSAGING_TIMEOUT, MACH_PORT_NULL); 449 | if (err) { 450 | } 451 | // Cleanup 452 | mach_port_mod_refs(self, replyPort, MACH_PORT_RIGHT_RECEIVE, -1); 453 | } 454 | mach_port_mod_refs(self, servicesPort, MACH_PORT_RIGHT_SEND, -1); 455 | } 456 | // Find it 457 | pid_t pid = pid_of_process("rocketd"); 458 | if (pid) { 459 | #ifdef DEBUG 460 | NSLog(@"RocketBootstrap: rocketd found: %d", pid); 461 | #endif 462 | daemon_die_queue = kqueue(); 463 | struct kevent changes; 464 | EV_SET(&changes, pid, EVFILT_PROC, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, NULL); 465 | (void)kevent(daemon_die_queue, &changes, 1, &changes, 1, NULL); 466 | daemon_die_fd = CFFileDescriptorCreate(NULL, daemon_die_queue, true, process_terminate_callback, NULL); 467 | daemon_die_source = CFFileDescriptorCreateRunLoopSource(NULL, daemon_die_fd, 0); 468 | CFRunLoopAddSource(CFRunLoopGetCurrent(), daemon_die_source, kCFRunLoopDefaultMode); 469 | CFFileDescriptorEnableCallBacks(daemon_die_fd, kCFFileDescriptorReadCallBack); 470 | } else { 471 | NSLog(@"RocketBootstrap: unable to find rocketd!"); 472 | } 473 | } 474 | 475 | static void process_terminate_callback(CFFileDescriptorRef fd, CFOptionFlags callBackTypes, void *info) 476 | { 477 | struct kevent event; 478 | (void)kevent(daemon_die_queue, NULL, 0, &event, 1, NULL); 479 | NSLog(@"RocketBootstrap: rocketd terminated: %d, relaunching", (int)(pid_t)event.ident); 480 | // Cleanup 481 | CFRunLoopRemoveSource(CFRunLoopGetCurrent(), daemon_die_source, kCFRunLoopDefaultMode); 482 | CFRelease(daemon_die_source); 483 | CFRelease(daemon_die_fd); 484 | close(daemon_die_queue); 485 | observe_rocketd(); 486 | } 487 | 488 | static void SanityCheckNotificationCallback(CFUserNotificationRef userNotification, CFOptionFlags responseFlags) 489 | { 490 | } 491 | 492 | %ctor 493 | { 494 | %init(); 495 | // Attach rockets when in the com.apple.ReportCrash.SimulateCrash job 496 | // (can't check in using the launchd APIs because it hates more than one checkin; this will do) 497 | const char **_argv = *_NSGetArgv(); 498 | if (strcmp(_argv[0], "/System/Library/CoreServices/ReportCrash") == 0 && _argv[1]) { 499 | if (strcmp(_argv[1], "-f") == 0) { 500 | isDaemon = YES; 501 | #ifdef DEBUG 502 | NSLog(@"RocketBootstrap: Initializing ReportCrash using mach_msg_server"); 503 | #endif 504 | MSHookFunction(mach_msg_server_once, $mach_msg_server_once, (void **)&_mach_msg_server_once); 505 | #ifdef __clang__ 506 | } else if (strcmp(_argv[1], "com.apple.ReportCrash.SimulateCrash") == 0) { 507 | isDaemon = YES; 508 | #ifdef DEBUG 509 | NSLog(@"RocketBootstrap: Initializing ReportCrash using XPC"); 510 | #endif 511 | MSImageRef libxpc = MSGetImageByName("/usr/lib/system/libxpc.dylib"); 512 | if (libxpc) { 513 | void *xpc_connection_create_mach_service = MSFindSymbol(libxpc, "_xpc_connection_create_mach_service"); 514 | if (xpc_connection_create_mach_service) { 515 | MSHookFunction(xpc_connection_create_mach_service, $xpc_connection_create_mach_service, (void **)&_xpc_connection_create_mach_service); 516 | } else { 517 | #ifdef DEBUG 518 | NSLog(@"RocketBootstrap: Could not find xpc_connection_create_mach_service symbol!"); 519 | #endif 520 | } 521 | void *_xpc_connection_mach_event = MSFindSymbol(libxpc, "__xpc_connection_mach_event"); 522 | if (_xpc_connection_mach_event) { 523 | MSHookFunction(_xpc_connection_mach_event, $_xpc_connection_mach_event, (void **)&__xpc_connection_mach_event); 524 | } else { 525 | #ifdef DEBUG 526 | NSLog(@"RocketBootstrap: Could not find _xpc_connection_mach_event symbol!"); 527 | #endif 528 | } 529 | } else { 530 | #ifdef DEBUG 531 | NSLog(@"RocketBootstrap: Could not find libxpc.dylib image!"); 532 | #endif 533 | } 534 | #endif 535 | } 536 | } else if (strcmp(argv[0], "/System/Library/CoreServices/SpringBoard.app/SpringBoard") == 0) { 537 | #ifdef DEBUG 538 | NSLog(@"RocketBootstrap: Initializing SpringBoard"); 539 | #endif 540 | if (kCFCoreFoundationVersionNumber < 847.20) { 541 | return; 542 | } 543 | // Sanity check on the SimulateCrash service 544 | mach_port_t bootstrap = MACH_PORT_NULL; 545 | mach_port_t self = mach_task_self(); 546 | task_get_bootstrap_port(self, &bootstrap); 547 | mach_port_t servicesPort = MACH_PORT_NULL; 548 | kern_return_t err = bootstrap_look_up(bootstrap, "com.apple.ReportCrash.SimulateCrash", &servicesPort); 549 | //bool has_simulate_crash; 550 | if (err) { 551 | //has_simulate_crash = false; 552 | } else { 553 | mach_port_mod_refs(self, servicesPort, MACH_PORT_RIGHT_SEND, -1); 554 | //has_simulate_crash = true; 555 | //servicesPort = MACH_PORT_NULL; 556 | //err = bootstrap_look_up(bootstrap, "com.rpetrich.rocketbootstrapd", &servicesPort); 557 | } 558 | if (err == 0) { 559 | mach_port_mod_refs(self, servicesPort, MACH_PORT_RIGHT_SEND, -1); 560 | observe_rocketd(); 561 | } else { 562 | const CFTypeRef keys[] = { 563 | kCFUserNotificationAlertHeaderKey, 564 | kCFUserNotificationAlertMessageKey, 565 | kCFUserNotificationDefaultButtonTitleKey, 566 | }; 567 | const CFTypeRef valuesCrash[] = { 568 | CFSTR("System files missing!"), 569 | CFSTR("RocketBootstrap has detected that your SimulateCrash crash reporting daemon is missing or disabled.\nThis daemon is required for proper operation of packages that depend on RocketBootstrap."), 570 | CFSTR("OK"), 571 | }; 572 | /*const CFTypeRef valuesRocket[] = { 573 | CFSTR("System files missing!"), 574 | CFSTR("RocketBootstrap has detected that your rocketbootstrap daemon is missing or disabled.\nThis daemon is required for proper operation of packages that depend on RocketBootstrap."), 575 | CFSTR("OK"), 576 | };*/ 577 | CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, /*has_simulate_crash ? (const void **)valuesRocket :*/ (const void **)valuesCrash, sizeof(keys) / sizeof(*keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 578 | SInt32 err = 0; 579 | CFUserNotificationRef notification = CFUserNotificationCreate(kCFAllocatorDefault, 0.0, kCFUserNotificationPlainAlertLevel, &err, dict); 580 | CFRunLoopSourceRef runLoopSource = CFUserNotificationCreateRunLoopSource(kCFAllocatorDefault, notification, SanityCheckNotificationCallback, 0); 581 | CFRunLoopAddSource(CFRunLoopGetMain(), runLoopSource, kCFRunLoopCommonModes); 582 | CFRelease(dict); 583 | } 584 | } 585 | } 586 | -------------------------------------------------------------------------------- /bootstrap.h: -------------------------------------------------------------------------------- 1 | #ifndef __BOOTSTRAP_H__ 2 | #define __BOOTSTRAP_H__ 3 | /* 4 | * Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved. 5 | * 6 | * @APPLE_APACHE_LICENSE_HEADER_START@ 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | * @APPLE_APACHE_LICENSE_HEADER_END@ 21 | */ 22 | 23 | /* 24 | * bootstrap -- fundamental service initiator and port server 25 | * Mike DeMoney, NeXT, Inc. 26 | * Copyright, 1990. All rights reserved. 27 | */ 28 | 29 | /* 30 | * Interface: Bootstrap server 31 | * 32 | * The bootstrap server is the first user-mode task initiated by the Mach 33 | * kernel at system boot time. The bootstrap server provides two services, 34 | * it initiates other system tasks, and manages a table of name-port bindings 35 | * for fundamental system services (e.g. lookupd, Window Manager, etc...). 36 | * 37 | * Name-port bindings can be established with the bootstrap server by either 38 | * of two mechanisms: 39 | * 40 | * 1. The binding can be indicated, in advance of the service that backs it 41 | * being available, via a "service create" request. In this case, bootstrap 42 | * will immediately create a port and bind the indicated name with that port. 43 | * At a later time, a service may "checkin" for the name-port 44 | * binding and will be returned receive rights for the bound port. Lookup's 45 | * on bindings created by this mechanism will return send rights to the port, 46 | * even if no service has "checked-in". In this case, requests sent to the 47 | * bound port will be queued until a server has checked-in and can satisfy the 48 | * request. 49 | * 50 | * 2. Bindings can be established dynamically via a "register" request. In 51 | * this case, the register request provides bootstrap with a name and send 52 | * rights for a port. Bootstrap will provide send rights for the bound port 53 | * to any requestor via the lookup request. 54 | * 55 | * Bootstrap provides its service port to descendant tasks via the Mach 56 | * "bootstrap" special task port. All direct descendants of bootstrap receive 57 | * a "privileged" bootstrap service port. System services that initiate 58 | * untrusted tasks should replace the Mach bootstrap task special port with 59 | * a subset bootstrap port to prevent them from infecting the namespace. 60 | * 61 | * The bootstrap server creates a "backup" port for each service that it 62 | * creates. This is used to detect when a checked out service is no longer 63 | * being served. The bootstrap server regains all rights to the port and 64 | * it is marked available for check-out again. This allows crashed servers to 65 | * resume service to previous clients. Lookup's on this named port will 66 | * continue to be serviced by bootstrap while holding receive rights for the 67 | * bound port. A client may detect that the service is inactive via the 68 | * bootstrap status request. If an inactive service re-registers rather 69 | * than "checking-in" the original bound port is destroyed. 70 | * 71 | * The status of a named service may be obtained via the "status" request. 72 | * A service is "active" if a name-port binding exists and receive rights 73 | * to the bound port are held by a task other than bootstrap. 74 | * 75 | * The bootstrap server may also (re)start server processes associated with 76 | * with a set of services. The definition of the server process is done 77 | * through the "create server" request. The server will be launched in the 78 | * same bootstrap context in which it was registered. 79 | */ 80 | #include 81 | #include 82 | #include 83 | #include 84 | #include 85 | #include 86 | 87 | __BEGIN_DECLS 88 | 89 | #pragma GCC visibility push(default) 90 | 91 | #define BOOTSTRAP_MAX_NAME_LEN 128 92 | #define BOOTSTRAP_MAX_CMD_LEN 512 93 | 94 | typedef char name_t[BOOTSTRAP_MAX_NAME_LEN]; 95 | typedef char cmd_t[BOOTSTRAP_MAX_CMD_LEN]; 96 | typedef name_t *name_array_t; 97 | typedef int bootstrap_status_t; 98 | typedef bootstrap_status_t *bootstrap_status_array_t; 99 | typedef unsigned int bootstrap_property_t; 100 | typedef bootstrap_property_t * bootstrap_property_array_t; 101 | 102 | typedef boolean_t *bool_array_t; 103 | 104 | #define BOOTSTRAP_MAX_LOOKUP_COUNT 20 105 | 106 | #define BOOTSTRAP_SUCCESS 0 107 | #define BOOTSTRAP_NOT_PRIVILEGED 1100 108 | #define BOOTSTRAP_NAME_IN_USE 1101 109 | #define BOOTSTRAP_UNKNOWN_SERVICE 1102 110 | #define BOOTSTRAP_SERVICE_ACTIVE 1103 111 | #define BOOTSTRAP_BAD_COUNT 1104 112 | #define BOOTSTRAP_NO_MEMORY 1105 113 | #define BOOTSTRAP_NO_CHILDREN 1106 114 | 115 | #define BOOTSTRAP_STATUS_INACTIVE 0 116 | #define BOOTSTRAP_STATUS_ACTIVE 1 117 | #define BOOTSTRAP_STATUS_ON_DEMAND 2 118 | 119 | /* 120 | * After main() starts, it is safe to assume that this variable is always set. 121 | */ 122 | extern mach_port_t bootstrap_port; 123 | 124 | /* 125 | * bootstrap_create_server() 126 | * 127 | * Declares a server that mach_init will re-spawn within the specified 128 | * bootstrap context. The server is considered already "active" 129 | * (i.e. will not be re-spawned) until the returned server_port is 130 | * deallocated. 131 | * 132 | * In the meantime, services can be declared against the server, 133 | * by using the server_port as the privileged bootstrap target of 134 | * subsequent bootstrap_create_service() calls. 135 | * 136 | * When mach_init re-spawns the server, its task bootstrap port 137 | * is set to the privileged sever_port. Through this special 138 | * bootstrap port, it can access all of parent bootstrap's context 139 | * (and all services are created in the parent's namespace). But 140 | * all additional service declarations (and declaration removals) 141 | * will be associated with this particular server. 142 | * 143 | * Only a holder of the server_port privilege bootstrap port can 144 | * check in or register over those services. 145 | * 146 | * When all services associated with a server are deleted, and the server 147 | * exits, it will automatically be deleted itself. 148 | * 149 | * If the server is declared "on_demand," then a non-running server 150 | * will be re-launched on first use of one of the service ports 151 | * registered against it. Otherwise, it will be re-launched 152 | * immediately upon exiting (whether any client is actively using 153 | * any of the service ports or not). 154 | * 155 | * Errors: Returns appropriate kernel errors on rpc failure. 156 | * Returns BOOTSTRAP_NOT_PRIVILEGED, bootstrap or uid invalid. 157 | */ 158 | kern_return_t bootstrap_create_server( 159 | mach_port_t bp, 160 | cmd_t server_cmd, 161 | uid_t server_uid, 162 | boolean_t on_demand, 163 | mach_port_t *server_port); 164 | 165 | /* 166 | * bootstrap_subset() 167 | * 168 | * Returns a new port to use as a bootstrap port. This port behaves 169 | * exactly like the previous bootstrap_port, except that ports dynamically 170 | * registered via bootstrap_register() are available only to users of this 171 | * specific subset_port. Lookups on the subset_port will return ports 172 | * registered with this port specifically, and ports registered with 173 | * ancestors of this subset_port. Duplications of services already 174 | * registered with an ancestor port may be registered with the subset port 175 | * are allowed. Services already advertised may then be effectively removed 176 | * by registering PORT_NULL for the service. 177 | * When it is detected that the requestor_port is destroyed the subset 178 | * port and all services advertized by it are destroyed as well. 179 | * 180 | * Errors: Returns appropriate kernel errors on rpc failure. 181 | */ 182 | kern_return_t bootstrap_subset( 183 | mach_port_t bp, 184 | mach_port_t requestor_port, 185 | mach_port_t *subset_port); 186 | 187 | /* 188 | * bootstrap_unprivileged() 189 | * 190 | * Given a bootstrap port, return its unprivileged equivalent. If 191 | * the port is already unprivileged, another reference to the same 192 | * port is returned. 193 | * 194 | * This is most often used by servers, which are launched with their 195 | * bootstrap port set to the privileged port for the server, to get 196 | * an unprivileged version of the same port for use by its unprivileged 197 | * children (or any offspring that it does not want to count as part 198 | * of the "server" for mach_init registration and re-launch purposes). 199 | * 200 | * Native launchd jobs are always started with an unprivileged port. 201 | */ 202 | kern_return_t bootstrap_unprivileged( 203 | mach_port_t bp, 204 | mach_port_t *unpriv_port) 205 | AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5; 206 | 207 | /* 208 | * bootstrap_parent() 209 | * 210 | * Given a bootstrap subset port, return the parent bootstrap port. 211 | * If the specified bootstrap port is already the root subset, 212 | * the same port will be returned. Much like "." and ".." are the same 213 | * in the file system name space for the root directory ("/"). 214 | * 215 | * Errors: 216 | * Returns BOOTSTRAP_NOT_PRIVILEGED if the caller is not running 217 | * with an effective user id of root (as determined by the security 218 | * token in the message trailer). 219 | */ 220 | kern_return_t bootstrap_parent( 221 | mach_port_t bp, 222 | mach_port_t *parent_port); 223 | 224 | /* 225 | * bootstrap_register() 226 | * 227 | * Registers a send right for service_port with the service identified by 228 | * service_name. Attempts to register a service where an active binding 229 | * already exists are rejected. 230 | * 231 | * If the service was previously declared with bootstrap_create_service(), 232 | * but is not currently active, this call can be used to undeclare the 233 | * service. The bootstrap port used must have sufficient privilege to 234 | * do so. (Registering MACH_PORT_NULL is especially useful for shutting 235 | * down declared services). 236 | * 237 | * This API is deprecated. Old scenarios and recommendations: 238 | * 239 | * 1) Code that used to call bootstrap_check_in() and then bootstrap_register() 240 | * can now always call bootstrap_check_in(). 241 | * 242 | * 2) If the code was registering a well known name, please switch to launchd. 243 | * 244 | * 3) If the code was registering a dynamically generated string and passing 245 | * the string to other applications, please rewrite the code to send a Mach 246 | * send-right directly. 247 | * 248 | * 4) If the launchd job maintained an optional Mach service, please reserve 249 | * the name with launchd and control the presense of the service through 250 | * ownership of the Mach receive right like so. 251 | * 252 | * MachServices 253 | * 254 | * com.apple.windowserver 255 | * 256 | * com.apple.windowserver.active 257 | * 258 | * HideUntilCheckIn 259 | * 260 | * 261 | * 262 | * 263 | * 264 | * Errors: Returns appropriate kernel errors on rpc failure. 265 | * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to 266 | * bootstrap port without privilege. 267 | * Returns BOOTSTRAP_NAME_IN_USE, if service has already been 268 | * register or checked-in. 269 | */ 270 | AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5 271 | kern_return_t 272 | bootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp); 273 | 274 | /* 275 | * bootstrap_create_service() 276 | * 277 | * Creates a service named "service_name" and returns a send right to that 278 | * port in "service_port." The port may later be checked in as if this 279 | * port were configured in the bootstrap configuration file. 280 | * 281 | * This API is deprecated. Please call bootstrap_check_in() instead. 282 | * 283 | * Errors: Returns appropriate kernel errors on rpc failure. 284 | * Returns BOOTSTRAP_SERVICE_ACTIVE, if service already exists. 285 | */ 286 | #ifdef AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6 287 | AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6 288 | #endif 289 | kern_return_t 290 | bootstrap_create_service(mach_port_t bp, name_t service_name, mach_port_t *sp); 291 | 292 | /* 293 | * bootstrap_check_in() 294 | * 295 | * Returns the receive right for the service named by service_name. The 296 | * service must have been declared in the launchd.plist(5) file associated 297 | * with the job. Attempts to check_in a service which is already active 298 | * are not allowed. 299 | * 300 | * If the service was declared as being associated with a server, the 301 | * check_in must come from the server's privileged port (server_port). 302 | * 303 | * Errors: Returns appropriate kernel errors on rpc failure. 304 | * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist. 305 | * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to 306 | * bootstrap port without privilege. 307 | * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been 308 | * registered or checked-in. 309 | */ 310 | kern_return_t bootstrap_check_in( 311 | mach_port_t bp, 312 | const name_t service_name, 313 | mach_port_t *sp); 314 | 315 | /* 316 | * bootstrap_look_up() 317 | * 318 | * Returns a send right for the service port declared/registered under the 319 | * name service_name. The service is not guaranteed to be active. Use the 320 | * bootstrap_status call to determine the status of the service. 321 | * 322 | * Errors: Returns appropriate kernel errors on rpc failure. 323 | * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist. 324 | */ 325 | kern_return_t bootstrap_look_up( 326 | mach_port_t bp, 327 | const name_t service_name, 328 | mach_port_t *sp); 329 | 330 | /* 331 | * bootstrap_status() 332 | * 333 | * In practice, this call was used to preflight whether the following two 334 | * APIs would succeed. 335 | * 336 | * bootstrap_look_up() 337 | * bootstrap_check_in() 338 | * 339 | * Please don't bother. Just call the above two APIs directly and check 340 | * for failure. 341 | */ 342 | kern_return_t bootstrap_status( 343 | mach_port_t bp, 344 | name_t service_name, 345 | bootstrap_status_t *service_active) 346 | AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5; 347 | 348 | /* bootstrap_strerror() 349 | * 350 | * Translate a return value from the bootstrap_*() APIs to a string. 351 | */ 352 | const char *bootstrap_strerror(kern_return_t r) __attribute__((__nothrow__, __pure__, __warn_unused_result__)); 353 | 354 | #pragma GCC visibility pop 355 | 356 | __END_DECLS 357 | 358 | #endif /* __BOOTSTRAP_H__ */ -------------------------------------------------------------------------------- /defaultheaders/launch.h: -------------------------------------------------------------------------------- 1 | /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/launch.h -------------------------------------------------------------------------------- /defaultheaders/xpc: -------------------------------------------------------------------------------- 1 | /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/xpc/ -------------------------------------------------------------------------------- /dispatch/mach_private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2013 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_APACHE_LICENSE_HEADER_START@ 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * @APPLE_APACHE_LICENSE_HEADER_END@ 19 | */ 20 | 21 | /* 22 | * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch 23 | * which are subject to change in future releases of Mac OS X. Any applications 24 | * relying on these interfaces WILL break. 25 | */ 26 | 27 | #ifndef __DISPATCH_MACH_PRIVATE__ 28 | #define __DISPATCH_MACH_PRIVATE__ 29 | 30 | #ifndef __DISPATCH_INDIRECT__ 31 | #error "Please #include instead of this file directly." 32 | #include // for HeaderDoc 33 | #endif 34 | 35 | __BEGIN_DECLS 36 | 37 | #if DISPATCH_MACH_SPI 38 | 39 | #include 40 | 41 | /*! 42 | * @functiongroup Dispatch Mach Channel SPI 43 | * 44 | * IMPORTANT: This is Libsystem-internal SPI not intended for general use and 45 | * is subject to change at any time without warning. 46 | */ 47 | 48 | /*! 49 | * @typedef dispatch_mach_t 50 | * A dispatch mach channel asynchronously recevives and sends mach messages. 51 | */ 52 | DISPATCH_DECL(dispatch_mach); 53 | 54 | /*! 55 | * @typedef dispatch_mach_reason_t 56 | * Reasons for a mach channel handler to be invoked. 57 | * 58 | * @const DISPATCH_MACH_CONNECTED 59 | * The channel has been connected. The first handler invocation on a channel 60 | * after calling dispatch_mach_connect() will have this reason. 61 | * 62 | * @const DISPATCH_MACH_MESSAGE_RECEIVED 63 | * A message was received, it is passed in the message parameter. 64 | * 65 | * @const DISPATCH_MACH_MESSAGE_SENT 66 | * A message was sent, it is passed in the message parameter (so that associated 67 | * resources can be disposed of). 68 | * 69 | * @const DISPATCH_MACH_MESSAGE_SEND_FAILED 70 | * A message failed to be sent, it is passed in the message parameter (so that 71 | * associated resources can be disposed of), along with the error code from 72 | * mach_msg(). 73 | * 74 | * @const DISPATCH_MACH_MESSAGE_NOT_SENT 75 | * A message was not sent due to the channel being canceled or reconnected, it 76 | * is passed in the message parameter (so that associated resources can be 77 | * disposed of). 78 | * 79 | * @const DISPATCH_MACH_BARRIER_COMPLETED 80 | * A barrier block has finished executing. 81 | * 82 | * @const DISPATCH_MACH_DISCONNECTED 83 | * The channel has been disconnected by a call to dispatch_mach_reconnect() or 84 | * dispatch_mach_cancel(), an empty message is passed in the message parameter 85 | * (so that associated port rights can be disposed of). 86 | * The message header will contain either a remote port with a previously 87 | * connected send right, or a local port with a previously connected receive 88 | * right (if the channel was canceled), or a local port with a receive right 89 | * that was being monitored for a direct reply to a message previously sent to 90 | * the channel (if no reply was received). 91 | * 92 | * @const DISPATCH_MACH_CANCELED 93 | * The channel has been canceled. 94 | */ 95 | DISPATCH_ENUM(dispatch_mach_reason, unsigned long, 96 | DISPATCH_MACH_CONNECTED = 1, 97 | DISPATCH_MACH_MESSAGE_RECEIVED, 98 | DISPATCH_MACH_MESSAGE_SENT, 99 | DISPATCH_MACH_MESSAGE_SEND_FAILED, 100 | DISPATCH_MACH_MESSAGE_NOT_SENT, 101 | DISPATCH_MACH_BARRIER_COMPLETED, 102 | DISPATCH_MACH_DISCONNECTED, 103 | DISPATCH_MACH_CANCELED, 104 | DISPATCH_MACH_REASON_LAST, /* unused */ 105 | ); 106 | 107 | /*! 108 | * @typedef dispatch_mach_trailer_t 109 | * Trailer type of mach message received by dispatch mach channels 110 | */ 111 | 112 | typedef mach_msg_context_trailer_t dispatch_mach_trailer_t; 113 | 114 | /*! 115 | * @constant DISPATCH_MACH_RECEIVE_MAX_INLINE_MESSAGE_SIZE 116 | * Maximum size of a message that can be received inline by a dispatch mach 117 | * channel, reception of larger messages requires an extra roundtrip through 118 | * the kernel. 119 | */ 120 | 121 | #define DISPATCH_MACH_RECEIVE_MAX_INLINE_MESSAGE_SIZE \ 122 | (0x4000 - sizeof(dispatch_mach_trailer_t)) 123 | 124 | /*! 125 | * @typedef dispatch_mach_msg_t 126 | * A dispatch mach message encapsulates messages received or sent with dispatch 127 | * mach channels. 128 | */ 129 | DISPATCH_DECL(dispatch_mach_msg); 130 | 131 | /*! 132 | * @typedef dispatch_mach_msg_destructor_t 133 | * Dispatch mach message object destructors. 134 | * 135 | * @const DISPATCH_MACH_MSG_DESTRUCTOR_DEFAULT 136 | * Message buffer storage is internal to the object, if a buffer is supplied 137 | * during object creation, its contents are copied. 138 | * 139 | * @const DISPATCH_MACH_MSG_DESTRUCTOR_FREE 140 | * Message buffer will be deallocated with free(3). 141 | * 142 | * @const DISPATCH_MACH_MSG_DESTRUCTOR_FREE 143 | * Message buffer will be deallocated with vm_deallocate. 144 | */ 145 | DISPATCH_ENUM(dispatch_mach_msg_destructor, unsigned int, 146 | DISPATCH_MACH_MSG_DESTRUCTOR_DEFAULT = 0, 147 | DISPATCH_MACH_MSG_DESTRUCTOR_FREE, 148 | DISPATCH_MACH_MSG_DESTRUCTOR_VM_DEALLOCATE, 149 | ); 150 | 151 | /*! 152 | * @function dispatch_mach_msg_create 153 | * Creates a dispatch mach message object, either with a newly allocated message 154 | * buffer of given size, or from an existing message buffer that will be 155 | * deallocated with the specified destructor when the object is released. 156 | * 157 | * If a non-NULL reference to a pointer is provided in 'msg_ptr', it is filled 158 | * with the location of the (possibly newly allocated) message buffer. 159 | * 160 | * It is the responsibility of the application to ensure that it does not modify 161 | * the underlying message buffer once the dispatch mach message object is passed 162 | * to other dispatch mach API. 163 | * 164 | * @param msg The message buffer to create the message object from. 165 | * If 'destructor' is DISPATCH_MACH_MSG_DESTRUCTOR_DEFAULT, 166 | * this argument may be NULL to leave the newly allocated 167 | * message buffer zero-initialized. 168 | * @param size The size of the message buffer. 169 | * Must be >= sizeof(mach_msg_header_t) 170 | * @param destructor The destructor to use to deallocate the message buffer 171 | * when the object is released. 172 | * @param msg_ptr A pointer to a pointer variable to be filled with the 173 | * location of the (possibly newly allocated) message 174 | * buffer, or NULL. 175 | * @result A newly created dispatch mach message object. 176 | */ 177 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0) 178 | DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT 179 | DISPATCH_NOTHROW 180 | dispatch_mach_msg_t 181 | dispatch_mach_msg_create(mach_msg_header_t *msg, size_t size, 182 | dispatch_mach_msg_destructor_t destructor, mach_msg_header_t **msg_ptr); 183 | 184 | /*! 185 | * @function dispatch_mach_msg_get_msg 186 | * Returns the message buffer underlying a dispatch mach message object. 187 | * 188 | * @param message The dispatch mach message object to query. 189 | * @param size_ptr A pointer to a size_t variable to be filled with the 190 | * size of the message buffer, or NULL. 191 | * @result Pointer to message buffer underlying the object. 192 | */ 193 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_7_0) 194 | DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW 195 | mach_msg_header_t* 196 | dispatch_mach_msg_get_msg(dispatch_mach_msg_t message, size_t *size_ptr); 197 | 198 | #ifdef __BLOCKS__ 199 | /*! 200 | * @typedef dispatch_mach_handler_t 201 | * Prototype of dispatch mach channel handler blocks. 202 | * 203 | * @param reason Reason the handler was invoked. 204 | * @param message Message object that was sent or received. 205 | * @param error Mach error code for the send operation. 206 | */ 207 | typedef void (^dispatch_mach_handler_t)(dispatch_mach_reason_t reason, 208 | dispatch_mach_msg_t message, mach_error_t error); 209 | 210 | /*! 211 | * @function dispatch_mach_create 212 | * Create a dispatch mach channel to asynchronously receive and send mach 213 | * messages. 214 | * 215 | * The specified handler will be called with the corresponding reason parameter 216 | * for each message received and for each message that was successfully sent, 217 | * that failed to be sent, or was not sent; as well as when a barrier block 218 | * has completed, or when channel connection, reconnection or cancellation has 219 | * taken effect. 220 | * 221 | * Dispatch mach channels are created in a disconnected state, they must be 222 | * connected via dispatch_mach_connect() to begin receiving and sending 223 | * messages. 224 | * 225 | * @param label 226 | * An optional string label to attach to the channel. The string is not copied, 227 | * if it is non-NULL it must point to storage that remains valid for the 228 | * lifetime of the channel object. May be NULL. 229 | * 230 | * @param queue 231 | * The target queue of the channel, where the handler and barrier blocks will 232 | * be submitted. 233 | * 234 | * @param handler 235 | * The handler block to submit when a message has been sent or received. 236 | * 237 | * @result 238 | * The newly created dispatch mach channel. 239 | */ 240 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 241 | DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT 242 | DISPATCH_NONNULL3 DISPATCH_NOTHROW 243 | dispatch_mach_t 244 | dispatch_mach_create(const char *label, dispatch_queue_t queue, 245 | dispatch_mach_handler_t handler); 246 | #endif 247 | 248 | /*! 249 | * @typedef dispatch_mach_handler_function_t 250 | * Prototype of dispatch mach channel handler functions. 251 | * 252 | * @param context Application-defined context parameter. 253 | * @param reason Reason the handler was invoked. 254 | * @param message Message object that was sent or received. 255 | * @param error Mach error code for the send operation. 256 | */ 257 | typedef void (*dispatch_mach_handler_function_t)(void *context, 258 | dispatch_mach_reason_t reason, dispatch_mach_msg_t message, 259 | mach_error_t error); 260 | 261 | /*! 262 | * @function dispatch_mach_create_f 263 | * Create a dispatch mach channel to asynchronously receive and send mach 264 | * messages. 265 | * 266 | * The specified handler will be called with the corresponding reason parameter 267 | * for each message received and for each message that was successfully sent, 268 | * that failed to be sent, or was not sent; as well as when a barrier block 269 | * has completed, or when channel connection, reconnection or cancellation has 270 | * taken effect. 271 | * 272 | * Dispatch mach channels are created in a disconnected state, they must be 273 | * connected via dispatch_mach_connect() to begin receiving and sending 274 | * messages. 275 | * 276 | * @param label 277 | * An optional string label to attach to the channel. The string is not copied, 278 | * if it is non-NULL it must point to storage that remains valid for the 279 | * lifetime of the channel object. May be NULL. 280 | * 281 | * @param queue 282 | * The target queue of the channel, where the handler and barrier blocks will 283 | * be submitted. 284 | * 285 | * @param context 286 | * The application-defined context to pass to the handler. 287 | * 288 | * @param handler 289 | * The handler function to submit when a message has been sent or received. 290 | * 291 | * @result 292 | * The newly created dispatch mach channel. 293 | */ 294 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 295 | DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT 296 | DISPATCH_NONNULL4 DISPATCH_NOTHROW 297 | dispatch_mach_t 298 | dispatch_mach_create_f(const char *label, dispatch_queue_t queue, void *context, 299 | dispatch_mach_handler_function_t handler); 300 | 301 | /*! 302 | * @function dispatch_mach_connect 303 | * Connect a mach channel to the specified receive and send rights. 304 | * 305 | * This function must only be called once during the lifetime of a channel, it 306 | * will initiate message reception and perform any already submitted message 307 | * sends or barrier operations. 308 | * 309 | * @param channel 310 | * The mach channel to connect. 311 | * 312 | * @param receive 313 | * The receive right to associate with the channel. May be MACH_PORT_NULL. 314 | * 315 | * @param send 316 | * The send right to associate with the channel. May be MACH_PORT_NULL. 317 | * 318 | * @param checkin 319 | * An optional message object encapsulating the initial check-in message to send 320 | * upon channel connection. The check-in message is sent immediately before the 321 | * first message submitted via dispatch_mach_send(). The message object will be 322 | * retained until the initial send operation is complete (or not peformed due 323 | * to channel cancellation or reconnection) and the channel handler has 324 | * returned. May be NULL. 325 | */ 326 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 327 | DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW 328 | void 329 | dispatch_mach_connect(dispatch_mach_t channel, mach_port_t receive, 330 | mach_port_t send, dispatch_mach_msg_t checkin); 331 | 332 | /*! 333 | * @function dispatch_mach_reconnect 334 | * Reconnect a mach channel to the specified send right. 335 | * 336 | * Disconnects the channel from the current send right, interrupts any pending 337 | * message sends (and returns the messages as unsent), and reconnects the 338 | * channel to a new send right. 339 | * 340 | * The application must wait for the channel handler to be invoked with 341 | * DISPATCH_MACH_DISCONNECTED before releasing the previous send right. 342 | * 343 | * @param channel 344 | * The mach channel to reconnect. 345 | * 346 | * @param send 347 | * The new send right to associate with the channel. May be MACH_PORT_NULL. 348 | * 349 | * @param checkin 350 | * An optional message object encapsulating the initial check-in message to send 351 | * upon channel reconnection. The check-in message is sent immediately before 352 | * the first message submitted via dispatch_mach_send() after this function 353 | * returns. The message object will be retained until the initial send operation 354 | * is complete (or not peformed due to channel cancellation or reconnection) 355 | * and the channel handler has returned. May be NULL. 356 | */ 357 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 358 | DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW 359 | void 360 | dispatch_mach_reconnect(dispatch_mach_t channel, mach_port_t send, 361 | dispatch_mach_msg_t checkin); 362 | 363 | /*! 364 | * @function dispatch_mach_cancel 365 | * Cancel a mach channel, preventing any further messages from being sent or 366 | * received. 367 | * 368 | * The application must wait for the channel handler to be invoked with 369 | * DISPATCH_MACH_DISCONNECTED before releasing the underlying send and receive 370 | * rights. 371 | * 372 | * Note: explicit cancellation of mach channels is required, no implicit 373 | * cancellation takes place on release of the last application reference 374 | * to the channel object. Failure to cancel will cause the channel and 375 | * its associated resources to be leaked. 376 | * 377 | * @param channel 378 | * The mach channel to cancel. 379 | */ 380 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 381 | DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW 382 | void 383 | dispatch_mach_cancel(dispatch_mach_t channel); 384 | 385 | /*! 386 | * @function dispatch_mach_send 387 | * Asynchronously send a message encapsulated in a dispatch mach message object 388 | * to the specified mach channel. 389 | * 390 | * Unless the message is being sent to a send-once right (as determined by the 391 | * presence of MACH_MSG_TYPE_MOVE_SEND_ONCE in the message header remote bits), 392 | * the message header remote port is set to the channel send right before the 393 | * send operation is performed. 394 | * 395 | * If the message expects a direct reply (as determined by the presence of 396 | * MACH_MSG_TYPE_MAKE_SEND_ONCE in the message header local bits) the receive 397 | * right specified in the message header local port will be monitored until a 398 | * reply message (or a send-once notification) is received, or the channel is 399 | * canceled. Hence the application must wait for the channel handler to be 400 | * invoked with a DISPATCH_MACH_DISCONNECTED message before releasing that 401 | * receive right. 402 | * 403 | * If the message send operation is attempted but the channel is canceled 404 | * before the send operation succesfully completes, the message returned to the 405 | * channel handler with DISPATCH_MACH_MESSAGE_NOT_SENT may be the result of a 406 | * pseudo-receive operation. If the message expected a direct reply, the 407 | * receive right originally specified in the message header local port will 408 | * returned in a DISPATCH_MACH_DISCONNECTED message. 409 | * 410 | * @param channel 411 | * The mach channel to which to send the message. 412 | * 413 | * @param message 414 | * The message object encapsulating the message to send. The object will be 415 | * retained until the send operation is complete and the channel handler has 416 | * returned. The storage underlying the message object may be modified by the 417 | * send operation. 418 | * 419 | * @param options 420 | * Additional send options to pass to mach_msg() when performing the send 421 | * operation. 422 | */ 423 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 424 | DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL2 DISPATCH_NOTHROW 425 | void 426 | dispatch_mach_send(dispatch_mach_t channel, dispatch_mach_msg_t message, 427 | mach_msg_option_t options); 428 | 429 | #ifdef __BLOCKS__ 430 | /*! 431 | * @function dispatch_mach_send_barrier 432 | * Submit a send barrier to the specified mach channel. Messages submitted to 433 | * the channel before the barrier will be sent before the barrier block is 434 | * executed, and messages submitted to the channel after the barrier will only 435 | * be sent once the barrier block has completed and the channel handler 436 | * invocation for the barrier has returned. 437 | * 438 | * @param channel 439 | * The mach channel to which to submit the barrier. 440 | * 441 | * @param barrier 442 | * The barrier block to submit to the channel target queue. 443 | */ 444 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 445 | DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW 446 | void 447 | dispatch_mach_send_barrier(dispatch_mach_t channel, dispatch_block_t barrier); 448 | #endif 449 | 450 | /*! 451 | * @function dispatch_mach_send_barrier_f 452 | * Submit a send barrier to the specified mach channel. Messages submitted to 453 | * the channel before the barrier will be sent before the barrier block is 454 | * executed, and messages submitted to the channel after the barrier will only 455 | * be sent once the barrier block has completed and the channel handler 456 | * invocation for the barrier has returned. 457 | * 458 | * @param channel 459 | * The mach channel to which to submit the barrier. 460 | * 461 | * @param context 462 | * The application-defined context parameter to pass to the function. 463 | * 464 | * @param barrier 465 | * The barrier function to submit to the channel target queue. 466 | */ 467 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 468 | DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW 469 | void 470 | dispatch_mach_send_barrier_f(dispatch_mach_t channel, void *context, 471 | dispatch_function_t barrier); 472 | 473 | #ifdef __BLOCKS__ 474 | /*! 475 | * @function dispatch_mach_receive_barrier 476 | * Submit a receive barrier to the specified mach channel. Channel handlers for 477 | * messages received by the channel after the receive barrier has been 478 | * submitted will only be invoked once the barrier block has completed and the 479 | * channel handler invocation for the barrier has returned. 480 | * 481 | * @param channel 482 | * The mach channel to which to submit the receive barrier. 483 | * 484 | * @param barrier 485 | * The barrier block to submit to the channel target queue. 486 | */ 487 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 488 | DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW 489 | void 490 | dispatch_mach_receive_barrier(dispatch_mach_t channel, 491 | dispatch_block_t barrier); 492 | #endif 493 | 494 | /*! 495 | * @function dispatch_mach_receive_barrier_f 496 | * Submit a receive barrier to the specified mach channel. Channel handlers for 497 | * messages received by the channel after the receive barrier has been 498 | * submitted will only be invoked once the barrier block has completed and the 499 | * channel handler invocation for the barrier has returned. 500 | * 501 | * @param channel 502 | * The mach channel to which to submit the receive barrier. 503 | * 504 | * @param context 505 | * The application-defined context parameter to pass to the function. 506 | * 507 | * @param barrier 508 | * The barrier function to submit to the channel target queue. 509 | */ 510 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 511 | DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW 512 | void 513 | dispatch_mach_receive_barrier_f(dispatch_mach_t channel, void *context, 514 | dispatch_function_t barrier); 515 | 516 | /*! 517 | * @function dispatch_mach_get_checkin_port 518 | * Returns the port specified in the message header remote port of the check-in 519 | * message passed to the most recent invocation of dispatch_mach_connect() or 520 | * dispatch_mach_reconnect() for the provided mach channel (irrespective of the 521 | * completion of the (re)connect or check-in operations in question). 522 | * 523 | * Returns MACH_PORT_NULL if dispatch_mach_connect() has not yet been called or 524 | * if the most recently specified check-in message was NULL, and MACH_PORT_DEAD 525 | * if the channel has been canceled. 526 | * 527 | * It is the responsibility of the application to ensure that the port 528 | * specified in a check-in message remains valid at the time this function is 529 | * called. 530 | * 531 | * @param channel 532 | * The mach channel to query. 533 | * 534 | * @result 535 | * The most recently specified check-in port for the channel. 536 | */ 537 | __OSX_AVAILABLE_STARTING(__MAC_10_9,__IPHONE_6_0) 538 | DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW 539 | mach_port_t 540 | dispatch_mach_get_checkin_port(dispatch_mach_t channel); 541 | 542 | #endif // DISPATCH_MACH_SPI 543 | 544 | __END_DECLS 545 | 546 | #endif -------------------------------------------------------------------------------- /entitlements.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | platform-application 5 | 6 | com.apple.private.skip-library-validation 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /framework: -------------------------------------------------------------------------------- 1 | /Users/coolstar/jb/theos -------------------------------------------------------------------------------- /fullheaders/launch.h: -------------------------------------------------------------------------------- 1 | /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/launch.h -------------------------------------------------------------------------------- /fullheaders/xpc: -------------------------------------------------------------------------------- 1 | /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/xpc/ -------------------------------------------------------------------------------- /layout/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: com.rpetrich.rocketbootstrap 2 | Depends: mobilesubstrate (>= 0.9.5000), firmware (>= 3.0) 3 | Name: RocketBootstrap 4 | Version: 1.0.7~beta3 5 | Architecture: iphoneos-arm 6 | Description: Support library allowing tweaks to communicate with sandboxed processes 7 | Depiction: https://www.rpetrich.com/cydia/rocketbootstrap/beta/ 8 | Homepage: https://www.rpetrich.com/cydia/rocketbootstrap/beta/ 9 | Maintainer: BigBoss 10 | Author: Ryan Petrich 11 | Sponsor: thebigboss.org 12 | Section: Tweaks 13 | dev: rpetrich 14 | Tag: purpose::extension, role::developer 15 | -------------------------------------------------------------------------------- /layout/DEBIAN/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | chown root:wheel /Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist 3 | launchctl load /Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist || true 4 | launchctl stop com.apple.ReportCrash.SimulateCrash || true 5 | mv /System/Library/LaunchDaemons{BAK,}/com.apple.ReportCrash.SimulateCrash.plist 2> /dev/null || true 6 | launchctl load /System/Library/LaunchDaemons/com.apple.ReportCrash.SimulateCrash.plist 2> /dev/null || true 7 | chown root:wheel /usr/libexec/_rocketd_reenable 8 | chmod +s /usr/libexec/_rocketd_reenable 9 | -------------------------------------------------------------------------------- /layout/DEBIAN/prerm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | launchctl unload /Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist || true 3 | launchctl stop com.apple.ReportCrash.SimulateCrash || true 4 | -------------------------------------------------------------------------------- /layout/Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ProgramArguments 6 | 7 | /usr/libexec/rocketd 8 | 9 | OnDemand 10 | 11 | UserName 12 | mobile 13 | MachServices 14 | 15 | com.rpetrich.rocketbootstrapd 16 | 17 | 18 | Label 19 | com.rpetrich.rocketbootstrapd 20 | JetsamProperties 21 | 22 | JetsamPriority 23 | 18 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /layout/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.dylib: -------------------------------------------------------------------------------- 1 | /usr/lib/librocketbootstrap.dylib -------------------------------------------------------------------------------- /layout/Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Filter 6 | 7 | Executables 8 | 9 | ReportCrash 10 | 11 | CoreFoundationVersion 12 | 13 | 800 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /libjailbreak_xpc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Flags for entp command. Any combination or none can be specified. */ 5 | /* Wait for xpcproxy to exec before continuing */ 6 | #define FLAG_WAIT_EXEC (1 << 5) 7 | /* Wait for 0.5 sec after acting */ 8 | #define FLAG_DELAY (1 << 4) 9 | /* Send SIGCONT after acting */ 10 | #define FLAG_SIGCONT (1 << 3) 11 | /* Set sandbox exception */ 12 | #define FLAG_SANDBOX (1 << 2) 13 | /* Set platform binary flag */ 14 | #define FLAG_PLATFORMIZE (1 << 1) 15 | /* Set basic entitlements */ 16 | #define FLAG_ENTITLE (1) 17 | 18 | typedef void *jb_connection_t; 19 | 20 | #if __BLOCKS__ 21 | typedef void (^jb_callback_t)(int result); 22 | 23 | /* These ones run asynchronously. Callbacks take 1 on success, 0 on failure. 24 | The queue which they run on is undefined. */ 25 | extern void jb_entitle(jb_connection_t connection, pid_t pid, uint32_t what, jb_callback_t done); 26 | extern void jb_fix_setuid(jb_connection_t connection, pid_t pid, jb_callback_t done); 27 | #endif 28 | 29 | extern jb_connection_t jb_connect(void); 30 | extern void jb_disconnect(jb_connection_t connection); 31 | 32 | extern int jb_entitle_now(jb_connection_t connection, pid_t pid, uint32_t what); 33 | extern int jb_fix_setuid_now(jb_connection_t connection, pid_t pid); 34 | 35 | extern void jb_oneshot_entitle_now(pid_t pid, uint32_t what); 36 | extern void jb_oneshot_fix_setuid_now(pid_t pid); 37 | -------------------------------------------------------------------------------- /log.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | // Tiny shim to convert NSLog to public os_log statements on iOS 10 4 | #ifdef __clang__ 5 | #if __has_include() 6 | #include 7 | #define NSLog(...) do { \ 8 | if (kCFCoreFoundationVersionNumber > 1299.0) { \ 9 | @autoreleasepool { \ 10 | os_log(OS_LOG_DEFAULT, "%{public}@", [NSString stringWithFormat:__VA_ARGS__]); \ 11 | } \ 12 | } else { \ 13 | NSLog(__VA_ARGS__); \ 14 | } \ 15 | } while(0) 16 | #endif 17 | #endif 18 | -------------------------------------------------------------------------------- /overlayheaders: -------------------------------------------------------------------------------- 1 | ../overlayheaders/ -------------------------------------------------------------------------------- /rocketbootstrap.h: -------------------------------------------------------------------------------- 1 | #ifndef ROCKETBOOTSTRAP_H 2 | #define ROCKETBOOTSTRAP_H 3 | 4 | #include 5 | #include 6 | #include "bootstrap.h" 7 | 8 | __BEGIN_DECLS 9 | #ifndef ROCKETBOOTSTRAP_LOAD_DYNAMIC 10 | 11 | // Look up a port by service name 12 | kern_return_t rocketbootstrap_look_up(mach_port_t bootstrap_port, const name_t service_name, mach_port_t *out_service_port); 13 | 14 | // Grant system-wide access to a particular service name 15 | // Note: Will return an error if called from within a sandboxed process 16 | kern_return_t rocketbootstrap_unlock(const name_t service_name); 17 | // Register a port with and grant system-wide access to a particular service name 18 | // Note: Will return an error if called from within a sandboxed process 19 | kern_return_t rocketbootstrap_register(mach_port_t bootstrap_port, name_t service_name, mach_port_t service_port); 20 | 21 | 22 | // CFMessagePort helpers 23 | 24 | #ifdef __COREFOUNDATION_CFMESSAGEPORT__ 25 | // Acquire access to a system-wide CFMessagePort service 26 | CFMessagePortRef rocketbootstrap_cfmessageportcreateremote(CFAllocatorRef allocator, CFStringRef name); 27 | // Expose access to a CFMessagePort service 28 | // Note: Will return an error if called from within a sandboxed process 29 | kern_return_t rocketbootstrap_cfmessageportexposelocal(CFMessagePortRef messagePort); 30 | #endif 31 | 32 | 33 | // CPDistributedMessagingCenter helpers 34 | 35 | #ifdef __OBJC__ 36 | // Unlock access to a system-wide CPDistributedMessagingCenter service 37 | // Note: Server processes may only run inside privileged processes 38 | @class CPDistributedMessagingCenter; 39 | void rocketbootstrap_distributedmessagingcenter_apply(CPDistributedMessagingCenter *messaging_center); 40 | #endif 41 | 42 | 43 | // XPC helpers 44 | 45 | #ifdef __XPC_CONNECTION_H__ 46 | // Create an XPC connection representing a system-wide service 47 | // flags should be XPC_CONNECTION_MACH_SERVICE_LISTENER for a listener connection, and 0 for a client client connection 48 | // XPC_CONNECTION_MACH_SERVICE_LISTENER will return an error if called from within a sandboxed process 49 | // 0 will return an error if the service name hasn't been registered 50 | xpc_connection_t rocketbootstrap_xpc_connection_create(const char *name, dispatch_queue_t targetq, uint64_t flags); 51 | // Copy the application bundle identifier of the peer connection 52 | xpc_object_t rocketbootstrap_xpc_connection_copy_application_identifier(xpc_connection_t connection); 53 | #endif 54 | 55 | 56 | #else 57 | #include "rocketbootstrap_dynamic.h" 58 | #endif 59 | __END_DECLS 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /rocketbootstrap_dynamic.h: -------------------------------------------------------------------------------- 1 | // DONT INCLUDE DIRECTLY 2 | // Set ROCKETBOOTSTRAP_LOAD_DYNAMIC and then include rocketbootstrap.h 3 | #include 4 | 5 | #if __has_include() 6 | #include 7 | 8 | __attribute__((unused)) 9 | static void *_rocketbootstrap_dlsym_func(const char *name) { 10 | void *handle = dlopen("/usr/lib/librocketbootstrap.dylib", RTLD_LAZY); 11 | if (handle) { 12 | void *result = dlsym(handle, name); 13 | if (result) { 14 | return ptrauth_sign_unauthenticated(ptrauth_strip(result, ptrauth_key_function_pointer), ptrauth_key_function_pointer, 0); 15 | } 16 | } 17 | return NULL; 18 | } 19 | 20 | #else 21 | 22 | __attribute__((unused)) 23 | static void *_rocketbootstrap_dlsym_func(const char *name) { 24 | void *handle = dlopen("/usr/lib/librocketbootstrap.dylib", RTLD_LAZY); 25 | if (handle) { 26 | return dlsym(handle, name); 27 | } 28 | return NULL; 29 | } 30 | 31 | #endif 32 | 33 | __attribute__((unused)) 34 | static kern_return_t rocketbootstrap_look_up(mach_port_t bp, const name_t service_name, mach_port_t *sp) 35 | { 36 | static kern_return_t (*impl)(mach_port_t bp, const name_t service_name, mach_port_t *sp); 37 | if (!impl) { 38 | impl = _rocketbootstrap_dlsym_func("rocketbootstrap_look_up"); 39 | if (!impl) { 40 | impl = bootstrap_look_up; 41 | } 42 | } 43 | return impl(bp, service_name, sp); 44 | } 45 | 46 | __attribute__((unused)) 47 | static kern_return_t rocketbootstrap_unlock(const name_t service_name) 48 | { 49 | static kern_return_t (*impl)(const name_t service_name); 50 | if (!impl) { 51 | impl = _rocketbootstrap_dlsym_func("rocketbootstrap_unlock"); 52 | if (!impl) { 53 | return -1; 54 | } 55 | } 56 | return impl(service_name); 57 | } 58 | 59 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 60 | __attribute__((unused)) 61 | static kern_return_t rocketbootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp) 62 | { 63 | static kern_return_t (*impl)(mach_port_t bp, name_t service_name, mach_port_t sp); 64 | if (!impl) { 65 | impl = _rocketbootstrap_dlsym_func("rocketbootstrap_register"); 66 | if (!impl) { 67 | impl = bootstrap_register; 68 | } 69 | } 70 | return impl(bp, service_name, sp); 71 | } 72 | #pragma GCC diagnostic warning "-Wdeprecated-declarations" 73 | 74 | #ifdef __COREFOUNDATION_CFMESSAGEPORT__ 75 | __attribute__((unused)) 76 | static CFMessagePortRef rocketbootstrap_cfmessageportcreateremote(CFAllocatorRef allocator, CFStringRef name) 77 | { 78 | static CFMessagePortRef (*impl)(CFAllocatorRef allocator, CFStringRef name); 79 | if (!impl) { 80 | impl = _rocketbootstrap_dlsym_func("rocketbootstrap_cfmessageportcreateremote"); 81 | if (!impl) { 82 | impl = CFMessagePortCreateRemote; 83 | } 84 | } 85 | return impl(allocator, name); 86 | } 87 | __attribute__((unused)) 88 | static kern_return_t rocketbootstrap_cfmessageportexposelocal(CFMessagePortRef messagePort) 89 | { 90 | static kern_return_t (*impl)(CFMessagePortRef messagePort); 91 | if (!impl) { 92 | impl = _rocketbootstrap_dlsym_func("rocketbootstrap_cfmessageportexposelocal"); 93 | if (!impl) { 94 | return -1; 95 | } 96 | } 97 | return impl(messagePort); 98 | } 99 | #endif 100 | 101 | #ifdef __OBJC__ 102 | @class CPDistributedMessagingCenter; 103 | __attribute__((unused)) 104 | static void rocketbootstrap_distributedmessagingcenter_apply(CPDistributedMessagingCenter *messaging_center) 105 | { 106 | static void (*impl)(CPDistributedMessagingCenter *messagingCenter); 107 | if (!impl) { 108 | impl = _rocketbootstrap_dlsym_func("rocketbootstrap_distributedmessagingcenter_apply"); 109 | if (!impl) 110 | return; 111 | } 112 | impl(messaging_center); 113 | } 114 | #endif 115 | 116 | #ifdef __XPC_CONNECTION_H__ 117 | __attribute__((unused)) 118 | static xpc_connection_t rocketbootstrap_xpc_connection_create(const char *name, dispatch_queue_t targetq, uint64_t flags) 119 | { 120 | static xpc_connection_t (*impl)(const char *name, dispatch_queue_t targetq, uint64_t flags); 121 | if (!impl) { 122 | impl = _rocketbootstrap_dlsym_func("rocketbootstrap_xpc_connection_create"); 123 | if (!impl) 124 | return NULL; 125 | } 126 | return impl(name, targetq, flags); 127 | } 128 | 129 | __attribute__((unused)) 130 | static xpc_object_t rocketbootstrap_xpc_connection_copy_application_identifier(xpc_connection_t connection) 131 | { 132 | static xpc_object_t (*impl)(xpc_connection_t connection); 133 | if (!impl) { 134 | impl = _rocketbootstrap_dlsym_func("rocketbootstrap_xpc_connection_copy_application_identifier"); 135 | if (!impl) 136 | return NULL; 137 | } 138 | return impl(connection); 139 | } 140 | #endif 141 | -------------------------------------------------------------------------------- /rocketbootstrap_internal.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "rocketbootstrap.h" 4 | 5 | #define kRocketBootstrapUnlockService "com.rpetrich.rocketbootstrapd" 6 | 7 | #define ROCKETBOOTSTRAP_LOOKUP_ID -1 8 | 9 | typedef struct { 10 | mach_msg_header_t head; 11 | mach_msg_body_t body; 12 | uint32_t name_length; 13 | char name[]; 14 | } _rocketbootstrap_lookup_query_t; 15 | 16 | typedef struct { 17 | mach_msg_header_t head; 18 | mach_msg_body_t body; 19 | mach_msg_port_descriptor_t response_port; 20 | } _rocketbootstrap_lookup_response_t; 21 | 22 | #import "LightMessaging/LightMessaging.h" 23 | 24 | __attribute__((unused)) 25 | static LMConnection connection = { 26 | MACH_PORT_NULL, 27 | kRocketBootstrapUnlockService 28 | }; 29 | 30 | __attribute__((unused)) 31 | static inline bool rocketbootstrap_is_passthrough(void) 32 | { 33 | return kCFCoreFoundationVersionNumber < 800.0; 34 | } 35 | 36 | kern_return_t _rocketbootstrap_is_unlocked(const name_t service_name); // Errors if not in a privileged process such as SpringBoard or backboardd 37 | -------------------------------------------------------------------------------- /rocketd.c: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #define LIGHTMESSAGING_USE_ROCKETBOOTSTRAP 0 4 | 5 | #import "rocketbootstrap_internal.h" 6 | 7 | static CFMutableSetRef allowedNames; 8 | 9 | static const uint32_t one = 1; 10 | 11 | static void machPortCallback(CFMachPortRef port, void *bytes, CFIndex size, void *info) 12 | { 13 | LMMessage *request = bytes; 14 | if (!LMDataWithSizeIsValidMessage(bytes, size)) { 15 | LMSendReply(request->head.msgh_remote_port, NULL, 0); 16 | LMResponseBufferFree(bytes); 17 | return; 18 | } 19 | // Send Response 20 | const void *data = LMMessageGetData(request); 21 | size_t length = LMMessageGetDataLength(request); 22 | const void *reply_data = NULL; 23 | uint32_t reply_length = 0; 24 | if (length) { 25 | CFStringRef name = CFStringCreateWithBytes(kCFAllocatorDefault, data, length, kCFStringEncodingUTF8, false); 26 | if (name) { 27 | switch (request->head.msgh_id) { 28 | case 0: // Register 29 | #ifdef DEBUG 30 | CFLog(kCFLogLevelWarning, CFSTR("Unlocking %@"), name); 31 | #endif 32 | CFSetAddValue(allowedNames, name); 33 | break; 34 | case 1: // Query 35 | if (CFSetContainsValue(allowedNames, name)) { 36 | reply_data = &one; 37 | reply_length = sizeof one; 38 | #ifdef DEBUG 39 | CFLog(kCFLogLevelWarning, CFSTR("Queried %@, is unlocked"), name); 40 | #endif 41 | } else { 42 | #ifdef DEBUG 43 | CFLog(kCFLogLevelWarning, CFSTR("Queried %@, is locked!"), name); 44 | #endif 45 | } 46 | break; 47 | case 2: 48 | // Good morning, still awake 49 | reply_data = &one; 50 | reply_length = sizeof one; 51 | break; 52 | } 53 | CFRelease(name); 54 | } 55 | } 56 | LMSendReply(request->head.msgh_remote_port, reply_data, reply_length); 57 | LMResponseBufferFree(bytes); 58 | } 59 | 60 | int main(int argc, char *argv[]) 61 | { 62 | allowedNames = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks); 63 | LMCheckInService(connection.serverName, CFRunLoopGetCurrent(), machPortCallback, NULL); 64 | notify_post("com.rpetrich.rocketd.started"); 65 | CFRunLoopRun(); 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /rocketd_reenable.c: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #ifdef __LP64__ 6 | #if __has_include() 7 | #include 8 | #define sign_function(ptr) ({ \ 9 | __typeof__(ptr) _ptr = ptr; \ 10 | ptr ? ptrauth_sign_unauthenticated(_ptr, ptrauth_key_function_pointer, 0) : _ptr; \ 11 | }) 12 | #else 13 | #define sign_function(ptr) ptr 14 | #endif 15 | #else 16 | #define sign_function(ptr) ptr 17 | #endif 18 | 19 | #ifdef __arm64__ 20 | #import "libjailbreak_xpc.h" 21 | static int fix_setuid(void) 22 | { 23 | void *libjailbreak = dlopen("/usr/lib/libjailbreak.dylib", RTLD_LAZY); 24 | if (libjailbreak) { 25 | jb_connection_t (*jb_connect)(void) = sign_function(dlsym(libjailbreak, "jb_connect")); 26 | int (*jb_fix_setuid_now)(jb_connection_t connection, pid_t pid) = sign_function(dlsym(libjailbreak, "jb_fix_setuid_now")); 27 | void (*jb_disconnect)(jb_connection_t connection) = sign_function(dlsym(libjailbreak, "jb_disconnect")); 28 | if (jb_connect && jb_fix_setuid_now && jb_disconnect) { 29 | jb_connection_t connection = jb_connect(); 30 | if (connection) { 31 | int result = jb_fix_setuid_now(connection, getpid()); 32 | jb_disconnect(connection); 33 | return result; 34 | } 35 | } 36 | } 37 | return 1; 38 | } 39 | #else 40 | static int fix_setuid(void) 41 | { 42 | // Does not apply to older iOS versions 43 | return 1; 44 | } 45 | #endif 46 | 47 | int main(int argc, char *argv[]) 48 | { 49 | close(0); 50 | close(1); 51 | close(2); 52 | fix_setuid(); 53 | setuid(0); 54 | setgid(0); 55 | seteuid(0); 56 | setegid(0); 57 | return execlp("launchctl", "launchctl", "load", "/Library/LaunchDaemons/com.rpetrich.rocketbootstrapd.plist", NULL); 58 | } 59 | -------------------------------------------------------------------------------- /sandbox.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2010 Apple Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | #ifndef _SANDBOX_H_ 24 | #define _SANDBOX_H_ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | __BEGIN_DECLS 31 | /* 32 | * @function sandbox_init 33 | * Places the current process in a sandbox with a profile as 34 | * specified. If the process is already in a sandbox, the new profile 35 | * is ignored and sandbox_init() returns an error. 36 | * 37 | * @param profile (input) The Sandbox profile to be used. The format 38 | * and meaning of this parameter is modified by the `flags' parameter. 39 | * 40 | * @param flags (input) Must be SANDBOX_NAMED. All other 41 | * values are reserved. 42 | * 43 | * @param errorbuf (output) In the event of an error, sandbox_init 44 | * will set `*errorbuf' to a pointer to a NUL-terminated string 45 | * describing the error. This string may contain embedded newlines. 46 | * This error information is suitable for developers and is not 47 | * intended for end users. 48 | * 49 | * If there are no errors, `*errorbuf' will be set to NULL. The 50 | * buffer `*errorbuf' should be deallocated with `sandbox_free_error'. 51 | * 52 | * @result 0 on success, -1 otherwise. 53 | */ 54 | int sandbox_init(const char *profile, uint64_t flags, char **errorbuf); 55 | 56 | /* 57 | * @define SANDBOX_NAMED The `profile' argument specifies a Sandbox 58 | * profile named by one of the kSBXProfile* string constants. 59 | */ 60 | #define SANDBOX_NAMED 0x0001 61 | 62 | #ifdef __APPLE_API_PRIVATE 63 | 64 | /* The following flags are reserved for Mac OS X. Developers should not 65 | * depend on their availability. 66 | */ 67 | 68 | /* 69 | * @define SANDBOX_NAMED_BUILTIN The `profile' argument specifies the 70 | * name of a builtin profile that is statically compiled into the 71 | * system. 72 | */ 73 | #define SANDBOX_NAMED_BUILTIN 0x0002 74 | 75 | /* 76 | * @define SANDBOX_NAMED_EXTERNAL The `profile' argument specifies the 77 | * pathname of a Sandbox profile. The pathname may be abbreviated: If 78 | * the name does not start with a `/' it is treated as relative to 79 | * /usr/share/sandbox and a `.sb' suffix is appended. 80 | */ 81 | #define SANDBOX_NAMED_EXTERNAL 0x0003 82 | 83 | /* 84 | * @define SANDBOX_NAMED_MASK Mask for name types: 4 bits, 15 possible 85 | * name types, 3 currently defined. 86 | */ 87 | #define SANDBOX_NAMED_MASK 0x000f 88 | 89 | #endif /* __APPLE_API_PRIVATE */ 90 | 91 | /* 92 | * Available Sandbox profiles. 93 | */ 94 | 95 | /* TCP/IP networking is prohibited. */ 96 | extern const char kSBXProfileNoInternet[]; 97 | 98 | /* All sockets-based networking is prohibited. */ 99 | extern const char kSBXProfileNoNetwork[]; 100 | 101 | /* File system writes are prohibited. */ 102 | extern const char kSBXProfileNoWrite[]; 103 | 104 | /* File system writes are restricted to temporary folders /var/tmp and 105 | * confstr(_CS_DARWIN_USER_DIR, ...). 106 | */ 107 | extern const char kSBXProfileNoWriteExceptTemporary[]; 108 | 109 | /* All operating system services are prohibited. */ 110 | extern const char kSBXProfilePureComputation[]; 111 | 112 | /* 113 | * @function sandbox_free_error 114 | * Deallocates an error string previously allocated by sandbox_init. 115 | * 116 | * @param errorbuf (input) The buffer to be freed. Must be a pointer 117 | * previously returned by sandbox_init in the `errorbuf' argument, or NULL. 118 | * 119 | * @result void 120 | */ 121 | void sandbox_free_error(char *errorbuf); 122 | 123 | 124 | #ifdef __APPLE_API_PRIVATE 125 | 126 | /* The following definitions are reserved for Mac OS X. Developers should not 127 | * depend on their availability. 128 | */ 129 | 130 | int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf); 131 | 132 | int sandbox_init_with_extensions(const char *profile, uint64_t flags, const char *const extensions[], char **errorbuf); 133 | 134 | enum sandbox_filter_type { 135 | SANDBOX_FILTER_NONE, 136 | SANDBOX_FILTER_PATH, 137 | SANDBOX_FILTER_GLOBAL_NAME, 138 | SANDBOX_FILTER_LOCAL_NAME, 139 | SANDBOX_FILTER_APPLEEVENT_DESTINATION, 140 | SANDBOX_FILTER_RIGHT_NAME, 141 | }; 142 | 143 | extern const enum sandbox_filter_type SANDBOX_CHECK_NO_REPORT __attribute__((weak_import)); 144 | 145 | enum sandbox_extension_flags { 146 | FS_EXT_DEFAULTS = 0, 147 | FS_EXT_FOR_PATH = (1 << 0), 148 | FS_EXT_FOR_FILE = (1 << 1), 149 | FS_EXT_READ = (1 << 2), 150 | FS_EXT_WRITE = (1 << 3), 151 | FS_EXT_PREFER_FILEID = (1 << 4), 152 | }; 153 | 154 | int sandbox_check(pid_t pid, const char *operation, enum sandbox_filter_type type, ...); 155 | 156 | int sandbox_note(const char *note); 157 | 158 | int sandbox_suspend(pid_t pid); 159 | int sandbox_unsuspend(void); 160 | 161 | int sandbox_issue_extension(const char *path, char **ext_token); 162 | int sandbox_issue_fs_extension(const char *path, uint64_t flags, char **ext_token); 163 | int sandbox_issue_fs_rw_extension(const char *path, char **ext_token); 164 | int sandbox_issue_mach_extension(const char *name, char **ext_token); 165 | 166 | int sandbox_consume_extension(const char *path, const char *ext_token); 167 | int sandbox_consume_fs_extension(const char *ext_token, char **path); 168 | int sandbox_consume_mach_extension(const char *ext_token, char **name); 169 | 170 | int sandbox_release_fs_extension(const char *ext_token); 171 | 172 | int sandbox_container_path_for_pid(pid_t pid, char *buffer, size_t bufsize); 173 | 174 | int sandbox_wakeup_daemon(char **errorbuf); 175 | 176 | const char *_amkrtemp(const char *); 177 | 178 | #endif /* __APPLE_API_PRIVATE */ 179 | 180 | __END_DECLS 181 | #endif /* _SANDBOX_H_ */ 182 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | LIBRARY_NAME = librocketbootstrap_tests 2 | librocketbootstrap_tests_FILES = tests.m 3 | librocketbootstrap_tests_LIBRARIES = rocketbootstrap 4 | librocketbootstrap_tests_FRAMEWORKS = Foundation UIKit 5 | 6 | ADDITIONAL_CFLAGS = -std=c99 -I../ 7 | 8 | IPHONE_ARCHS = armv6 arm64 9 | 10 | SDKVERSION_armv6 = 5.1 11 | INCLUDE_SDKVERSION_armv6 = 8.4 12 | TARGET_IPHONEOS_DEPLOYMENT_VERSION = 4.0 13 | 14 | TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv6 = 3.0 15 | THEOS_PLATFORM_SDK_ROOT_armv6 = /Applications/Xcode_Legacy.app/Contents/Developer 16 | 17 | include framework/makefiles/common.mk 18 | include framework/makefiles/library.mk 19 | -------------------------------------------------------------------------------- /tests/control: -------------------------------------------------------------------------------- 1 | Package: com.rpetrich.rocketbootstrap.tests 2 | Depends: com.rpetrich.rocketbootstrap 3 | Name: RocketBootstrap Tests 4 | Version: 0.1 5 | Architecture: iphoneos-arm 6 | Description: Tests for RocketBootstrap 7 | Maintainer: BigBoss 8 | Author: Ryan Petrich 9 | Sponsor: thebigboss.org 10 | Section: Tweaks 11 | dev: rpetrich 12 | -------------------------------------------------------------------------------- /tests/framework: -------------------------------------------------------------------------------- 1 | ../framework -------------------------------------------------------------------------------- /tests/tests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #include "log.h" 3 | 4 | #import "rocketbootstrap.h" 5 | 6 | @implementation NSObject (rocketbootstrap) 7 | 8 | + (kern_return_t)rocketbootstrap_unlock:(NSString *)name 9 | { 10 | return rocketbootstrap_unlock([name UTF8String]); 11 | } 12 | 13 | static CFDataRef messagePortCallback(CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info) 14 | { 15 | NSLog(@"rockettest_messageport_server: received %@", data); 16 | return CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"bootstrap", 9); 17 | } 18 | 19 | + (kern_return_t)rockettest_messageport_server 20 | { 21 | static CFMessagePortRef messagePort; 22 | if (messagePort) 23 | return 0; 24 | messagePort = CFMessagePortCreateLocal(kCFAllocatorDefault, CFSTR("rockettest_messageport"), messagePortCallback, NULL, NULL); 25 | CFRunLoopSourceRef source = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, messagePort, 0); 26 | CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); 27 | CFRunLoopAddSource(CFRunLoopGetCurrent(), source, (CFStringRef)UITrackingRunLoopMode); 28 | return rocketbootstrap_cfmessageportexposelocal(messagePort); 29 | } 30 | 31 | + (NSData *)rockettest_messageport_client 32 | { 33 | CFMessagePortRef remote = rocketbootstrap_cfmessageportcreateremote(kCFAllocatorDefault, CFSTR("rockettest_messageport")); 34 | if (!remote) 35 | return nil; 36 | CFDataRef request = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"rocket", 6); 37 | CFDataRef response = NULL; 38 | CFMessagePortSendRequest(remote, 0, request, 10, 10, CFSTR("rocketboostrap_wait"), &response); 39 | CFRelease(remote); 40 | CFRelease(request); 41 | return [(NSData *)response autorelease]; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /unfair_lock.h: -------------------------------------------------------------------------------- 1 | #if __IPHONE_OS_VERSION_MAX_ALLOWED > 100000 2 | // New SDK 3 | #include 4 | #define unfair_lock os_unfair_lock 5 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000 6 | // Only targeting new iOS, always use unfair locks 7 | #define unfair_lock_lock os_unfair_lock_lock 8 | #define unfair_lock_trylock os_unfair_lock_trylock 9 | #define unfair_lock_unlock os_unfair_lock_unlock 10 | #else 11 | // Support both at runtime 12 | #import 13 | static inline void unfair_lock_lock(unfair_lock *lock) 14 | { 15 | if (&os_unfair_lock_lock != NULL) { 16 | os_unfair_lock_lock(lock); 17 | } else { 18 | OSSpinLockLock((volatile OSSpinLock *)lock); 19 | } 20 | } 21 | static inline bool unfair_lock_trylock(unfair_lock *lock) 22 | { 23 | if (&os_unfair_lock_trylock != NULL) { 24 | return os_unfair_lock_trylock(lock); 25 | } else { 26 | return OSSpinLockTry((volatile OSSpinLock *)lock); 27 | } 28 | } 29 | static inline void unfair_lock_unlock(unfair_lock *lock) 30 | { 31 | if (&os_unfair_lock_unlock != NULL) { 32 | os_unfair_lock_unlock(lock); 33 | } else { 34 | OSSpinLockUnlock((volatile OSSpinLock *)lock); 35 | } 36 | } 37 | #endif 38 | #else 39 | // Old SDK, fallback to using regular old spinlocks 40 | #import 41 | #define unfair_lock volatile OSSpinLock 42 | #define unfair_lock_lock OSSpinLockLock 43 | #define unfair_lock_trylock OSSpinLockTry 44 | #define unfair_lock_unlock OSSpinLockUnlock 45 | #endif --------------------------------------------------------------------------------