Hacker News new | ask | show | jobs
by mmastrac 4414 days ago
The reason is basically that you can't easily provide a guaranteed W^X [1] environment alongside a JIT in the same address space -- that is unless you write a ROP-based JIT.

[1] http://en.wikipedia.org/wiki/W%5EX

2 comments

I thought the problem was code-signing, with Safari and only Safari authorised to use JIT.
It is -- code-signing is how they enforce W^X. Only code loaded from signed applications is given pages with execute permission, and those pages are denied write access.
mmastrac is correct, the problem with JIT is W^X. The default sandbox for iOS processes prevents marking any page as executable that has ever been marked as writable. Safari is not "authorized to use JIT" so much as it has a special sandbox that lifts this restriction. It's not about code-signing, it's about the security provided by W^X. If it was merely about code-signing, the JIT could simply codesign its output using a certificate provided by Apple for this purpose.
There's nothing that prevents W^X and JIT from coexisting. All the JIT has to do is change the permissions on the generated code after generating it so that it becomes executable instead of writable. W^X just says that any given chunk of memory cannot be both writeable and executable at the same time.

What Apple does on iOS goes beyond W^X. They give you a one-way trap door, where you're not allowed to mark any memory as executable, ever, once it's marked non-executable. (Obviously, there is an exception made for the OS facilities that actually load your code from the disk, and an exception made for Safari's JIT, but us mere mortals don't get access to that stuff.)

As for the reason, it's hard to say. It's probably because of code signing and Apple's desire for control to prevent you from downloading and running unreviewed, unapproved code, although even that doesn't entirely make sense, because you can always embed an interpreter and download and run code in that.

They can co-exist, but not in the same process. If there's a JIT running in the same process as my C-based program, it has the permissions as I do.

Any secure JIT would have to exist out-of-process with extended permissions, and would require some sort of RPC back-and-forth as the code was shuttled between the two processes.

W^X is not some code word for "secure". It has a specific meaning, and that specific meaning is completely compatible with JIT code. All it means is that you have to call mprotect() after generating code.

One can debate the security implications of allowing programs to mark code as executable at all, but that debate is unrelated to W^X.

I'm guessing there are two reasons -

1. Preventing any app code from allocating memory and setting it executable: Apple doesn't seem to want to allow dynamically adding code to any app store apps. See: No .dylib support, the earlier bans on all types of interpreters, etc. It would be too easy to get a "Loader"-type app into the app store that could download and execute random app code from the internet that hasn't been vetted by the app store review team. (Emulators, plugins, addons that call private APIs, etc. etc. etc.)

2. Limiting the vulnerability surface: Reduce the risk of webkit exploits targeting app store apps (or even non-webkit random exploits in the app's code allowing loading of shellcode)

You are correct. I'm (incorrectly) using W^X here to refer to Apple's W^X, which is effectively setting W^X on pages at image load time for preventing execution of dynamic code -- and possibly for security, but I imagine that is more of a bonus from their point of view.