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 > >