After upgrading to Mojave, existing PHP modules built on an older system version fail to load:
PHP Warning: PHP Startup: Unable to load dynamic library '/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so' - dlopen(/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so, 0x0009): code signature in (/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so) not valid for use in process: mapped file has no cdhash, completely unsigned? Code has to be at least ad-hoc signed. in Unknown on line 0
This is broadly a System Integrity Protection (SIP) thing. Googling for this error reveals a lot of "disable SIP" (probably very bad advice) and "reinstall the thing" (probably practical, but not very helpful in this case).
I currently assume SIP is "Probably a Good Idea", although I have a very limited understanding of it and largely reserve judgement. My very fuzzy sense here is that SELinux is a bit more of a cautionary tale, where enabling SELinux breaks every application silently and the path back to the light is very unclear (see T4947). In contrast, SIP seems to generally produce obvious and reasonably clear errors, which is a major point in its favor.
An initial workaround for this narrow case (PHP extension binaries you built locally) is to do perform ad-hoc signature with -s -:
$ codesign -s - /Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so
However, that only gets us one level deeper:
PHP Warning: PHP Startup: Unable to load dynamic library '/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so' - dlopen(/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so, 0x0009): code signature in (/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so) not valid for use in process: mapped file has no Team ID and is not a platform binary (signed with custom identity or adhoc?) in Unknown on line 0
It looks like the net effect here is "ad-hoc signatures are not sufficient".
This technical note appears to have an overview of the system as a whole:
https://developer.apple.com/library/archive/technotes/tn2206/_index.html
...although this guide is more clear:
If you are generating a code signing identity from scratch, Apple strongly recommends you use the Certificate Assistant component of Keychain Access
This appears to be Keychain Access → Certificate Assistant → Create a Certificate..., then pick "Code Signing".
You can then sign with:
$ codesign -s "name of the certificate" /Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so
...but I'm still getting the "file has no Team ID" error.
I think this is a bit more complex than it appears. I believe what's happening here is something like this?
- Apple has enabled library validation for the httpd binary under Mojave and signed it?
- This means that Apache will only load modules signed by Apple?
- So it doesn't matter how we sign some php-extension.so, it won't match the signature on the parent binary so it can't dl(...).
Everyone seems to be working around this issue by replacing the Apple version of Apache with the Homebrew version. Presumably, this version is built without library validation so it can load modules.
See also:
if [[ $OS_VERSION == "10.14" ]]; then echo "****" echo "[WARNING]" echo "Detected macOS Mojave 10.14. There are serious issues with it, due to the original apache not loading" echo "foreign libraries anymore. PHP within apache will most certainly not work anymore if you proceed!" echo "The cli version still will." echo "See this issue at https://github.com/liip/php-osx/issues/249 for details and discussion"
...so this appears to be a huge mess.
I think options today are either:
- (Lots of Work) Replace Apache with a version that doesn't use Library Validation, from Homebrew, by building from source, or via some other mechanism.
- (Very Bad) Disable SIP.
- (Partial Workaround) Just don't run any PHP extensions.
This is actually potentially quite bad because:
- It affects both the system httpd and the system php.
- The system php is not built with the pcntl extension.
- We require pcntl to do some stuff in arc, notably signal handling.
We also require pcntl to run daemons. So there are limits to how far we can get here.
(The errors above come out of php, but Apache produces similar errors:)
PHP Warning: PHP Startup: Unable to load dynamic library '/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so' - dlopen(/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so, 9): no suitable image found. Did find:\n\t/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so: code signature in (/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so) not valid for use in process using Library Validation: mapped file has no Team ID and is not a platform binary (signed with custom identity or adhoc?)\n\t/Users/epriestley/src/apcu-5.1.12/apcu-5.1.12/modules/apcu.so: stat() failed with errno=25 in Unknown on line 0