[PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor

Madhavan T. Venkataraman madvenka at linux.microsoft.com
Tue Aug 11 21:12:35 UTC 2020


I am working on version 2 of trampfd. Will send it out soon.

Thanks for all the comments so far!

Madhavan

On 8/10/20 12:34 PM, Madhavan T. Venkataraman wrote:
> Resending because of mailer problems. Some of the recipients did not receive
> my email. I apologize. Sigh.
> 
> Here is a redefinition of trampfd based on review comments.
> 
> I wanted to address dynamic code in 3 different ways:
> 
>     Remove the need for dynamic code where possible
>     --------------------------------------------------------------------
> 
>     If the kernel itself can perform the work of some dynamic code, then
>     the code can be replaced by the kernel.
> 
>     This is what I implemented in the patchset. But reviewers objected
>     to the performance impact. One trip to the kernel was needed for each
>     trampoline invocation. So, I have decided to defer this approach.
> 
>     Convert dynamic code to static code where possible
>     ----------------------------------------------------------------------
> 
>     This is possible with help from the kernel. This has no performance
>     impact and can be used in libffi, GCC nested functions, etc. I have
>     described the approach below.
> 
>     Deal with code generation
>     -----------------------------------
> 
>     For cases like generating JIT code from Java byte code, I wanted to
>     establish a framework. However, reviewers felt that details are missing.
> 
>     Should the kernel generate code or should it use a user-level code generator?
>     How do you make sure that a user level code generator can be trusted?
>     How would the communication work? ABI details? Architecture support?
>     Support for different types - JIT, DBT, etc?
> 
>     I have come to the conclusion that this is best done separately.
> 
> My main interest is to provide a way to convert dynamic code such as
> trampolines to static code without any special architecture support.
> This can be done with the kernel's help. Any code that gets written in
> the future can conform to this as well.
> 
> So, in version 2 of the Trampfd RFC, I would like to simplify trampfd and
> just address item 2. I will reimplement the support in libffi and present it.
> 
> Convert dynamic code to static code
> ------------------------------------------------
> 
> One problem with dynamic code is that it cannot be verified or authenticated
> by the kernel. The kernel cannot tell the difference between genuine dynamic
> code and an attacker's code. Where possible, dynamic code should be converted
> to static code and placed in the text segment of a binary file. This allows
> the kernel to verify the code by verifying the signature of the file.
> 
> The other problem is using user-level methods to load and execute dynamic code
> can potentially be exploited by an attacker to inject his code and have it be
> executed. To prevent this, a system may enforce W^X. If W^X is enforced
> properly, genuine dynamic code will not be able to run. This is another
> reason to convert dynamic code to static code.
> 
> The issue in converting dynamic code to static code is that the data is
> dynamic. The code does not know before hand where the data is going to be
> at runtime.
> 
> Some architectures support PC-relative data references. So, if you co-locate
> code and data, then the code can find the data at runtime. But this is not
> supported on all architectures. When supported, there may be limitations to
> deal with. Plus you have to take the trouble to co-locate code and data.
> And, to deal with W^X, code and data need to be in different pages.
> 
> All architectures must be supported without any limitations. Fortunately,
> the kernel can solve this problem quite easily. I suggest the following:
> 
> Convert dynamic code to static code like this:
> 
>     - Decide which register should point to the data that the code needs.
>       Call it register R.
> 
>     - Write the static code assuming that R already points to the data.
> 
>     - Use trampfd and pass the following to the kernel:
> 
>         - pointers to the code and data
>         - the name of the register R
> 
> The kernel will write the following instructions in a trampoline page
> mapped into the caller's address space with R-X.
> 
>     - Load the data address in register R
>     - Jump to the static code
> 
> Basically, the kernel provides a trampoline to jump to the user's code
> and returns the kernel-provided trampoline's address to the user.
> 
> It is trivial to implement a trampoline table in the trampoline page to
> conserve memory.
> 
> Issues raised previously
> -------------------------------
> 
> I believe that the following issues that were raised by reviewers is not
> a problem in this scheme. Please rereview.
> 
>     - Florian mentioned the libffi trampoline table. Trampoline tables can be
>       implemented in this scheme easily.
> 
>     - Florian mentioned stack unwinders. I am not an expert on unwinders.
>       But I don't see an issue with unwinders.
> 
>     - Mark Rutland mentioned Intel's CET and CFI. Don't see a problem there.
> 
>     - Mark Rutland mentioned PAC+BTI on ARM64. Don't see a problem there.
> 
> If I have missed addressing any previously raised issue, I apologize.
> Please let me know.
> 
> Thanks!
> 
> Madhavan
> 
> 



More information about the Linux-security-module-archive mailing list