Thread (24 messages) flat view 24 messages, 3 authors, 2021-08-11

Re: [PATCH v5 2/8] lkdtm/powerpc: Add test to hijack a patch mapping

From: Kees Cook <hidden>
Date: 2021-08-11 18:08:20
Also in: linux-hardening

On Wed, Aug 11, 2021 at 12:57:00PM -0500, Christopher M. Riedl wrote:
On Thu Aug 5, 2021 at 4:13 AM CDT, Christophe Leroy wrote:
quoted

Le 13/07/2021 à 07:31, Christopher M. Riedl a écrit :
quoted
When live patching with STRICT_KERNEL_RWX the CPU doing the patching
must temporarily remap the page(s) containing the patch site with +W
permissions. While this temporary mapping is in use, another CPU could
write to the same mapping and maliciously alter kernel text. Implement a
LKDTM test to attempt to exploit such an opening during code patching.
The test is implemented on powerpc and requires LKDTM built into the
kernel (building LKDTM as a module is insufficient).

The LKDTM "hijack" test works as follows:

   1. A CPU executes an infinite loop to patch an instruction. This is
      the "patching" CPU.
   2. Another CPU attempts to write to the address of the temporary
      mapping used by the "patching" CPU. This other CPU is the
      "hijacker" CPU. The hijack either fails with a fault/error or
      succeeds, in which case some kernel text is now overwritten.
[...]
+#if (IS_BUILTIN(CONFIG_LKDTM) && defined(CONFIG_STRICT_KERNEL_RWX) && \
+	defined(CONFIG_PPC))
I think this test shouldn't be limited to CONFIG_PPC and shouldn't be
limited to CONFIG_STRICT_KERNEL_RWX. It should be there all the time.
Agreed: if the machinery exists to provide this defense on even one
arch/config/whatever combo, I'd like LKDTM to test for it. This lets use
compare defenses across different combinations more easily, and means
folks must answer questions like "why doesn't $combination provide
$defense?"
quoted
Also why limiting it to IS_BUILTIN(CONFIG_LKDTM) ?
The test needs read_cpu_patching_addr() which definitely cannot be
exposed outside of the kernel (ie. builtin).
FWIW, I'm okay with this. There isn't a solution that feels entirely
"right", so either a build-time requirement like this, or using an
exception for modules like this:

arch/x86/kernel/cpu/common.c:#if IS_MODULE(CONFIG_LKDTM)
arch/x86/kernel/cpu/common.c-EXPORT_SYMBOL_GPL(native_write_cr4);
arch/x86/kernel/cpu/common.c-#endif

I think neither is great. Another idea is maybe using a name-spaced
export, like:

EXPORT_SYMBOL_NS_GPL(native_write_cr4, LKDTM);

But that still means it gets exposed to malicious discovery, so probably
not.

I suspect the best is to just do the BUILTIN check, since building LKDTM
as a module on a _production_ kernel is rare if it exists at all. The
only downside is needing to completely reboot to perform updated tests,
but then, I frequently find myself breaking the kernel badly on bad
tests, so I have to reboot anyway. ;)

-Kees

-- 
Kees Cook
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help