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.
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.
mmastrac|11 years ago
[1] http://en.wikipedia.org/wiki/W%5EX
TazeTSchnitzel|11 years ago
mikeash|11 years ago
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.