Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On Linux, pages are marked as simultaneously writable and executable #371

Open
addisoncrump opened this issue Jan 17, 2024 · 5 comments
Open
Labels
JIT Relating to the JIT feature

Comments

@addisoncrump
Copy link
Contributor

addisoncrump commented Jan 17, 2024

Currently, the memory mapped for sljit output marks the regions as rwx. This is a security risk, as attackers can use rwx regions to bypass compiler- and OS-managed exploit prevention.

Instead, sljit should emit instructions to an rw region, then protect the region as rx afterward.

I believe this relates to #212.

@MatthewVernon
Copy link
Contributor

FWIW, this was reported to Debian as bug 1013448, where I suggested the submitter might like to take it up with upstream; At that point, SLJIT_PROT_EXECUTABLE_ALLOCATOR was marked as experimental (and possibly having other security issues) so I didn't think it was a good thing to change in Debian.

@addisoncrump
Copy link
Contributor Author

Looking at that, it also seems that the "solution" is to have a writable mapping and an executable mapping of the same region. This has the same ultimate security impact.

@carenas
Copy link
Contributor

carenas commented Jan 18, 2024

This has the same ultimate security impact.

It is actually even worst, see #162 for details.

@carenas
Copy link
Contributor

carenas commented Jan 18, 2024

Instead, sljit should emit instructions to an rw region, then protect the region as rx afterward.

sadly it is not "that" simple, because sljit also supports self modifying code (which include also modifying "constants", ex in jump tables).

the "default" executable allocator implements a very simple, mostly efficient way to allocate pages, but MUST be able to write to those most of the time, or will segfault.

when hardware support is available (ex: in macOS with arm64), then only one thread gets access to the pages to write while the others have only RO access, but "fixing" this requires building a completely different allocator and most likely also changing the way sljit interacts with it, so that the generator will (for example) use a RW page independent from the code where to store data, instead of writing everything together (the s390x implementation does something on that line, as it was needed to workaround instruction size limits with very large constant values).

for the point of view of PCRE2, sljit allows for a custom allocator to be defined, and it is expected that people with specific security needs will do so.

@zherczeg
Copy link
Collaborator

zherczeg commented Jun 1, 2024

Self modifying code is part of the issue, but the generic use case is simpler. Since a mapped region can hold multiple functions, it is possible that one thread compiles a function (writes instructions), while another thread executes another one. MacOS has an elegant way of doing this (flipping a flag), and many unix like OS-es also do this better than Linux. I think Linux simply needs to improve in this area to reduce risks.

@NWilson NWilson added the JIT Relating to the JIT feature label Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JIT Relating to the JIT feature
Projects
None yet
Development

No branches or pull requests

5 participants