|
9ba55921
|
2021-03-05T10:07:30
|
|
Static tramp v5 (#624)
* Static Trampolines
Closure Trampoline Security Issue
=================================
Currently, the trampoline code used in libffi is not statically defined in
a source file (except for MACH). The trampoline is either pre-defined
machine code in a data buffer. Or, it is generated at runtime. In order to
execute a trampoline, it needs to be placed in a page with executable
permissions.
Executable data pages are attack surfaces for attackers who may try to
inject their own code into the page and contrive to have it executed. The
security settings in a system may prevent various tricks used in user land
to write code into a page and to have it executed somehow. On such systems,
libffi trampolines would not be able to run.
Static Trampoline
=================
To solve this problem, the trampoline code needs to be defined statically
in a source file, compiled and placed in the text segment so it can be
mapped and executed naturally without any tricks. However, the trampoline
needs to be able to access the closure pointer at runtime.
PC-relative data referencing
============================
The solution implemented in this patch set uses PC-relative data references.
The trampoline is mapped in a code page. Adjacent to the code page, a data
page is mapped that contains the parameters of the trampoline:
- the closure pointer
- pointer to the ABI handler to jump to
The trampoline code uses an offset relative to its current PC to access its
data.
Some architectures support PC-relative data references in the ISA itself.
E.g., X64 supports RIP-relative references. For others, the PC has to
somehow be loaded into a general purpose register to do PC-relative data
referencing. To do this, we need to define a get_pc() kind of function and
call it to load the PC in a desired register.
There are two cases:
1. The call instruction pushes the return address on the stack.
In this case, get_pc() will extract the return address from the stack
and load it in the desired register and return.
2. The call instruction stores the return address in a designated register.
In this case, get_pc() will copy the return address to the desired
register and return.
Either way, the PC next to the call instruction is obtained.
Scratch register
================
In order to do its job, the trampoline code would need to use a scratch
register. Depending on the ABI, there may not be a register available for
scratch. This problem needs to be solved so that all ABIs will work.
The trampoline will save two values on the stack:
- the closure pointer
- the original value of the scratch register
This is what the stack will look like:
sp before trampoline ------> --------------------
| closure pointer |
--------------------
| scratch register |
sp after trampoline -------> --------------------
The ABI handler can do the following as needed by the ABI:
- the closure pointer can be loaded in a desired register
- the scratch register can be restored to its original value
- the stack pointer can be restored to its original value
(the value when the trampoline was invoked)
To do this, I have defined prolog code for each ABI handler. The legacy
trampoline jumps to the ABI handler directly. But the static trampoline
defined in this patch jumps tp the prolog code which performs the above
actions before jumping to the ABI handler.
Trampoline Table
================
In order to reduce the trampoline memory footprint, the trampoline code
would be defined as a code array in the text segment. This array would be
mapped into the address space of the caller. The mapping would, therefore,
contain a trampoline table.
Adjacent to the trampoline table mapping, there will be a data mapping that
contains a parameter table, one parameter block for each trampoline. The
parameter block will contain:
- a pointer to the closure
- a pointer to the ABI handler
The static trampoline code would finally look like this:
- Make space on the stack for the closure and the scratch register
by moving the stack pointer down
- Store the original value of the scratch register on the stack
- Using PC-relative reference, get the closure pointer
- Store the closure pointer on the stack
- Using PC-relative reference, get the ABI handler pointer
- Jump to the ABI handler
Mapping size
============
The size of the code mapping that contains the trampoline table needs to be
determined on a per architecture basis. If a particular architecture
supports multiple base page sizes, then the largest supported base page size
needs to be chosen. E.g., we choose 16K for ARM64.
Trampoline allocation and free
==============================
Static trampolines are allocated in ffi_closure_alloc() and freed in
ffi_closure_free().
Normally, applications use these functions. But there are some cases out
there where the user of libffi allocates and manages its own closure
memory. In such cases, static trampolines cannot be used. These will
fall back to using legacy trampolines. The user has to make sure that
the memory is executable.
ffi_closure structure
=====================
I did not want to make any changes to the size of the closure structure for
this feature to guarantee compatibility. But the opaque static trampoline
handle needs to be stored in the closure. I have defined it as follows:
- char tramp[FFI_TRAMPOLINE_SIZE];
+ union {
+ char tramp[FFI_TRAMPOLINE_SIZE];
+ void *ftramp;
+ };
If static trampolines are used, then tramp[] is not needed to store a
dynamic trampoline. That space can be reused to store the handle. Hence,
the union.
Architecture Support
====================
Support has been added for x64, i386, aarch64 and arm. Support for other
architectures can be added very easily in the future.
OS Support
==========
Support has been added for Linux. Support for other OSes can be added very
easily.
Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
* x86: Support for Static Trampolines
- Define the arch-specific initialization function ffi_tramp_arch ()
that returns trampoline size information to common code.
- Define the trampoline code mapping and data mapping sizes.
- Define the trampoline code table statically. Define two tables,
actually, one with CET and one without.
- Introduce a tiny prolog for each ABI handling function. The ABI
handlers addressed are:
- ffi_closure_unix64
- ffi_closure_unix64_sse
- ffi_closure_win64
The prolog functions are called:
- ffi_closure_unix64_alt
- ffi_closure_unix64_sse_alt
- ffi_closure_win64_alt
The legacy trampoline jumps to the ABI handler. The static
trampoline jumps to the prolog function. The prolog function uses
the information provided by the static trampoline, sets things up
for the ABI handler and then jumps to the ABI handler.
- Call ffi_tramp_set_parms () in ffi_prep_closure_loc () to
initialize static trampoline parameters.
Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
* i386: Support for Static Trampolines
- Define the arch-specific initialization function ffi_tramp_arch ()
that returns trampoline size information to common code.
- Define the trampoline code table statically. Define two tables,
actually, one with CET and one without.
- Define the trampoline code table statically.
- Introduce a tiny prolog for each ABI handling function. The ABI
handlers addressed are:
- ffi_closure_i386
- ffi_closure_STDCALL
- ffi_closure_REGISTER
The prolog functions are called:
- ffi_closure_i386_alt
- ffi_closure_STDCALL_alt
- ffi_closure_REGISTER_alt
The legacy trampoline jumps to the ABI handler. The static
trampoline jumps to the prolog function. The prolog function uses
the information provided by the static trampoline, sets things up
for the ABI handler and then jumps to the ABI handler.
- Call ffi_tramp_set_parms () in ffi_prep_closure_loc () to
initialize static trampoline parameters.
Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
* arm64: Support for Static Trampolines
- Define the arch-specific initialization function ffi_tramp_arch ()
that returns trampoline size information to common code.
- Define the trampoline code mapping and data mapping sizes.
- Define the trampoline code table statically.
- Introduce a tiny prolog for each ABI handling function. The ABI
handlers addressed are:
- ffi_closure_SYSV
- ffi_closure_SYSV_V
The prolog functions are called:
- ffi_closure_SYSV_alt
- ffi_closure_SYSV_V_alt
The legacy trampoline jumps to the ABI handler. The static
trampoline jumps to the prolog function. The prolog function uses
the information provided by the static trampoline, sets things up
for the ABI handler and then jumps to the ABI handler.
- Call ffi_tramp_set_parms () in ffi_prep_closure_loc () to
initialize static trampoline parameters.
Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
* arm: Support for Static Trampolines
- Define the arch-specific initialization function ffi_tramp_arch ()
that returns trampoline size information to common code.
- Define the trampoline code mapping and data mapping sizes.
- Define the trampoline code table statically.
- Introduce a tiny prolog for each ABI handling function. The ABI
handlers addressed are:
- ffi_closure_SYSV
- ffi_closure_VFP
The prolog functions are called:
- ffi_closure_SYSV_alt
- ffi_closure_VFP_alt
The legacy trampoline jumps to the ABI handler. The static
trampoline jumps to the prolog function. The prolog function uses
the information provided by the static trampoline, sets things up
for the ABI handler and then jumps to the ABI handler.
- Call ffi_tramp_set_parms () in ffi_prep_closure_loc () to
initialize static trampoline parameters.
Signed-off-by: Madhavan T. Venkataraman <madvenka@linux.microsoft.com>
|
|
8cc8f446
|
2020-11-10T20:41:33
|
|
Allow to build with mingw-clang (#579)
For some reason, compiling sysv.S with mingw-clang fails with:
```
error: invalid variant 'ffi_closure_inner@8'
```
This can be fixed (worked around?) by quoting the symbol. This works
fine with mingw-gcc too.
|
|
78556561
|
2020-02-21T19:08:06
|
|
x86: Add indirect branch tracking support (#540)
Intel Control-flow Enforcement Technology (CET):
https://software.intel.com/en-us/articles/intel-sdm
contains shadow stack (SHSTK) and indirect branch tracking (IBT). When
CET is enabled, ELF object files must be marked with .note.gnu.property
section. When Intel CET is enabled, include <cet.h> in assembly codes
to mark Intel CET support.
Also when IBT is enabled, all indirect branch targets must start with
ENDBR instruction and notrack prefix can be used to disable IBT on
indirect branch. <cet.h> defines _CET_ENDBR which can be used in
assembly codes for ENDBR instruction. If <cet.h> isn't included,
define _CET_ENDBR as empty so that _CET_ENDBR can be used in assembly
codes.
Trampoline must be enlarged to add ENDBR instruction unconditionally,
which is NOP on non-CET processors. This is required regardless if
libffi is enabled with CET since libffi.so will be marked in legacy
bitmap, but trampoline won't. Update library version for larger
FFI_TRAMPOLINE_SIZE.
This fixed:
https://github.com/libffi/libffi/issues/474
Tested with
$ CC="gcc -Wl,-z,cet-report=error -fcf-protection" CXX="g++ -Wl,-z,cet-report=error -fcf-protection" .../configure
on Linux CET machines in i686, x32 and x86-64 modes.
|
|
05a17964
|
2019-02-19T04:11:28
|
|
Cleanup symbol exports on darwin and add architecture preprocessor checks to assist in building fat binaries (eg: i386+x86_64 on macOS or arm+aarch64 on iOS) (#450)
* x86: Ensure _efi64 suffixed symbols are not exported
* x86: Ensure we do not export ffi_prep_cif_machdep
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
* x86: Ensure we don't export ffi_call_win64, ffi_closure_win64, or ffi_go_closure_win64
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
* closures: Silence a semantic warning
libffi/src/closures.c:175:23: This function declaration is not a prototype
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
* aarch64: Ensure we don't export ffi_prep_cif_machdep
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
* arm: Ensure we don't export ffi_prep_cif_machdep
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
* aarch64, arm, x86: Add architecture preprocessor checks to support easier fat builds (eg: iOS)
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
* x86: Silence some static analysis warnings
libffi/src/x86/ffi64.c:286:21: The left operand of '!=' is a garbage value due to array index out of bounds
libffi/src/x86/ffi64.c:297:22: The left operand of '!=' is a garbage value due to array index out of bounds
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
* aarch: Use FFI_HIDDEN rather than .hidden
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
* ffi.h: Don't advertise ffi_java_rvalue_to_raw, ffi_prep_java_raw_closure, and ffi_prep_java_raw_closure_loc when FFI_NATIVE_RAW_API is 0
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
|
|
ba73a671
|
2018-07-20T09:37:43
|
|
Update FFI_HIDDEN() to use .private_extern on Apple platforms and use the macro where appropriate
Fix issue #439
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org>
|
|
65da63ab
|
2018-06-25T04:38:58
|
|
Add compact unwind for darwin/i386 (#440)
* x86: Add implementation of compact unwind for ffi_call_i386, et al.
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org>
* x86: Use __text as the section name to avoid deprecated section name warnings.
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org>
* darwin: Add missing regular,debug attributes for compact unwind sections
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org>
|
|
2309b584
|
2018-06-17T17:04:24
|
|
Mark sysv.S as SafeSEH compatible (#438)
It contains no exception handler, so we can just emit the special
@feat.00 symbol to indicate that it's trivially SafeSEH compatible.
SafeSEH only applies to x86 and not x86-64, hence its inclusion in the
x86-specific block. See [1] for details.
[1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms680547(v=vs.85).aspx#the_.sxdata_section_
|
|
b5ee3957
|
2018-05-05T07:41:53
|
|
Revert "Remove some symbol exports and cleanup newline warnings (#433)"
This reverts commit a5a0f3cf36dfb4d64316414a872288c3170e6c1d.
|
|
a5a0f3cf
|
2018-05-05T03:44:33
|
|
Remove some symbol exports and cleanup newline warnings (#433)
* build: Ensure darwin generated sources end with a new line
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org>
* build: Use .private_extern where missing to prevent exporting symbols that are not API
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@macports.org>
|
|
28d3b61b
|
2018-01-20T23:56:17
|
|
Fix x86 SysV closure in PIC mode
The assembly single-line comments swallowed up the remaining assembly
code of the macros due to lack of line-endings.
This is a regression introduced in b7f6d7a.
|
|
a94c999b
|
2017-03-19T07:36:07
|
|
Handle fastcall declaration differently for some Microsoft compilers
|
|
3ac1610a
|
2015-01-19T20:48:40
|
|
x86: Fix cygwin32 build
The section syntax is just that little bit different.
|
|
f1560b7b
|
2015-01-16T11:31:37
|
|
x86: Solaris fixes
* Solaris/x86 /bin/as doesn't support .org, so I've just disabled the
uses in src/x86/{sysv, unix64}.S, as on Darwin.
* Solaris/x86 needs to use EH_FRAME_FLAGS so manually and compiler
generated .eh_frame sections match, otherwise libffi.so fails to link:
* Solaris/x86 /bin/as has different COMDAT syntax; I've disabled it for
the moment.
|
|
3fa5d70c
|
2015-01-05T13:03:06
|
|
x86: Avoid fastcall when building with pcc
Apparently, PCC doesn't support the fastcall calling convention.
Nor does it issue a warning or error for the attribute that it
does not understand.
|
|
a03d2310
|
2014-12-24T16:03:34
|
|
x86: Load structure return address into eax
|
|
b7f6d7aa
|
2014-12-10T13:37:36
|
|
x86: Reinstate hand-written unwind info for sysv.S
|
|
6cedf81c
|
2014-12-10T09:43:58
|
|
x86: Expand FFI_GO_CLOSURE
If we're going to have to hand-write unwind info for darwin,
these macros make the job harder.
|
|
5f35e0ff
|
2014-11-24T16:26:50
|
|
x86: Avoid using gas local labels
Which are unsupported by Darwin cctools as.
Thankfully this doesn't uglify the source too much.
|
|
ed1ca277
|
2014-11-24T13:02:03
|
|
x86: Remove use of .cfi_escape
The unwind info isn't 100% correct at all points during the epilogue,
and not annotating is just as incorrect as the annotation. This works
better on systems that do not support DW_OP_call_frame_cfa.
|
|
042b8daf
|
2014-11-24T11:24:02
|
|
x86: Use .balign not .align
The Apple assembler defaults to power of two alignment, rather than
byte alignment like everyone else. Force byte alignment by using
the proper directive.
|
|
0172bc02
|
2014-11-24T10:42:02
|
|
x86: Disable .org for Darwin
|
|
9f112619
|
2014-11-22T20:02:43
|
|
x86: Best guess at update for Darwin
|
|
097ccfd6
|
2014-12-10T13:25:14
|
|
x86: Fix some unwind errors
|
|
0e303c06
|
2014-11-12T03:58:58
|
|
x86: Work around clang bugs
http://llvm.org/bugs/show_bug.cgi?21500
http://llvm.org/bugs/show_bug.cgi?21501
http://llvm.org/bugs/show_bug.cgi?21515
|
|
2650f47f
|
2014-11-06T10:57:04
|
|
x86: Use win32 name mangling for fastcall functions
|
|
f8c64e24
|
2014-11-05T17:04:29
|
|
x86: Add support for Go closures
|
|
b21ec1ce
|
2014-11-05T10:15:25
|
|
x86: Rewrite closures
Move everything into sysv.S, removing win32.S and freebsd.S.
Handle all abis with a single ffi_closure_inner function.
Move complexity of the raw THISCALL trampoline into assembly
instead of the trampoline itself.
Only push the context for the REGISTER abi; let the rest
receive it in a register.
|
|
b9ac94f3
|
2014-11-01T15:10:34
|
|
x86: Rewrite ffi_call
Decouple the assembly from FFI_TYPE_*. Merge prep_args with ffi_call,
passing the frame and the stack to the assembly.
Note that this patch isn't really standalone, as this breaks closures.
|
|
159d3788
|
2014-10-31T12:07:02
|
|
x86: Convert to gas generated unwind info
|
|
fd07c9e4
|
2013-02-07T18:00:36
|
|
Add cache flushing routine for sun compiler on sparc solaris 2.8
|
|
2d9b3939
|
2013-01-09T21:14:54
|
|
Fix for closures with sunpro compiler
|
|
35ddb69c
|
2013-01-08T07:53:37
|
|
Only emit DWARF unwind info when building with GCC
|
|
0e584399
|
2011-02-08T07:52:40
|
|
Refresh from GCC
|
|
3f5b1375
|
2010-07-12T14:39:18
|
|
rebase
|
|
c6dddbd0
|
2009-10-04T08:11:33
|
|
Initial commit
|