Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,868
    • Issues 4,868
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 458
    • Merge requests 458
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #21495
Closed
Open
Created May 04, 2022 by Kasper Dissing Bargsteen@Bargsteen

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 May 04, 2022 by Kasper Dissing Bargsteen
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking