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

Fork regression in Mojave due to MAP_JIT #13445

Closed
migueldeicaza opened this issue Mar 13, 2019 · 2 comments
Assignees

Comments

@migueldeicaza
Copy link
Member

@migueldeicaza migueldeicaza commented Mar 13, 2019

Since Mono started using MAP_JIT on Mojave, this causes fork() to break, as the child process does not get access to the JITed code pages. Those pages seem to have been removed after fork.

MAP_JIT is only needed for application bundles, so it would make sense that we only use this in combination with Xamarin.Mac, and not in other scenarios. This means that we should probably surface an API on the embedding interface that Xamarin.Mac can call to enable this.

Steps to Reproduce

The following example shows the problem, this crashes the child process with Mono, works with .NET Core:

using System;
using System.Runtime.InteropServices;


class X {
        [DllImport ("libc")]
        extern static int fork ();

        [DllImport ("libc")]
        extern static int execv (string process, string [] args);

        static void Main ()
        {
                var d = fork ();

                if (d == 0){
                        execv ("/bin/bash", new string [] { "/bin/bash", "-c", "/bin/ls" });
                } else {
                        Console.WriteLine ("parent got: " + d);
                        Console.ReadLine ();
                }
        }
}

Current Behavior

parent got: 53446

=================================================================
	Native Crash Reporting
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================

=================================================================
	Basic Fault Adddress Reporting
=================================================================
Memory around native instruction pointer (0x10a867887):0x10a867877

Expected Behavior

If I remove the MAP_JIT flag, this works and produces a file listing:

$ mono test.exe
[ File listed removed]
parent got: 12345
$

This works as expected in .NET Core.

On which platforms did you notice this

[x] macOS
[ ] Linux
[ ] Windows

Version Used:

Mono JIT compiler version 5.18.0.273 (2018-08/89d7665e281 Wed Mar  6 20:53:39 PST 2019)

And also:

Mono JIT compiler version 6.1.0 (master/5f5ef1efe50 Wed Mar 13 11:11:18 EDT 2019)

More details

It is possible to confirm that the pages are not mapped on the child process by using MONO_DEBUG=suspend-on-sigsegv and attaching to the child process, the context pointer will point to the wrapper code for fork, and the crash happens exactly on the instruction after the call is made to libc to call into fork.

Also, running vmmap shows that the mapping for the code pages that were done with MAP_JIT are gone, only the mmap() region that is allocated from mono_shared_area_for_pid survives.

@migueldeicaza

This comment has been minimized.

Copy link
Member Author

@migueldeicaza migueldeicaza commented Mar 13, 2019

Confirmed, on the XNU source code, the support for mmap explicitly prevents pages mapped with MAP_JIT from being inherited across fork:

osfmk/vm/vm_map.c

The code looks like this:

                                (entry_for_jit)? VM_INHERIT_NONE: inheritance,
@akoeplinger

This comment has been minimized.

Copy link
Member

@akoeplinger akoeplinger commented Apr 11, 2019

Fixed by #13958, later revised by #14395.

dndx added a commit to dndx/lua-resty-core that referenced this issue Apr 11, 2019
…hen running on macOS.

PCRE 8.43 applies the `MAP_JIT` flag to `mmap`ed region used to store PCRE JIT
compiled code. Unfortunately regions created this way does not survive across `fork()`
calls and will cause any further attempt to use the PCRE JIT compiler or execution
of JIT compiled regex to crash the worker immediately.

This patch work around that limitation by disabling PCRE JIT compiler and regex
cache when using regexes in the `init` phase. Note that the compilation cache has to
be disabled to avoid applications who uses the same regex in both `init` and later phases with
JIT turned on to suffer from bad runtime performance.

See:
* https://bugs.exim.org/show_bug.cgi?id=2334#c37
* mono/mono#13445
* Kong/kong#4471
dndx added a commit to dndx/lua-resty-core that referenced this issue Apr 11, 2019
…hen running on macOS.

PCRE 8.43 applies the `MAP_JIT` flag to `mmap`ed region used to store PCRE JIT
compiled code. Unfortunately regions created this way does not survive across `fork()`
calls and will cause any further attempt to use the PCRE JIT compiler or execution
of JIT compiled regex to crash the worker immediately.

This patch work around that limitation by disabling PCRE JIT compiler and regex
cache when using regexes in the `init` phase. Note that the compilation cache has to
be disabled to avoid applications who uses the same regex in both `init` and later phases with
JIT turned on to suffer from bad runtime performance.

See:
* https://bugs.exim.org/show_bug.cgi?id=2334#c37
* mono/mono#13445
* Kong/kong#4471
dndx added a commit to dndx/lua-resty-core that referenced this issue Apr 11, 2019
…hen running on macOS.

PCRE 8.43 applies the `MAP_JIT` flag to `mmap`ed region used to store PCRE JIT
compiled code. Unfortunately regions created this way does not survive across `fork()`
calls and will cause any further attempt to use the PCRE JIT compiler or execution
of JIT compiled regex to crash the worker immediately.

This patch work around that limitation by disabling PCRE JIT compiler and regex
cache when using regexes in the `init` phase. Note that the compilation cache has to
be disabled to avoid applications who uses the same regex in both `init` and later phases with
JIT turned on to suffer from bad runtime performance.

See:
* https://bugs.exim.org/show_bug.cgi?id=2334#c37
* mono/mono#13445
* Kong/kong#4471
thibaultcha added a commit to openresty/lua-resty-core that referenced this issue Apr 22, 2019
…e when running on macOS.

PCRE 8.43 applies the `MAP_JIT` flag to `mmap`ed region used to store
PCRE JIT compiled code. Unfortunately regions created this way does not
survive across `fork()` calls and will cause any further attempt to use
the PCRE JIT compiler or execution of JIT compiled regex to crash the
worker immediately.

This patch work around that limitation by disabling PCRE JIT compiler
and regex cache when using regexes in the `init` phase. Note that the
compilation cache has to be disabled to avoid applications who uses the
same regex in both `init` and later phases with JIT turned on to suffer
from bad runtime performance.

See:
* https://bugs.exim.org/show_bug.cgi?id=2334#c37
* mono/mono#13445
* Kong/kong#4471

Signed-off-by: Thibault Charbonnier <thibaultcha@me.com>
akoeplinger added a commit to akoeplinger/mono that referenced this issue Jul 17, 2019
…to hardened runtime entitlements

This avoids the issue from mono#13445 when hardened runtime is enabled.
akoeplinger added a commit that referenced this issue Jul 17, 2019
…to hardened runtime entitlements (#15721)

This avoids the issue from #13445 when hardened runtime is enabled.
monojenkins added a commit to monojenkins/mono that referenced this issue Jul 17, 2019
…to hardened runtime entitlements

This avoids the issue from mono#13445 when hardened runtime is enabled.
akoeplinger added a commit that referenced this issue Jul 17, 2019
…to hardened runtime entitlements (#15725)

This avoids the issue from #13445 when hardened runtime is enabled.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.