Skip to content

Commit cee73b1

Browse files
committed
Merge tag 'riscv-for-linus-7.0-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux
Pull RISC-V updates from Paul Walmsley: - Add support for control flow integrity for userspace processes. This is based on the standard RISC-V ISA extensions Zicfiss and Zicfilp - Improve ptrace behavior regarding vector registers, and add some selftests - Optimize our strlen() assembly - Enable the ISO-8859-1 code page as built-in, similar to ARM64, for EFI volume mounting - Clean up some code slightly, including defining copy_user_page() as copy_page() rather than memcpy(), aligning us with other architectures; and using max3() to slightly simplify an expression in riscv_iommu_init_check() * tag 'riscv-for-linus-7.0-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (42 commits) riscv: lib: optimize strlen loop efficiency selftests: riscv: vstate_exec_nolibc: Use the regular prctl() function selftests: riscv: verify ptrace accepts valid vector csr values selftests: riscv: verify ptrace rejects invalid vector csr inputs selftests: riscv: verify syscalls discard vector context selftests: riscv: verify initial vector state with ptrace selftests: riscv: test ptrace vector interface riscv: ptrace: validate input vector csr registers riscv: csr: define vtype register elements riscv: vector: init vector context with proper vlenb riscv: ptrace: return ENODATA for inactive vector extension kselftest/riscv: add kselftest for user mode CFI riscv: add documentation for shadow stack riscv: add documentation for landing pad / indirect branch tracking riscv: create a Kconfig fragment for shadow stack and landing pad support arch/riscv: add dual vdso creation logic and select vdso based on hw arch/riscv: compile vdso with landing pad and shadow stack note riscv: enable kernel access to shadow stack memory via the FWFT SBI call riscv: add kernel command line option to opt out of user CFI riscv/hwprobe: add zicfilp / zicfiss enumeration in hwprobe ...
2 parents 7563f7e + 18be4ca commit cee73b1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+3655
-122
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6641,6 +6641,14 @@ Kernel parameters
66416641
replacement properties are not found. See the Kconfig
66426642
entry for RISCV_ISA_FALLBACK.
66436643

6644+
riscv_nousercfi=
6645+
all Disable user CFI ABI to userspace even if cpu extension
6646+
are available.
6647+
bcfi Disable user backward CFI ABI to userspace even if
6648+
the shadow stack extension is available.
6649+
fcfi Disable user forward CFI ABI to userspace even if the
6650+
landing pad extension is available.
6651+
66446652
ro [KNL] Mount root device read-only on boot
66456653

66466654
rodata= [KNL,EARLY]

Documentation/arch/riscv/hwprobe.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ The following keys are defined:
6767
programs (it may still be executed in userspace via a
6868
kernel-controlled mechanism such as the vDSO).
6969

