From: "Madhavan T. Venkataraman" <madvenka@linux.microsoft.com> To: Andy Lutomirski <luto@kernel.org> Cc: Kernel Hardening <kernel-hardening@lists.openwall.com>, Linux API <linux-api@vger.kernel.org>, linux-arm-kernel <linux-arm-kernel@lists.infradead.org>, Linux FS Devel <linux-fsdevel@vger.kernel.org>, linux-integrity <linux-integrity@vger.kernel.org>, LKML <linux-kernel@vger.kernel.org>, LSM List <linux-security-module@vger.kernel.org>, Oleg Nesterov <oleg@redhat.com>, X86 ML <x86@kernel.org> Subject: Re: [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor Date: Fri, 31 Jul 2020 12:13:49 -0500 [thread overview] Message-ID: <46a1adef-65f0-bd5e-0b17-54856fb7e7ee@linux.microsoft.com> (raw) In-Reply-To: <CALCETrWnNR5v3ZCLfBVQGYK8M0jAvQMaAc9uuO05kfZuh-4d6w@mail.gmail.com> On 7/30/20 3:54 PM, Andy Lutomirski wrote: > On Thu, Jul 30, 2020 at 7:24 AM Madhavan T. Venkataraman > <madvenka@linux.microsoft.com> wrote: >> ... >> Creating a code page >> -------------------- >> >> We can do this in one of the following ways: >> >> - Allocate a writable page at run time, write the template code into >> the page and have execute permissions on the page. >> >> - Allocate a writable page at run time, write the template code into >> the page and remap the page with just execute permissions. >> >> - Allocate a writable page at run time, write the template code into >> the page, write the page into a temporary file and map the file with >> execute permissions. >> >> - Include the template code in a code page at build time itself and >> just remap the code page each time you need a code page. > This latter part shouldn't need any special permissions as far as I know. Agreed. > >> Pros and Cons >> ------------- >> >> As long as the OS provides the functionality to do this and the security >> subsystem in the OS allows the actions, this is totally feasible. If not, >> we need something like trampfd. >> >> As Floren mentioned, libffi does implement something like this for MACH. >> >> In fact, in my libffi changes, I use trampfd only after all the other methods >> have failed because of security settings. >> >> But the above approach only solves the problem for this simple type of >> trampoline. It does not provide a framework for addressing more complex types >> or even other forms of dynamic code. >> >> Also, each application would need to implement this solution for itself >> as opposed to relying on one implementation provided by the kernel. > I would argue this is a benefit. If the whole implementation is in > userspace, there is no ABI compatibility issue. The user program > contains the trampoline code and the code that uses it. The current trampfd implementation also does not have an ABI issue. ABI details are to be handled in user land. In the case of libffi, they are. Trampfd only addresses the trampoline required to jump to the ABI handler. > >> Trampfd-based solution >> ---------------------- >> >> I outlined an enhancement to trampfd in a response to David Laight. In this >> enhancement, the kernel is the one that would set up the code page. >> >> The kernel would call an arch-specific support function to generate the >> code required to load registers, push values on the stack and jump to a PC >> for a trampoline instance based on its current context. The trampoline >> instance data could be baked into the code. >> >> My initial idea was to only have one trampoline instance per page. But I >> think I can implement multiple instances per page. I just have to manage >> the trampfd file private data and VMA private data accordingly to map an >> element in a code page to its trampoline object. >> >> The two approaches are similar except for the detail about who sets up >> and manages the trampoline pages. In both approaches, the performance problem >> is addressed. But trampfd can be used even when security settings are >> restrictive. >> >> Is my solution acceptable? > Perhaps. In general, before adding a new ABI to the kernel, it's nice > to understand how it's better than doing the same thing in userspace. > Saying that it's easier for user code to work with if it's in the > kernel isn't necessarily an adequate justification. Fair enough. Dealing with multiple architectures ----------------------------------------------- One good reason to use trampfd is multiple architecture support. The trampoline table in a code page approach is neat. I don't deny that at all. But my question is - can it be used in all cases? It requires PC-relative data references. I have not worked on all architectures. So, I need to study this. But do all ISAs support PC-relative data references? Even in an ISA that supports it, there would be a maximum supported offset from the current PC that can be reached for a data reference. That maximum needs to be at least the size of a base page in the architecture. This is because the code page and the data page need to be separate for security reasons. Do all ISAs support a sufficiently large offset? When the kernel generates the code for a trampoline, it can hard code data values in the generated code itself so it does not need PC-relative data referencing. And, for ISAs that do support the large offset, we do have to implement and maintain the code page stuff for different ISAs for each application and library if we did not use trampfd. If you look at the libffi reference patch that I have linked in the cover letter, I have added functions in common code that wrap trampfd calls. From architecture specific code, there is just one function call to one of those wrapper functions to set the register context for the trampoline. This is a very small C code change in each architecture. So, support can be extended to all architectures without exception easily. Runtime generated trampolines ------------------------------------------- libffi trampolines are simple. But there may be many cases out there where the trampoline code cannot be statically defined at build time. It may have to be generated at runtime. For this, we will need trampfd. Security ----------- With the user level trampoline table approach, the data part of the trampoline table can be hacked by an attacker if an application has a vulnerability. Specifically, the target PC can be altered to some arbitrary location. Trampfd implements an "Allowed PCS" context. In the libffi changes, I have created a read-only array of all ABI handlers used in closures for each architecture. This read-only array can be used to restrict the PC values for libffi trampolines to prevent hacking. To generalize, we can implement security rules/features if the trampoline object is in the kernel. Standardization --------------------- Trampfd is a framework that can be used to implement multiple things. May be, a few of those things can also be implemented in user land itself. But I think having just one mechanism to execute dynamic code objects is preferable to having multiple mechanisms not standardized across all applications. As an example, let us say that I am able to implement support for JIT code. Let us say that an interpreter uses libffi to execute a generated function. The interpreter would use trampfd for the JIT code object and get an address. Then, it would pass that to libffi which would then use trampfd for the trampoline. So, trampfd based code objects can be chained. > Why would remapping two pages of actual application text ever fail? Remapping a page may not be available on all OSes. However, that is not a problem for the code page approach. One can always memory map the code page from the binary file directly. So, yes, this would not fail. Madhavan
WARNING: multiple messages have this Message-ID (diff)
From: "Madhavan T. Venkataraman" <madvenka@linux.microsoft.com> To: Andy Lutomirski <luto@kernel.org> Cc: Kernel Hardening <kernel-hardening@lists.openwall.com>, Linux API <linux-api@vger.kernel.org>, X86 ML <x86@kernel.org>, LKML <linux-kernel@vger.kernel.org>, Oleg Nesterov <oleg@redhat.com>, LSM List <linux-security-module@vger.kernel.org>, Linux FS Devel <linux-fsdevel@vger.kernel.org>, linux-integrity <linux-integrity@vger.kernel.org>, linux-arm-kernel <linux-arm-kernel@lists.infradead.org> Subject: Re: [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor Date: Fri, 31 Jul 2020 12:13:49 -0500 [thread overview] Message-ID: <46a1adef-65f0-bd5e-0b17-54856fb7e7ee@linux.microsoft.com> (raw) In-Reply-To: <CALCETrWnNR5v3ZCLfBVQGYK8M0jAvQMaAc9uuO05kfZuh-4d6w@mail.gmail.com> On 7/30/20 3:54 PM, Andy Lutomirski wrote: > On Thu, Jul 30, 2020 at 7:24 AM Madhavan T. Venkataraman > <madvenka@linux.microsoft.com> wrote: >> ... >> Creating a code page >> -------------------- >> >> We can do this in one of the following ways: >> >> - Allocate a writable page at run time, write the template code into >> the page and have execute permissions on the page. >> >> - Allocate a writable page at run time, write the template code into >> the page and remap the page with just execute permissions. >> >> - Allocate a writable page at run time, write the template code into >> the page, write the page into a temporary file and map the file with >> execute permissions. >> >> - Include the template code in a code page at build time itself and >> just remap the code page each time you need a code page. > This latter part shouldn't need any special permissions as far as I know. Agreed. > >> Pros and Cons >> ------------- >> >> As long as the OS provides the functionality to do this and the security >> subsystem in the OS allows the actions, this is totally feasible. If not, >> we need something like trampfd. >> >> As Floren mentioned, libffi does implement something like this for MACH. >> >> In fact, in my libffi changes, I use trampfd only after all the other methods >> have failed because of security settings. >> >> But the above approach only solves the problem for this simple type of >> trampoline. It does not provide a framework for addressing more complex types >> or even other forms of dynamic code. >> >> Also, each application would need to implement this solution for itself >> as opposed to relying on one implementation provided by the kernel. > I would argue this is a benefit. If the whole implementation is in > userspace, there is no ABI compatibility issue. The user program > contains the trampoline code and the code that uses it. The current trampfd implementation also does not have an ABI issue. ABI details are to be handled in user land. In the case of libffi, they are. Trampfd only addresses the trampoline required to jump to the ABI handler. > >> Trampfd-based solution >> ---------------------- >> >> I outlined an enhancement to trampfd in a response to David Laight. In this >> enhancement, the kernel is the one that would set up the code page. >> >> The kernel would call an arch-specific support function to generate the >> code required to load registers, push values on the stack and jump to a PC >> for a trampoline instance based on its current context. The trampoline >> instance data could be baked into the code. >> >> My initial idea was to only have one trampoline instance per page. But I >> think I can implement multiple instances per page. I just have to manage >> the trampfd file private data and VMA private data accordingly to map an >> element in a code page to its trampoline object. >> >> The two approaches are similar except for the detail about who sets up >> and manages the trampoline pages. In both approaches, the performance problem >> is addressed. But trampfd can be used even when security settings are >> restrictive. >> >> Is my solution acceptable? > Perhaps. In general, before adding a new ABI to the kernel, it's nice > to understand how it's better than doing the same thing in userspace. > Saying that it's easier for user code to work with if it's in the > kernel isn't necessarily an adequate justification. Fair enough. Dealing with multiple architectures ----------------------------------------------- One good reason to use trampfd is multiple architecture support. The trampoline table in a code page approach is neat. I don't deny that at all. But my question is - can it be used in all cases? It requires PC-relative data references. I have not worked on all architectures. So, I need to study this. But do all ISAs support PC-relative data references? Even in an ISA that supports it, there would be a maximum supported offset from the current PC that can be reached for a data reference. That maximum needs to be at least the size of a base page in the architecture. This is because the code page and the data page need to be separate for security reasons. Do all ISAs support a sufficiently large offset? When the kernel generates the code for a trampoline, it can hard code data values in the generated code itself so it does not need PC-relative data referencing. And, for ISAs that do support the large offset, we do have to implement and maintain the code page stuff for different ISAs for each application and library if we did not use trampfd. If you look at the libffi reference patch that I have linked in the cover letter, I have added functions in common code that wrap trampfd calls. From architecture specific code, there is just one function call to one of those wrapper functions to set the register context for the trampoline. This is a very small C code change in each architecture. So, support can be extended to all architectures without exception easily. Runtime generated trampolines ------------------------------------------- libffi trampolines are simple. But there may be many cases out there where the trampoline code cannot be statically defined at build time. It may have to be generated at runtime. For this, we will need trampfd. Security ----------- With the user level trampoline table approach, the data part of the trampoline table can be hacked by an attacker if an application has a vulnerability. Specifically, the target PC can be altered to some arbitrary location. Trampfd implements an "Allowed PCS" context. In the libffi changes, I have created a read-only array of all ABI handlers used in closures for each architecture. This read-only array can be used to restrict the PC values for libffi trampolines to prevent hacking. To generalize, we can implement security rules/features if the trampoline object is in the kernel. Standardization --------------------- Trampfd is a framework that can be used to implement multiple things. May be, a few of those things can also be implemented in user land itself. But I think having just one mechanism to execute dynamic code objects is preferable to having multiple mechanisms not standardized across all applications. As an example, let us say that I am able to implement support for JIT code. Let us say that an interpreter uses libffi to execute a generated function. The interpreter would use trampfd for the JIT code object and get an address. Then, it would pass that to libffi which would then use trampfd for the trampoline. So, trampfd based code objects can be chained. > Why would remapping two pages of actual application text ever fail? Remapping a page may not be available on all OSes. However, that is not a problem for the code page approach. One can always memory map the code page from the binary file directly. So, yes, this would not fail. Madhavan _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2020-07-31 17:13 UTC|newest] Thread overview: 146+ messages / expand[flat|nested] mbox.gz Atom feed top [not found] <aefc85852ea518982e74b233e11e16d2e707bc32> 2020-07-28 13:10 ` [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor madvenka 2020-07-28 13:10 ` madvenka 2020-07-28 13:10 ` [PATCH v1 1/4] [RFC] fs/trampfd: Implement the trampoline file descriptor API madvenka 2020-07-28 13:10 ` madvenka 2020-07-28 14:50 ` Oleg Nesterov 2020-07-28 14:50 ` Oleg Nesterov 2020-07-28 14:58 ` Madhavan T. Venkataraman 2020-07-28 14:58 ` Madhavan T. Venkataraman 2020-07-28 16:06 ` Oleg Nesterov 2020-07-28 16:06 ` Oleg Nesterov 2020-07-28 19:48 ` kernel test robot 2020-07-29 2:33 ` kernel test robot 2020-07-28 13:10 ` [PATCH v1 2/4] [RFC] x86/trampfd: Provide support for the trampoline file descriptor madvenka 2020-07-28 13:10 ` madvenka 2020-07-28 18:38 ` kernel test robot 2020-07-30 9:06 ` Greg KH 2020-07-30 9:06 ` Greg KH 2020-07-30 14:25 ` Madhavan T. Venkataraman 2020-07-30 14:25 ` Madhavan T. Venkataraman 2020-07-28 13:10 ` [PATCH v1 3/4] [RFC] arm64/trampfd: " madvenka 2020-07-28 13:10 ` madvenka 2020-07-28 13:10 ` [PATCH v1 4/4] [RFC] arm/trampfd: " madvenka 2020-07-28 13:10 ` madvenka 2020-07-28 15:13 ` [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor David Laight 2020-07-28 15:13 ` David Laight 2020-07-28 15:13 ` David Laight 2020-07-28 16:32 ` Madhavan T. Venkataraman 2020-07-28 16:32 ` Madhavan T. Venkataraman 2020-07-28 16:32 ` Madhavan T. Venkataraman 2020-07-28 17:16 ` Andy Lutomirski 2020-07-28 17:16 ` Andy Lutomirski 2020-07-28 17:16 ` Andy Lutomirski 2020-07-28 17:39 ` Madhavan T. Venkataraman 2020-07-29 5:16 ` Andy Lutomirski 2020-07-29 5:16 ` Andy Lutomirski 2020-07-29 5:16 ` Andy Lutomirski 2020-07-28 18:52 ` Madhavan T. Venkataraman 2020-07-28 18:52 ` Madhavan T. Venkataraman 2020-07-28 18:52 ` Madhavan T. Venkataraman 2020-07-29 8:36 ` David Laight 2020-07-29 8:36 ` David Laight 2020-07-29 8:36 ` David Laight 2020-07-29 17:55 ` Madhavan T. Venkataraman 2020-07-29 17:55 ` Madhavan T. Venkataraman 2020-07-29 17:55 ` Madhavan T. Venkataraman 2020-07-28 16:05 ` Casey Schaufler 2020-07-28 16:05 ` Casey Schaufler 2020-07-28 16:49 ` Madhavan T. Venkataraman 2020-07-28 16:49 ` Madhavan T. Venkataraman 2020-07-28 17:05 ` James Morris 2020-07-28 17:05 ` James Morris 2020-07-28 17:08 ` Madhavan T. Venkataraman 2020-07-28 17:08 ` Madhavan T. Venkataraman 2020-07-28 17:31 ` Andy Lutomirski 2020-07-28 17:31 ` Andy Lutomirski 2020-07-28 17:31 ` Andy Lutomirski 2020-07-28 19:01 ` Madhavan T. Venkataraman 2020-07-28 19:01 ` Madhavan T. Venkataraman 2020-07-29 13:29 ` Florian Weimer 2020-07-29 13:29 ` Florian Weimer 2020-07-29 13:29 ` Florian Weimer 2020-07-30 13:09 ` David Laight 2020-07-30 13:09 ` David Laight 2020-08-02 11:56 ` Pavel Machek 2020-08-02 11:56 ` Pavel Machek 2020-08-03 8:08 ` David Laight 2020-08-03 8:08 ` David Laight 2020-08-03 15:57 ` Madhavan T. Venkataraman 2020-08-03 15:57 ` Madhavan T. Venkataraman 2020-07-30 14:24 ` Madhavan T. Venkataraman 2020-07-30 20:54 ` Andy Lutomirski 2020-07-30 20:54 ` Andy Lutomirski 2020-07-30 20:54 ` Andy Lutomirski 2020-07-31 17:13 ` Madhavan T. Venkataraman [this message] 2020-07-31 17:13 ` Madhavan T. Venkataraman 2020-07-31 18:31 ` Mark Rutland 2020-07-31 18:31 ` Mark Rutland 2020-08-03 8:27 ` David Laight 2020-08-03 8:27 ` David Laight 2020-08-03 16:03 ` Madhavan T. Venkataraman 2020-08-03 16:03 ` Madhavan T. Venkataraman 2020-08-03 16:57 ` David Laight 2020-08-03 16:57 ` David Laight 2020-08-03 17:00 ` Madhavan T. Venkataraman 2020-08-03 17:00 ` Madhavan T. Venkataraman 2020-08-03 17:58 ` Madhavan T. Venkataraman 2020-08-03 17:58 ` Madhavan T. Venkataraman 2020-08-04 13:55 ` Mark Rutland 2020-08-04 13:55 ` Mark Rutland 2020-08-04 14:33 ` David Laight 2020-08-04 14:33 ` David Laight 2020-08-04 14:44 ` David Laight 2020-08-04 14:44 ` David Laight 2020-08-04 14:48 ` Madhavan T. Venkataraman 2020-08-04 14:48 ` Madhavan T. Venkataraman 2020-08-04 15:46 ` Madhavan T. Venkataraman 2020-08-04 15:46 ` Madhavan T. Venkataraman 2020-08-02 13:57 ` Florian Weimer 2020-08-02 13:57 ` Florian Weimer 2020-08-02 13:57 ` Florian Weimer 2020-07-30 14:42 ` Madhavan T. Venkataraman 2020-07-30 14:42 ` Madhavan T. Venkataraman 2020-08-02 18:54 ` Madhavan T. Venkataraman 2020-08-02 18:54 ` Madhavan T. Venkataraman 2020-08-02 20:00 ` Andy Lutomirski 2020-08-02 20:00 ` Andy Lutomirski 2020-08-02 20:00 ` Andy Lutomirski 2020-08-02 22:58 ` Madhavan T. Venkataraman 2020-08-02 22:58 ` Madhavan T. Venkataraman 2020-08-03 18:36 ` Madhavan T. Venkataraman 2020-08-03 18:36 ` Madhavan T. Venkataraman 2020-08-10 17:20 ` Madhavan T. Venkataraman 2020-08-10 17:34 ` Madhavan T. Venkataraman 2020-08-10 17:34 ` Madhavan T. Venkataraman 2020-08-11 21:12 ` Madhavan T. Venkataraman 2020-08-11 21:12 ` Madhavan T. Venkataraman 2020-08-03 8:23 ` David Laight 2020-08-03 8:23 ` David Laight 2020-08-03 15:59 ` Madhavan T. Venkataraman 2020-08-03 15:59 ` Madhavan T. Venkataraman 2020-07-31 18:09 ` Mark Rutland 2020-07-31 18:09 ` Mark Rutland 2020-07-31 20:08 ` Madhavan T. Venkataraman 2020-07-31 20:08 ` Madhavan T. Venkataraman 2020-08-03 16:57 ` Madhavan T. Venkataraman 2020-08-03 16:57 ` Madhavan T. Venkataraman 2020-08-04 14:30 ` Mark Rutland 2020-08-04 14:30 ` Mark Rutland 2020-08-06 17:26 ` Madhavan T. Venkataraman 2020-08-06 17:26 ` Madhavan T. Venkataraman 2020-08-08 22:17 ` Pavel Machek 2020-08-08 22:17 ` Pavel Machek 2020-08-11 12:41 ` Madhavan T. Venkataraman 2020-08-11 12:41 ` Madhavan T. Venkataraman 2020-08-11 13:08 ` Pavel Machek 2020-08-11 13:08 ` Pavel Machek 2020-08-11 15:54 ` Madhavan T. Venkataraman 2020-08-11 15:54 ` Madhavan T. Venkataraman 2020-08-12 10:06 ` Mark Rutland 2020-08-12 10:06 ` Mark Rutland 2020-08-12 18:47 ` Madhavan T. Venkataraman 2020-08-12 18:47 ` Madhavan T. Venkataraman 2020-08-19 18:53 ` Mickaël Salaün 2020-08-19 18:53 ` Mickaël Salaün 2020-09-01 15:42 ` Mark Rutland 2020-09-01 15:42 ` Mark Rutland
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=46a1adef-65f0-bd5e-0b17-54856fb7e7ee@linux.microsoft.com \ --to=madvenka@linux.microsoft.com \ --cc=kernel-hardening@lists.openwall.com \ --cc=linux-api@vger.kernel.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-fsdevel@vger.kernel.org \ --cc=linux-integrity@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-security-module@vger.kernel.org \ --cc=luto@kernel.org \ --cc=oleg@redhat.com \ --cc=x86@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.