xref: /linux/Documentation/arch/riscv/zicfilp.rst (revision cee73b1e840c154f64ace682cb477c1ae2e29cc4)
1*f6eeb67bSDeepak Gupta.. SPDX-License-Identifier: GPL-2.0
2*f6eeb67bSDeepak Gupta
3*f6eeb67bSDeepak Gupta:Author: Deepak Gupta <debug@rivosinc.com>
4*f6eeb67bSDeepak Gupta:Date:   12 January 2024
5*f6eeb67bSDeepak Gupta
6*f6eeb67bSDeepak Gupta====================================================
7*f6eeb67bSDeepak GuptaTracking indirect control transfers on RISC-V Linux
8*f6eeb67bSDeepak Gupta====================================================
9*f6eeb67bSDeepak Gupta
10*f6eeb67bSDeepak GuptaThis document briefly describes the interface provided to userspace by Linux
11*f6eeb67bSDeepak Guptato enable indirect branch tracking for user mode applications on RISC-V.
12*f6eeb67bSDeepak Gupta
13*f6eeb67bSDeepak Gupta1. Feature Overview
14*f6eeb67bSDeepak Gupta--------------------
15*f6eeb67bSDeepak Gupta
16*f6eeb67bSDeepak GuptaMemory corruption issues usually result in crashes.  However, in the
17*f6eeb67bSDeepak Guptahands of a creative adversary, these can result in a variety of
18*f6eeb67bSDeepak Guptasecurity issues.
19*f6eeb67bSDeepak Gupta
20*f6eeb67bSDeepak GuptaSome of those security issues can be code re-use attacks, where an
21*f6eeb67bSDeepak Guptaadversary can use corrupt function pointers, chaining them together to
22*f6eeb67bSDeepak Guptaperform jump oriented programming (JOP) or call oriented programming
23*f6eeb67bSDeepak Gupta(COP) and thus compromise control flow integrity (CFI) of the program.
24*f6eeb67bSDeepak Gupta
25*f6eeb67bSDeepak GuptaFunction pointers live in read-write memory and thus are susceptible
26*f6eeb67bSDeepak Guptato corruption.  This can allow an adversary to control the program
27*f6eeb67bSDeepak Guptacounter (PC) value.  On RISC-V, the zicfilp extension enforces a
28*f6eeb67bSDeepak Guptarestriction on such indirect control transfers:
29*f6eeb67bSDeepak Gupta
30*f6eeb67bSDeepak Gupta- Indirect control transfers must land on a landing pad instruction ``lpad``.
31*f6eeb67bSDeepak Gupta  There are two exceptions to this rule:
32*f6eeb67bSDeepak Gupta
33*f6eeb67bSDeepak Gupta  - rs1 = x1 or rs1 = x5, i.e. a return from a function and returns are
34*f6eeb67bSDeepak Gupta    protected using shadow stack (see zicfiss.rst)
35*f6eeb67bSDeepak Gupta
36*f6eeb67bSDeepak Gupta  - rs1 = x7. On RISC-V, the compiler usually does the following to reach a
37*f6eeb67bSDeepak Gupta    function which is beyond the offset of possible J-type instruction::
38*f6eeb67bSDeepak Gupta
39*f6eeb67bSDeepak Gupta      auipc x7, <imm>
40*f6eeb67bSDeepak Gupta      jalr (x7)
41*f6eeb67bSDeepak Gupta
42*f6eeb67bSDeepak Gupta    This form of indirect control transfer is immutable and doesn't
43*f6eeb67bSDeepak Gupta    rely on memory.  Thus rs1=x7 is exempted from tracking and
44*f6eeb67bSDeepak Gupta    these are considered software guarded jumps.
45*f6eeb67bSDeepak Gupta
46*f6eeb67bSDeepak GuptaThe ``lpad`` instruction is a pseudo-op of ``auipc rd, <imm_20bit>``
47*f6eeb67bSDeepak Guptawith ``rd=x0``.  This is a HINT op.  The ``lpad`` instruction must be
48*f6eeb67bSDeepak Guptaaligned on a 4 byte boundary.  It compares the 20 bit immediate with
49*f6eeb67bSDeepak Guptax7. If ``imm_20bit`` == 0, the CPU doesn't perform any comparison with
50*f6eeb67bSDeepak Gupta``x7``. If ``imm_20bit`` != 0, then ``imm_20bit`` must match ``x7``
51*f6eeb67bSDeepak Guptaelse CPU will raise ``software check exception`` (``cause=18``) with
52*f6eeb67bSDeepak Gupta``*tval = 2``.
53*f6eeb67bSDeepak Gupta
54*f6eeb67bSDeepak GuptaThe compiler can generate a hash over function signatures and set them
55*f6eeb67bSDeepak Guptaup (truncated to 20 bits) in x7 at callsites.  Function prologues can
56*f6eeb67bSDeepak Guptahave ``lpad`` instructions encoded with the same function hash. This
57*f6eeb67bSDeepak Guptafurther reduces the number of valid program counter addresses a call
58*f6eeb67bSDeepak Guptasite can reach.
59*f6eeb67bSDeepak Gupta
60*f6eeb67bSDeepak Gupta2. ELF and psABI
61*f6eeb67bSDeepak Gupta-----------------
62*f6eeb67bSDeepak Gupta
63*f6eeb67bSDeepak GuptaThe toolchain sets up :c:macro:`GNU_PROPERTY_RISCV_FEATURE_1_FCFI` for
64*f6eeb67bSDeepak Guptaproperty :c:macro:`GNU_PROPERTY_RISCV_FEATURE_1_AND` in the notes
65*f6eeb67bSDeepak Guptasection of the object file.
66*f6eeb67bSDeepak Gupta
67*f6eeb67bSDeepak Gupta3. Linux enabling
68*f6eeb67bSDeepak Gupta------------------
69*f6eeb67bSDeepak Gupta
70*f6eeb67bSDeepak GuptaUser space programs can have multiple shared objects loaded in their
71*f6eeb67bSDeepak Guptaaddress spaces.  It's a difficult task to make sure all the
72*f6eeb67bSDeepak Guptadependencies have been compiled with indirect branch support. Thus
73*f6eeb67bSDeepak Guptait's left to the dynamic loader to enable indirect branch tracking for
74*f6eeb67bSDeepak Guptathe program.
75*f6eeb67bSDeepak Gupta
76*f6eeb67bSDeepak Gupta4. prctl() enabling
77*f6eeb67bSDeepak Gupta--------------------
78*f6eeb67bSDeepak Gupta
79*f6eeb67bSDeepak Gupta:c:macro:`PR_SET_INDIR_BR_LP_STATUS` / :c:macro:`PR_GET_INDIR_BR_LP_STATUS` /
80*f6eeb67bSDeepak Gupta:c:macro:`PR_LOCK_INDIR_BR_LP_STATUS` are three prctls added to manage indirect
81*f6eeb67bSDeepak Guptabranch tracking.  These prctls are architecture-agnostic and return -EINVAL if
82*f6eeb67bSDeepak Guptathe underlying functionality is not supported.
83*f6eeb67bSDeepak Gupta
84*f6eeb67bSDeepak Gupta* prctl(PR_SET_INDIR_BR_LP_STATUS, unsigned long arg)
85*f6eeb67bSDeepak Gupta
86*f6eeb67bSDeepak GuptaIf arg1 is :c:macro:`PR_INDIR_BR_LP_ENABLE` and if CPU supports
87*f6eeb67bSDeepak Gupta``zicfilp`` then the kernel will enable indirect branch tracking for the
88*f6eeb67bSDeepak Guptatask.  The dynamic loader can issue this :c:macro:`prctl` once it has
89*f6eeb67bSDeepak Guptadetermined that all the objects loaded in the address space support
90*f6eeb67bSDeepak Guptaindirect branch tracking.  Additionally, if there is a `dlopen` to an
91*f6eeb67bSDeepak Guptaobject which wasn't compiled with ``zicfilp``, the dynamic loader can
92*f6eeb67bSDeepak Guptaissue this prctl with arg1 set to 0 (i.e. :c:macro:`PR_INDIR_BR_LP_ENABLE`
93*f6eeb67bSDeepak Guptacleared).
94*f6eeb67bSDeepak Gupta
95*f6eeb67bSDeepak Gupta* prctl(PR_GET_INDIR_BR_LP_STATUS, unsigned long * arg)
96*f6eeb67bSDeepak Gupta
97*f6eeb67bSDeepak GuptaReturns the current status of indirect branch tracking. If enabled
98*f6eeb67bSDeepak Guptait'll return :c:macro:`PR_INDIR_BR_LP_ENABLE`
99*f6eeb67bSDeepak Gupta
100*f6eeb67bSDeepak Gupta* prctl(PR_LOCK_INDIR_BR_LP_STATUS, unsigned long arg)
101*f6eeb67bSDeepak Gupta
102*f6eeb67bSDeepak GuptaLocks the current status of indirect branch tracking on the task. User
103*f6eeb67bSDeepak Guptaspace may want to run with a strict security posture and wouldn't want
104*f6eeb67bSDeepak Guptaloading of objects without ``zicfilp`` support in them, to disallow
105*f6eeb67bSDeepak Guptadisabling of indirect branch tracking. In this case, user space can
106*f6eeb67bSDeepak Guptause this prctl to lock the current settings.
107*f6eeb67bSDeepak Gupta
108*f6eeb67bSDeepak Gupta5. violations related to indirect branch tracking
109*f6eeb67bSDeepak Gupta--------------------------------------------------
110*f6eeb67bSDeepak Gupta
111*f6eeb67bSDeepak GuptaPertaining to indirect branch tracking, the CPU raises a software
112*f6eeb67bSDeepak Guptacheck exception in the following conditions:
113*f6eeb67bSDeepak Gupta
114*f6eeb67bSDeepak Gupta- missing ``lpad`` after indirect call / jmp
115*f6eeb67bSDeepak Gupta- ``lpad`` not on 4 byte boundary
116*f6eeb67bSDeepak Gupta- ``imm_20bit`` embedded in ``lpad`` instruction doesn't match with ``x7``
117*f6eeb67bSDeepak Gupta
118*f6eeb67bSDeepak GuptaIn all 3 cases, ``*tval = 2`` is captured and software check exception is
119*f6eeb67bSDeepak Guptaraised (``cause=18``).
120*f6eeb67bSDeepak Gupta
121*f6eeb67bSDeepak GuptaThe kernel will treat this as :c:macro:`SIGSEGV` with code =
122*f6eeb67bSDeepak Gupta:c:macro:`SEGV_CPERR` and follow the normal course of signal delivery.
123