-
Notifications
You must be signed in to change notification settings - Fork 74
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
Attempts to mprotect() with MAP_JIT failing on Apple Silicon as of macOS 11.2 #99
Comments
I don't know much about macs, but if you submit a patch, and people are happy with it, I am gladly accept your contribution. |
there is no need to run PCRE under rosetta when there is support for it to run in Apple Silicon natively if you apply #90; agree though that we should improve the detection code as well, but as you had noticed macOS is a moving target (even making API breaking changes within minor versions) and we haven't been given access to M1 hardware |
Thanks for the note! However, we are running it under Apple Silicon natively (we aren't using Rosetta). I will review that pull request to see if it improves things, but it was all calls to I'm happy to put a merge request together with anything that might be necessary for support under macOS 11.2. |
FWIW, the mprotect() test is doing EXACTLY what it was designed to do; and it is to detect if the OS is lying to us and will otherwise segfault when we write/exec it because the page was not marked writable/executable (even if mmap returned without error). you can find more details in the discusion in the downstream PCRE bug: https://bugs.exim.org/show_bug.cgi?id=2618 note that for macOS mprotect would normally fail for Apple Silicon for the reason you explained starting with 11.2, but can also fail in x86 depending on the way the library was compiled and the entitlements the application using it might had been given. the issue predates Big Sur an it has been around since the last versions of 10.13 when MAP_JIT made its undocumented release and as explained in: |
Completely understandable! I definitely don't know much about how all of this works. I'm just coming through with the information we've gathered and what Apple was willing to send along. Thanks for referencing everything and your continued help in this! |
it would seem this is because macOS not failing the mprotect call when requested an RWX that was silently converted to RX by mmap was considered a "bug" and so now there is at least a way to detect it was lying and would had crashed (as it still does at least in HardenedBSD). an alternative (which shouldn't be used unless there is really no better option) and that wastes a lot of memory is to use the alternative WX allocator (-DSLJIT_WX_EXECUTABLE_ALLOCATOR) that should be also available starting with PCRE 10.36 using the corresponding configure/cmake flag. |
starting with macOS 11.2, the mprotect calls for RWX pages will fail at least in Apple Silicon. avoid the additional check that was originally added to workaround WX implementations that lie about the permission of pages that were allocated (ex: HardenedBSD) unless it has been specifically requested (through a compile flag). for macOS this allows the implementation provided for Apple Silicon in hardware through pthread_jit_write_protect_np() for the versions that had that support. fixes: zherczeg#99
Starting with macOS 11.2, mprotect calls for RWX pages will fail in Apple Silicon, even if the page was granted permission and it was requested the MAP_JIT flag, to better reflect the fact that the page returned by mmap wasn't really RWX. In macOS, there is an implementation for the executable allocator since e87e1cc (macos: add BigSur support to execalloc (zherczeg#90), 2020-11-30) that flips the bits as needed, so this extra safeward is no longer needed. HardenedBSD seems to be the last implementation of PaX that still lies, so restrict the code only to that platform. Fixes: zherczeg#99
Starting with macOS 11.2, mprotect calls for RWX pages will fail in Apple Silicon, even if the page was granted permission and it was requested the MAP_JIT flag, to better reflect the fact that the page returned by mmap wasn't really RWX. In macOS, there is an implementation for the executable allocator since e87e1cc (macos: add BigSur support to execalloc (#90), 2020-11-30) that flips the bits as needed, so this extra safeward is no longer needed. HardenedBSD seems to be the last implementation of PaX that still lies, so restrict the code only to that platform. Fixes: #99
We are using the PCRE2 regular expression library (version 10.36, and by extension, SLJIT), and have noticed a change in behavior after macOS 11.2 came out. Now, any attempt to allocate memory with SLJIT fails. It's okay for us, as PCRE2 can fall back to not using JIT for an expression. However, I wanted to dig in and figure out why it was suddenly failing.
It turns out that, with
sljitExecAllocator.c
, themmap()
withMAP_JIT
call is succeeding, but the subsequent call tomprotect()
(on line 185) fails with a generic "permission denied" error from the system. This was working in macOS 11.0 and 11.1, but something changed with the 11.2 update. After spending a day not really being able to tell "why", we filed a feedback issue with Apple DTS.Apple DTS provided the following response:
We already apply the
pthread_jit_write_protect_np()
calls before and after invoking PCRE2 to compile a regex. But, it sounds like they are saying that SLJIT needs to not callmprotect()
when on Apple Silicon no matter what.We're planning on making the relevant change in our copy of PCRE2 and SLJIT, but I wanted to bring this up to you in case you have other consumers of the library hit this issue in the future.
Thank you for your time!
The text was updated successfully, but these errors were encountered: