-
Notifications
You must be signed in to change notification settings - Fork 710
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
Upstream arm64e ptrauth changes from Apple's libffi #565
Conversation
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.
Yay, love it! 😍 My PR obviously took the lazy route, so I'm super-excited to see a proper implementation! 👏
include/ffi.h.in
Outdated
@@ -357,6 +357,11 @@ ffi_prep_closure_loc (ffi_closure*, | |||
void *user_data, | |||
void*codeloc); | |||
|
|||
#if defined(__x86_64__) || defined(__arm64__) |
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.
Would it make sense to make this available on all architectures?
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.
If this seems valuable outside of our internal use case, then I certainly can. One of the main reasons I'm putting all this up is to see if any of this work is valuable to the larger OSS community or should remain Apple-internal changes for our specific cases.
We only wrote the implementation in src/aarch64/ffi.c and arc/x86/ffi64.c since that is all we use, but it should be usable elsewhere. This was necessitated by the trampoline changes, and I think we ended up using it in python3 and a few other places where there were assumptions that codeloc == closure.
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.
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.
Leave it for now. We may come back to this as we need to do something for the Linux architectures.
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.
Ok. I'll break that out into a separate PR that adds the API to all archs.
@atgreen What are your opinions on the API naming? Is ffi_find_closure_for_code() ok, or would you prefer something different?
src/aarch64/trampoline.S
Outdated
.endr | ||
|
||
#endif /* FFI_EXEC_TRAMPOLINE_TABLE */ | ||
#endif /* __arm64 */ |
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.
Build system changes seem to be missing for this file.
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.
Yeah, the build system changes were specific to our Xcode project. I'm not looking forward to figuring that out for autotools.
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.
Ah no worries, I can take a stab at it and post a suggestion here.
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.
Just pushed a rough draft here.
Here's how I tested it:
1. Generated a build environment
$ git clone https://github.com/frida/frida.git
$ cd frida
$ make build/frida-env-ios-arm64e.rc
Piggybacking on the autotools legacy build environment in Frida, which we still use for building a few dependencies that haven't yet moved to Meson.
2. Bootstrapped and built for iOS/arm64e
$ . build/frida-env-ios-arm64e.rc
$ cd ~/src/libffi
$ ./autogen.sh
$ ./configure --prefix=/usr --enable-shared
$ make
$ make install DESTDIR="$(echo ~/Desktop/libffi-ios-arm64e)"
--enable-shared is only needed because Frida's $CONFIG_SITE defaults to enable_shared=no
3. Built for macOS as a sanity check
$ . ~/src/frida/build/frida-env-macos-x86_64.rc
$ ./configure --prefix=/usr --enable-shared
$ make
$ make install DESTDIR="$(echo ~/Desktop/libffi-macos-x86_64)"
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.
Cool, thanks for the help. FWIW, I am crazy busy with WWDC work and taking care of kids at home, but I plan to circle back to this after WWDC, break out some of the smaller less offensive pieces into individual PRs, and then polish up the rest.
src/closures.c
Outdated
static void *ffi_closure_trampoline_table_page; | ||
|
||
dispatch_once(&trampoline_template_init_once, ^{ | ||
void * const trampoline_handle = dlopen("/usr/lib/libffi-trampolines.dylib", RTLD_NOW | RTLD_LOCAL | RTLD_FIRST); |
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.
This should take libdir
into account instead of hardcoding it.
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.
Yep, good point.
src/closures.c
Outdated
void * const trampoline_handle = dlopen("/usr/lib/libffi-trampolines.dylib", RTLD_NOW | RTLD_LOCAL | RTLD_FIRST); | ||
assert(trampoline_handle); | ||
|
||
ffi_closure_trampoline_table_page = dlsym(trampoline_handle, "ffi_closure_trampoline_table_page"); |
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.
ffi_closure_trampoline_table_page = dlsym(trampoline_handle, "ffi_closure_trampoline_table_page"); | |
ffi_closure_trampoline_table_page = dlsym (trampoline_handle, "ffi_closure_trampoline_table_page"); |
Here and elsewhere. It looks like the coding style has eroded somewhat since the early days, but this seems to be the most prevalent style.
src/closures.c
Outdated
extern void *ffi_closure_trampoline_table_page; | ||
#if __has_feature(ptrauth_calls) | ||
#include <ptrauth.h> | ||
#define sign_ptr(p) ptrauth_sign_unauthenticated(p, ptrauth_key_function_pointer, 0) |
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.
This appears to be an unused macro.
src/aarch64/ffi.c
Outdated
@@ -31,6 +31,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ | |||
#include <windows.h> /* FlushInstructionCache */ | |||
#endif | |||
|
|||
#if __has_feature(ptrauth_calls) |
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.
We're just using __has_feature() unconditionally. Before requesting merge, I will change this to use HAVE_PTRAUTH.
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.
Thanks. I just noticed this caused a build failure here: https://travis-ci.org/github/libffi/libffi/jobs/692670895#L652
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.
Cool! I love CI that works =) I've updated the title to make it more clear that I'm soliciting feedback on what you think is interesting to upstream rather than merge this in wholesale. Parts that you find interesting, I'll definitely work to get integrated with autotools builds and cross-platform (as best I can at least) and spin off separate PRs for isolated changes.
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 put a lot of effort into getting the CI to work for lots of platforms, even implementing a new tool (https://rl.gl , you can see the libffi policy @ https://github.com/libffi/rlgl-policy/blob/master/XFAIL ), HOWEVER one big gap is around iOS testing. I've never really participated in the iOS ecosystem. If there was some way to run the testsuite on travis using a simulator, that would be wonderful. Do you know if this is possible?
configure.ac
Outdated
@@ -176,28 +176,6 @@ case "$TARGET" in | |||
;; | |||
esac | |||
|
|||
AC_CACHE_CHECK([whether compiler supports pointer authentication], |
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.
This will be resurrected to allow better portability. I just wanted to quickly get Apple's changes into a PR for discussion and reverted the conflicting change wholesale.
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.
src/prep_cif.c
Outdated
@@ -234,7 +234,7 @@ ffi_status ffi_prep_cif_var(ffi_cif *cif, | |||
return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes); | |||
} | |||
|
|||
#if FFI_CLOSURES | |||
#if FFI_CLOSURES && FFI_LEGACY_CLOSURE_API |
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.
What is FFI_LEGACY_CLOSURE_API?
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.
In our build, it's defined in our ffitarget.hs as:
darwin/include/ffitarget_arm64.h
54:#define FFI_LEGACY_CLOSURE_API 0
darwin/include/ffitarget_armv7.h
68:#define FFI_LEGACY_CLOSURE_API 0
darwin/include/ffitarget_x86.h
125:#define FFI_LEGACY_CLOSURE_API 1
We just didn't want to make ffi_prep_closure() available on arm since it won't work there... better to catch issues at build time than at runtime. We should omit these bits from the final PR.
include/ffi.h.in
Outdated
@@ -357,6 +357,11 @@ ffi_prep_closure_loc (ffi_closure*, | |||
void *user_data, | |||
void*codeloc); | |||
|
|||
#if defined(__x86_64__) || defined(__arm64__) |
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.
Leave it for now. We may come back to this as we need to do something for the Linux architectures.
Sorry, time's been a bit more scarce for me recently. I haven't had a chance to circle back to this. I'm hoping to have some time this month to at least start forking off some of these changes into their own PRs and then look into the autoconf build system work. |
61179c3
to
6aa41be
Compare
@jeremyhu I can help finish the autotools changes if you like. |
Accidentally posted one extra comment (now deleted). Ran into the build system integration issue while trying to get libffi to work within ghc 8.10.3 on an Apple Silicon Mac. |
The PR adds a patch that brings in improvements from Apple's libffi (specifically libffi-26). These improvements are needed to use libffi with ghc. Commits: libffi/libffi@4c7bde3 libffi/libffi#565 I added additional configure logic to ensure that FFI_TRAMPOLINE_WHOLE_DYLIB is set on Apple Silicon (it is hard-coded to 1 in libffi-26 for aarch64). Signed-off-by: Nathan Hjelm <hjelmn@cs.unm.edu>
The PR adds a patch that brings in improvements from Apple's libffi (specifically libffi-26). These improvements are needed to use libffi with ghc. Commits: libffi/libffi@4c7bde3 libffi/libffi#565 I added additional configure logic to ensure that FFI_TRAMPOLINE_WHOLE_DYLIB is set on Apple Silicon (it is hard-coded to 1 in libffi-26 for aarch64). Signed-off-by: Nathan Hjelm <hjelmn@cs.unm.edu>
6aa41be
to
e066ba1
Compare
I split off some more preprocessing changes in #620, and I removed the whole-dylib trampoline changes such that this can focus on the arm64e changes. I'll file a subsequent pull request with the |
e066ba1
to
7bd776a
Compare
That would be greatly appreciated. I've cleaned up the patches a bit. This one and #620 are ready to merge. The remaining piece is the trampoline changes. I've split that out into #621. Please feel free to jump on that. I hope I'll have time in the next few weeks to look at this again, but not sure. |
0ad45a7
to
81d487a
Compare
…i port NOTES: This changes the ptrauth support from libffi#548 to match what Apple is shipping in its libffi-27 tag. Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
Currently, upstream libffi doesn't support Apple Silicon. However, there are several PRs from Apple employees: * libffi/libffi#565 * libffi/libffi#621 Homebrew formulae for libffi contains patch that is based on these pull requests. We use this patch here to build our own version of libffi.
This reverts a recent incomplete change for arm64e support (#548) and includes all potentially upstreamable changes to libffi made in macOS 10.15.5 and iOS 13.4, including Apple's arm64e support.
Note: Please do not merge this yet. It is here for comments first as I also want to hear from @oleavr and others from #548 .
I have not tested these changes against the current master, I have only tested them with our libffi-26 tag based on c2a6859
Note that I have omitted our Xcode project changes, but if there is interest in upstreaming those as well, please let me know.