All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Christopher M. Riedl" <cmr@informatik.wtf>
To: linuxppc-dev@ozlabs.org
Subject: [RFC PATCH 0/3] Use per-CPU temporary mappings for patching
Date: Sun, 22 Mar 2020 23:52:02 -0500	[thread overview]
Message-ID: <20200323045205.20314-1-cmr@informatik.wtf> (raw)

When compiled with CONFIG_STRICT_KERNEL_RWX, the kernel must create
temporary mappings when patching itself. These mappings temporarily
override the strict RWX text protections to permit a write. Currently,
powerpc allocates a per-CPU VM area for patching. Patching occurs as
follows:

	1. Map page of text to be patched to per-CPU VM area w/
	   PAGE_KERNEL protection
	2. Patch text
	3. Remove the temporary mapping

While the VM area is per-CPU, the mapping is actually inserted into the
kernel page tables. Presumably, this could allow another CPU to access
the normally write-protected text - either malicously or accidentally -
via this same mapping if the address of the VM area is known. Ideally,
the mapping should be kept local to the CPU doing the patching (or any
other sensitive operations requiring temporarily overriding memory
protections) [0].

x86 introduced "temporary mm" structs which allow the creation of
mappings local to a particular CPU [1]. This series intends to bring the
notion of a temporary mm to powerpc and harden powerpc by using such a
mapping for patching a kernel with strict RWX permissions.

The first patch introduces the temporary mm struct and API for powerpc
along with a new function to retrieve a current hw breakpoint.

The second patch uses the `poking_init` init hook added by the x86
patches to initialize a temporary mm and patching address. The patching
address is randomized between 0 and DEFAULT_MAP_WINDOW-PAGE_SIZE. The
upper limit is necessary due to how the hash MMU operates - by default
the space above DEFAULT_MAP_WINDOW is not available. For now, both hash
and radix randomize inside this range. The number of possible random
addresses is dependent on PAGE_SIZE and limited by DEFAULT_MAP_WINDOW.

Bits of entropy with 64K page size on BOOK3S_64:

	bits-o-entropy = log2(DEFAULT_MAP_WINDOW_USER64 / PAGE_SIZE)

	PAGE_SIZE=64K, DEFAULT_MAP_WINDOW_USER64=128TB
	bits-o-entropy = log2(128TB / 64K)
	bits-o-entropy = 31

Currently, randomization occurs only once during initialization at boot.

The third patch replaces the VM area with the temporary mm in the
patching code. The page for patching has to be mapped PAGE_SHARED with
the hash MMU since hash prevents the kernel from accessing userspace
pages with PAGE_PRIVILEGED bit set. There is on-going work on my side to
explore if this is actually necessary in the hash codepath.

Testing so far is limited to booting on QEMU (power8 and power9 targets)
and a POWER8 VM along with setting some simple xmon breakpoints (which
makes use of code-patching). A POC lkdtm test is in-progress to actually
exploit the existing vulnerability (ie. the mapping during patching is
exposed in kernel page tables and accessible by other CPUS) - this will
accompany a future v1 of this series.

[0]: https://github.com/linuxppc/issues/issues/224
[1]: https://lore.kernel.org/kernel-hardening/20190426232303.28381-1-nadav.amit@gmail.com/

Christopher M. Riedl (3):
  powerpc/mm: Introduce temporary mm
  powerpc/lib: Initialize a temporary mm for code patching
  powerpc/lib: Use a temporary mm for code patching

 arch/powerpc/include/asm/debug.h       |   1 +
 arch/powerpc/include/asm/mmu_context.h |  56 +++++++++-
 arch/powerpc/kernel/process.c          |   5 +
 arch/powerpc/lib/code-patching.c       | 140 ++++++++++++++-----------
 4 files changed, 137 insertions(+), 65 deletions(-)

-- 
2.25.1


             reply	other threads:[~2020-03-23  5:03 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-23  4:52 Christopher M. Riedl [this message]
2020-03-23  4:52 ` [RFC PATCH 1/3] powerpc/mm: Introduce temporary mm Christopher M. Riedl
2020-03-23  6:10   ` kbuild test robot
2020-03-24 16:07   ` Christophe Leroy
2020-03-31  2:41     ` Christopher M Riedl
2020-04-18 10:36   ` Christophe Leroy
2020-03-23  4:52 ` [RFC PATCH 2/3] powerpc/lib: Initialize a temporary mm for code patching Christopher M. Riedl
2020-03-24 16:10   ` Christophe Leroy
2020-03-31  3:19     ` Christopher M Riedl
2020-04-08 11:01       ` Christophe Leroy
2020-04-15  4:39         ` Christopher M Riedl
2020-04-17  0:57         ` Michael Ellerman
2020-04-24 13:11           ` Steven Rostedt
2020-03-23  4:52 ` [RFC PATCH 3/3] powerpc/lib: Use " Christopher M. Riedl
2020-03-24 16:25   ` Christophe Leroy
2020-04-15  5:11     ` Christopher M Riedl
2020-04-15  8:45       ` Christophe Leroy
2020-04-15 16:24         ` Christopher M Riedl
2020-03-23 11:30 ` [RFC PATCH 0/3] Use per-CPU temporary mappings for patching Christophe Leroy
2020-03-23 14:04   ` Christophe Leroy
     [not found]     ` <738663735.45060.1584982175261@privateemail.com>
2020-03-23 16:59       ` Christophe Leroy
2020-03-24 16:02     ` Christophe Leroy
2020-03-25  2:51 ` Andrew Donnellan

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=20200323045205.20314-1-cmr@informatik.wtf \
    --to=cmr@informatik.wtf \
    --cc=linuxppc-dev@ozlabs.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: link
Be 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.