€•sœŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ&/translations/zh_CN/arch/riscv/zicfiss”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/zh_TW/arch/riscv/zicfiss”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/it_IT/arch/riscv/zicfiss”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/ja_JP/arch/riscv/zicfiss”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/ko_KR/arch/riscv/zicfiss”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/pt_BR/arch/riscv/zicfiss”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/sp_SP/arch/riscv/zicfiss”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)”}”(hŒ SPDX-License-Identifier: GPL-2.0”h]”hŒ SPDX-License-Identifier: GPL-2.0”…””}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³Œ@/var/lib/git/docbuild/linux/Documentation/arch/riscv/zicfiss.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒ8Shadow stack to protect function returns on RISC-V Linux”h]”hŒ8Shadow stack to protect function returns on RISC-V Linux”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhŒ paragraph”“”)”}”(hŒŠThis document briefly describes the interface provided to userspace by Linux to enable shadow stacks for user mode applications on RISC-V.”h]”hŒŠThis document briefly describes the interface provided to userspace by Linux to enable shadow stacks for user mode applications on RISC-V.”…””}”(hhßh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K hhÊh²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒ1. Feature Overview”h]”hŒ1. Feature Overview”…””}”(hhðh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhíh²hh³hÇh´KubhÞ)”}”(hŒž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.”h]”hŒž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.”…””}”(hhþh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khhíh²hubhÞ)”}”(hXSome 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.”h]”hXSome 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.”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khhíh²hubhÞ)”}”(hXReturn 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:”h]”(hŒ±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 ”…””}”(hjh²hh³Nh´NubhŒliteral”“”)”}”(hŒ ``zicfiss``”h]”hŒzicfiss”…””}”(hj$h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjubhŒ³ 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 ”…””}”(hjh²hh³Nh´Nubj#)”}”(hŒ ``zicfiss``”h]”hŒzicfiss”…””}”(hj6h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjubhŒ' extension makes the following changes:”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khhíh²hubhŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ·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. ”h]”hÞ)”}”(hŒ¶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.”h]”hŒ¶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.”…””}”(hjYh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K"hjUubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjPh²hh³hÇh´NubjT)”}”(hŒLThe ``sspush x1/x5`` instruction pushes (stores) ``x1/x5`` to shadow stack. ”h]”hÞ)”}”(hŒKThe ``sspush x1/x5`` instruction pushes (stores) ``x1/x5`` to shadow stack.”h]”(hŒThe ”…””}”(hjqh²hh³Nh´Nubj#)”}”(hŒ``sspush x1/x5``”h]”hŒ sspush x1/x5”…””}”(hjyh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjqubhŒ instruction pushes (stores) ”…””}”(hjqh²hh³Nh´Nubj#)”}”(hŒ ``x1/x5``”h]”hŒx1/x5”…””}”(hj‹h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjqubhŒ to shadow stack.”…””}”(hjqh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K&hjmubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjPh²hh³hÇh´NubjT)”}”(hŒ±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`` ”h]”hÞ)”}”(hŒ°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``”h]”(hŒThe ”…””}”(hj­h²hh³Nh´Nubj#)”}”(hŒ``sspopchk x1/x5``”h]”hŒsspopchk x1/x5”…””}”(hjµh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hj­ubhŒ> instruction pops (loads) from shadow stack and compares with ”…””}”(hj­h²hh³Nh´Nubj#)”}”(hŒ ``x1/x5``”h]”hŒx1/x5”…””}”(hjÇh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hj­ubhŒ$ and if not equal, the CPU raises a ”…””}”(hj­h²hh³Nh´Nubj#)”}”(hŒ``software check exception``”h]”hŒsoftware check exception”…””}”(hjÙh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hj­ubhŒ with ”…””}”(hj­h²hh³Nh´Nubj#)”}”(hŒ ``*tval = 3``”h]”hŒ *tval = 3”…””}”(hjëh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hj­ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K(hj©ubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjPh²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1jNh³hÇh´K"hhíh²hubhÞ)”}”(hXYThe 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.”h]”(hŒh]”hŒPR_LOCK_SHADOW_STACK_STATUS”…””}”(hj@h²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hj<ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒPR_LOCK_SHADOW_STACK_STATUS”uh1hh³hÇh´KdhjòubhŒ‘ are three prctls added to manage shadow stack enabling for tasks. These prctls are architecture-agnostic and return -EINVAL if not implemented.”…””}”(hjòh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kdhjáh²hubjO)”}”(hhh]”jT)”}”(hŒ5prctl(PR_SET_SHADOW_STACK_STATUS, unsigned long arg) ”h]”hÞ)”}”(hŒ4prctl(PR_SET_SHADOW_STACK_STATUS, unsigned long arg)”h]”hŒ4prctl(PR_SET_SHADOW_STACK_STATUS, unsigned long arg)”…””}”(hjlh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kihjhubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjeh²hh³hÇh´Nubah}”(h]”h ]”h"]”h$]”h&]”j Œ*”uh1jNh³hÇh´Kihjáh²hubhÞ)”}”(hXì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)”h]”(hŒ If arg = ”…””}”(hj‡h²hh³Nh´Nubh)”}”(hŒ!:c:macro:`PR_SHADOW_STACK_ENABLE`”h]”j#)”}”(hj‘h]”hŒPR_SHADOW_STACK_ENABLE”…””}”(hj“h²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒPR_SHADOW_STACK_ENABLE”uh1hh³hÇh´Kkhj‡ubhŒ and if CPU supports ”…””}”(hj‡h²hh³Nh´Nubj#)”}”(hŒ ``zicfiss``”h]”hŒzicfiss”…””}”(hj²h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hj‡ubhŒ[ then the kernel will enable shadow stacks for the task. The dynamic loader can issue this ”…””}”(hj‡h²hh³Nh´Nubh)”}”(hŒ:c:macro:`prctl`”h]”j#)”}”(hjÆh]”hŒprctl”…””}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjÄubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒprctl”uh1hh³hÇh´Kkhj‡ubhŒ‚ once it has determined that all the objects loaded in address space have support for shadow stacks. Additionally, if there is a ”…””}”(hj‡h²hh³Nh´Nubh)”}”(hŒ:c:macro:`dlopen`”h]”j#)”}”(hjéh]”hŒdlopen”…””}”(hjëh²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjçubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒdlopen”uh1hh³hÇh´Kkhj‡ubhŒ+ to an object which wasn’t compiled with ”…””}”(hj‡h²hh³Nh´Nubj#)”}”(hŒ ``zicfiss``”h]”hŒzicfiss”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hj‡ubhŒB, the dynamic loader can issue this prctl with arg set to 0 (i.e. ”…””}”(hj‡h²hh³Nh´Nubh)”}”(hŒ!:c:macro:`PR_SHADOW_STACK_ENABLE`”h]”j#)”}”(hjh]”hŒPR_SHADOW_STACK_ENABLE”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒPR_SHADOW_STACK_ENABLE”uh1hh³hÇh´Kkhj‡ubhŒ being clear)”…””}”(hj‡h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kkhjáh²hubjO)”}”(hhh]”jT)”}”(hŒ7prctl(PR_GET_SHADOW_STACK_STATUS, unsigned long * arg) ”h]”hÞ)”}”(hŒ6prctl(PR_GET_SHADOW_STACK_STATUS, unsigned long * arg)”h]”hŒ6prctl(PR_GET_SHADOW_STACK_STATUS, unsigned long * arg)”…””}”(hjLh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KthjHubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjEh²hh³hÇh´Nubah}”(h]”h ]”h"]”h$]”h&]”j j†uh1jNh³hÇh´Kthjáh²hubhÞ)”}”(hŒrReturns the current status of indirect branch tracking. If enabled it'll return :c:macro:`PR_SHADOW_STACK_ENABLE`.”h]”(hŒRReturns the current status of indirect branch tracking. If enabled it’ll return ”…””}”(hjfh²hh³Nh´Nubh)”}”(hŒ!:c:macro:`PR_SHADOW_STACK_ENABLE`”h]”j#)”}”(hjph]”hŒPR_SHADOW_STACK_ENABLE”…””}”(hjrh²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjnubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒPR_SHADOW_STACK_ENABLE”uh1hh³hÇh´KvhjfubhŒ.”…””}”(hjfh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kvhjáh²hubjO)”}”(hhh]”jT)”}”(hŒ6prctl(PR_LOCK_SHADOW_STACK_STATUS, unsigned long arg) ”h]”hÞ)”}”(hŒ5prctl(PR_LOCK_SHADOW_STACK_STATUS, unsigned long arg)”h]”hŒ5prctl(PR_LOCK_SHADOW_STACK_STATUS, unsigned long arg)”…””}”(hjžh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kyhjšubah}”(h]”h ]”h"]”h$]”h&]”uh1jShj—h²hh³hÇh´Nubah}”(h]”h ]”h"]”h$]”h&]”j j†uh1jNh³hÇh´Kyhjáh²hubhÞ)”}”(hX 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.”h]”(hŒ§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 ”…””}”(hj¸h²hh³Nh´Nubj#)”}”(hŒ ``zicfiss``”h]”hŒzicfiss”…””}”(hjÀh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hj¸ubhŒp support. In this case userspace can use this prctl to disallow disabling of shadow stacks on the current task.”…””}”(hj¸h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K{hjáh²hubeh}”(h]”Œprctl-enabling”ah ]”h"]”Œ5. prctl() enabling”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KbubhÉ)”}”(hhh]”(hÎ)”}”(hŒ:5. violations related to returns with shadow stack enabled”h]”hŒ:5. violations related to returns with shadow stack enabled”…””}”(hjãh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjàh²hh³hÇh´K‚ubhÞ)”}”(hŒò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.”h]”(hŒ.Pertaining to shadow stacks, the CPU raises a ”…””}”(hjñh²hh³Nh´Nubj#)”}”(hŒ``software check exception``”h]”hŒsoftware check exception”…””}”(hjùh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjñubhŒ upon executing ”…””}”(hjñh²hh³Nh´Nubj#)”}”(hŒ``sspopchk x1/x5``”h]”hŒsspopchk x1/x5”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjñubhŒ if ”…””}”(hjñh²hh³Nh´Nubj#)”}”(hŒ ``x1/x5``”h]”hŒx1/x5”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjñubhŒT doesn’t match the top of shadow stack. If a mismatch happens, then the CPU sets ”…””}”(hjñh²hh³Nh´Nubj#)”}”(hŒ ``*tval = 3``”h]”hŒ *tval = 3”…””}”(hj/h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjñubhŒ and raises the exception.”…””}”(hjñh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K„hjàh²hubhÞ)”}”(hŒ‹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.”h]”(hŒ&The Linux kernel will treat this as a ”…””}”(hjGh²hh³Nh´Nubh)”}”(hŒ:c:macro:`SIGSEGV`”h]”j#)”}”(hjQh]”hŒSIGSEGV”…””}”(hjSh²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjOubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒSIGSEGV”uh1hh³hÇh´K‰hjGubhŒ with code = ”…””}”(hjGh²hh³Nh´Nubh)”}”(hŒ:c:macro:`SEGV_CPERR`”h]”j#)”}”(hjth]”hŒ SEGV_CPERR”…””}”(hjvh²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjrubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒ SEGV_CPERR”uh1hh³hÇh´K‰hjGubhŒ1 and follow the normal course of signal delivery.”…””}”(hjGh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K‰hjàh²hubeh}”(h]”Œ7violations-related-to-returns-with-shadow-stack-enabled”ah ]”h"]”Œ:5. violations related to returns with shadow stack enabled”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K‚ubhÉ)”}”(hhh]”(hÎ)”}”(hŒ6. Shadow stack tokens”h]”hŒ6. Shadow stack tokens”…””}”(hj¦h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj£h²hh³hÇh´KubhÞ)”}”(hX¿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:”h]”(hŒÊ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 ”…””}”(hj´h²hh³Nh´Nubj#)”}”(hŒ ``CSR_SSP``”h]”hŒCSR_SSP”…””}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hj´ubhŒH. This will change the active shadow stack for the program. Writes to ”…””}”(hj´h²hh³Nh´Nubj#)”}”(hŒ ``CSR_SSP``”h]”hŒCSR_SSP”…””}”(hjÎh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hj´ubhX™ 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:”…””}”(hj´h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khj£h²hubjO)”}”(hhh]”(jT)”}”(hŒ¦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``). ”h]”hÞ)”}”(hŒ¥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``).”h]”(hŒ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 ”…””}”(hjíh²hh³Nh´Nubj#)”}”(hŒ``shadow stack token``”h]”hŒshadow stack token”…””}”(hjõh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjíubhŒ).”…””}”(hjíh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K›hjéubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjæh²hh³hÇh´NubjT)”}”(hŒÑ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. ”h]”hÞ)”}”(hŒÐ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.”h]”(hŒAWhen software is switching to a shadow stack, it should read the ”…””}”(hjh²hh³Nh´Nubj#)”}”(hŒ``shadow stack token``”h]”hŒshadow stack token”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjubhŒ3 from the shadow stack pointer and verify that the ”…””}”(hjh²hh³Nh´Nubj#)”}”(hŒ``shadow stack token``”h]”hŒshadow stack token”…””}”(hj1h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjubhŒ0 itself is a pointer to the shadow stack itself.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KŸhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjæh²hh³hÇh´NubjT)”}”(hŒlOnce the token verification is done, software can perform the write to ``CSR_SSP`` to switch shadow stacks. ”h]”hÞ)”}”(hŒkOnce the token verification is done, software can perform the write to ``CSR_SSP`` to switch shadow stacks.”h]”(hŒGOnce the token verification is done, software can perform the write to ”…””}”(hjSh²hh³Nh´Nubj#)”}”(hŒ ``CSR_SSP``”h]”hŒCSR_SSP”…””}”(hj[h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjSubhŒ to switch shadow stacks.”…””}”(hjSh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K¤hjOubah}”(h]”h ]”h"]”h$]”h&]”uh1jShjæh²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”j j uh1jNh³hÇh´K›hj£h²hubhÞ)”}”(hXHere "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`.”h]”(hXˆ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 ”…””}”(hjh²hh³Nh´Nubh)”}”(hŒ:c:macro:`sigreturn`”h]”j#)”}”(hj‰h]”hŒ sigreturn”…””}”(hj‹h²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hj‡ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒ sigreturn”uh1hh³hÇh´K§hjubhŒí 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 ”…””}”(hjh²hh³Nh´Nubh)”}”(hŒ:c:macro:`sigreturn`”h]”j#)”}”(hj¬h]”hŒ sigreturn”…””}”(hj®h²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjªubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒ sigreturn”uh1hh³hÇh´K§hjubhŒ;. Adversaries will have to make sure that there is a valid ”…””}”(hjh²hh³Nh´Nubj#)”}”(hŒ``shadow stack token``”h]”hŒshadow stack token”…””}”(hjÍh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j"hjubhŒ in addition to invoking ”…””}”(hjh²hh³Nh´Nubh)”}”(hŒ:c:macro:`sigreturn`”h]”j#)”}”(hjáh]”hŒ sigreturn”…””}”(hjãh²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjßubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒ sigreturn”uh1hh³hÇh´K§hjubhŒ.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K§hj£h²hubeh}”(h]”Œshadow-stack-tokens”ah ]”h"]”Œ6. shadow stack tokens”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒ7. Signal shadow stack”h]”hŒ7. Signal shadow stack”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´KµubhÞ)”}”(hŒAThe following structure has been added to sigcontext for RISC-V::”h]”hŒ@The following structure has been added to sigcontext for RISC-V:”…””}”(hj!h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K¶hjh²hubhŒ literal_block”“”)”}”(hŒ:struct __sc_riscv_cfi_state { unsigned long ss_ptr; };”h]”hŒ:struct __sc_riscv_cfi_state { unsigned long ss_ptr; };”…””}”hj1sbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1j/h³hÇh´K¸hjh²hubhÞ)”}”(hXË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.”h]”(hŒŠ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 ”…””}”(hj?h²hh³Nh´Nubh)”}”(hŒ:c:macro:`ss_ptr`”h]”j#)”}”(hjIh]”hŒss_ptr”…””}”(hjKh²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjGubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒss_ptr”uh1hh³hÇh´K¼hj?ubhŒ field in ”…””}”(hj?h²hh³Nh´Nubh)”}”(hŒ:c:macro:`__sc_riscv_cfi_state`”h]”j#)”}”(hjlh]”hŒ__sc_riscv_cfi_state”…””}”(hjnh²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒ__sc_riscv_cfi_state”uh1hh³hÇh´K¼hj?ubhŒ under ”…””}”(hj?h²hh³Nh´Nubh)”}”(hŒ:c:macro:`sigcontext`”h]”j#)”}”(hjh]”hŒ sigcontext”…””}”(hj‘h²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒ sigcontext”uh1hh³hÇh´K¼hj?ubhŒL. The existing shadow stack allocation is used for signal delivery. During ”…””}”(hj?h²hh³Nh´Nubh)”}”(hŒ:c:macro:`sigreturn`”h]”j#)”}”(hj²h]”hŒ sigreturn”…””}”(hj´h²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hj°ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒ sigreturn”uh1hh³hÇh´K¼hj?ubhŒ, kernel will obtain ”…””}”(hj?h²hh³Nh´Nubh)”}”(hŒ:c:macro:`ss_ptr`”h]”j#)”}”(hjÕh]”hŒss_ptr”…””}”(hj×h²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjÓubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒss_ptr”uh1hh³hÇh´K¼hj?ubhŒ from ”…””}”(hj?h²hh³Nh´Nubh)”}”(hŒ:c:macro:`sigcontext`”h]”j#)”}”(hjøh]”hŒ sigcontext”…””}”(hjúh²hh³Nh´Nubah}”(h]”h ]”(jpjqŒc-macro”eh"]”h$]”h&]”uh1j"hjöubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”j}Œ refdomain”jqŒreftype”Œmacro”Œ refexplicit”‰Œrefwarn”‰jƒŒ sigcontext”uh1hh³hÇh´K¼hj?ubhŒJ, verify the saved token on the shadow stack, and switch the shadow stack.”…””}”(hj?h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K¼hjh²hubeh}”(h]”Œsignal-shadow-stack”ah ]”h"]”Œ7. signal shadow stack”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´Kµubeh}”(h]”Œ8shadow-stack-to-protect-function-returns-on-risc-v-linux”ah ]”h"]”Œ8shadow stack to protect function returns on risc-v linux”ah$]”h&]”uh1hÈhhh²hh³hÇh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÇuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hÍNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jR Œerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÇŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j, j) jVjSjFjCj·j´jÞjÛjÝjÚj jj j j$ j! uŒ nametypes”}”(j, ‰jV‰jF‰j·‰jÞ‰j݉j ‰j ‰j$ ‰uh}”(j) hÊjShíjCjYj´jIjÛjºjÚjájjàj j£j! juŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.