qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v1 RFC Zisslpcfi 0/9] zimops and zisslpcfi extension to riscv


From: Deepak Gupta
Subject: [PATCH v1 RFC Zisslpcfi 0/9] zimops and zisslpcfi extension to riscv
Date: Wed, 8 Feb 2023 22:29:38 -0800

Still learning to use git send-mail. Hopefully this time cover-letter
also reaches everyone.

I am sending this patch series as RFC for an extension which helps
software enforce control-flow integrity (cfi) on riscv CPUs. Currently
spec is called zisslpcfi spec - https://github.com/riscv/riscv-cfi.
This literally means "unprivileged integer shadow stack & landing pad
based cfi".

Sending this as RFC because
- Even though I dont expect major change in zimops, it's still on the stove.
- zisslpcfi is tied up nicely still being worked on.
- I would like eyeballing on indirect branch tracking implementation.

zisslpcfi (CFI) extends ISA in following manner:

Forward cfi (indirect call/jmp)
- Landing pad instruction requirement for indirect call/jmp
  All indirect call and jump must land on landing pad instruction `lpcll`
  else CPU will raise illegal instruction exception. `lpcll` stands for
  land pad check lower label.

- Static label (25bit label) checking instructions for indirect call/jmp
  Extension provides mechanism using which a compiler generated label
  value can be set in a designated CSR at call site and it can be checked
  at the call target. If mismatch happens, CPU will raise illegal
  instruction exception. Compiler can generate hash based on function
  signature type. Extension provide mechanisms using which label value
  is part of the instruction itself as immediate and thus has static
  immutable property.

Backward cfi (returns)
- Shadow stack (SS) for function returns
  Extension provides sspush x1/x5, sspop x1/x5 and sschkra instructions.
  sspush will push on shadow stack while sspop will pop from shadow stack
  sschkra will succeed only when x1 == x5 is true else it will raise
  illegal instruction exception. Shadow stacks introduces new virtual
  memory type and thus new PTE encodings. Existing reserved encoding of
  R=0,W=1,X=0 is now shadow stack PTE encoding (only if backward cfi is
  enabled for current mode). New virtual memory type allows CPU to
  distinguish so that stores coming from sspush or ssamoswap can succeed
  while regular stores raise access violations.

opcodes:
zisslpcfi opcodes are carved out of new opcode encodings. These opcodes
encodings were reserved until now. A new extension called zimops make
these opcodes into "may be operations". zimops stands for unprivileged
may be operations (mops) and if implemented default behavior is to mov 0
to rd. zisslpcfi extension changes executable in a way where it should be
able to run on riscv cpu which implements cfi extension as well as riscv
cpu which doesn't implement cfi extension. As long as zimops is
implemented, all such instructions will not fault and simply move 0 to rd.
A hart implementing cfi must implement zimops. Any future extension can
re-purpose zimops to change behavior and claim them while also not
breaking binary/executable compatiblity . zisslpcfi is first such
extension to modify zimops behavior.

Instructions:
zisslpcfi defines following instructions.

Backward control flow
*********************

sspush x1/x5:
Decrement shadow stack pointer and pushes x1 or x5 on shadow stack.

sspop x1/x5:
Pops from shadow stack into x1 or x5. Increments shadow stack pointer.

ssprr:
Reads current shadow stack pointer into a destination register.

sschckra:
Compares x1 with x5. Raises illegal instr exception if x1 != x5.

ssamoswap:
Atomically swaps value on top of shadow stack.


Forward control flow
********************
Forward control flow extends architecture to allow software to set labels
(25bits of label) at call/jmp site and check labels at target. Extension
gives instructions to set label as part of immediate in instruction itself
. Since immediate is limited in terms of bit length, labels are set and
checked in ladder fashion of 9, 8 and 8 bits.

lpsll, lpsml, lpsul:
sets lower (9bit), mid (8bit) and upper (8bit) label values in CSR_LPLR
respectively.

lpcll, lpcml, lpcul:
checks lower (9bit), mid (8bit) and upper (8bit) label values with
CSR_LPLR respectively. Check label instructions raise illegal instruction
fault when labels mismatch. `lpcll` has dual purpose; it acts as landing
pad instruction as well label checking for lower 9 bits.

More on shadow stack
********************
Shadow stacks have new encodings (R=0,W=1,X=0) in first level page tables
to ensure they can be writeable only via special shadow stack management
instructions and regular stores are disallowed. Regular stores on shadow
stack memory raise AMO/store access fault. Shadow stack load (sspop) on
non-shadow stack memory raise load access fault. Shadow stack store
(sspush) on non-shadow stack memory raise store access fault.

To provide each mode their own shadow stack translations, this
implementation flushes shadow stack translations on privilege change and
thus each mode keep their own translation as long as mode doesn't change.
Shadow stack accesses need to coexist with normal accesses, but have
different permission checks. Since hypervisor access instructions and
shadow stack accesses are mutually exclusive (both use dedicated
instructions), they don't need independent bits in the MMU index assignments.

Tests and other bits
********************
For convenience this patch is based on below qemu branch
https://github.com/deepak0414/qemu/tree/scfi_menvcfg_gh_Zisslpcfi-0.1

I've been able to boot linux kernel using this implementation and run
test apps. Kernel branch I am using is below
https://github.com/deepak0414/linux-riscv-cfi/tree/Zisslpcfi-0.4_v6.1-rc2

In order to perform unit-tests, I've been using riscv-test and created
unit tests to test implementation. riscv-tests branch URL is below
https://github.com/deepak0414/riscv-tests/tree/cfi_tests

Deepak Gupta (9):
  target/riscv: adding zimops and zisslpcfi extension to RISCV cpu
    config
  target/riscv: zisslpcfi CSR, bit positions and other definitions
  target/riscv: implements CSRs and new bits in existing CSRs in
    zisslpcfi
  target/riscv: helper functions for forward and backward cfi
  target/riscv: state save and restore of zisslppcfi state
  target/riscv: MMU changes for back cfi's shadow stack
  target/riscv: Tracking indirect branches (fcfi) using TCG
  target/riscv: Instructions encodings, implementation and handlers
  target/riscv: diassembly support for zisslpcfi instructions

 disas/riscv.c                                 | 127 ++++++-
 target/riscv/cpu-param.h                      |   1 +
 target/riscv/cpu.c                            |  15 +
 target/riscv/cpu.h                            |  15 +
 target/riscv/cpu_bits.h                       |  40 +++
 target/riscv/cpu_helper.c                     | 196 +++++++++--
 target/riscv/csr.c                            | 137 +++++++-
 target/riscv/helper.h                         |   7 +
 target/riscv/insn32.decode                    |  29 ++
 target/riscv/insn_trans/trans_rvi.c.inc       |  14 +
 target/riscv/insn_trans/trans_zimops.c.inc    |  53 +++
 target/riscv/insn_trans/trans_zisslpcfi.c.inc | 310 ++++++++++++++++++
 target/riscv/op_helper.c                      |  79 +++++
 target/riscv/pmp.c                            |   9 +
 target/riscv/pmp.h                            |   3 +-
 target/riscv/translate.c                      |  54 +++
 16 files changed, 1067 insertions(+), 22 deletions(-)
 create mode 100644 target/riscv/insn_trans/trans_zimops.c.inc
 create mode 100644 target/riscv/insn_trans/trans_zisslpcfi.c.inc

-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]