Skip to content

Creating function pointers from closures results in setExecutable runtime error on macOS 12+

Summary

Running a signed binary on macOS 12+ that creates a FunPtr from a closure results in a runtime error that mentions setExecutable.

According to https://www.securemac.com/news/arm-macs-faq, this will also be a problem in unsigned binaries when running on Apple Silicon(ARM).

Steps to reproduce

  1. Create two files, Main.hs and bar.c:

    -- Main.hs
    module Main where
    
    import Foreign.Ptr (FunPtr)
    foreign import ccall "bar" bar :: Callback -> Int
    
    main :: IO ()
    main = do
      cb <- createFooCallback (foo 2)
      let res = bar cb
      print res
    
    type CallbackType = Int -> Int
    type Callback = FunPtr CallbackType
    
    foo :: Int -> Int -> Int
    foo = (+)
    
    foreign import ccall "wrapper" createFooCallback :: CallbackType -> IO Callback
    // bar.c
    extern int (*fun_ptr)(int);
    
    int bar(int (*f)(int)) {
      return (*f)(3);
    }
  2. Compile them: ghc --make -main-is Main Main.hs bar.c

  3. Sign the binary: sudo codesign -f --options runtime -s DEVELOPER_ID Main

    • The program runs as expected if this step is omitted.
    • This step requires a developer signing certificate.
  4. Run the signed binary: ./Main

Expected behavior

Expected:

$ ./Main
5

Actual:

$ ./Main
Main: internal error: setExecutable: failed to protect 0x0x42001fc000

    (GHC version 8.10.4 for x86_64_apple_darwin)
    Please report this as a GHC bug:  https://www.haskell.org/ghc/reportabug
fish: Job 1, './Main' terminated by signal SIGABRT (Abort)

Extra notes

I believe #18376 (closed) is the root cause, and I created this new issue to draw attention to a use-case that triggers the bug. Hoping that it might be fixed :-)

We managed to work around the issue by allowing unsigned executable memory when signing: https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-unsigned-executable-memory However, that is not an ideal solution.

Environment

  • GHC version used: 8.10.4 and 8.10.7

Optional:

  • Operating System: macOS 12.1
  • System Architecture: Intel
Edited by Kasper Dissing Bargsteen
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information