-
Notifications
You must be signed in to change notification settings - Fork 9
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
Create backward sentries for function returns and add more checks in cjalr #54
Merged
Commits on May 20, 2024
-
Based on discussions with David Chisnall:
Background: A typical (non-malicious) function call is as follows: - caller saves callee-saved registers (tmp registers) in the caller stack - caller saves arguments in arg registers, and overflow arguments in the callee stack - caller stores the return address (i.e. address of the instruction next to the call) in the return-address register (or stack in x86) - caller jumps to the entry point of the callee function (stored in a register). (RISC-V stores return address and jumps to the address in the register via a single jalr instruction) - callee executes the function; it might spill registers in the stack as needed - callee jumps back to the caller using the return-address register (jr) Even if the callee code is bug-free, the caller can violate callee’s CFI in two ways: - Jump to an address different from the entry point of the callee: + For instance, if the callee’s code internally performs operations in a specific branch which the caller did not have access to originally (because of various checks by the callee), the caller can instead directly jump to that branch of the callee (bypassing the checks) and execute that privileged code. (Note that PMP or MMU will not protect against this attack as a caller that can execute a function will have access to execute any part of the function; RISC-V has, for instance, proposed a “landing pad” to protect against this) - Setting a return address different from the correct return address + The caller can make a callee jump to an arbitrary location in some other library that the caller has access to. (This is the basis for Return Oriented Programming (ROP) attack, the returned location called a "gadget") + The return address that is spilled in the stack in overwritten (either with a buffer overflow attack or directly by feeding a wrong return address), and such gadgets chained. How CHERI prevents CFI: - Cross-compartment and Library functions can be jumped only through sealed capabilities (sentries) + jalr instruction to sentry ensures that the offset is 0, so the caller can only jump to published entry point sentries that are accessible by the caller, not arbitrary code inside another library + This prevents jumping to a privileged portion of the callee code bypassing the callee’s checks + This also prevents most of the ROP attacks using gadgets, as gadgets must be published entry points - Return address can only be manipulated by the caller to contain one of the following: + Sentry representing the correct return address + Sentry that the caller has access to already (either a function call entry point that the caller has access to, or the return address sentry of its caller, or some other return address sentry the caller previously had access to) + Non-sealed capability to its own code (Note that in all the 3 cases above, the manipulated return address has no effect, because the caller could have just jumped to that return address in the code) CHERIoT inherits all the above benefits. However, because CHERIoT allows manipulating the status of the interrupt through a function call (and function return), by encoding the interrupt type of the callee in the otype of the calling sentry and the interrupt type of the caller in the otype of the return-to-caller sentry, the following attack can occur: A caller calling an interrupt-disabling callee X can set the return address of the callee to be the same interrupt-disabling sentry to X. This means, the callee, on return will call itself all the while operating with interrupts disabled. This will lead to infinite repeated calls to X with interrupts disabled, violating availability. This attack can be prevented in CHERIoT by adding two new "backwards-edge" sentries and adding more checks on cjalr: otype 4: Backwards-edge, interrupts-disabled sentry otype 5: Backwards-edge, interrupts-enabled sentry. cjalr with a non-cnull link register always creates otype 4 or 5, i.e. backward sentries. (Currently it always creates otype 2 or 3 (forward explicit interrupt control sentries), so this is just a slightly different constant, but in the same place). - cjr $cra (a.k.a. cjalr $cra, $cnull, 0) must take a backwards-edge sentry. Sealing violation exception for other otypes. - cjr with a non-$cra target may be used only with otypes 0 (unsealed) or 1 (inheriting sentry). Sealing violation exception for other otypes. - cjalr with a non-zero return link register will generate a sealing violation for otypes 4 or 5 (backward sentry). - cjalr with a target that is otype 2 or 3 (forward, explicit interrupt control) must use $cra as the link register. Any other link register generates a sealing violation. Note that this disallows tail calls optimization of functions that change interrupt state. (They’re currently disabled and there’s a FIXME in the compiler to enable them. The compiler change is now to remove the FIXME, and then document this for programmers). Note that cjal currently sets a forward edge sentry on the link register. This change makes cjal set an unsealed cap in the link register. This is okay because cjal is not used in cross-compartment calls, and hence the caller and callee are ostensibly in the same security domain.
Configuration menu - View commit details
-
Copy full SHA for 971183c - Browse repository at this point
Copy the full SHA 971183cView commit details -
Configuration menu - View commit details
-
Copy full SHA for 774e678 - Browse repository at this point
Copy the full SHA 774e678View commit details
Commits on May 21, 2024
-
Configuration menu - View commit details
-
Copy full SHA for 04aa9c3 - Browse repository at this point
Copy the full SHA 04aa9c3View commit details -
Configuration menu - View commit details
-
Copy full SHA for 4de2462 - Browse repository at this point
Copy the full SHA 4de2462View commit details -
Configuration menu - View commit details
-
Copy full SHA for bf2c5ea - Browse repository at this point
Copy the full SHA bf2c5eaView commit details -
Configuration menu - View commit details
-
Copy full SHA for 039b141 - Browse repository at this point
Copy the full SHA 039b141View commit details
Commits on May 22, 2024
-
Configuration menu - View commit details
-
Copy full SHA for 73b967e - Browse repository at this point
Copy the full SHA 73b967eView commit details -
Configuration menu - View commit details
-
Copy full SHA for 4829964 - Browse repository at this point
Copy the full SHA 4829964View commit details -
Configuration menu - View commit details
-
Copy full SHA for d84c384 - Browse repository at this point
Copy the full SHA d84c384View commit details -
Configuration menu - View commit details
-
Copy full SHA for 624103b - Browse repository at this point
Copy the full SHA 624103bView commit details
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.