Linux shell for iOS
Clone or download
Latest commit be3811b Dec 12, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
app Add auto lock control setting Dec 11, 2018
emu Clear c2 in fprem Dec 11, 2018
fastlane Release build 35 to testflight Dec 9, 2018
fs add /dev/zero and /dev/full Dec 10, 2018
iSH.xcodeproj Release build 35 to testflight Dec 9, 2018
jit Unbreak cbw on aarch64 Dec 8, 2018
kernel Don't send sigwinch if there's no handler Dec 11, 2018
subprojects Remove gdbm Nov 30, 2018
tests Disable tests for unimplemented instructions in the QEMU test program Nov 19, 2018
tools Add /dev/tty in fakefsify Dec 7, 2018
util Pass &lock->m to pthread functions Dec 1, 2018
vdso Check for homebrew clang, and check that it actually works Aug 14, 2018
.gitignore Update to GDBM 1.18 Sep 30, 2018
.lvimrc Replace exrc with lvimrc Nov 16, 2017
.travis.yml use apt for ninja on xenial Dec 10, 2018 Update changelog Dec 12, 2018 Update Dec 1, 2018
LICENSE Use GPL, not LGPL Oct 11, 2018
LICENSE.IOS Add license terms to allow App Store distribution Nov 10, 2018 added preview Nov 14, 2018
debug.h Add function to report error and crash Nov 30, 2018
ish-gdb.gdb Ignore SIGPIPE in gdb Sep 30, 2018
main.c Pass $TERM to emulated process Apr 6, 2018 Remove dependency on Security.framework Dec 11, 2018
meson_options.txt Merge branch 'jit' Aug 13, 2018
misc.h Support killing process groups Dec 10, 2018
xX_main_Xx.h Pass $TERM to emulated process Apr 6, 2018 Handle meson config vars with spaces Nov 30, 2018


Build Status goto counter fuck counter

A project to get a Linux shell running on iOS, using usermode x86 emulation and syscall translation.

For the current status of the project, check the Compatibility and Emulation projects, and the commit logs.

You can join the Testflight beta now. There's also a Discord server (for some reason).


You'll need these things to build the project:

  • Python 3
  • Ninja
  • Yarn (only when building for iOS)
  • Meson (pip install meson)
  • Clang and LLD (on mac, brew install llvm, on linux, sudo apt install clang lld or sudo pacman -S clang lld or whatever)

To set up your environment, cd to the project and run meson build to create a build directory in build. Then cd to the build directory and run ninja.

To set up a self-contained Alpine linux filesystem, download the Alpine minirootfs tarball for i386 from the Alpine website and run the tools/ script. Specify the minirootfs tarball as the first argument and the name of the output directory as the second argument. Then you can run things inside the Alpine filesystem with ./ish -f alpine /bin/login, assuming the output directory is called alpine.

You can replace ish with tools/ptraceomatic to run the program in a real process and single step and compare the registers at each step. I use it for debugging. Requires 64-bit Linux 4.11 or later.

To compile the iOS app, just open the Xcode project and click run. There are scripts that should download and set up the alpine filesystem and create build directories for cross compilation and so on automatically.

Further setup guide

To enable local development there are a few more steps that needs to be done.

  • Go to the project settings in Xcode find the "iSH" target

  • Under "General" change the bundle identifier to a specific identifier for you

  • Under "Capabilities" change the name of the "App Group" and remove the old app group

  • Go to the "iSHFileProvider" target

  • Under "General" use the same bundle identifier you created before and add .FileProvider to it

  • Under "Capabilities" use the same name of the "App Group" as for the "iSH" target

  • Go to the file app/AppDelegate.m

  • Change the string in the function manager containerURLForSecurityApplicationGroupIdentifier: to your App Group name that you entered in the step before.

Congratulations! You should now have the app running!

A note on the JIT

Possibly the most interesting thing I wrote as part of iSH is the JIT. It's not actually a JIT since it doesn't target machine code. Instead it generates an array of pointers to functions called gadgets, and each gadget ends with a tailcall to the next function; like the threaded code technique used by some Forth interpreters. The result is a speedup of roughly 3-5x compared to pure emulation.

Unfortunately, I made the decision to write nearly all of the gadgets in assembly language. This was probably a good decision with regards to performance (though I'll never know for sure), but a horrible decision with regards to readability, maintainability, and my sanity. The amount of bullshit I've had to put up with from the compiler/assembler/linker is insane. It's like there's a demon in there that makes sure my code is sufficiently deformed, and if not, makes up stupid reasons why it shouldn't compile. In order to stay sane while writing this code, I've had to ignore best practices in code structure and naming. You'll find macros and variables with such descriptive names as ss and s and a. Assembler macros nested beyond belief. And to top it off, there are almost no comments.

So a warning: Long-term exposure to this code may cause loss of sanity, nightmares about GAS macros and linker errors, or any number of other debilitating side effects. This code is known to the State of California to cause cancer, birth defects, and reproductive harm.