Hi Ben,
(Please don't drop CC.)
Glad I could help. Don't be too hard on yourself, hindsight is easy.
For defensive programming reasons (which also makes attacks harder),
it's good to have a non-zero guard for your caps which doesn't overlap
with your virtual address space, at least for the first level.
For the last level it depends on how you want overflows to behave:
If you want to seamlessly continue into the next CNode, have a zero
guard size (good for e.g. dynamic CNode allocation). If you want to
detect overflow errors on sets of caps, make sure you have a guard
size of at least 1 bit. Having a non-zero guard value has less
advantage for later CNode levels.
Greetings,
Indan
On 2024-11-15 16:25, Ben McCart wrote:
> Indan,
>
> Thank you so much! seL4_CNode_Mint instead of seL4_CNode_Copy solved
> my problem. The piece I was missing was that I needed to change the
> guard on the original seL4_CapInitThreadCNode when copying it into the
> first CSlot of the new root CNode. (Doh!) I should have caught that
> as you said explicitly in you prior response that each CNode capability
> can have different guard bits set. (I just didn't think carefully
> enough about that.)
>
> On 11/15/2024 4:55 AM, Indan Zupancic wrote:
>>
>> seL4_CNode_Copy can't change the guard, you have to use
>> seL4_CNode_Mint() if you need to change it:
>>
>> assert(bi->initThreadCNodeSizeBits <= 16);
>> seL4_CNode_Mint(
>> cspace_cap,
>> 0, // Destination index in the
>> new Cap table.
>> 16, // Number of bits for the new
>> Cap table.
>> seL4_CapInitThreadCNode,
>> seL4_CapInitThreadCNode,
>> seL4_WordBits,
>> seL4_AllRights,
>> 16 - bi->initThreadCNodeSizeBits); // Zero pad guard to reach 16
>> bits.
>> <SNIP>
>> Indan
>
> -Ben