[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