-
Notifications
You must be signed in to change notification settings - Fork 13
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
Add example showing inter-compartment switch #53
Conversation
void* __capability comps_addr = (void* __capability) &comps; | ||
comps_addr = cheri_bounds_set(comps_addr, COMP_COUNT * COMP_SIZE); | ||
|
||
asm("mov c19, %w0\n\t" |
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 think there might be a mix of tabs and spaces here? Let's use all spaces.
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.
Ah, well, this will be fixed by the subsequent clang-format
process (which I haven't applied for the PR at this point). I prefer spaces myself, but clang-format
seems to put tabs.
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.
Does it? Ye gods! In general, it's best to do clang-format
before opening a PR. And then if it does mix tabs and spaces we'll just have to live with it (we can still grumble about it though :)).
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 ease, I've just ran one now [1]. In the future, I will run one at the point of making the PR, and the point of merging (until I hopefully am able to do the hooks thing).
[1] 5ae74cf
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.
Thanks!
You're going to have to spell out a few things in more details so that idiots like me can understand what's going on :) For example, what does "shows a possible design to achieve inter-compartment switching without (much) privilege escalation" mean? I guess this PR is still subject to the same "any compartment can get access to another compartments DDC and read/write to its heap" as the previous PR? |
Yes, however I briefly mention [1]:
This might be a good direction for a future PR, or even this one, to make it slightly meatier.
The top-level comment is a high-level view, so it's kept intentionally less exact (to not be overly verbose with detail), while the steps are more spelled out in the in-line comments. Do those not help? |
I forgot to mention in the leading comment, there are a things I'd like to improve. Primarily, the PCC bounds on And the security can (and should) be tightened further, primarily via sealing capabilities for the compartment switcher (DDC/PCC) and copying them in memory for each specific compartment. I have an idea of how to do that as well in here, and could integrate it in this PR, or a separate "security strengthening" pass. [1] https://github.com/capablevms/cheri-examples/pull/53/files#diff-bd3f0e982085d3f24aabff1a3429bddce60c0605c9d6047f8354c515a685b477R96 |
My guess is that the easiest way of handling this is for the compartment switcher to keep these things private to itself. But we can handle that in a later PR.
Sounds like a good idea for the next PR :) |
void executive_switch(struct comp c) | ||
{ | ||
void *__capability switch_cap = (void *__capability) switch_compartment; | ||
switch_cap = cheri_bounds_set(switch_cap, 80 * 4); |
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.
Ah, are these used as PCC bounds?
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.
Yes, hardcoded approximate bounds so things can execute, since I'm unaware of a way to compute this at compile-time, if it is possible. They would potentially be handled by the linker, an an actual implementation. Could maybe use labels, to mark start/end?
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.
Good question -- I have no idea! Certainly it should be possible via ELF but it might be possible some other way, though I doubt that it's portable either way. I'm fine with punting on that for this PR. Maybe add an issue to this repo "How to calculate a function's length at runtime" as we'll then be able to ask Edd for suggestions (he knows more about such things than I do!).
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.
Opened #54 to at least start a conversation maybe.
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.
Thanks!
new_comp.ddc = comp_ddc; | ||
|
||
void *__capability comp_fn = (void *__capability) _comp_fn; | ||
comp_fn = cheri_bounds_set(comp_fn, 40); |
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 guess these are also PCC bounds?
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.
Yes, bounds as well.
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 I suggest we use pcc
somewhere in the var name? Maybe something like comp_pcc
or similar? Failing that, a comment will help readers like me.
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've added a comment which helpfully clarifies things.
At this point, I think the following is a rather core property of CHERI, and maybe we should make it obvious somewhere: creating a capability which has the value
field the address of a function, then calling (or jumping to) that capability implies installing that capability as the PCC.
Please squash. |
This example adds a second compartment, and shows a possible design to achieve inter-compartment switching without (much) privilege escalation. In this file, we setup compartment information within array `comps` (`main.c:84`). This information will be used by the assembly function `switch_compartment`. Further, we save a capability to `switch_compartment()` in a register (`main.c:102`), to be able to call it from a bounded-PCC context, as well as a capability defining the area of memory with compartment information (`main.c:101`). These could be added to the memory area of each created compartment for better security, as well as sealed. Our two compartments provide one entry point each, `comp_f_fn` (`shared.S:93`), and `comp_g_fn` (`shared.S:109`). The design is that compartment `f` will perform a switch to compartment `g`, which performs some observable action (in this instance, sets a specific memory location to a specific integer value). The switching process in (almost) entirely bound within `switch_compartment`, on the execution side, and the memory area with compartment information, for memory access. We note almost, as the executable area is approximated (`main.c:96`).
a30278b
to
07f387e
Compare
Squashed. |
bors r+ |
Build succeeded: |
This example adds a second compartment, and shows a possible design to
achieve inter-compartment switching without (much) privilege escalation.
In this file, we setup compartment information within array
comps
(
main.c:84
). This information will be used by the assembly functionswitch_compartment
. Further, we save a capability toswitch_compartment()
in a register (main.c:102
), to be able to callit from a bounded-PCC context, as well as a capability defining the area
of memory with compartment information (
main.c:101
). These could beadded to the memory area of each created compartment for better
security, as well as sealed.
Our two compartments provide one entry point each,
comp_f_fn
(
shared.S:93
), andcomp_g_fn
(shared.S:109
). The design is thatcompartment
f
will perform a switch to compartmentg
, which performssome observable action (in this instance, sets a specific memory
location to a specific integer value). The switching process in (almost)
entirely bound within
switch_compartment
, on the execution side, andthe memory area with compartment information, for memory access. We note
almost, as the executable area is approximated (
main.c:96
).