The compatibility requirement is the result of the historic lack of x86 platform support, though: x86 used not to support r-- permissions, so it put rodata in an r-x segment, so there are likely programs in the wild which accidentally rely on that, so the linker can't now tighten the rodata permissions without breaking some existing set of programs of unknown size. Whether you think that's a good tradeoff depends on your opinion on the size of that set of programs and how heavily you weight 'avoid breaking code that used to work' against 'tighten permissions for security reasons'.
It would be interesting to know if you can ask the linux linker to put rodata in its own r-- segment -- I scanned the docs but didn't see an option for it.
Depends on what you mean, the original page table entries have a R (Read/Write) flag, if not set the page is read-only. What you couldn't do was mark a page non-executable. But nevertheless the second LOAD segment is marked rw- and not rwx, so it would seem that it wasn't deemed a problem in the past having segments with unsupported permissions.
At the time when we got the NX bit it did happen that some programs broke because they expected executable data, but the security benefits were more important.
> It would be interesting to know if you can ask the linux linker to put rodata in its own r-- segment -- I scanned the docs but didn't see an option for it.
You have to write your own linker script, see e.g. [0].
By the r-- syntax I meant specifically 'readable, not writable, not executable' as distinct from rw- 'readable, writable, not executable' or r-x 'readable, not writable, executable'.
On i386 the descriptor cannot be both writable and executable at same time. But in order to support sane semantics for C, typical Unix OS (which for purposes of this discussion includes 32bit Windows) loads CS, DS and SS with different descriptor selectors that nevertheless alias to same range of linear addresses and thus essentially disable most of the MMU's protection logic and rely only on paging. And traditional 32bit i386 page table entries only have two flags: accessible at all (called "present") and writable.
It would be interesting to know if you can ask the linux linker to put rodata in its own r-- segment -- I scanned the docs but didn't see an option for it.