-
Notifications
You must be signed in to change notification settings - Fork 179
Add program property and PLT for CFI extension #417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
0bf517a
0ef6c79
2287e78
674fdc1
26f8548
7a17daa
6870e06
b0c58fa
3100056
79af4a7
f209417
714f4b9
efe20ea
6662782
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -727,20 +727,42 @@ The PLT (Procedure Linkage Table) exists to allow function calls between | |
| dynamically linked shared objects. Each dynamic object has its own | ||
| GOT (Global Offset Table) and PLT (Procedure Linkage Table). | ||
|
|
||
| RISC-V defines several PLT styles, which are used in different situations. | ||
| The default PLT style should be used if the program does not meet the conditions | ||
| for using any of the other PLT sytles. | ||
|
|
||
| [[plt-style]] | ||
| .PLT styles | ||
| [cols="1,2"] | ||
| [width=70%] | ||
| |=== | ||
| | Default PLT | - | ||
| | Landing pad PLT | Must use this PLT style when `GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED` is set. | ||
| |=== | ||
|
|
||
| The first entry of a shared object PLT is a special entry that calls | ||
| `_dl_runtime_resolve` to resolve the GOT offset for the called function. | ||
| The `_dl_runtime_resolve` function in the dynamic loader resolves the | ||
| GOT offsets lazily on the first call to any function, except when | ||
| `LD_BIND_NOW` is set in which case the GOT entries are populated by the | ||
| dynamic linker before the executable is started. Lazy resolution of GOT | ||
| entries is intended to speed up program loading by deferring symbol | ||
| resolution to the first time the function is called. The first entry | ||
| in the PLT occupies two 16 byte entries: | ||
| resolution to the first time the function is called. | ||
|
|
||
| Landing pad PLT can't be used with lazy binding. | ||
|
|
||
| NOTE: Landing pads are designed for use with Control-Flow Integrity (CFI). | ||
| Lazy binding may delay resolution of indirect branches until runtime, potentially | ||
| allowing attackers to hijack control flow before CFI protections are fully | ||
| enforced. Therefore, lazy binding is considered unsafe in conjunction with | ||
| landing pad-based PLTs. | ||
|
|
||
| The first entry in the PLT occupies two 16 byte entries for the default PLT style: | ||
|
|
||
| [,asm] | ||
| ---- | ||
| 1: auipc t2, %pcrel_hi(.got.plt) | ||
| sub t1, t1, t3 # shifted .got.plt offset + hdr size + 12 | ||
| sub t1, t1, t3 # shifted .got.plt offset + hdr size + 12 | ||
| l[w|d] t3, %pcrel_lo(1b)(t2) # _dl_runtime_resolve | ||
| addi t1, t1, -(hdr size + 12) # shifted .got.plt offset | ||
| addi t0, t2, %pcrel_lo(1b) # &.got.plt | ||
|
|
@@ -749,11 +771,30 @@ in the PLT occupies two 16 byte entries: | |
| jr t3 | ||
| ---- | ||
|
|
||
| Subsequent function entry stubs in the PLT take up 16 bytes and load a | ||
| function pointer from the GOT. On the first call to a function, the | ||
| entry redirects to the first PLT entry which calls `_dl_runtime_resolve` | ||
| and fills in the GOT entry for subsequent calls to the function: | ||
| And occupies two 16 byte entries for the unlabeled landing pad PLT style: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess we don't need to distinguish between unlabeled and func-sig landing pad PLT styles anymore. |
||
|
|
||
| [,asm] | ||
| ---- | ||
| 1: auipc t3, %pcrel_hi(.got.plt) | ||
| sub t1, t1, t2 # shifted .got.plt offset + hdr size + 16 | ||
| l[w|d] t2, %pcrel_lo(1b)(t3) # _dl_runtime_resolve | ||
| addi t1, t1, -(hdr size + 16) # shifted .got.plt offset | ||
| addi t0, t3, %pcrel_lo(1b) # &.got.plt | ||
| srli t1, t1, log2(16/PTRSIZE) # .got.plt offset | ||
| l[w|d] t0, PTRSIZE(t0) # link map | ||
| jr t2 | ||
| ---- | ||
|
|
||
| NOTE: Although lazy binding is prohibited for landing pad PLTs, the PLT | ||
| header is still retained so that features implemented by the C library, such | ||
| as LD_AUDIT and LD_PROFILE in glibc, continue to function as intended. | ||
|
|
||
| Subsequent function entry stubs in the PLT take up 16 bytes. | ||
| On the first call to a function, the entry redirects to the first PLT entry | ||
| which calls `_dl_runtime_resolve` and fills in the GOT entry for subsequent | ||
| calls to the function. | ||
|
|
||
| The code sequences of the PLT entry for the default PLT style: | ||
| [,asm] | ||
| ---- | ||
| 1: auipc t3, %pcrel_hi([email protected]) | ||
|
|
@@ -762,6 +803,15 @@ and fills in the GOT entry for subsequent calls to the function: | |
| nop | ||
| ---- | ||
|
|
||
| The code sequences of the PLT entry for the landing pad PLT style: | ||
| [,asm] | ||
| ---- | ||
| lpad 0 | ||
| 1: auipc t2, %pcrel_hi([email protected]) | ||
| l[w|d] t2, %pcrel_lo(1b)(t2) | ||
| jalr t1, t2 | ||
| ---- | ||
|
|
||
| ==== Procedure Calls | ||
|
|
||
| `R_RISCV_CALL` and `R_RISCV_CALL_PLT` relocations are associated with | ||
|
|
@@ -1445,6 +1495,94 @@ that a linker or runtime loader needs to check for compatibility. | |
| The linker should ignore and discard unknown bits in program properties, and | ||
| issue warnings or errors. | ||
|
|
||
| <<rv-prog-prop-type>> provides details of the RISC-V ELF program property; the | ||
| meaning of each column is given below: | ||
|
|
||
|
|
||
| Name:: The name of the program property type, omitting the prefix of `GNU_PROPERTY_RISCV_`. | ||
|
|
||
| Value:: The `pr_type` value for the program property type. | ||
|
|
||
| Size:: The size (`pr_datasz`) of data type held within this program property | ||
| type. | ||
|
|
||
| Description:: Additional information about the program property type. | ||
|
|
||
|
|
||
| [[rv-prog-prop-type]] | ||
| .RISC-V-specific program property types | ||
| [cols="3,3,2,5"] | ||
| [width=100%] | ||
| |=== | ||
| | Name | Value | Size | Description | ||
|
|
||
kito-cheng marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| | FEATURE_1_AND | 0xc0000000 | 4-bytes | RISC-V processor-specific features used in program. | ||
| |=== | ||
|
|
||
| ==== GNU_PROPERTY_RISCV_FEATURE_1_AND | ||
|
|
||
| `GNU_PROPERTY_RISCV_FEATURE_1_AND` describe a set of processor features with | ||
| each bit indicating a feature that the object file is compatible with. The | ||
| linker should perform a bitwise AND operation when merging different objects. | ||
|
|
||
kito-cheng marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| The value of `GNU_PROPERTY_RISCV_FEATURE_1_AND` is defined in <<rv-prog-prop-type>>. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This link does not make sense to me here. We are here in the section that defines the values in the lines below. |
||
|
|
||
| [%autowidth] | ||
| |=== | ||
| | Bit | Bit Name | ||
| | 0 | GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED | ||
| | 1 | GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need a bit for unlabeled landing pads? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For easy migration of distros we will probably need at least:
|
||
| |=== | ||
|
|
||
| `GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED`: This bit indicates that all | ||
| executable sections are built to be compatible with the landing pad mechanism | ||
| provided by the Zicfilp extension in the unlabeled scheme: Executables and | ||
| shared libraries with this bit set are required to generate PLTs in the | ||
| unlabeled landing pad PLT style, and all of the labels of lpad instructions are | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| set to 0, i.e. unlabeled. | ||
| See <<Tool Requirements for Generating Landing Pad Instruction>> for more details. | ||
|
|
||
| `GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS`: This bit indicates that all executable | ||
| sections are built to be compatible with the shadow stack mechanism provided by | ||
| the `Zicfiss` extension. Loading an executable or shared library with this bit | ||
| set requires the execution environment to provide either the `Zicfiss` extension | ||
| or the `Zimop` extension. When the executable or shared library is compiled with | ||
| compressed instructions then loading it with this bit set requires the execution | ||
| environment to provide the `Zicfiss` extension or the `Zcmop` extensions. | ||
|
|
||
| === Tool Requirements for Generating Landing Pad Instructions | ||
|
|
||
| For an executable or shared library to set the GNU property | ||
| `GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED`, every indirect branch targeting | ||
| a location guarded by landing pads must point to a landing pad (`lpad`) | ||
| instruction with a compatible label value. Indirect branches may originate from: | ||
|
|
||
| * Relocatable object producers, such as a compiler or assembler. | ||
|
|
||
| * Static linkers when generating PLT entries. | ||
|
|
||
| * Other executables and shared libraries via calls through PLT entries or | ||
| function pointers. | ||
|
|
||
|
Comment on lines
+1562
to
+1566
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we force LD_BIND_NOW with LPAD PLTs, I guess these won't count as "indirect branches" anymore? Perhaps this two items should be replaced as a note that explains their exemption from this list. |
||
| It is desirable to minimize the number of landing pad instructions to limit the | ||
| number of indirect branch destinations within the program. The following tool | ||
| requirements determine which tool is responsible for inserting landing pad | ||
| instructions, allowing tools to omit landing pad instructions if it can be | ||
| proven that there are no indirect branches targeting the location. | ||
|
|
||
| A relocatable object producer is required to insert a landing pad instruction at | ||
| the target of an indirect branch originating from within the same relocatable | ||
| object. | ||
|
|
||
| A relocatable object producer must insert a landing pad instruction at any | ||
| location whose address escapes the relocatable object. This includes all symbols | ||
| that can be exported into the dynamic symbol table by a static linker. | ||
|
|
||
| A static linker is required to generate PLT entries with appropriate landing pad | ||
| instructions. During linker relaxation, a static linker may remove unnecessary | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a relocation associated with the LPAD instruction?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here is a follow up PR for adding relocation for lpad: #452 |
||
| landing pad instructions if it can prove that there are no indirect branches | ||
| targeting the corresponding location. | ||
|
|
||
| === Mapping Symbol | ||
|
|
||
| The section can have a mixture of code and data or code with different ISAs. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extraneous space.