Difference between revisions of "Updating extensions for iOS 9"

From iPhone Development Wiki
Jump to: navigation, search
(Compiling ldid on El Capitan: brew install ldid <3)
m (Formatting changes.)
 
(47 intermediate revisions by 21 users not shown)
Line 7: Line 7:
 
If you want to see what's been recently updated on this page, you can use the wiki's [http://iphonedevwiki.net/index.php?title=Updating_extensions_for_iOS_9&action=history history feature] to compare the revisions (to look at the diff) since the last time you visited this page.
 
If you want to see what's been recently updated on this page, you can use the wiki's [http://iphonedevwiki.net/index.php?title=Updating_extensions_for_iOS_9&action=history history feature] to compare the revisions (to look at the diff) since the last time you visited this page.
  
== Compiling ldid on El Capitan ==
+
[[Category:Updating extensions]]
  
Not quite iOS 9, but still something to be aware of: El Capitan does not include OpenSSL, which ldid requires to compile. In order to get OpenSSL and modify ldid's make script to use it, follow these steps.
+
= Compiling ldid on El Capitan =
  
* Install [http://brew.sh Homebrew] if you haven't already.
+
ldid [https://github.com/Homebrew/homebrew/commit/ac8d9201b8ae5ffe2d6aef6acf08cf1f654caccc was recently added to] the main Homebrew repo.
* Install OpenSSL through Homebrew:
 
brew install openssl
 
* Clone ldid as normal.
 
* Download [https://gist.github.com/aarzee/7b071088c4fca0b3ee25/raw/d62d89e72c0a0625512a81eea7562cef970f430e/make.sh this modded make.sh] and replace the old one with this one.
 
* Make as normal:
 
./make.sh
 
  
Alternatively, kirb (hi, that's me) just got ldid [https://github.com/Homebrew/homebrew/commit/ac8d9201b8ae5ffe2d6aef6acf08cf1f654caccc added to] the main Homebrew repo.
+
brew update
 +
brew install ldid
  
brew update
+
This is more convenient for ensuring ldid is kept up to date in future.
brew install ldid
 
  
This may be seen as more convenient for ensuring ldid is kept up to date in future.
+
= What has changed in iOS 9? (Classes, frameworks, etc.) =
  
== What has changed in iOS 9? (Classes, frameworks, etc.) ==
+
== Compilation changes ==
 
 
=== Compilation changes ===
 
  
 
32 bit binaries loaded on 64 bit devices fail to do so since the 32 bit pagesize has been changed from 4096 bytes to 16384 bytes.
 
32 bit binaries loaded on 64 bit devices fail to do so since the 32 bit pagesize has been changed from 4096 bytes to 16384 bytes.
Line 34: Line 26:
 
Tweaks targeted at 32 bit binaries on iOS 9 must now be compiled with
 
Tweaks targeted at 32 bit binaries on iOS 9 must now be compiled with
  
    -Wl,-segalign,4000
+
<source lang="text">
 +
-Wl,-segalign,4000
 +
</source>
  
 
This LDFLAG can be used to compile for older iOS versions as it had to be a multiple of 1000 and this new alignment is compatible.
 
This LDFLAG can be used to compile for older iOS versions as it had to be a multiple of 1000 and this new alignment is compatible.
Line 40: Line 34:
 
If using [[Theos]], add it like so to your makefile:
 
If using [[Theos]], add it like so to your makefile:
  
    XXX_LDFLAGS += -Wl,-segalign,4000
+
<source lang="makefile">
 +
XXX_LDFLAGS += -Wl,-segalign,4000
 +
</source>
 +
 
 +
This fix is [https://github.com/kirb/theos/commit/bbf282bd3d2fccd5cbadaeac699820fec0f1e533 integrated with kirb/theos]. (Be sure to <code>make update-theos</code> regularly.)
  
 
If using [[Xcode]], add a new entry to ''Other linker flags'' containing "-Wl,-segalign,4000" to the build settings of your project or target and make sure that the build option "Enable Bitcode" is disabled.
 
If using [[Xcode]], add a new entry to ''Other linker flags'' containing "-Wl,-segalign,4000" to the build settings of your project or target and make sure that the build option "Enable Bitcode" is disabled.
Line 48: Line 46:
 
One example of this are tweaks that modify Cydia, which is a 32 bit app.
 
One example of this are tweaks that modify Cydia, which is a 32 bit app.
  
=== Entitlements ===
+
== Entitlements ==
 +
 
 +
'''''Every''''' dylib meant for injection has to be signed to work on iOS, even if no entitlements are required. Please make sure that your toolchain of choice is producing signed dylibs, if it is a fat binary, make sure that ''all'' slices are signed.
 +
 
 +
Use ldid to sign:
 +
 
 +
    ldid -S Tweak.dylib
 +
 
 +
Failure to do this will invalidate the process and make it lose all entitlements. The standard symptom is the following, but frankly, it is confusing why any binaries are in the wild that haven't at least been passed through ldid, so please don't rely on this symptom and just fix your build environment.
  
Tweaks interacting with BackBoardServices now require an entitlement and will fail with the following error if it's not present on the binary:
+
When the process is invalid and thus entitlements are lost, this is output to console on launch:
 +
 
 +
<source lang="text">
 +
pmpd[13381] <Error>: MS:Error: process is not CS_VALID
 +
</source>
 +
 
 +
And then this is shown when the required entitlement no longer exists, despite being included in the binary!
  
 
<source lang="text">
 
<source lang="text">
Line 57: Line 69:
 
</source>
 
</source>
  
Use [[ldid]] to sign your tweak with the following entitlement XML file:
+
=== Granting them at runtime ===
  
<source lang="xml">
+
To grant entitlements to a specific process in iOS 9, it seems that iOS 8's _BSAuditTokenTaskHasEntitlement function in assertiond no longer does the trick, the new _BSXPCConnectionHasEntitlement needs to be hooked instead.
<?xml version="1.0" encoding="UTF-8"?>
+
 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+
== Sandbox Restrictions ==
<plist version="1.0">
+
 
<dict>
+
Tweaks that create or edit files from a sandbox application outside the app's container is no longer allowed
<key>com.apple.backboard.client</key>
+
*  Use an XPC method to communicate with SpringBoard from the sandbox application
<true/>
+
See [http://iphonedevwiki.net/index.php/CPDistributedMessagingCenter CPDistributedMessagingCenter] for some example code.
</dict>
+
 
</plist>
+
This way you could communicate with a SpringBoard class to get it to save or create your files
 +
 
 +
You would need to add AppSupport framework in your makefile
 +
 
 +
<source lang="makefile">
 +
XXX_FRAMEWORKS = AppSupport
 
</source>
 
</source>
  
Using ldid:
+
* After the v1.1 Pangu Untether update it is no longer possible to save/create/modify the preferences from Sandboxed applications in "atomically" mode.
    ldid -Sentitlements.xml Tweak.dylib
+
You will get something like this:
  
Using theos, add this to your makefile:
+
<source lang="text">
    XXX_CODESIGN_FLAGS = -Sentitlements.xml
+
Sandbox: processname(PID) deny(1) file-write-unlink/file-write-create  /private/var/mobile/Library/Preferences/prefs_file_name.plist
 +
</source>
  
== Which tools and other preexisting things are still working on iOS 9? Which ones don't work? ==
+
As a workaround you can just replace "atomically:YES" with "atomically:NO":
  
No fixes for the following at the time of this writing. Note that these work on 32-bit devices, such as an iPhone 5.
+
<source lang="objc">
 +
[prefsDict writeToFile:settingsFilePath atomically:NO];
 +
</source>
  
* Cycript fails with the following error:
+
* some sysctl calls and proc_* functions cannot be used in a sandbox now
 +
trying to use these functions in a sandboxed app will throw an error like:
  
 
<source lang="text">
 
<source lang="text">
dyld: Library not loaded: /usr/lib/libapr-1.0.dylib
+
Sandbox: [PROCCESSNAME] deny(1) process-info-listpids
  Referenced from: /usr/bin/cycript
+
</source>
  Reason: no suitable image found.  Did find:
+
 
    /usr/lib/libapr-1.0.dylib: mmap() error 22 at address=0x0013F000, size=0x00001000 segment=__DATA in Segment::map() mapping /usr/lib/libapr-1.0.dylib
+
== UIScreen changes ==
    /usr/lib/libapr-1.0.dylib: mmap() error 22 at address=0x00163000, size=0x00001000 segment=__DATA in Segment::map() mapping /usr/lib/libapr-1.0.dylib
+
 
Trace/BPT trap: 5
+
UIScreen bounds on iPad no longer takes orientation into account. You must now use the bounds of the shared application's keyWindow property.
 +
 
 +
<source lang="objc">
 +
CGRect bounds = [[[UIApplication sharedApplication] keyWindow] bounds];
 
</source>
 
</source>
  
* wget fails with the following error
+
== File protection after reboot ==
 +
 
 +
Some tweaks are still affected by file access being restricted after a reboot until the device is unlocked, e.g. a Springboard tweak cannot read some file it previously created causing undefined behaviour and most likely cause a Springboard crash. e.g.
 +
https://www.reddit.com/r/jailbreak/comments/458dl0/question_why_does_some_tweaks_stop_working_after/?
 +
This post discusses workarounds:
 +
http://stackoverflow.com/questions/15079765/dealing-with-background-location-updates-and-core-data-file-protection
 +
I was using Core Data and used the option key NSPersistentStoreFileProtectionKey with value NSFileProtectionNone to fix my crash. Other APIs that create files have similar ways to disable the protection.
 +
 
 +
== Using iOS 9 SDK while supporting iOS 8 ==
 +
 
 +
If you updated to build with the iOS 9.2 SDK (maybe others as well) and you are using `@[]` - you might get a crash on iOS 8 devices. To fix this, use `[[NSArray alloc] init]` instead.
 +
 
 +
Example crash:
  
 
<source lang="text">
 
<source lang="text">
dyld: Library not loaded: /usr/lib/libintl.8.dylib
+
Feb  3 08:56:27 Jonathan-Winger-langs-iPad SpringBoard[682] <Error>: MS:Error: dlopen(/Library/MobileSubstrate/DynamicLibraries/InstaLauncher.dylib, 9): Symbol not found: ___NSArray0__
   Referenced from: /usr/bin/wget
+
   Referenced from: /Library/MobileSubstrate/DynamicLibraries/InstaLauncher.dylib (which was built for iOS 9.2)
  Reason: no suitable image found.  Did find:
+
  Expected in: /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
/usr/lib/libintl.8.dylib: mmap() error 22 at address=0x00387000, size=0x00001000 segment=__DATA in Segment::map() mapping /usr/lib/libintl.8.dylib
+
in /Library/MobileSubstrate/DynamicLibraries/InstaLauncher.dylib
/usr/lib/libintl.8.dylib: mmap() error 22 at address=0x00393000, size=0x00001000 segment=__DATA in Segment::map() mapping /usr/lib/libintl.8.dylib
 
Trace/BPT trap: 5
 
 
</source>
 
</source>
  
* python fails with the following error
+
== iOS 9.3.3 ==
 +
 
 +
Since this version is quite different from the previous, see [[Updating extensions for iOS 9.3.3]].
 +
 
 +
= Which tools and other preexisting things are still working on iOS 9? Which ones don't work? =
 +
 
 +
No fixes for the following at the time of this writing. Note that these work on 32-bit devices, such as an iPhone 5.
 +
 
 +
* Cycript works as of 28/10/2015 version 0.9.503
 +
 
 +
* the official python from cydia may fail however due to the work of Linus Yang and reddit user ryley_angus we have a working binary that works on iOS 9 !
 +
install all packages from [https://www.ryleyangus.com/Python-2.7.8-arm64.zip], most things I tested worked. The Python packages built by ryley_angus are also available from his repo [https://ryleyangus.com/repo].
 +
 
 +
* python fails with the following error (the one on cydia)
  
 
<source lang="text">
 
<source lang="text">
Line 113: Line 160:
 
</source>
 
</source>
  
* lighttpd fails with the following error
+
* As of (unknown date) in version 1.4.18-7, lighttpd works on iOS 9.
 +
 
 +
* ruby fails with the following error
  
 
<source lang="text">
 
<source lang="text">
dyld: Library not loaded: /usr/lib/lighttpd/liblightcomp.dylib
+
dyld: lazy symbol binding failed: re-exported symbol 'unknown' not found for image libgcc_s.1.dylib expected re-exported in libSystem.B.dylib, node=0x3980b148
  Referenced from: /usr/sbin/lighttpd
 
  Reason: no suitable image found. Did find:
 
/usr/lib/lighttpd/liblightcomp.dylib: mmap() error 22 at address=0x0012F000, size=0x00001000 segment=__DATA in Segment::map() mapping /usr/lib/lighttpd/liblightcomp.dylib
 
Trace/BPT trap: 5
 
 
</source>
 
</source>
  
=== Killed: 9 ===
+
This occurs due to the change in the 32-bit pagesize on 64-bit CPUs in iOS 9. The libraries noted above need to be rebuilt with "-Wl,-segalign,4000".
 +
 
 +
== Killed: 9 ==
  
 
Pangu9 causes many command-line tools to not work, with the error "Killed: 9"
 
Pangu9 causes many command-line tools to not work, with the error "Killed: 9"
Line 129: Line 176:
 
This can be solved by running "ldid -S `which <command>`"
 
This can be solved by running "ldid -S `which <command>`"
  
=== Daemons ===
+
== Daemons ==
  
 
In iOS 9 the way daemons are loaded appears to have changed. Daemons prefixed with "com.apple" are loaded first with other daemons being loaded by launchd significantly later. This creates a bug for daemons that use XPC to communicate with SpringBoard. SpringBoard will be loaded before the daemon meaning a connection can never be established. Changing the daemon prefix to "com.apple" appears to make it load at the same time as SpringBoard allowing for the connection to succeed. More research is required into why other daemons are being loaded much later than in iOS 8.
 
In iOS 9 the way daemons are loaded appears to have changed. Daemons prefixed with "com.apple" are loaded first with other daemons being loaded by launchd significantly later. This creates a bug for daemons that use XPC to communicate with SpringBoard. SpringBoard will be loaded before the daemon meaning a connection can never be established. Changing the daemon prefix to "com.apple" appears to make it load at the same time as SpringBoard allowing for the connection to succeed. More research is required into why other daemons are being loaded much later than in iOS 8.
  
 
Additionally, daemons are now outputting the error:
 
Additionally, daemons are now outputting the error:
 +
 
<source lang="text">
 
<source lang="text">
 
This daemon is not allowed to execute. Running anyway.
 
This daemon is not allowed to execute. Running anyway.
 
</source>
 
</source>
  
This may be related to daemons being loaded late and needs to be looked into.
+
This can be fixed by adding the plist entry ExecuteAllowed with a boolean YES.
 +
 
 +
Daemons that use more than 5MB are killed via Jetsam with no crash report saved:
 +
 
 +
<source lang="text">
 +
Oct 28 12:24:29 My-iPhone-6s ReportCrash[13169] <Notice>: MS:Notice: Injecting: (null) [ReportCrash] (1240.10)
 +
Oct 28 12:24:29 My-iPhone-6s ReportCrash[13169] <Notice>: MS:Notice: Loading: /Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.dylib
 +
Oct 28 12:24:30 My-iPhone-6s diagnosticd[209] <Error>: error evaluating process info - pid: 13166, punique: 13166
 +
Oct 28 12:24:30 My-iPhone-6s ReportCrash[13169] <Notice>: Formulating report for process[13166] pmpd
 +
Oct 28 12:24:30 My-iPhone-6s com.apple.xpc.launchd[1] (org.protectmyprivacy.pmpd) <Notice>: Service only ran for 0 seconds. Pushing respawn out by 10 seconds.
 +
Oct 28 12:24:30 My-iPhone-6s UserEventAgent[128] <Notice>: jetsam: kernel termination snapshot being created
 +
Oct 28 12:24:30 My-iPhone-6s ReportCrash[13169] <Warning>: report not saved because it is non-actionable
 +
</source>
 +
 
 +
This can be fixed by using [https://github.com/mariociabarra/jetslammed jetslammed] and raising the memory limit, e.g.
 +
 
 +
<source lang="objc">
 +
if ([UIDevice currentDevice].systemVersion.integerValue > 8){
 +
jetslammed_updateWaterMark(240, "pmpd"); // the param is currently range checked by the library and must be > 0 and < 1024. The string param can be anything in a daemon, it's main use is in tweaks to ensure its set to the highest of all the different calls to that method.
 +
} else {
 +
NSLog(@"jetslammed_updateWaterMark not required");
 +
}
 +
</source>
 +
 
 +
== Connecting to UNIX sockets ==
 +
 
 +
Tweaks built with a library injected into an app, communicating to a daemon using a UNIX a socket, might fail to connect to the UNIX socket, with error code EPERM, and the following syslog message:
 +
 
 +
kernel[0] <Notice>: Sandbox: app-name(<pid>) deny(1) network-outbound /private/var/tmp/mysocket
 +
 
 +
Note that this worked with the original Pangu untether and has been failing to work (as described) with the latest (1.1.0) Pangu Fuxi Qin.
 +
 
 +
'''Update:''' This seems to be untrue. This doesn't work with the original Pangu untether as well. Maybe the Cydia update process has to do something with it? Maybe stashing?
 +
 
 +
A current workaround is to place the UNIX socket inside the app's sandbox.
 +
 
 +
== Extension does not have filter ==
 +
 
 +
Starting on 0.9.6100 version of CydiaSubstrate, tweaks '''''must''''' specify a [[Cydia_Substrate#MobileLoader|MobileLoader filter]] or Substrate will prevent the tweak from getting injected at all, with the following error:
 +
 
 +
<source lang="text">
 +
MS:Error: extension does not have filter
 +
</source>
 +
 
 +
== canOpenURL restrictions ==
 +
 
 +
If you have a tweak that relies on canOpenURL it might not work because now the URLs that are allowed to be checked are required to be specified in the host app's Info.plist under LSApplicationQueriesSchemes. Unfortunately editing this list does not work because it appears to be checked at installation time, and also it can only be called with 50 URLs, once that limit is reached it fails regardless of any edits to the list. It's currently unknown where the database is stored on the device.
 +
 
 +
iOS 9 Launch scheme approval where it asks for permission to open an app:
 +
/private/var/preferences/com.apple.launchservices.schemeapproval.plist
 +
 
 +
For error-free access to this data query the canOpenURL: status in a daemon with the appropriate entitlements or inside SpringBoard using its entitlements and make the specific query accessible over IPC using RocketBootstrap, darwin_set_state or similar if necessary.
 +
 
 +
'''Update:''' It's now possible to bypass this restriction by hooking isApplicationAvailableToOpenURL in LSApplicationWorkspace. For example code, see this issue in a redundant project that was created before this hook was known: https://github.com/r-plus/libcanopenurl/issues/3

Latest revision as of 16:02, 8 September 2019

Let's collect knowledge like we did with Updating extensions for iOS 8 and Updating extensions for iOS 7 - paste in your notes and share what you've learned, and somebody else will organize it later. :) If you want to ask questions and share tips over chat with other developers, see How to use IRC for how to connect to #theos and #iphonedev.

Hey developer, you can add your knowledge here! Yes, you! Make an account and edit this page!

It's also helpful to double-check the statements here and add more info! These are notes and drafts from early research - feel free to update them.

If you want to see what's been recently updated on this page, you can use the wiki's history feature to compare the revisions (to look at the diff) since the last time you visited this page.

Compiling ldid on El Capitan

ldid was recently added to the main Homebrew repo.

brew update brew install ldid

This is more convenient for ensuring ldid is kept up to date in future.

What has changed in iOS 9? (Classes, frameworks, etc.)

Compilation changes

32 bit binaries loaded on 64 bit devices fail to do so since the 32 bit pagesize has been changed from 4096 bytes to 16384 bytes.

Tweaks targeted at 32 bit binaries on iOS 9 must now be compiled with

-Wl,-segalign,4000

This LDFLAG can be used to compile for older iOS versions as it had to be a multiple of 1000 and this new alignment is compatible.

If using Theos, add it like so to your makefile:

XXX_LDFLAGS += -Wl,-segalign,4000

This fix is integrated with kirb/theos. (Be sure to make update-theos regularly.)

If using Xcode, add a new entry to Other linker flags containing "-Wl,-segalign,4000" to the build settings of your project or target and make sure that the build option "Enable Bitcode" is disabled.

Source: saurik's tweet

One example of this are tweaks that modify Cydia, which is a 32 bit app.

Entitlements

Every dylib meant for injection has to be signed to work on iOS, even if no entitlements are required. Please make sure that your toolchain of choice is producing signed dylibs, if it is a fat binary, make sure that all slices are signed.

Use ldid to sign:

   ldid -S Tweak.dylib

Failure to do this will invalidate the process and make it lose all entitlements. The standard symptom is the following, but frankly, it is confusing why any binaries are in the wild that haven't at least been passed through ldid, so please don't rely on this symptom and just fix your build environment.

When the process is invalid and thus entitlements are lost, this is output to console on launch:

pmpd[13381] <Error>: MS:Error: process is not CS_VALID

And then this is shown when the required entitlement no longer exists, despite being included in the binary!

xbs/Sources/BackBoardServices/SpringBoard-3296.10.2/megatrond/SystemAppService/BKSSystemApplicationClient.m:32
Oct 14 21:29:57 iPhone SpringBoard[1860] <Error>: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Client lacks entitlement com.apple.backboard.client’

Granting them at runtime

To grant entitlements to a specific process in iOS 9, it seems that iOS 8's _BSAuditTokenTaskHasEntitlement function in assertiond no longer does the trick, the new _BSXPCConnectionHasEntitlement needs to be hooked instead.

Sandbox Restrictions

Tweaks that create or edit files from a sandbox application outside the app's container is no longer allowed

  • Use an XPC method to communicate with SpringBoard from the sandbox application

See CPDistributedMessagingCenter for some example code.

This way you could communicate with a SpringBoard class to get it to save or create your files

You would need to add AppSupport framework in your makefile

XXX_FRAMEWORKS = AppSupport
  • After the v1.1 Pangu Untether update it is no longer possible to save/create/modify the preferences from Sandboxed applications in "atomically" mode.

You will get something like this:

Sandbox: processname(PID) deny(1) file-write-unlink/file-write-create  /private/var/mobile/Library/Preferences/prefs_file_name.plist

As a workaround you can just replace "atomically:YES" with "atomically:NO":

[prefsDict writeToFile:settingsFilePath atomically:NO];
  • some sysctl calls and proc_* functions cannot be used in a sandbox now

trying to use these functions in a sandboxed app will throw an error like:

Sandbox: [PROCCESSNAME] deny(1) process-info-listpids

UIScreen changes

UIScreen bounds on iPad no longer takes orientation into account. You must now use the bounds of the shared application's keyWindow property.

CGRect bounds = [[[UIApplication sharedApplication] keyWindow] bounds];

File protection after reboot

Some tweaks are still affected by file access being restricted after a reboot until the device is unlocked, e.g. a Springboard tweak cannot read some file it previously created causing undefined behaviour and most likely cause a Springboard crash. e.g. https://www.reddit.com/r/jailbreak/comments/458dl0/question_why_does_some_tweaks_stop_working_after/? This post discusses workarounds: http://stackoverflow.com/questions/15079765/dealing-with-background-location-updates-and-core-data-file-protection I was using Core Data and used the option key NSPersistentStoreFileProtectionKey with value NSFileProtectionNone to fix my crash. Other APIs that create files have similar ways to disable the protection.

Using iOS 9 SDK while supporting iOS 8

If you updated to build with the iOS 9.2 SDK (maybe others as well) and you are using `@[]` - you might get a crash on iOS 8 devices. To fix this, use `[[NSArray alloc] init]` instead.

Example crash:

Feb  3 08:56:27 Jonathan-Winger-langs-iPad SpringBoard[682] <Error>: MS:Error: dlopen(/Library/MobileSubstrate/DynamicLibraries/InstaLauncher.dylib, 9): Symbol not found: ___NSArray0__
  Referenced from: /Library/MobileSubstrate/DynamicLibraries/InstaLauncher.dylib (which was built for iOS 9.2)
  Expected in: /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
 in /Library/MobileSubstrate/DynamicLibraries/InstaLauncher.dylib

iOS 9.3.3

Since this version is quite different from the previous, see Updating extensions for iOS 9.3.3.

Which tools and other preexisting things are still working on iOS 9? Which ones don't work?

No fixes for the following at the time of this writing. Note that these work on 32-bit devices, such as an iPhone 5.

  • Cycript works as of 28/10/2015 version 0.9.503
  • the official python from cydia may fail however due to the work of Linus Yang and reddit user ryley_angus we have a working binary that works on iOS 9 !

install all packages from [1], most things I tested worked. The Python packages built by ryley_angus are also available from his repo [2].

  • python fails with the following error (the one on cydia)
dyld: Library not loaded: /usr/lib/libpython2.7.dylib
  Referenced from: /usr/bin/python
  Reason: no suitable image found.  Did find:
	/usr/lib/libpython2.7.dylib: mmap() error 22 at address=0x00242000, size=0x0002A000 segment=__DATA in Segment::map() mapping /usr/lib/libpython2.7.dylib
	/usr/lib/libpython2.7.dylib: mmap() error 22 at address=0x003D6000, size=0x0002A000 segment=__DATA in Segment::map() mapping /usr/lib/libpython2.7.dylib
Trace/BPT trap: 5
  • As of (unknown date) in version 1.4.18-7, lighttpd works on iOS 9.
  • ruby fails with the following error
dyld: lazy symbol binding failed: re-exported symbol 'unknown' not found for image libgcc_s.1.dylib expected re-exported in libSystem.B.dylib, node=0x3980b148

This occurs due to the change in the 32-bit pagesize on 64-bit CPUs in iOS 9. The libraries noted above need to be rebuilt with "-Wl,-segalign,4000".

Killed: 9

Pangu9 causes many command-line tools to not work, with the error "Killed: 9"

This can be solved by running "ldid -S `which <command>`"

Daemons

In iOS 9 the way daemons are loaded appears to have changed. Daemons prefixed with "com.apple" are loaded first with other daemons being loaded by launchd significantly later. This creates a bug for daemons that use XPC to communicate with SpringBoard. SpringBoard will be loaded before the daemon meaning a connection can never be established. Changing the daemon prefix to "com.apple" appears to make it load at the same time as SpringBoard allowing for the connection to succeed. More research is required into why other daemons are being loaded much later than in iOS 8.

Additionally, daemons are now outputting the error:

This daemon is not allowed to execute. Running anyway.

This can be fixed by adding the plist entry ExecuteAllowed with a boolean YES.

Daemons that use more than 5MB are killed via Jetsam with no crash report saved:

Oct 28 12:24:29 My-iPhone-6s ReportCrash[13169] <Notice>: MS:Notice: Injecting: (null) [ReportCrash] (1240.10)
Oct 28 12:24:29 My-iPhone-6s ReportCrash[13169] <Notice>: MS:Notice: Loading: /Library/MobileSubstrate/DynamicLibraries/RocketBootstrap.dylib
Oct 28 12:24:30 My-iPhone-6s diagnosticd[209] <Error>: error evaluating process info - pid: 13166, punique: 13166
Oct 28 12:24:30 My-iPhone-6s ReportCrash[13169] <Notice>: Formulating report for process[13166] pmpd
Oct 28 12:24:30 My-iPhone-6s com.apple.xpc.launchd[1] (org.protectmyprivacy.pmpd) <Notice>: Service only ran for 0 seconds. Pushing respawn out by 10 seconds.
Oct 28 12:24:30 My-iPhone-6s UserEventAgent[128] <Notice>: jetsam: kernel termination snapshot being created
Oct 28 12:24:30 My-iPhone-6s ReportCrash[13169] <Warning>: report not saved because it is non-actionable

This can be fixed by using jetslammed and raising the memory limit, e.g.

if ([UIDevice currentDevice].systemVersion.integerValue > 8){
	jetslammed_updateWaterMark(240, "pmpd"); // the param is currently range checked by the library and must be > 0 and < 1024. The string param can be anything in a daemon, it's main use is in tweaks to ensure its set to the highest of all the different calls to that method.
} else {
	NSLog(@"jetslammed_updateWaterMark not required");
}

Connecting to UNIX sockets

Tweaks built with a library injected into an app, communicating to a daemon using a UNIX a socket, might fail to connect to the UNIX socket, with error code EPERM, and the following syslog message:

kernel[0] <Notice>: Sandbox: app-name(<pid>) deny(1) network-outbound /private/var/tmp/mysocket

Note that this worked with the original Pangu untether and has been failing to work (as described) with the latest (1.1.0) Pangu Fuxi Qin.

Update: This seems to be untrue. This doesn't work with the original Pangu untether as well. Maybe the Cydia update process has to do something with it? Maybe stashing?

A current workaround is to place the UNIX socket inside the app's sandbox.

Extension does not have filter

Starting on 0.9.6100 version of CydiaSubstrate, tweaks must specify a MobileLoader filter or Substrate will prevent the tweak from getting injected at all, with the following error:

MS:Error: extension does not have filter

canOpenURL restrictions

If you have a tweak that relies on canOpenURL it might not work because now the URLs that are allowed to be checked are required to be specified in the host app's Info.plist under LSApplicationQueriesSchemes. Unfortunately editing this list does not work because it appears to be checked at installation time, and also it can only be called with 50 URLs, once that limit is reached it fails regardless of any edits to the list. It's currently unknown where the database is stored on the device.

iOS 9 Launch scheme approval where it asks for permission to open an app: /private/var/preferences/com.apple.launchservices.schemeapproval.plist

For error-free access to this data query the canOpenURL: status in a daemon with the appropriate entitlements or inside SpringBoard using its entitlements and make the specific query accessible over IPC using RocketBootstrap, darwin_set_state or similar if necessary.

Update: It's now possible to bypass this restriction by hooking isApplicationAvailableToOpenURL in LSApplicationWorkspace. For example code, see this issue in a redundant project that was created before this hook was known: https://github.com/r-plus/libcanopenurl/issues/3