That's like saying there's no point in locking your doors because thieves can go in through the window. Instead, you're better off applying separate defenses against separate attacks: read-only code against code injection and other defenses (like CFI or randomization) against ROP.
> Besides, any secure JIT will only keep a page either writable or executable, but not both in the same time.
Sure, but it's amazing how few actual JITs do that. V8, for example, actually maps its entire code cache as RWX.
> It's not that simple. ROP relies on known or predictable addresses and pretty much all modern OSes have some form of address space layout randomization (which keeps getting better and more sophisticated).
> With good ASLR, ROP is not possible without relying on information leak bugs which are finite. So the cost for the attacker increases and it gets harder and more time intensive for reliable exploits to be written.
> Allowing JIT for everything is a TREMENDOUS security violation, since it's trivially abusable and page permissions are irrelevant. There are just too many ways for clever attackers to abuse it.
Of course ASLR makes ROP harder. It makes all exploits harder. I still don't agree with your last paragraph. As someone else mentioned, good JIT implementations never leave code both writable and executable. It's simply not the case that "page permissions are irrelevant". Page permissions are central because they defeat the specific attacks you have in mind. A JIT is no more vulnerable to them than the dynamic loader is.
I still don't buy that banning PROT_EXEC buys you any protection from attackers exploiting applications.
On the other hand, banning PROT_EXEC provides plenty of protection against uppity application developers trying to "abuse" the platform you "own" by attempting to program in unapproved ways.
To add, nothing prevents from allocating pages from random addresses to get protection similar to ASLR.
It can actually be harder to attack dynamically generated code, because instruction offsets and instructions used will vary from application invocation to another. You could even do intentional variations to ensure no relative instruction offsets are deterministic. So dynamically generated code can have not only have random address (ASLR) but also random relative offsets. Obviously statically compiled code must have those offsets static, known by the attacker.
ASLR just means you don't necessarily know where. But once the attacker knows where or has some clever trick so it doesn't matter, it's game over. Unfortunately the creativity of attackers getting around ASLR seems to be endless.
With good ASLR, ROP is not possible without relying on information leak bugs which are finite. So the cost for the attacker increases and it gets harder and more time intensive for reliable exploits to be written.
Allowing JIT for everything is a TREMENDOUS security violation, since it's trivially abusable and page permissions are irrelevant. There are just too many ways for clever attackers to abuse it.