|
20 | 20 | #include "Registers.hpp"
|
21 | 21 | #include "DwarfParser.hpp"
|
22 | 22 | #include "config.h"
|
| 23 | +#if defined(__CHERI_PURE_CAPABILITY__) && defined(_LIBUNWIND_CHERI_C18N_SUPPORT) |
23 | 24 | #include "CompartmentInfo.hpp"
|
| 25 | +#endif // __CHERI_PURE_CAPABILITY__ && _LIBUNWIND_CHERI_C18N_SUPPORT |
24 | 26 |
|
25 | 27 |
|
26 | 28 | namespace libunwind {
|
@@ -55,14 +57,6 @@ class DwarfInstructions {
|
55 | 57 | typedef typename CFI_Parser<A>::FDE_Info FDE_Info;
|
56 | 58 | typedef typename CFI_Parser<A>::CIE_Info CIE_Info;
|
57 | 59 |
|
58 |
| -#if defined(__CHERI_PURE_CAPABILITY__) && defined(_LIBUNWIND_CHERI_C18N_SUPPORT) |
59 |
| - static pint_t restoreRegistersFromSandbox(pint_t csp, A &addressSpace, |
60 |
| - R &newRegisters, |
61 |
| - CompartmentInfo &CI, pint_t sealer); |
62 |
| - static bool isCompartmentTransitionTrampoline(pint_t ecsp, A &addressSpace, |
63 |
| - CompartmentInfo &CI, |
64 |
| - pint_t returnAddress); |
65 |
| -#endif |
66 | 60 | static pint_t evaluateExpression(pint_t expression, A &addressSpace,
|
67 | 61 | const R ®isters,
|
68 | 62 | pint_t initialStackValue);
|
@@ -105,6 +99,9 @@ class DwarfInstructions {
|
105 | 99 | static bool getRA_SIGN_STATE(A &addressSpace, R registers, pint_t cfa,
|
106 | 100 | PrologInfo &prolog);
|
107 | 101 | #endif
|
| 102 | +#if defined(__CHERI_PURE_CAPABILITY__) && defined(_LIBUNWIND_CHERI_C18N_SUPPORT) |
| 103 | + static constexpr CompartmentInfo<A, R> CompartInfo{}; |
| 104 | +#endif |
108 | 105 | };
|
109 | 106 |
|
110 | 107 | template <typename R>
|
@@ -255,75 +252,6 @@ bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers,
|
255 | 252 | }
|
256 | 253 | #endif
|
257 | 254 |
|
258 |
| -#if defined(__CHERI_PURE_CAPABILITY__) && defined(_LIBUNWIND_CHERI_C18N_SUPPORT) |
259 |
| -#if defined(_LIBUNWIND_TARGET_AARCH64) |
260 |
| -template <typename A, typename R> |
261 |
| -typename A::pint_t DwarfInstructions<A, R>::restoreRegistersFromSandbox( |
262 |
| - pint_t csp, A &addressSpace, R &newRegisters, CompartmentInfo &CI, |
263 |
| - pint_t sealer) { |
264 |
| - // Get the unsealed executive CSP |
265 |
| - assert(__builtin_cheri_tag_get((void *)csp) && |
266 |
| - "Executive stack should be tagged!"); |
267 |
| - // Derive the new executive CSP |
268 |
| - pint_t nextCSP = addressSpace.getP(csp + CI.kNextOffset); |
269 |
| - // Seal ECSP |
270 |
| - nextCSP = __builtin_cheri_seal(nextCSP, sealer); |
271 |
| - assert(__builtin_cheri_tag_get((void *)nextCSP) && |
272 |
| - "Next executive stack should be tagged!"); |
273 |
| - CHERI_DBG("SANDBOX: SETTING EXECUTIVE CSP %#p\n", (void *)nextCSP); |
274 |
| - newRegisters.setTrustedStack(nextCSP); |
275 |
| - // Restore the next RCSP |
276 |
| - pint_t nextRCSP = addressSpace.getP(csp + CI.kNewSPOffset); |
277 |
| - newRegisters.setSP(nextRCSP); |
278 |
| - CHERI_DBG("SANDBOX: SETTING RESTRICTED CSP: %#p\n", |
279 |
| - (void *)newRegisters.getSP()); |
280 |
| - // Restore callee-saved registers |
281 |
| - // Restore: c19-c28 |
282 |
| - for (size_t i = 0, offset = CI.kCalleeSavedOffset; i < CI.kCalleeSavedCount; |
283 |
| - ++i, offset += sizeof(void *)) { |
284 |
| - pint_t regValue = addressSpace.getP(csp + offset); |
285 |
| - newRegisters.setCapabilityRegister(UNW_ARM64_C19 + i, regValue); |
286 |
| - CHERI_DBG("SETTING CALLEE SAVED CAPABILITY REGISTER: %lu (%s): %#p " |
287 |
| - "(offset=%zu)\n", |
288 |
| - UNW_ARM64_C19 + i, |
289 |
| - newRegisters.getRegisterName(UNW_ARM64_C19 + i), (void *)regValue, |
290 |
| - offset); |
291 |
| - } |
292 |
| - // Restore the frame pointer |
293 |
| - pint_t newFP = addressSpace.getP(csp); |
294 |
| - CHERI_DBG("SANDBOX: SETTING CFP %#p\n", (void *)newFP); |
295 |
| - newRegisters.setFP(newFP); |
296 |
| - // Get the new return address. |
297 |
| - return addressSpace.getP(csp + CI.kPCOffset); |
298 |
| -} |
299 |
| - |
300 |
| -template <typename A, typename R> |
301 |
| -bool DwarfInstructions<A, R>::isCompartmentTransitionTrampoline( |
302 |
| - pint_t ecsp, A &addressSpace, CompartmentInfo &CI, pint_t returnAddress) { |
303 |
| - ptraddr_t expectedReturnAddress = |
304 |
| - addressSpace.template get<ptraddr_t>(ecsp + CI.kReturnAddressOffset); |
305 |
| - CHERI_DBG( |
306 |
| - "isCompartmentTransitionTrampoline(): expectedReturnAddress: 0x%lx\n", |
307 |
| - expectedReturnAddress); |
308 |
| - return expectedReturnAddress == returnAddress; |
309 |
| -} |
310 |
| -#else // _LIBUNWIND_TARGET_AARCH64 |
311 |
| -template <typename A, typename R> |
312 |
| -typename A::pint_t DwarfInstructions<A, R>::restoreRegistersFromSandbox( |
313 |
| - pint_t csp, A &addressSpace, R &newRegisters, CompartmentInfo &CI, |
314 |
| - pint_t sealer) { |
315 |
| - assert(0 && "not implemented on this architecture"); |
316 |
| - return (pint_t)0; |
317 |
| -} |
318 |
| -template <typename A, typename R> |
319 |
| -bool DwarfInstructions<A, R>::isCompartmentTransitionTrampoline( |
320 |
| - pint_t ecsp, A &addressSpace, CompartmentInfo &CI, pint_t returnAddress) { |
321 |
| - assert(0 && "not implemented on this architecture"); |
322 |
| - return false; |
323 |
| -} |
324 |
| -#endif // _LIBUNWIND_TARGET_AARCH64 |
325 |
| -#endif // __CHERI_PURE_CAPABILITY__ && _LIBUNWIND_CHERI_C18N_SUPPORT |
326 |
| - |
327 | 255 | template <typename A, typename R>
|
328 | 256 | int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pc_t pc,
|
329 | 257 | pint_t fdeStart, R ®isters,
|
@@ -484,23 +412,14 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pc_t pc,
|
484 | 412 | #endif
|
485 | 413 |
|
486 | 414 | #if defined(__CHERI_PURE_CAPABILITY__) && defined(_LIBUNWIND_CHERI_C18N_SUPPORT)
|
487 |
| - // If the sealer is not valid (only the case when we're running without |
488 |
| - // c18n), check if the return address has the executive mode bit set. |
489 |
| - // If so, we should be calling into the c18n RTLD as this is a |
490 |
| - // compartment boundary. We need to restore registers from the executive |
491 |
| - // stack and ask rtld for it. |
492 |
| - uintptr_t sealer = addressSpace.getUnwindSealer(); |
493 |
| - if (addressSpace.isValidSealer(sealer)) { |
| 415 | + // If c18n is enabled, check if we are at a compartment boundary. If so, |
| 416 | + // restore registers from the trusted stack by asking rtld for them. |
| 417 | + if (CompartInfo.isC18NEnabled()) { |
494 | 418 | pint_t csp = registers.getTrustedStack();
|
495 |
| - if (__builtin_cheri_sealed_get(csp)) |
496 |
| - csp = __builtin_cheri_unseal(csp, sealer); |
497 |
| - CompartmentInfo &CI = CompartmentInfo::sThisCompartmentInfo; |
498 |
| - if (csp != 0 && isCompartmentTransitionTrampoline(csp, addressSpace, CI, |
499 |
| - returnAddress)) { |
| 419 | + if (CompartInfo.isC18NTramp(returnAddress, csp)) { |
500 | 420 | CHERI_DBG("%#p: detected a trampoline, unwinding from sandbox\n",
|
501 | 421 | (void *)returnAddress);
|
502 |
| - returnAddress = restoreRegistersFromSandbox( |
503 |
| - csp, addressSpace, newRegisters, CI, sealer); |
| 422 | + returnAddress = CompartInfo.fillC18NState(newRegisters, csp); |
504 | 423 | }
|
505 | 424 | }
|
506 | 425 | #endif
|
|
0 commit comments