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

Workaround problems with hardened runtime, needed for notarization #259

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

djs55
Copy link
Collaborator

@djs55 djs55 commented Aug 20, 2019

On macOS 10.15 Catalina and later applications need to be Notarized where notarization is an Apple malware- and security-check of the released binaries.

As part of the notarization process, Apple require that hardened runtime is enabled. This prevents

  • code injection into running processes
  • attaching debuggers
  • allocating writable + executable memory

Currently hyperkit uses valloc to allocate memory for the VM and then grants the VM READ, WRITE and EXECUTE, which will fail if the hardened runtime is enabled.

One workaround is to grant the hyperkit binary the Allow Unsigned Executable Memory Entitlement which disables the writable+executable check for all allocations done by the process.

This patch proposes another workaround, which is to switch from using valloc to mmap with the special flag MAP_JIT. This allows us to use the weaker Allow Execution of JIT-compiled Code entitlement, so that only the VM memory allocation is writable+executable, other allocations are not.

Note that, according to the mono project mono/mono@a502768 the MAP_JIT flag causes problems with older version of macOS, so they recommend only enabling it for Mojave and later.

Note that enabling the hardened runtime and adding entitlements is done at the codesign stage which means we can't easily test this from the current CI as the binaries are unsigned.

This will allow us to customise the flags in a later patch.

Signed-off-by: David Scott <[email protected]>

int
vmm_mem_init(void)
{
if (vmm_get_kern_osrelease() >= OSRELEASE_MOJAVE) {
fprintf(stderr, "Detected Mojave or later, will use MAP_JIT\n");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would log on the pre Mojave case, as thats the "buggy" case

@justincormack
Copy link
Collaborator

This seems reasonable to me. Have you tested that it works with this?

The VM requires writeable + executable memory which is blocked when
the "hardened runtime" is enabled at the codesigning stage.

If we pass the `MAP_JIT` flag then we can add the capability

  com.apple.security.cs.allow-jit [1]

to permit the allocation. The alternative is to globally enable
write+execute for all allocations in the process which seems worse [2]

[1] https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-jit
[2] https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-unsigned-executable-memory

Signed-off-by: David Scott <[email protected]>
@Saviq
Copy link

Saviq commented Aug 20, 2020

FWIW alternatively one can use the following entitlement:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.cs.disable-executable-page-protection</key>
    <true/>
</dict>
</plist>

This is working for us in Multipass for a while now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants