mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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 ...
This commit is contained in:
@@ -6641,6 +6641,14 @@ Kernel parameters
|
||||
replacement properties are not found. See the Kconfig
|
||||
entry for RISCV_ISA_FALLBACK.
|
||||
|
||||
riscv_nousercfi=
|
||||
all Disable user CFI ABI to userspace even if cpu extension
|
||||
are available.
|
||||
bcfi Disable user backward CFI ABI to userspace even if
|
||||
the shadow stack extension is available.
|
||||
fcfi Disable user forward CFI ABI to userspace even if the
|
||||
landing pad extension is available.
|
||||
|
||||
ro [KNL] Mount root device read-only on boot
|
||||
|
||||
rodata= [KNL,EARLY]
|
||||
|
||||
@@ -67,7 +67,7 @@ The following keys are defined:
|
||||
programs (it may still be executed in userspace via a
|
||||
kernel-controlled mechanism such as the vDSO).
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0`: A bitmask containing the extensions
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_0`: A bitmask containing extensions
|
||||
that are compatible with the :c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`:
|
||||
base system behavior.
|
||||
|
||||
@@ -387,3 +387,7 @@ The following keys are defined:
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE`: An unsigned int which
|
||||
represents the size of the Zicbop block in bytes.
|
||||
|
||||
* :c:macro:`RISCV_HWPROBE_KEY_IMA_EXT_1`: A bitmask containing additional
|
||||
extensions that are compatible with the
|
||||
:c:macro:`RISCV_HWPROBE_BASE_BEHAVIOR_IMA`: base system behavior.
|
||||
|
||||
@@ -14,5 +14,7 @@ RISC-V architecture
|
||||
uabi
|
||||
vector
|
||||
cmodx
|
||||
zicfilp
|
||||
zicfiss
|
||||
|
||||
features
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
:Author: Deepak Gupta <debug@rivosinc.com>
|
||||
:Date: 12 January 2024
|
||||
|
||||
====================================================
|
||||
Tracking indirect control transfers on RISC-V Linux
|
||||
====================================================
|
||||
|
||||
This document briefly describes the interface provided to userspace by Linux
|
||||
to enable indirect branch tracking for user mode applications on RISC-V.
|
||||
|
||||
1. Feature Overview
|
||||
--------------------
|
||||
|
||||
Memory corruption issues usually result in crashes. However, in the
|
||||
hands of a creative adversary, these can result in a variety of
|
||||
security issues.
|
||||
|
||||
Some of those security issues can be code re-use attacks, where an
|
||||
adversary can use corrupt function pointers, chaining them together to
|
||||
perform jump oriented programming (JOP) or call oriented programming
|
||||
(COP) and thus compromise control flow integrity (CFI) of the program.
|
||||
|
||||
Function pointers live in read-write memory and thus are susceptible
|
||||
to corruption. This can allow an adversary to control the program
|
||||
counter (PC) value. On RISC-V, the zicfilp extension enforces a
|
||||
restriction on such indirect control transfers:
|
||||
|
||||
- Indirect control transfers must land on a landing pad instruction ``lpad``.
|
||||
There are two exceptions to this rule:
|
||||
|
||||
- rs1 = x1 or rs1 = x5, i.e. a return from a function and returns are
|
||||
protected using shadow stack (see zicfiss.rst)
|
||||
|
||||
- rs1 = x7. On RISC-V, the compiler usually does the following to reach a
|
||||
function which is beyond the offset of possible J-type instruction::
|
||||
|
||||
auipc x7, <imm>
|
||||
jalr (x7)
|
||||
|
||||
This form of indirect control transfer is immutable and doesn't
|
||||
rely on memory. Thus rs1=x7 is exempted from tracking and
|
||||
these are considered software guarded jumps.
|
||||
|
||||
The ``lpad`` instruction is a pseudo-op of ``auipc rd, <imm_20bit>``
|
||||
with ``rd=x0``. This is a HINT op. The ``lpad`` instruction must be
|
||||
aligned on a 4 byte boundary. It compares the 20 bit immediate with
|
||||
x7. If ``imm_20bit`` == 0, the CPU doesn't perform any comparison with
|
||||
``x7``. If ``imm_20bit`` != 0, then ``imm_20bit`` must match ``x7``
|
||||
else CPU will raise ``software check exception`` (``cause=18``) with
|
||||
``*tval = 2``.
|
||||
|
||||
The compiler can generate a hash over function signatures and set them
|
||||
up (truncated to 20 bits) in x7 at callsites. Function prologues can
|
||||
have ``lpad`` instructions encoded with the same function hash. This
|
||||
further reduces the number of valid program counter addresses a call
|
||||
site can reach.
|
||||
|
||||
2. ELF and psABI
|
||||
-----------------
|
||||
|
||||
The toolchain sets up :c:macro:`GNU_PROPERTY_RISCV_FEATURE_1_FCFI` for
|
||||
property :c:macro:`GNU_PROPERTY_RISCV_FEATURE_1_AND` in the notes
|
||||
section of the object file.
|
||||
|
||||
3. Linux enabling
|
||||
------------------
|
||||
|
||||
User space programs can have multiple shared objects loaded in their
|
||||
address spaces. It's a difficult task to make sure all the
|
||||
dependencies have been compiled with indirect branch support. Thus
|
||||
it's left to the dynamic loader to enable indirect branch tracking for
|
||||
the program.
|
||||
|
||||
4. prctl() enabling
|
||||
--------------------
|
||||
|
||||
:c:macro:`PR_SET_INDIR_BR_LP_STATUS` / :c:macro:`PR_GET_INDIR_BR_LP_STATUS` /
|
||||
:c:macro:`PR_LOCK_INDIR_BR_LP_STATUS` are three prctls added to manage indirect
|
||||
branch tracking. These prctls are architecture-agnostic and return -EINVAL if
|
||||
the underlying functionality is not supported.
|
||||
|
||||
* prctl(PR_SET_INDIR_BR_LP_STATUS, unsigned long arg)
|
||||
|
||||
If arg1 is :c:macro:`PR_INDIR_BR_LP_ENABLE` and if CPU supports
|
||||
``zicfilp`` then the kernel will enable indirect branch tracking for the
|
||||
task. The dynamic loader can issue this :c:macro:`prctl` once it has
|
||||
determined that all the objects loaded in the address space support
|
||||
indirect branch tracking. Additionally, if there is a `dlopen` to an
|
||||
object which wasn't compiled with ``zicfilp``, the dynamic loader can
|
||||
issue this prctl with arg1 set to 0 (i.e. :c:macro:`PR_INDIR_BR_LP_ENABLE`
|
||||
cleared).
|
||||
|
||||
* prctl(PR_GET_INDIR_BR_LP_STATUS, unsigned long * arg)
|
||||
|
||||
Returns the current status of indirect branch tracking. If enabled
|
||||
it'll return :c:macro:`PR_INDIR_BR_LP_ENABLE`
|
||||
|
||||
* prctl(PR_LOCK_INDIR_BR_LP_STATUS, unsigned long arg)
|
||||
|
||||
Locks the current status of indirect branch tracking on the task. User
|
||||
space may want to run with a strict security posture and wouldn't want
|
||||
loading of objects without ``zicfilp`` support in them, to disallow
|
||||
disabling of indirect branch tracking. In this case, user space can
|
||||
use this prctl to lock the current settings.
|
||||
|
||||
5. violations related to indirect branch tracking
|
||||
--------------------------------------------------
|
||||
|
||||
Pertaining to indirect branch tracking, the CPU raises a software
|
||||
check exception in the following conditions:
|
||||
|
||||
- missing ``lpad`` after indirect call / jmp
|
||||
- ``lpad`` not on 4 byte boundary
|
||||
- ``imm_20bit`` embedded in ``lpad`` instruction doesn't match with ``x7``
|
||||
|
||||
In all 3 cases, ``*tval = 2`` is captured and software check exception is
|
||||
raised (``cause=18``).
|
||||
|
||||
The kernel will treat this as :c:macro:`SIGSEGV` with code =
|
||||
:c:macro:`SEGV_CPERR` and follow the normal course of signal delivery.
|
||||
@@ -0,0 +1,194 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
:Author: Deepak Gupta <debug@rivosinc.com>
|
||||
:Date: 12 January 2024
|
||||
|
||||
=========================================================
|
||||
Shadow stack to protect function returns on RISC-V Linux
|
||||
=========================================================
|
||||
|
||||
This document briefly describes the interface provided to userspace by Linux
|
||||
to enable shadow stacks for user mode applications on RISC-V.
|
||||
|
||||
1. Feature Overview
|
||||
--------------------
|
||||
|
||||
Memory corruption issues usually result in crashes. However, in the
|
||||
hands of a creative adversary, these issues can result in a variety of
|
||||
security problems.
|
||||
|
||||
Some of those security issues can be code re-use attacks on programs
|
||||
where an adversary can use corrupt return addresses present on the
|
||||
stack. chaining them together to perform return oriented programming
|
||||
(ROP) and thus compromising the control flow integrity (CFI) of the
|
||||
program.
|
||||
|
||||
Return addresses live on the stack in read-write memory. Therefore
|
||||
they are susceptible to corruption, which allows an adversary to
|
||||
control the program counter. On RISC-V, the ``zicfiss`` extension
|
||||
provides an alternate stack (the "shadow stack") on which return
|
||||
addresses can be safely placed in the prologue of the function and
|
||||
retrieved in the epilogue. The ``zicfiss`` extension makes the
|
||||
following changes:
|
||||
|
||||
- PTE encodings for shadow stack virtual memory
|
||||
An earlier reserved encoding in first stage translation i.e.
|
||||
PTE.R=0, PTE.W=1, PTE.X=0 becomes the PTE encoding for shadow stack pages.
|
||||
|
||||
- The ``sspush x1/x5`` instruction pushes (stores) ``x1/x5`` to shadow stack.
|
||||
|
||||
- The ``sspopchk x1/x5`` instruction pops (loads) from shadow stack and compares
|
||||
with ``x1/x5`` and if not equal, the CPU raises a ``software check exception``
|
||||
with ``*tval = 3``
|
||||
|
||||
The compiler toolchain ensures that function prologues have ``sspush
|
||||
x1/x5`` to save the return address on shadow stack in addition to the
|
||||
regular stack. Similarly, function epilogues have ``ld x5,
|
||||
offset(x2)`` followed by ``sspopchk x5`` to ensure that a popped value
|
||||
from the regular stack matches with the popped value from the shadow
|
||||
stack.
|
||||
|
||||
2. Shadow stack protections and linux memory manager
|
||||
-----------------------------------------------------
|
||||
|
||||
As mentioned earlier, shadow stacks get new page table encodings that
|
||||
have some special properties assigned to them, along with instructions
|
||||
that operate on the shadow stacks:
|
||||
|
||||
- Regular stores to shadow stack memory raise store access faults. This
|
||||
protects shadow stack memory from stray writes.
|
||||
|
||||
- Regular loads from shadow stack memory are allowed. This allows
|
||||
stack trace utilities or backtrace functions to read the true call
|
||||
stack and ensure that it has not been tampered with.
|
||||
|
||||
- Only shadow stack instructions can generate shadow stack loads or
|
||||
shadow stack stores.
|
||||
|
||||
- Shadow stack loads and stores on read-only memory raise AMO/store
|
||||
page faults. Thus both ``sspush x1/x5`` and ``sspopchk x1/x5`` will
|
||||
raise AMO/store page fault. This simplies COW handling in kernel
|
||||
during fork(). The kernel can convert shadow stack pages into
|
||||
read-only memory (as it does for regular read-write memory). As
|
||||
soon as subsequent ``sspush`` or ``sspopchk`` instructions in
|
||||
userspace are encountered, the kernel can perform COW.
|
||||
|
||||
- Shadow stack loads and stores on read-write or read-write-execute
|
||||
memory raise an access fault. This is a fatal condition because
|
||||
shadow stack loads and stores should never be operating on
|
||||
read-write or read-write-execute memory.
|
||||
|
||||
3. ELF and psABI
|
||||
-----------------
|
||||
|
||||
The toolchain sets up :c:macro:`GNU_PROPERTY_RISCV_FEATURE_1_BCFI` for
|
||||
property :c:macro:`GNU_PROPERTY_RISCV_FEATURE_1_AND` in the notes
|
||||
section of the object file.
|
||||
|
||||
4. Linux enabling
|
||||
------------------
|
||||
|
||||
User space programs can have multiple shared objects loaded in their
|
||||
address space. It's a difficult task to make sure all the
|
||||
dependencies have been compiled with shadow stack support. Thus
|
||||
it's left to the dynamic loader to enable shadow stacks for the
|
||||
program.
|
||||
|
||||
5. prctl() enabling
|
||||
--------------------
|
||||
|
||||
:c:macro:`PR_SET_SHADOW_STACK_STATUS` / :c:macro:`PR_GET_SHADOW_STACK_STATUS` /
|
||||
:c:macro:`PR_LOCK_SHADOW_STACK_STATUS` are three prctls added to manage shadow
|
||||
stack enabling for tasks. These prctls are architecture-agnostic and return
|
||||
-EINVAL if not implemented.
|
||||
|
||||
* prctl(PR_SET_SHADOW_STACK_STATUS, unsigned long arg)
|
||||
|
||||
If arg = :c:macro:`PR_SHADOW_STACK_ENABLE` and if CPU supports
|
||||
``zicfiss`` then the kernel will enable shadow stacks for the task.
|
||||
The dynamic loader can issue this :c:macro:`prctl` once it has
|
||||
determined that all the objects loaded in address space have support
|
||||
for shadow stacks. Additionally, if there is a :c:macro:`dlopen` to
|
||||
an object which wasn't compiled with ``zicfiss``, the dynamic loader
|
||||
can issue this prctl with arg set to 0 (i.e.
|
||||
:c:macro:`PR_SHADOW_STACK_ENABLE` being clear)
|
||||
|
||||
* prctl(PR_GET_SHADOW_STACK_STATUS, unsigned long * arg)
|
||||
|
||||
Returns the current status of indirect branch tracking. If enabled
|
||||
it'll return :c:macro:`PR_SHADOW_STACK_ENABLE`.
|
||||
|
||||
* prctl(PR_LOCK_SHADOW_STACK_STATUS, unsigned long arg)
|
||||
|
||||
Locks the current status of shadow stack enabling on the
|
||||
task. Userspace may want to run with a strict security posture and
|
||||
wouldn't want loading of objects without ``zicfiss`` support. In this
|
||||
case userspace can use this prctl to disallow disabling of shadow
|
||||
stacks on the current task.
|
||||
|
||||
5. violations related to returns with shadow stack enabled
|
||||
-----------------------------------------------------------
|
||||
|
||||
Pertaining to shadow stacks, the CPU raises a ``software check
|
||||
exception`` upon executing ``sspopchk x1/x5`` if ``x1/x5`` doesn't
|
||||
match the top of shadow stack. If a mismatch happens, then the CPU
|
||||
sets ``*tval = 3`` and raises the exception.
|
||||
|
||||
The Linux kernel will treat this as a :c:macro:`SIGSEGV` with code =
|
||||
:c:macro:`SEGV_CPERR` and follow the normal course of signal delivery.
|
||||
|
||||
6. Shadow stack tokens
|
||||
-----------------------
|
||||
|
||||
Regular stores on shadow stacks are not allowed and thus can't be
|
||||
tampered with via arbitrary stray writes. However, one method of
|
||||
pivoting / switching to a shadow stack is simply writing to the CSR
|
||||
``CSR_SSP``. This will change the active shadow stack for the
|
||||
program. Writes to ``CSR_SSP`` in the program should be mostly
|
||||
limited to context switches, stack unwinds, or longjmp or similar
|
||||
mechanisms (like context switching of Green Threads) in languages like
|
||||
Go and Rust. CSR_SSP writes can be problematic because an attacker can
|
||||
use memory corruption bugs and leverage context switching routines to
|
||||
pivot to any shadow stack. Shadow stack tokens can help mitigate this
|
||||
problem by making sure that:
|
||||
|
||||
- When software is switching away from a shadow stack, the shadow
|
||||
stack pointer should be saved on the shadow stack itself (this is
|
||||
called the ``shadow stack token``).
|
||||
|
||||
- When software is switching to a shadow stack, it should read the
|
||||
``shadow stack token`` from the shadow stack pointer and verify that
|
||||
the ``shadow stack token`` itself is a pointer to the shadow stack
|
||||
itself.
|
||||
|
||||
- Once the token verification is done, software can perform the write
|
||||
to ``CSR_SSP`` to switch shadow stacks.
|
||||
|
||||
Here "software" could refer to the user mode task runtime itself,
|
||||
managing various contexts as part of a single thread. Or "software"
|
||||
could refer to the kernel, when the kernel has to deliver a signal to
|
||||
a user task and must save the shadow stack pointer. The kernel can
|
||||
perform similar procedure itself by saving a token on the user mode
|
||||
task's shadow stack. This way, whenever :c:macro:`sigreturn` happens,
|
||||
the kernel can read and verify the token and then switch to the shadow
|
||||
stack. Using this mechanism, the kernel helps the user task so that
|
||||
any corruption issue in the user task is not exploited by adversaries
|
||||
arbitrarily using :c:macro:`sigreturn`. Adversaries will have to make
|
||||
sure that there is a valid ``shadow stack token`` in addition to
|
||||
invoking :c:macro:`sigreturn`.
|
||||
|
||||
7. Signal shadow stack
|
||||
-----------------------
|
||||
The following structure has been added to sigcontext for RISC-V::
|
||||
|
||||
struct __sc_riscv_cfi_state {
|
||||
unsigned long ss_ptr;
|
||||
};
|
||||
|
||||
As part of signal delivery, the shadow stack token is saved on the
|
||||
current shadow stack itself. The updated pointer is saved away in the
|
||||
:c:macro:`ss_ptr` field in :c:macro:`__sc_riscv_cfi_state` under
|
||||
:c:macro:`sigcontext`. The existing shadow stack allocation is used
|
||||
for signal delivery. During :c:macro:`sigreturn`, kernel will obtain
|
||||
:c:macro:`ss_ptr` from :c:macro:`sigcontext`, verify the saved
|
||||
token on the shadow stack, and switch the shadow stack.
|
||||
@@ -589,6 +589,20 @@ properties:
|
||||
The standard Zicboz extension for cache-block zeroing as ratified
|
||||
in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
|
||||
|
||||
- const: zicfilp
|
||||
description: |
|
||||
The standard Zicfilp extension for enforcing forward edge
|
||||
control-flow integrity as ratified in commit 3f8e450 ("merge
|
||||
pull request #227 from ved-rivos/0709") of riscv-cfi
|
||||
github repo.
|
||||
|
||||
- const: zicfiss
|
||||
description: |
|
||||
The standard Zicfiss extension for enforcing backward edge
|
||||
control-flow integrity as ratified in commit 3f8e450 ("merge
|
||||
pull request #227 from ved-rivos/0709") of riscv-cfi
|
||||
github repo.
|
||||
|
||||
- const: zicntr
|
||||
description:
|
||||
The standard Zicntr extension for base counters and timers, as
|
||||
|
||||
@@ -1163,6 +1163,28 @@ config RANDOMIZE_BASE
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config RISCV_USER_CFI
|
||||
def_bool y
|
||||
bool "riscv userspace control flow integrity"
|
||||
depends on 64BIT && MMU && \
|
||||
$(cc-option,-mabi=lp64 -march=rv64ima_zicfiss_zicfilp -fcf-protection=full)
|
||||
depends on RISCV_ALTERNATIVE
|
||||
select RISCV_SBI
|
||||
select ARCH_HAS_USER_SHADOW_STACK
|
||||
select ARCH_USES_HIGH_VMA_FLAGS
|
||||
select DYNAMIC_SIGFRAME
|
||||
help
|
||||
Provides CPU-assisted control flow integrity to userspace tasks.
|
||||
Control flow integrity is provided by implementing shadow stack for
|
||||
backward edge and indirect branch tracking for forward edge.
|
||||
Shadow stack protection is a hardware feature that detects function
|
||||
return address corruption. This helps mitigate ROP attacks.
|
||||
Indirect branch tracking enforces that all indirect branches must land
|
||||
on a landing pad instruction else CPU will fault. This mitigates against
|
||||
JOP / COP attacks. Applications must be enabled to use it, and old userspace
|
||||
does not get protection "for free".
|
||||
default y.
|
||||
|
||||
endmenu # "Kernel features"
|
||||
|
||||
menu "Boot options"
|
||||
|
||||
+7
-1
@@ -81,9 +81,12 @@ riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZACAS) := $(riscv-march-y)_zacas
|
||||
# Check if the toolchain supports Zabha
|
||||
riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZABHA) := $(riscv-march-y)_zabha
|
||||
|
||||
KBUILD_BASE_ISA = -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)fd([^v_]*)v?/\1\2/')
|
||||
export KBUILD_BASE_ISA
|
||||
|
||||
# Remove F,D,V from isa string for all. Keep extensions between "fd" and "v" by
|
||||
# matching non-v and non-multi-letter extensions out with the filter ([^v_]*)
|
||||
KBUILD_CFLAGS += -march=$(shell echo $(riscv-march-y) | sed -E 's/(rv32ima|rv64ima)fd([^v_]*)v?/\1\2/')
|
||||
KBUILD_CFLAGS += $(KBUILD_BASE_ISA)
|
||||
|
||||
KBUILD_AFLAGS += -march=$(riscv-march-y)
|
||||
|
||||
@@ -158,6 +161,8 @@ ifeq ($(CONFIG_MMU),y)
|
||||
prepare: vdso_prepare
|
||||
vdso_prepare: prepare0
|
||||
$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h
|
||||
$(if $(CONFIG_RISCV_USER_CFI),$(Q)$(MAKE) \
|
||||
$(build)=arch/riscv/kernel/vdso_cfi include/generated/vdso-cfi-offsets.h)
|
||||
$(if $(CONFIG_COMPAT),$(Q)$(MAKE) \
|
||||
$(build)=arch/riscv/kernel/compat_vdso include/generated/compat_vdso-offsets.h)
|
||||
|
||||
@@ -165,6 +170,7 @@ endif
|
||||
endif
|
||||
|
||||
vdso-install-y += arch/riscv/kernel/vdso/vdso.so.dbg
|
||||
vdso-install-$(CONFIG_RISCV_USER_CFI) += arch/riscv/kernel/vdso_cfi/vdso-cfi.so.dbg
|
||||
vdso-install-$(CONFIG_COMPAT) += arch/riscv/kernel/compat_vdso/compat_vdso.so.dbg
|
||||
|
||||
BOOT_TARGETS := Image Image.gz Image.bz2 Image.lz4 Image.lzma Image.lzo Image.zst Image.xz loader loader.bin xipImage vmlinuz.efi
|
||||
|
||||
@@ -295,7 +295,7 @@ CONFIG_NFS_V4_2=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_9P_FS=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=m
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_SELINUX=y
|
||||
CONFIG_SECURITY_APPARMOR=y
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# RISCV specific kernel hardening options
|
||||
|
||||
# Enable control flow integrity support for usermode.
|
||||
CONFIG_RISCV_USER_CFI=y
|
||||
@@ -51,6 +51,7 @@ DECLARE_DO_ERROR_INFO(do_trap_ecall_u);
|
||||
DECLARE_DO_ERROR_INFO(do_trap_ecall_s);
|
||||
DECLARE_DO_ERROR_INFO(do_trap_ecall_m);
|
||||
DECLARE_DO_ERROR_INFO(do_trap_break);
|
||||
DECLARE_DO_ERROR_INFO(do_trap_software_check);
|
||||
|
||||
asmlinkage void ret_from_fork_kernel(void *fn_arg, int (*fn)(void *), struct pt_regs *regs);
|
||||
asmlinkage void ret_from_fork_user(struct pt_regs *regs);
|
||||
|
||||
@@ -80,3 +80,47 @@
|
||||
.endm
|
||||
|
||||
#endif /* __ASM_ASSEMBLER_H */
|
||||
|
||||
#if defined(VDSO_CFI) && (__riscv_xlen == 64)
|
||||
.macro vdso_lpad, label = 0
|
||||
lpad \label
|
||||
.endm
|
||||
#else
|
||||
.macro vdso_lpad, label = 0
|
||||
.endm
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This macro emits a program property note section identifying
|
||||
* architecture features which require special handling, mainly for
|
||||
* use in assembly files included in the VDSO.
|
||||
*/
|
||||
#define NT_GNU_PROPERTY_TYPE_0 5
|
||||
#define GNU_PROPERTY_RISCV_FEATURE_1_AND 0xc0000000
|
||||
|
||||
#define GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP BIT(0)
|
||||
#define GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS BIT(1)
|
||||
|
||||
#if defined(VDSO_CFI) && (__riscv_xlen == 64)
|
||||
#define GNU_PROPERTY_RISCV_FEATURE_1_DEFAULT \
|
||||
(GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP | GNU_PROPERTY_RISCV_FEATURE_1_ZICFISS)
|
||||
#endif
|
||||
|
||||
#ifdef GNU_PROPERTY_RISCV_FEATURE_1_DEFAULT
|
||||
.macro emit_riscv_feature_1_and, feat = GNU_PROPERTY_RISCV_FEATURE_1_DEFAULT
|
||||
.pushsection .note.gnu.property, "a"
|
||||
.p2align 3
|
||||
.word 4
|
||||
.word 16
|
||||
.word NT_GNU_PROPERTY_TYPE_0
|
||||
.asciz "GNU"
|
||||
.word GNU_PROPERTY_RISCV_FEATURE_1_AND
|
||||
.word 4
|
||||
.word \feat
|
||||
.word 0
|
||||
.popsection
|
||||
.endm
|
||||
#else
|
||||
.macro emit_riscv_feature_1_and, feat = 0
|
||||
.endm
|
||||
#endif
|
||||
|
||||
@@ -152,4 +152,16 @@ static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsi
|
||||
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
|
||||
}
|
||||
|
||||
static inline bool cpu_supports_shadow_stack(void)
|
||||
{
|
||||
return (IS_ENABLED(CONFIG_RISCV_USER_CFI) &&
|
||||
riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICFISS));
|
||||
}
|
||||
|
||||
static inline bool cpu_supports_indirect_br_lp_instr(void)
|
||||
{
|
||||
return (IS_ENABLED(CONFIG_RISCV_USER_CFI) &&
|
||||
riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICFILP));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,15 @@
|
||||
#define SR_MPP _AC(0x00001800, UL) /* Previously Machine */
|
||||
#define SR_SUM _AC(0x00040000, UL) /* Supervisor User Memory Access */
|
||||
|
||||
/* zicfilp landing pad status bit */
|
||||
#define SR_SPELP _AC(0x00800000, UL)
|
||||
#define SR_MPELP _AC(0x020000000000, UL)
|
||||
#ifdef CONFIG_RISCV_M_MODE
|
||||
#define SR_ELP SR_MPELP
|
||||
#else
|
||||
#define SR_ELP SR_SPELP
|
||||
#endif
|
||||
|
||||
#define SR_FS _AC(0x00006000, UL) /* Floating-point Status */
|
||||
#define SR_FS_OFF _AC(0x00000000, UL)
|
||||
#define SR_FS_INITIAL _AC(0x00002000, UL)
|
||||
@@ -212,6 +221,8 @@
|
||||
#define ENVCFG_PMM_PMLEN_16 (_AC(0x3, ULL) << 32)
|
||||
#define ENVCFG_CBZE (_AC(1, UL) << 7)
|
||||
#define ENVCFG_CBCFE (_AC(1, UL) << 6)
|
||||
#define ENVCFG_LPE (_AC(1, UL) << 2)
|
||||
#define ENVCFG_SSE (_AC(1, UL) << 3)
|
||||
#define ENVCFG_CBIE_SHIFT 4
|
||||
#define ENVCFG_CBIE (_AC(0x3, UL) << ENVCFG_CBIE_SHIFT)
|
||||
#define ENVCFG_CBIE_ILL _AC(0x0, UL)
|
||||
@@ -321,6 +332,9 @@
|
||||
#define CSR_STIMECMP 0x14D
|
||||
#define CSR_STIMECMPH 0x15D
|
||||
|
||||
/* zicfiss user mode csr. CSR_SSP holds current shadow stack pointer */
|
||||
#define CSR_SSP 0x011
|
||||
|
||||
/* xtheadvector symbolic CSR names */
|
||||
#define CSR_VXSAT 0x9
|
||||
#define CSR_VXRM 0xa
|
||||
@@ -444,6 +458,23 @@
|
||||
#define CSR_VTYPE 0xc21
|
||||
#define CSR_VLENB 0xc22
|
||||
|
||||
#define VTYPE_VLMUL _AC(7, UL)
|
||||
#define VTYPE_VLMUL_FRAC _AC(4, UL)
|
||||
#define VTYPE_VSEW_SHIFT 3
|
||||
#define VTYPE_VSEW (_AC(7, UL) << VTYPE_VSEW_SHIFT)
|
||||
#define VTYPE_VTA_SHIFT 6
|
||||
#define VTYPE_VTA (_AC(1, UL) << VTYPE_VTA_SHIFT)
|
||||
#define VTYPE_VMA_SHIFT 7
|
||||
#define VTYPE_VMA (_AC(1, UL) << VTYPE_VMA_SHIFT)
|
||||
#define VTYPE_VILL_SHIFT (__riscv_xlen - 1)
|
||||
#define VTYPE_VILL (_AC(1, UL) << VTYPE_VILL_SHIFT)
|
||||
|
||||
#define VTYPE_VLMUL_THEAD _AC(3, UL)
|
||||
#define VTYPE_VSEW_THEAD_SHIFT 2
|
||||
#define VTYPE_VSEW_THEAD (_AC(7, UL) << VTYPE_VSEW_THEAD_SHIFT)
|
||||
#define VTYPE_VEDIV_THEAD_SHIFT 5
|
||||
#define VTYPE_VEDIV_THEAD (_AC(3, UL) << VTYPE_VEDIV_THEAD_SHIFT)
|
||||
|
||||
/* Scalar Crypto Extension - Entropy */
|
||||
#define CSR_SEED 0x015
|
||||
#define SEED_OPST_MASK _AC(0xC0000000, UL)
|
||||
|
||||
@@ -40,4 +40,6 @@ static inline int handle_misaligned_store(struct pt_regs *regs)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool handle_user_cfi_violation(struct pt_regs *regs);
|
||||
|
||||
#endif /* _ASM_RISCV_ENTRY_COMMON_H */
|
||||
|
||||
@@ -110,6 +110,8 @@
|
||||
#define RISCV_ISA_EXT_ZALASR 101
|
||||
#define RISCV_ISA_EXT_ZILSD 102
|
||||
#define RISCV_ISA_EXT_ZCLSD 103
|
||||
#define RISCV_ISA_EXT_ZICFILP 104
|
||||
#define RISCV_ISA_EXT_ZICFISS 105
|
||||
|
||||
#define RISCV_ISA_EXT_XLINUXENVCFG 127
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <uapi/asm/hwprobe.h>
|
||||
|
||||
#define RISCV_HWPROBE_MAX_KEY 15
|
||||
#define RISCV_HWPROBE_MAX_KEY 16
|
||||
|
||||
static inline bool riscv_hwprobe_key_is_valid(__s64 key)
|
||||
{
|
||||
@@ -20,6 +20,7 @@ static inline bool hwprobe_key_is_bitmask(__s64 key)
|
||||
switch (key) {
|
||||
case RISCV_HWPROBE_KEY_BASE_BEHAVIOR:
|
||||
case RISCV_HWPROBE_KEY_IMA_EXT_0:
|
||||
case RISCV_HWPROBE_KEY_IMA_EXT_1:
|
||||
case RISCV_HWPROBE_KEY_CPUPERF_0:
|
||||
case RISCV_HWPROBE_KEY_VENDOR_EXT_THEAD_0:
|
||||
case RISCV_HWPROBE_KEY_VENDOR_EXT_MIPS_0:
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_MMAN_H__
|
||||
#define __ASM_MMAN_H__
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/mm.h>
|
||||
#include <uapi/asm/mman.h>
|
||||
|
||||
static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot,
|
||||
unsigned long pkey __always_unused)
|
||||
{
|
||||
unsigned long ret = 0;
|
||||
|
||||
/*
|
||||
* If PROT_WRITE was specified, force it to VM_READ | VM_WRITE.
|
||||
* Only VM_WRITE means shadow stack.
|
||||
*/
|
||||
if (prot & PROT_WRITE)
|
||||
ret = (VM_READ | VM_WRITE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define arch_calc_vm_prot_bits(prot, pkey) arch_calc_vm_prot_bits(prot, pkey)
|
||||
|
||||
#endif /* ! __ASM_MMAN_H__ */
|
||||
@@ -48,6 +48,13 @@ static inline unsigned long mm_untag_mask(struct mm_struct *mm)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define deactivate_mm deactivate_mm
|
||||
static inline void deactivate_mm(struct task_struct *tsk,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
shstk_release(tsk);
|
||||
}
|
||||
|
||||
#include <asm-generic/mmu_context.h>
|
||||
|
||||
#endif /* _ASM_RISCV_MMU_CONTEXT_H */
|
||||
|
||||
@@ -50,8 +50,7 @@ void clear_page(void *page);
|
||||
#endif
|
||||
#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE)
|
||||
|
||||
#define copy_user_page(vto, vfrom, vaddr, topg) \
|
||||
memcpy((vto), (vfrom), PAGE_SIZE)
|
||||
#define copy_user_page(vto, vfrom, vaddr, topg) copy_page(vto, vfrom)
|
||||
|
||||
/*
|
||||
* Use struct definitions to apply C type checking
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user