forked from CHERIoT-Platform/cheriot-rtos
-
Notifications
You must be signed in to change notification settings - Fork 4
/
compartment.h
138 lines (124 loc) · 3.52 KB
/
compartment.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright Microsoft and CHERIoT Contributors.
// SPDX-License-Identifier: MIT
#pragma once
#include <cdefs.h>
#include <compartment-macros.h>
#include <stdint.h>
#ifdef __cplusplus
# include <cheri.hh>
template<typename T>
static inline CHERI::Capability<T> compart_seal(T *in)
{
void *key = SEALING_CAP();
return CHERI::Capability{in}.seal(key);
}
template<typename T>
static inline CHERI::Capability<T> compart_unseal(T *in)
{
void *key = SEALING_CAP();
return CHERI::Capability{in}.unseal(key);
}
template<typename T>
static inline auto compart_unseal(void *in)
{
return compart_unseal(static_cast<T *>(in));
}
#else
# include <cheri-builtins.h>
static inline void *compart_seal(void *in)
{
void *key = SEALING_CAP();
return cseal(in, key);
}
static inline void *compart_unseal(void *in)
{
void *key = SEALING_CAP();
return cunseal(in, key);
}
#endif
/**
* State for error handlers to use.
*
* Note: This structure should have the same layout as the register-save area.
*/
struct ErrorState
{
/**
* The faulting program counter. Error handlers may modify this but the
* result *must* point into the compartment's program counter capability.
* If it does not then the trusted stack will be unwound forcibly to the
* caller's compartment.
*
* Note: This is passed as an *untagged* capability. This allows error
* handlers to inspect the bounds and permissions, but does not convey the
* rights.
*/
void *pcc;
/**
* The register state where the fault occurred. These may be modified by
* an error handler.
*/
void *registers[15];
#ifdef __cplusplus
/**
* Templated method to get a reference to value of given
* CHERI::RegisterNumber.
*
* Static asserts that the register is one of the general purpose ones
* excluding CZR. This doesn't support getting PCC because in that case
* you can Use ErrorState.pcc directly.
*/
template<CHERI::RegisterNumber ARegisterNumber>
[[nodiscard]] void *&get_register_value()
{
static_assert(ARegisterNumber > CHERI::RegisterNumber::CZR &&
ARegisterNumber <= CHERI::RegisterNumber::CA5,
"get_register_value: invalid RegisterNumber");
return this->registers[static_cast<size_t>(ARegisterNumber) - 1];
}
/**
* Returns a pointer to the value of the given CHERI::RegisterNumber from
* this ErrorState.
*
* Will either select the appropriate index into ErrorState.registers
* accounting for the missing CZR, ErrorState.PCC, or if registerNumber is
* invalid or not contained in ErrorState then nullptr is returned.
*/
[[nodiscard]] void **
get_register_value(CHERI::RegisterNumber registerNumber)
{
if (registerNumber > CHERI::RegisterNumber::CZR &&
registerNumber <= CHERI::RegisterNumber::CA5)
{
return &this->registers[static_cast<size_t>(registerNumber) - 1];
}
if (registerNumber == CHERI::RegisterNumber::PCC)
{
return &this->pcc;
}
return nullptr;
}
#endif
};
/**
* Valid return values from an error handler.
*/
enum ErrorRecoveryBehaviour
{
/// Install the modified context.
InstallContext,
/// Unwind the trusted stack to the caller.
ForceUnwind
};
__BEGIN_DECLS
/**
* The error handler for the current compartment. A compartment may choose to
* implement this. If not implemented then compartment faults will unwind the
* trusted stack.
*/
__attribute__((
section(".compartment_error_handler"))) enum ErrorRecoveryBehaviour
compartment_error_handler(struct ErrorState *frame,
size_t mcause,
size_t mtval);
__END_DECLS