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