diff options
author | comex | 2015-07-11 18:41:10 -0400 |
---|---|---|
committer | comex | 2015-07-11 18:41:10 -0400 |
commit | f5089d804a2697ce590e42c9858ea044bec4db36 (patch) | |
tree | 8e26066e157cbb4396cacec4d56c692532534156 /darwin-bootstrap | |
parent | working on safety (diff) | |
download | substitute-f5089d804a2697ce590e42c9858ea044bec4db36.tar.gz |
progress
Diffstat (limited to 'darwin-bootstrap')
-rw-r--r-- | darwin-bootstrap/safemode-ui-hook.m | 93 | ||||
-rw-r--r-- | darwin-bootstrap/substituted.m | 37 |
2 files changed, 121 insertions, 9 deletions
diff --git a/darwin-bootstrap/safemode-ui-hook.m b/darwin-bootstrap/safemode-ui-hook.m new file mode 100644 index 0000000..f762c6d --- /dev/null +++ b/darwin-bootstrap/safemode-ui-hook.m @@ -0,0 +1,93 @@ +#include "substitute.h" +#include <objc/runtime.h> +#include <notify.h> +#include <dispatch/dispatch.h> +#import <Foundation/Foundation.h> +#import <UIKit/UIKit.h> + +/* TODO: test what happens when both are required */ + +static bool g_did_say_in_setup_mode; +static bool g_did_exit_safety_dance; + +@interface _SBApplicationController +- (id)applicationWithBundleIdentifier:(NSString *)identifier; +@end + +@interface _SBSetupManager +- (bool)updateInSetupMode; +- (bool)_setInSetupMode:(bool)inSetupMode; +- (id)applicationWithBundleIdentifier:(NSString *)identifier; +@end + +@interface _SpringBoard +- (void)relaunchSpringBoard; +@end + +static id (*old_setupApplication)(id, SEL); +static id my_setupApplication(id self, SEL sel) { + if (g_did_say_in_setup_mode) + return [self applicationWithBundleIdentifier:@"com.ex.SafetyDance"]; + return old_setupApplication(self, sel); +} + +static bool (*old_updateInSetupMode)(id, SEL); +static bool my_updateInSetupMode(id self, SEL sel) { + if (g_did_exit_safety_dance) { + g_did_say_in_setup_mode = false; + return old_updateInSetupMode(self, sel); + } else { + /* take priority over real setup */ + g_did_say_in_setup_mode = true; + [self _setInSetupMode:true]; + return true; + } +} + +static bool (*old__handleSetupExited)(id, SEL, id); +static bool my__handleSetupExited(id self, SEL sel, id app) { + if (g_did_say_in_setup_mode) + g_did_exit_safety_dance = true; + return old__handleSetupExited(self, sel, app); +} + +__attribute__((constructor)) +static void init() { + #define GET(clsname) \ + Class clsname = objc_getClass(#clsname); \ + if (!clsname) { \ + NSLog(@"substitute safe mode failed to find %s", #clsname); \ + return; \ + } + + GET(SBApplicationController); + GET(SBSetupManager); + GET(SBWorkspace); + + int notify_token; + uint32_t notify_status = notify_register_dispatch( + "com.ex.substitute.safemode-restart-springboard-plz", + ¬ify_token, dispatch_get_main_queue(), ^(int tok) { + id sb = [UIApplication sharedApplication]; + [sb relaunchSpringBoard]; + } + ); + + #define HOOK(cls, sel, selvar) do { \ + int ret = substitute_hook_objc_message(cls, @selector(sel), \ + my_##selvar, \ + &old_##selvar, NULL); \ + if (ret) { \ + NSLog(@"substitute safe mode '%s' hook failed: %d", #sel, ret); \ + return; \ + } \ + } while(0) + + /* note: any of these might fail, leaving the previous ones hooked */ + + HOOK(SBApplicationController, setupApplication, setupApplication); + HOOK(SBWorkspace, _handleSetupExited:, _handleSetupExited); + HOOK(SBSetupManager, updateInSetupMode, updateInSetupMode); + + +} diff --git a/darwin-bootstrap/substituted.m b/darwin-bootstrap/substituted.m index 5cb1b11..43654c2 100644 --- a/darwin-bootstrap/substituted.m +++ b/darwin-bootstrap/substituted.m @@ -9,7 +9,11 @@ * libraries into the target binary (unless actually required by loaded * libraries). In the future it will help with hot loading. */ -static bool g_springboard_needs_safe; +static enum { + NO_SAFE, + NEEDS_SAFE, + REALLY_SAFE, +} g_springboard_needs_safe; extern kern_return_t bootstrap_look_up3(mach_port_t bp, const char *service_name, mach_port_t *sp, pid_t target_pid, @@ -91,17 +95,22 @@ enum convert_filters_ret { } } - bool safe_mode = false; + bool for_safe_mode = false; NSNumber *safe_mode_num = [filter objectForKey:@"SafeMode"]; if (safe_mode_num) { if ([safe_mode_num isEqual:[NSNumber numberWithBool:true]]) - safe_mode = true; + for_safe_mode = true; else if (![safe_mode_num isEqual:[NSNumber numberWithBool:false]]) return INVALID; } - if ((safe_mode && !_is_springboard) || - safe_mode != g_springboard_needs_safe) - return FAIL; + /* in REALLY_SAFE mode, nothing gets loaded */ + if (for_safe_mode) { + if (!_is_springboard || g_springboard_needs_safe != NEEDS_SAFE) + return FAIL; + } else { + if (_is_springboard && g_springboard_needs_safe != NO_SAFE) + return FAIL; + } bool any = false; NSString *mode_str = [filter objectForKey:@"Mode"]; @@ -249,9 +258,19 @@ enum convert_filters_ret { - (void)handleHangup { /* this could be false because hello hasn't been sent, but in that case it * hasn't loaded any substitute dylibs, so not our problem *whistle* */ - if (_is_springboard && !_got_bye) { - NSLog(@"SpringBoard hung up without saying bye; using safe mode next time."); - g_springboard_needs_safe = true; + if (_is_springboard) { + bool needs_safe = !_got_bye; + if (needs_safe) { + if (g_springboard_needs_safe) { + NSLog(@"SpringBoard hung up more than once without without saying bye; using Really Safe Mode (no UI) next time :("); + g_springboard_needs_safe = REALLY_SAFE; + } else { + NSLog(@"SpringBoard hung up without saying bye; using safe mode next time."); + g_springboard_needs_safe = NEEDS_SAFE; + } + } else { + g_springboard_needs_safe = NO_SAFE; + } } } |