-
-
Notifications
You must be signed in to change notification settings - Fork 14.8k
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
python310Packages.cffi: patch closures to work on M1 machines #187636
Conversation
Can you offer guidance on how to properly test this? I own an M1 machine.
I'm not sure what the implication of this is, will pyOpenSSL work as it did before? Do I need to make any system configuration changes to test this? |
When it comes to this patch, I tested on my M1 machine by re-enabling the tests in
You asked a great question, and I also do not know how to test this. I think it should be possible to trigger this by code signing an app that ends up using |
On macOS 12.5 with Nix 2.8.1 and commit pyopenssl failure log
|
It is also what I saw. I had looked into |
@ofborg eval |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The security implications make me a bit uncomfortable but I'm not sure we have much of a choice? LGTM
This was something I stumbled on as well and can at least share my crack at it. I substituted libffi for Apple's system version, it also works but I could only find the trampoline that loads the library at runtime. emilytrau@56c8491 |
What do you mean by this? If I'm understanding this correctly: the only difference between your patches is that @tjni's patch uses the system copy, while yours pulls it from our packaged SDK, right? |
From my understanding(?) Apple doesn't ship the actual libffi in the SDK and what I pulled (a .tbd) is a trampoline that loads the OS-tied version(?) |
|
In practice, if this can be made to work with Apple's fork of I'm currently under the impression that libffi/libffi#621 is the only gap remaining for closures to work on signed apps with hardened runtime enabled, so I treated that gap as the only one that would make using Apple's preferred to using the open source version, but I haven't done a thorough analysis of the differences. With respect to security, I don't yet fully understand how the implementation in If the decision is made to continue using |
Oh, I see, this is using libffi from Nixpkgs -- sorry, I misunderstood. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried building this on x86_64-darwin and both Python 2.7 and 3.10 cffi tests failed with one error. Maybe a rebase can help since it's been a while? Though currently a Rustc fix is going through staging-next, so until that's in staging I think we'd need to wait.
I can confirm this fixes the issue with pyopenssl. Tested it using scrapy ( |
I will take some time today to get this into a mergeable state again. |
@toonn After the most recent rebase, I can build cffi successfully on aarch64-darwin and x86_64-darwin using Python 3.10. There are many errors for me when run against Python 2.7. |
Python 2.7 is EOL. I am not sure if we even need to worry. |
In the spirit of do no harm, I disabled tests that were failing on Python 2.7 + Darwin so that the package still builds. If we find this does break someone's use case, we can follow up by reverting this change for that Python version. |
I agree. Let's not add more code to deal with Python 2.7. |
Can we merge this? |
If you want we can just disable tests on Python 2.7, but I think we shouldn't care at all. |
I have a small preference to keep the disabled tests for now so that this builds on Python 2.7 if only because disabling the tests in this case was easy, and I don't want knowingly to break someone's potential flow with no warning. If you or others feel strongly enough about removing the Python 2.7 workaround here, I don't mind removing it either though; let me know. I'm supportive overall of spending less time and less code on Python 2.7, and I don't personally currently plan on spending any non-trivial time on supporting this package for Python 2.7. Is there already a plan for phasing out Python 2.7 from nixpkgs? If not, I feel having that discussion somewhere (forums, issue, RFC?) is worth it. |
Then please do so in
Not really. See e.g. #148779. |
Trusts the libffi library inside of nixpkgs on Apple devices. When Apple's fork of libffi is not detected, cffi assumes that libffi uses a strategy for creating closures (i.e. callbacks) that is in certain cases susceptible to a security exploit. Based on some analysis I did: https://groups.google.com/g/python-cffi/c/xU0Usa8dvhk I believe that libffi already contains the code from Apple's fork that is deemed safe to trust in cffi. It uses a more sophisticated strategy for creating trampolines to support closures that works on Apple Silicon, while the simple approach that cffi falls back on does not, so this patch enables code that uses closures on M1 Macs again. Notably, pyOpenSSL is impacted and will be fixed by this, reported in pyca/pyopenssl#873 Note that libffi closures still will not work on signed apps without the com.apple.security.cs.allow-unsigned-executable-memory entitlement while libffi/libffi#621 is still open (which I haven't tested but is my best guess from reading). I am hopeful that all of these changes will be upstreamed back into cffi and libffi, and that this comment provides enough breadcrumbs for future maintainers to track and clean this up.
Moved the disabled tests logic to |
Successfully created backport PR #203450 for |
Git push to origin failed for release-22.11 with exitcode 1 |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
Closes #153783
Summary
Currently, a feature in cffi called closures (i.e. callbacks) is broken on M1 machines. A notable consequence is that pyOpenSSL is broken on M1 machines as well, and that is depended upon by many packages. I believe that, even though closures are broken still on M1 machines in certain cases (seems to be cases where apps are signed), it can be unbroken for other cases.
The patch is simple and mergeable but will leave to maintainers to determine whether they feel the benefit is worth the risk now, or if it is better to wait for more developments.
Details
Trusts the libffi library inside of nixpkgs on Apple devices.
When Apple's fork of libffi is not detected, cffi assumes that libffi uses a strategy for creating closures (i.e. callbacks) that is in certain cases susceptible to a security exploit.
Based on some analysis I did:
https://groups.google.com/g/python-cffi/c/xU0Usa8dvhk
I believe that libffi already contains the code from Apple's fork that is deemed safe to trust in cffi.
It uses a more sophisticated strategy for creating trampolines to support closures that works on Apple Silicon, while the simple approach that cffi falls back on does not, so this patch enables code that uses closures on M1 Macs again.
Notably, pyOpenSSL is impacted and will be fixed by this, reported in pyca/pyopenssl#873
Note that libffi closures still will not work on signed apps without the com.apple.security.cs.allow-unsigned-executable-memory entitlement while libffi/libffi#621 is still open (which I haven't tested but is my best guess from reading).
I am hopeful that all of these changes will be upstreamed back into cffi and libffi
Note for pyOpenSSL
Many tests that used to fail now pass, but there are still three or four (I can't remember exactly) failures that use a callback. I looked into one and do not have a root cause, but I don't believe it's because callbacks do not work. In that test, printing something during SSL handshake led to the callback working, so it feels more like something related to buffers.
Things done
sandbox = true
set innix.conf
? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)nixos/doc/manual/md-to-db.sh
to update generated release notes