Skip to content

Conversation

@bsdjhb
Copy link
Collaborator

@bsdjhb bsdjhb commented Jun 30, 2025

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_PCC is 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.

@bsdjhb bsdjhb requested a review from kwitaszczyk June 30, 2025 12:28
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)
Copy link
Collaborator Author

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.

* 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)
Copy link
Collaborator Author

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);
Copy link
Collaborator Author

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.

bsdjhb added 5 commits July 21, 2025 14:20
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.
@bsdjhb
Copy link
Collaborator Author

bsdjhb commented Jul 21, 2025

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 dev separately from some of the other kernel c18n changes.

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;
Copy link
Member

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?

Copy link
Collaborator Author

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?

Copy link
Member

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?

Copy link
Collaborator Author

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) {
Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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.

bsdjhb added 3 commits July 22, 2025 11:29
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants