[RFC PATCH v3 0/5] Libffi Static Trampolines

Madhavan T. Venkataraman madvenka@linux.microsoft.com
Wed Jan 27 19:45:10 GMT 2021



On 1/27/21 12:00 PM, Anthony Green wrote:
> Thanks, Madhaven.   I think I understand now.   Are these statements true?:
> 
> (a) These patches implement trampoline tables, similar to what is implemented in the iOS port.  This hardens the library by eliminating the requirement for writable executable memory.
> (b) These patches expose a new public API for hardened trampolines.  (a) uses (b), but doesn't require that (b) be public.
> (c) We can release libffi with (a) and not (b).
> 
> Is this correct?  
> 

Yes. This is correct. The public API part is not required.

It is just to provide the open source community with a way to help convert their dynamic code.
We could also consider exposing the public API at a later time when the changes are considered
well exercised.

Madhavan

> AG
> 
> On Wed, Jan 27, 2021 at 12:20 PM Madhavan T. Venkataraman <madvenka@linux.microsoft.com <mailto:madvenka@linux.microsoft.com>> wrote:
> 
> 
> 
>     On 1/26/21 5:41 PM, Anthony Green wrote:
>     > Madhaven,
>     >
>     >   Thank you for your continued efforts here.
>     >
>     > On Fri, Jan 15, 2021 at 1:47 PM <madvenka@linux.microsoft.com <mailto:madvenka@linux.microsoft.com> <mailto:madvenka@linux.microsoft.com <mailto:madvenka@linux.microsoft.com>>> wrote:
>     >
>     >     Trampoline API
>     >     ==============
>     >
>     >     There is a lot of dynamic code out there. They all have the same security
>     >     issue. Dynamic code can be re-written into static code provided the data
>     >     required by the static code can be passed to it just like we pass the closure
>     >     pointer to an ABI handler.
>     >
>     >     So, the same trampoline functions used by libffi internally need to be
>     >     made available to the rest of the world in the form of an API. The
>     >     following API has been defined in this solution:
>     >
>     >
>     >
>     > I need a better explanation around why this new API is required, and this new capability isn't just an implementation detail supporting the old API.
>     >
> 
>     Example 1
>     =========
> 
>     Let us say that an application or a library has a simple trampoline - load a value or
>     an address in a register or the stack and transfer control to some target function.
>     It would have dynamic code to do that just like libffi currently does.
> 
>     Dynamic code has a security issue as I have explained in the cover letter. It needs
>     to be loaded in an executable page. A clever hacker may be able to inject his code
>     in that page. To prevent that, dynamic code has to be converted into static code
>     so that it is in a read-only text segment.
> 
>     I have solved this problem for libffi and I have provided statically defined trampolines.
> 
>     The application or library that is currently using dynamic code for its trampoline could
>     instead use the libffi API and replace its trampoline. This would eliminate dynamic code
>     from that application or library and make it more secure.
> 
>     The only thing is that the target function should now expect its data in the libffi
>     designated scratch register instead of whatever it was using. This is trivial to do.
> 
>     Example 2
>     ==========
> 
>     Let us say that an application or library uses something more complicated than the
>     libffi trampoline. For example, a piece of dynamic code that unmarshalls parameters
>     from a structure and calls a target function.
> 
>     The application developer is interested in eliminating this piece of dynamic code
>     for security purposes. The developer could rewrite the dynamic code into static
>     code. The only thing is that the structure pointer needs to be passed to the static
>     code. Either the application developer can write his own code (using PC-relative
>     accesses, etc) to pass data. Or, he can use the libffi API to do it.
> 
>     So, the only effort for the developer/maintainer of the application/library is to
>     rewrite the unmarshalling dynamic code into static code. That should be straight forward.
> 
>     Example 3
>     =========
> 
>     Let us say that an application or library has a piece of dynamic code to perform
>     some computation and produce results. It is written as dynamic code because
>     the exact set of arguments and the exact computation is known only at runtime.
>     So, the dynamic code is generated at runtime accordingly. When the code is
>     generated, the data needed by the code is embedded in the generated code.
> 
>     In this case, the developer needs to do a little extra work. E.g.,
> 
>     - Define a union of structures with each structure defining a particular
>       computation and set of arguments.
> 
>     - Write static code to accept a pointer to the union and perform
>       different computations and return results in that union.
> 
>     - Then, the static code can be invoked using the libffi API and the union
>       pointer can be passed to it.
> 
>     Summary
>     =======
> 
>     There are a lot of applications that use dynamic code out there. Dynamic code
>     should be eliminated as far as possible for security purposes.
> 
>     I believe most of them can be converted to static code by the maintainers. All
>     they need is a method to pass data to their static code without having to implement
>     the method themselves. The libffi API provides that.
> 
>     The libffi API can also be supported easily for multiple architectures so that
>     applications can use the API in an architecture-independent way.
> 
>     Is this sufficient justification for the API?
> 
>     Madhavan
> 


More information about the Libffi-discuss mailing list