-
Notifications
You must be signed in to change notification settings - Fork 69
Use PCC bounds from .caprelocs / .rela.dyn #2423
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: dev
Are you sure you want to change the base?
Conversation
| stp c9, c10, [PTRN(sp)] | ||
| adrp PTR(9), smccc_ddc_el0 | ||
| ldr c9, [PTR(9), :lo12:smccc_ddc_el0] | ||
| LDR_LABEL(c9, PTR(9), smccc_ddc_el0) |
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.
This failed once PCC bounds for the kernel were narrowed to PT_CHERI_PCC by trusting bounds in relative relocations.
sys/cheri/cheri_cap_relocs.c
Outdated
| * When building for hybrid or with the pc-relative captable ABI we do | ||
| * not further constrain the given code_cap. | ||
| * TODO: Set code bounds if the ABI allows it (presence of | ||
| * PT_CHERI_PCC) |
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.
For this case it is probably simpler to depend on an #ifdef for a macro defined in c18n kernels (so it is set to true in that case) rather than trying to walk the phdrs to find PT_CHERI_PCC. Eventually this can just be defined to true always once toolchains without the caprelocs changes are no longer supported.
| init_linker_file_cap_relocs(ef->caprelocs, | ||
| (char *)ef->caprelocs + ef->caprelocssize, data_cap, | ||
| (ptraddr_t)ef->address, resolve_cap_reloc, ef); | ||
| (ptraddr_t)ef->address, false, resolve_cap_reloc, ef); |
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.
The intention is that on the c18n branch, you would pass the equivalent of ef->npcc_caps != 0 here instead of false.
This macro is responsible for returning a valid capability to a symbol before any relocations have been performed. It is intended for use in early relocation code.
…esent For caprelocs, use cheri_init_globals_impl() instead of cheri_init_globals_3(). This requires using CHERI_RODATA_PTR to lookup the start and and end of the caprelocs section. For ELF relocations, trust the bounds from relative relocations for code pointers if PT_CHERI_PCC is present.
This trusts the bounds from both cap relocs and relative ELF relocations if PT_CHERI_PCC bounds program headers are present.
|
Since the bounds cannot be used on Morello without PT_CHERI_PCC due to a bug in Morello lld (it's PCC bounds didn't cover .data.rel.ro), I've reworked this to always require PT_CHERI_PCC. It now also doesn't try to do arch-specific commits, but instead static binaries (csu) vs userspace runtime loader vs kernel. The kernel bits are incomplete as I don't want to duplicate Konrad's work. However, once Konrad's changes are rebased, we can perhaps pull out the changes to teach the kernel linker about PT_CHERI_PCC into |
sys/cheri/cheri_cap_relocs.c
Outdated
| init_cap_relocs(void *data_cap, void *code_cap) | ||
| { | ||
| cheri_init_globals_3(data_cap, code_cap, data_cap); | ||
| const struct capreloc *start_relocs, *stop_relocs; |
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.
Can we hoist init_linker_file_cap_relocs into a common function that this uses rather than duplicating it?
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.
Hmm, I'm not sure since init_cap_relocs() is called before GOT accesses can work, so I'm assuming I can't pass a callback function to init_linker_file_cap_relocs directly? Perhaps we could define a callback function for early kernel startup and lookup the pointer to that in assembly and call init_linker_file_cap_relocs from assembly?
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.
I suppose you could have a default implementation if it’s NULL?
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.
I ended up adding a callback for the kernel and using cllc to create the callback pointer. That does seem to work. I will upload it as a fixup commit in a bit so you can decide if you prefer it.
Explicitly inline the logic for cap relocs handling for the kernel instead of using cheri_init_globals_3. This will permit customizing the behavior in future changes.
| src = __builtin_cheri_seal_entry(src); | ||
| } | ||
| *dest = src; | ||
| if (function) { |
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.
If we are willing to trust the permissions narrowing in this callback instead of doing it in locore in assembly, (which effectively ends up a duplicate), we could pass a PCC-derived cap as arg directly and just use it instead of caps->code_cap and caps->data_cap. This is what happens for kernel modules where ef->address is RWX and is used as the single source of truth. PCC in locore is still RWX but is bounded to the kernel (KERNBASE, end). This would simplify the assembly a bit by avoiding allocating a structure on the stack, etc.
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.
Have done this in a second fixup.
We set the flags to 0 in locore to avoid leaking them into data capabilities, so the flag now has to be set explicitly as for the kernel module case.
Prepare for preferring the bounds from cap relocs and relative ELF relocations when PT_CHERI_PCC is present. For now the bounds are always disabled, but this provides the hooks to enable this in the future when support for PT_CHERI_PCC is added to the kernel linker.
Note that for CHERI-RISC-V, this depends on changes in the c18n toolchain that are not yet in the packaged version. My assumption is that for our next release we will be requiring a newer c18n toolchain anyway, so we can assume that if
PT_CHERI_PCCis present, we are using an updated toolchain that writes caprelocs with the per-compartment PCC bounds.We probably need to get an updated c18n package built (after my rebasing work finishes) before landing the last change.