70-
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0`: A bitmask containing the extensions
70+
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0`: A bitmask containing extensions
7171
that are compatible with the :c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`:
7272
base system behavior.
7373

@@ -387,3 +387,7 @@ The following keys are defined:
387387

388388
* :c:macro:`RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE`: An unsigned int which
389389
represents the size of the Zicbop block in bytes.
390+
391+
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_1`: A bitmask containing additional
392+
extensions that are compatible with the
393+
:c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`: base system behavior.

Documentation/arch/riscv/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,7 @@ RISC-V architecture
1414
uabi
1515
vector
1616
cmodx
17+
zicfilp
18+
zicfiss
1719

1820
features
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
:Author: Deepak Gupta <debug@rivosinc.com>
4+
:Date: 12 January 2024
5+
6+
====================================================
7+
Tracking indirect control transfers on RISC-V Linux
8+
====================================================
9+
10+
This document briefly describes the interface provided to userspace by Linux
11+
to enable indirect branch tracking for user mode applications on RISC-V.
12+
13+
1. Feature Overview
14+
--------------------
15+
16+
Memory corruption issues usually result in crashes. However, in the
17+
hands of a creative adversary, these can result in a variety of
18+
security issues.
19+
20+
Some of those security issues can be code re-use attacks, where an
21+
adversary can use corrupt function pointers, chaining them together to
22+
perform jump oriented programming (JOP) or call oriented programming
23+
(COP) and thus compromise control flow integrity (CFI) of the program.
24+
25+
Function pointers live in read-write memory and thus are susceptible
26+
to corruption. This can allow an adversary to control the program
27+
counter (PC) value. On RISC-V, the zicfilp extension enforces a
28+
restriction on such indirect control transfers:
29+
30+
- Indirect control transfers must land on a landing pad instruction ``lpad``.
31+
There are two exceptions to this rule:
32+
33+
- rs1 = x1 or rs1 = x5, i.e. a return from a function and returns are
34+
protected using shadow stack (see zicfiss.rst)
35+
36+
- rs1 = x7. On RISC-V, the compiler usually does the following to reach a
37+
function which is beyond the offset of possible J-type instruction::
38+
39+
auipc x7, <imm>
40+
jalr (x7)
41+
42+
This form of indirect control transfer is immutable and doesn't
43+
rely on memory. Thus rs1=x7 is exempted from tracking and
44+
these are considered software guarded jumps.
45+
46+
The ``lpad`` instruction is a pseudo-op of ``auipc rd, <imm_20bit>``
47+
with ``rd=x0``. This is a HINT op. The ``lpad`` instruction must be
48+
aligned on a 4 byte boundary. It compares the 20 bit immediate with
49+
x7. If ``imm_20bit`` == 0, the CPU doesn't perform any comparison with
50+
``x7``. If ``imm_20bit`` != 0, then ``imm_20bit`` must match ``x7``
51+
else CPU will raise ``software check exception`` (``cause=18``) with
52+
``*tval = 2``.
53+
54+
The compiler can generate a hash over function signatures and set them
55+
up (truncated to 20 bits) in x7 at callsites. Function prologues can
56+
have ``lpad`` instructions encoded with the same function hash. This
57+
further reduces the number of valid program counter addresses a call
58+
site can reach.
59+
60+
2. ELF and psABI
61+
-----------------
62+
63+
The toolchain sets up :c:macro:`GNU_PROPERTY_RISCV_FEATURE_1_FCFI` for
64+
property :c:macro:`GNU_PROPERTY_RISCV_FEATURE_1_AND` in the notes
65+
section of the object file.
66+
67+
3. Linux enabling
68+
------------------
69+
70+
User space programs can have multiple shared objects loaded in their
71+
address spaces. It's a difficult task to make sure all the
72+
dependencies have been compiled with indirect branch support. Thus
73+
it's left to the dynamic loader to enable indirect branch tracking for
74+
the program.
75+
76+
4. prctl() enabling
77+
--------------------
78+
79+
:c:macro:`PR_SET_INDIR_BR_LP_STATUS` / :c:macro:`PR_GET_INDIR_BR_LP_STATUS` /
80+
:c:macro:`PR_LOCK_INDIR_BR_LP_STATUS` are three prctls added to manage indirect
81+
branch tracking. These prctls are architecture-agnostic and return -EINVAL if
82+
the underlying functionality is not supported.
83+
84+
* prctl(PR_SET_INDIR_BR_LP_STATUS, unsigned long arg)
85+
86+
If arg1 is :c:macro:`PR_INDIR_BR_LP_ENABLE` and if CPU supports
87+
``zicfilp`` then the kernel will enable indirect branch tracking for the
88+
task. The dynamic loader can issue this :c:macro:`prctl` once it has
89+
determined that all the objects loaded in the address space support
90+
indirect branch tracking. Additionally, if there is a `dlopen` to an
91+
object which wasn't compiled with ``zicfilp``, the dynamic loader can
92+
issue this prctl with arg1 set to 0 (i.e. :c:macro:`PR_INDIR_BR_LP_ENABLE`
93+
cleared).
94+
95+
* prctl(PR_GET_INDIR_BR_LP_STATUS, unsigned long * arg)
96+
97+
Returns the current status of indirect branch tracking. If enabled
98+
it'll return :c:macro:`PR_INDIR_BR_LP_ENABLE`
99+
100+
* prctl(PR_LOCK_INDIR_BR_LP_STATUS, unsigned long arg)
101+
102+
Locks the current status of indirect branch tracking on the task. User
103+
space may want to run with a strict security posture and wouldn't want
104+
loading of objects without ``zicfilp`` support in them, to disallow
105+
disabling of indirect branch tracking. In this case, user space can
106+
use this prctl to lock the current settings.
107+
108+
5. violations related to indirect branch tracking
109+
--------------------------------------------------
110+
111+
Pertaining to indirect branch tracking, the CPU raises a software
112+
check exception in the following conditions:
113+
114+
- missing ``lpad`` after indirect call / jmp
115+
- ``lpad`` not on 4 byte boundary
116+
- ``imm_20bit`` embedded in ``lpad`` instruction doesn't match with ``x7``
117+
118+
In all 3 cases, ``*tval = 2`` is captured and software check exception is
119+
raised (``cause=18``).
120+
121+
The kernel will treat this as :c:macro:`SIGSEGV` with code =
122+
:c:macro:`SEGV_CPERR` and follow the normal course of signal delivery.
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
:Author: Deepak Gupta <debug@rivosinc.com>
4+
:Date: 12 January 2024
5+
6+
=========================================================
7+
Shadow stack to protect function returns on RISC-V Linux
8+
=========================================================
9+
10+
This document briefly describes the interface provided to userspace by Linux
11+
to enable shadow stacks for user mode applications on RISC-V.
12+
13+
1. Feature Overview
14+
--------------------
15+
16+
Memory corruption issues usually result in crashes. However, in the
17+
hands of a creative adversary, these issues can result in a variety of
18+
security problems.
19+
20+
Some of those security issues can be code re-use attacks on programs
21+
where an adversary can use corrupt return addresses present on the
22+
stack. chaining them together to perform return oriented programming
23+
(ROP) and thus compromising the control flow integrity (CFI) of the
24+
program.
25+
26+
Return addresses live on the stack in read-write memory. Therefore
27+
they are susceptible to corruption, which allows an adversary to
28+
control the program counter. On RISC-V, the ``zicfiss`` extension
29+
provides an alternate stack (the "shadow stack") on which return
30+
addresses can be safely placed in the prologue of the function and
31+
retrieved in the epilogue. The ``zicfiss`` extension makes the
32+
following changes:
33+
34+
- PTE encodings for shadow stack virtual memory
35+
An earlier reserved encoding in first stage translation i.e.
36+
PTE.R=0, PTE.W=1, PTE.X=0 becomes the PTE encoding for shadow stack pages.
37+
38+
- The ``sspush x1/x5`` instruction pushes (stores) ``x1/x5`` to shadow stack.
39+
40+
- The ``sspopchk x1/x5`` instruction pops (loads) from shadow stack and compares
41+
with ``x1/x5`` and if not equal, the CPU raises a ``software check exception``
42+
with ``*tval = 3``
43+
44+
The compiler toolchain ensures that function prologues have ``sspush
45+
x1/x5`` to save the return address on shadow stack in addition to the
46+
regular stack. Similarly, function epilogues have ``ld x5,
47+
offset(x2)`` followed by ``sspopchk x5`` to ensure that a popped value
48+
from the regular stack matches with the popped value from the shadow
49+
stack.
50+
51+
2. Shadow stack protections and linux memory manager
52+
-----------------------------------------------------
53+
54+
As mentioned earlier, shadow stacks get new page table encodings that
55+
have some special properties assigned to them, along with instructions
56+
that operate on the shadow stacks:
57+
58+
- Regular stores to shadow stack memory raise store access faults. This
59+
protects shadow stack memory from stray writes.
60+
61+
- Regular loads from shadow stack memory are allowed. This allows
62+
stack trace utilities or backtrace functions to read the true call
63+
stack and ensure that it has not been tampered with.
64+
65+
- Only shadow stack instructions can generate shadow stack loads or
66+
shadow stack stores.
67+
68+
- Shadow stack loads and stores on read-only memory raise AMO/store
69+
page faults. Thus both ``sspush x1/x5`` and ``sspopchk x1/x5`` will
70+
raise AMO/store page fault. This simplies COW handling in kernel
71+
during fork(). The kernel can convert shadow stack pages into
72+
read-only memory (as it does for regular read-write memory). As
73+
soon as subsequent ``sspush`` or ``sspopchk`` instructions in
74+
userspace are encountered, the kernel can perform COW.
75+
76+
- Shadow stack loads and stores on read-write or read-write-execute
77+
memory raise an access fault. This is a fatal condition because
78+
shadow stack loads and stores should never be operating on
79+
read-write or read-write-execute memory.
80+
81+
3. ELF and psABI
82+
-----------------
83+
84+
The toolchain sets up :c:macro:`GNU_PROPERTY_RISCV_FEATURE_1_BCFI` for
85+
property :c:macro:`GNU_PROPERTY_RISCV_FEATURE_1_AND` in the notes
86+
section of the object file.
87+
88+
4. Linux enabling
89+
------------------
90+
91+
User space programs can have multiple shared objects loaded in their
92+
address space. It's a difficult task to make sure all the
93+
dependencies have been compiled with shadow stack support. Thus
94+
it's left to the dynamic loader to enable shadow stacks for the
95+
program.
96+
97+
5. prctl() enabling
98+
--------------------
99+
100+
:c:macro:`PR_SET_SHADOW_STACK_STATUS` / :c:macro:`PR_GET_SHADOW_STACK_STATUS` /
101+
:c:macro:`PR_LOCK_SHADOW_STACK_STATUS` are three prctls added to manage shadow
102+
stack enabling for tasks. These prctls are architecture-agnostic and return
103+
-EINVAL if not implemented.
104+
105+
* prctl(PR_SET_SHADOW_STACK_STATUS, unsigned long arg)
106+
107+
If arg = :c:macro:`PR_SHADOW_STACK_ENABLE` and if CPU supports
108+
``zicfiss`` then the kernel will enable shadow stacks for the task.
109+
The dynamic loader can issue this :c:macro:`prctl` once it has
110+
determined that all the objects loaded in address space have support
111+
for shadow stacks. Additionally, if there is a :c:macro:`dlopen` to
112+
an object which wasn't compiled with ``zicfiss``, the dynamic loader
113+
can issue this prctl with arg set to 0 (i.e.
114+
:c:macro:`PR_SHADOW_STACK_ENABLE` being clear)
115+
116+
* prctl(PR_GET_SHADOW_STACK_STATUS, unsigned long * arg)
117+
118+
Returns the current status of indirect branch tracking. If enabled
119+
it'll return :c:macro:`PR_SHADOW_STACK_ENABLE`.
120+
121+
* prctl(PR_LOCK_SHADOW_STACK_STATUS, unsigned long arg)
122+
123+
Locks the current status of shadow stack enabling on the
124+
task. Userspace may want to run with a strict security posture and
125+
wouldn't want loading of objects without ``zicfiss`` support. In this
126+
case userspace can use this prctl to disallow disabling of shadow
127+
stacks on the current task.
128+
129+
5. violations related to returns with shadow stack enabled
130+
-----------------------------------------------------------
131+
132+
Pertaining to shadow stacks, the CPU raises a ``software check
133+
exception`` upon executing ``sspopchk x1/x5`` if ``x1/x5`` doesn't
134+
match the top of shadow stack. If a mismatch happens, then the CPU
135+
sets ``*tval = 3`` and raises the exception.
136+
137+
The Linux kernel will treat this as a :c:macro:`SIGSEGV` with code =
138+
:c:macro:`SEGV_CPERR` and follow the normal course of signal delivery.
139+
140+
6. Shadow stack tokens
141+
-----------------------
142+
143+
Regular stores on shadow stacks are not allowed and thus can't be
144+
tampered with via arbitrary stray writes. However, one method of
145+
pivoting / switching to a shadow stack is simply writing to the CSR
146+
``CSR_SSP``. This will change the active shadow stack for the
147+
program. Writes to ``CSR_SSP`` in the program should be mostly
148+
limited to context switches, stack unwinds, or longjmp or similar
149+
mechanisms (like context switching of Green Threads) in languages like
150+
Go and Rust. CSR_SSP writes can be problematic because an attacker can
151+
use memory corruption bugs and leverage context switching routines to
152+
pivot to any shadow stack. Shadow stack tokens can help mitigate this
153+
problem by making sure that:
154+
155+
- When software is switching away from a shadow stack, the shadow
156+
stack pointer should be saved on the shadow stack itself (this is
157+
called the ``shadow stack token``).
158+
159+
- When software is switching to a shadow stack, it should read the
160+
``shadow stack token`` from the shadow stack pointer and verify that
161+
the ``shadow stack token`` itself is a pointer to the shadow stack
162+
itself.
163+
164+
- Once the token verification is done, software can perform the write
165+
to ``CSR_SSP`` to switch shadow stacks.
166+
167+
Here "software" could refer to the user mode task runtime itself,
168+
managing various contexts as part of a single thread. Or "software"
169+
could refer to the kernel, when the kernel has to deliver a signal to
170+
a user task and must save the shadow stack pointer. The kernel can
171+
perform similar procedure itself by saving a token on the user mode
172+
task's shadow stack. This way, whenever :c:macro:`sigreturn` happens,
173+
the kernel can read and verify the token and then switch to the shadow
174+
stack. Using this mechanism, the kernel helps the user task so that
175+
any corruption issue in the user task is not exploited by adversaries
176+
arbitrarily using :c:macro:`sigreturn`. Adversaries will have to make
177+
sure that there is a valid ``shadow stack token`` in addition to
178+
invoking :c:macro:`sigreturn`.
179+
180+
7. Signal shadow stack
181+
-----------------------
182+
The following structure has been added to sigcontext for RISC-V::
183+
184+
struct __sc_riscv_cfi_state {
185+
unsigned long ss_ptr;
186+
};
187+
188+
As part of signal delivery, the shadow stack token is saved on the
189+
current shadow stack itself. The updated pointer is saved away in the
190+
:c:macro:`ss_ptr` field in :c:macro:`__sc_riscv_cfi_state` under
191+
:c:macro:`sigcontext`. The existing shadow stack allocation is used
192+
for signal delivery. During :c:macro:`sigreturn`, kernel will obtain
193+
:c:macro:`ss_ptr` from :c:macro:`sigcontext`, verify the saved
194+
token on the shadow stack, and switch the shadow stack.

Documentation/devicetree/bindings/riscv/extensions.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,20 @@ properties:
589589
The standard Zicboz extension for cache-block zeroing as ratified
590590
in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
591591

592+
- const: zicfilp
593+
description: |
594+
The standard Zicfilp extension for enforcing forward edge
595+
control-flow integrity as ratified in commit 3f8e450 ("merge
596+
pull request #227 from ved-rivos/0709") of riscv-cfi
597+
github repo.
598+
599+
- const: zicfiss
600+
description: |
601+
The standard Zicfiss extension for enforcing backward edge
602+
control-flow integrity as ratified in commit 3f8e450 ("merge
603+
pull request #227 from ved-rivos/0709") of riscv-cfi
604+
github repo.
605+
592606
- const: zicntr
593607
description:
594608
The standard Zicntr extension for base counters and timers, as

0 commit comments

Comments
 (0)