1use nix::errno::Errno;
4use std::{fmt, io};
5
6const NE_ERR_VCPU_ALREADY_USED: i32 = 256;
7const NE_ERR_VCPU_NOT_IN_CPU_POOL: i32 = 257;
8const NE_ERR_VCPU_INVALID_CPU_CORE: i32 = 258;
9const NE_ERR_INVALID_MEM_REGION_SIZE: i32 = 259;
10const NE_ERR_INVALID_MEM_REGION_ADDR: i32 = 260;
11const NE_ERR_UNALIGNED_MEM_REGION_ADDR: i32 = 261;
12const NE_ERR_MEM_REGION_ALREADY_USED: i32 = 262;
13const NE_ERR_MEM_NOT_HUGE_PAGE: i32 = 263;
14const NE_ERR_MEM_DIFFERENT_NUMA_NODE: i32 = 264;
15const NE_ERR_MEM_MAX_REGIONS: i32 = 265;
16const NE_ERR_NO_MEM_REGIONS_ADDED: i32 = 266;
17const NE_ERR_NO_VCPUS_ADDED: i32 = 267;
18const NE_ERR_ENCLAVE_MEM_MIN_SIZE: i32 = 268;
19const NE_ERR_FULL_CORES_NOT_USED: i32 = 269;
20const NE_ERR_NOT_IN_INIT_STATE: i32 = 270;
21const NE_ERR_INVALID_VCPU: i32 = 271;
22const NE_ERR_NO_CPUS_AVAIL_IN_POOL: i32 = 272;
23const NE_ERR_INVALID_PAGE_SIZE: i32 = 273;
24const NE_ERR_INVALID_FLAG_VALUE: i32 = 274;
25const NE_ERR_INVALID_ENCLAVE_CID: i32 = 275;
26
27#[derive(Debug)]
29pub enum LaunchError {
30 Ioctl(IoctlError),
32
33 MemInit(MemInitError),
35
36 CidInvalid,
38}
39
40impl LaunchError {
41 pub fn ioctl_err_from_errno() -> Self {
43 Self::Ioctl(IoctlError::from_errno())
44 }
45}
46
47impl From<nix::errno::Errno> for LaunchError {
48 fn from(_e: nix::errno::Errno) -> Self {
49 LaunchError::Ioctl(IoctlError::from_errno())
50 }
51}
52
53impl fmt::Display for LaunchError {
54 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55 let msg = match self {
56 Self::Ioctl(e) => format!("ioctl error: {e}"),
57 Self::MemInit(e) => format!("memory initialization error: {e}"),
58 Self::CidInvalid => "the value of the provided CID is invalid".to_string(),
59 };
60
61 write!(f, "{}", msg)
62 }
63}
64
65#[derive(Debug)]
67pub enum IoctlError {
68 CopyToUser,
70
71 InternalMemAllocation,
73
74 DifferentTaskMm,
76
77 InvalidFlagValue,
79
80 NoCpusAvailInPool,
82
83 NotInInitState,
85
86 VcpuAlreadyUsed,
88
89 VcpuNotInCpuPool,
91
92 VcpuInvalidCpuCore,
94
95 InvalidVcpu,
97
98 InvalidPhysicalMemRegion,
100
101 InvalidMemRegionSize,
103
104 InvalidMemRegionAddr,
106
107 UnalignedMemRegionAddr,
109
110 MemRegionAlreadyUsed,
112
113 MemNotHugePage,
115
116 MemDifferentNumaNode,
118
119 MemMaxRegions,
121
122 InvalidPageSize,
124
125 NoMemRegionsAdded,
127
128 NoVcpusAdded,
130
131 FullCoresNotUsed,
133
134 EnclaveMemMinSize,
136
137 InvalidEnclaveCid,
139
140 Unknown(Errno),
142}
143
144impl IoctlError {
145 pub fn from_errno() -> Self {
147 Self::from(Errno::last())
148 }
149}
150
151impl From<Errno> for IoctlError {
152 fn from(err: Errno) -> Self {
153 match err {
154 Errno::EFAULT => Self::CopyToUser,
156 Errno::ENOMEM => Self::InternalMemAllocation,
157 Errno::EIO => Self::DifferentTaskMm,
158 Errno::EINVAL => Self::InvalidPhysicalMemRegion,
159 _ => {
160 let raw = err as i32;
161 match raw {
162 NE_ERR_VCPU_ALREADY_USED => Self::VcpuAlreadyUsed,
164 NE_ERR_VCPU_NOT_IN_CPU_POOL => Self::VcpuNotInCpuPool,
165 NE_ERR_VCPU_INVALID_CPU_CORE => Self::VcpuInvalidCpuCore,
166 NE_ERR_INVALID_MEM_REGION_SIZE => Self::InvalidMemRegionSize,
167 NE_ERR_INVALID_MEM_REGION_ADDR => Self::InvalidMemRegionAddr,
168 NE_ERR_UNALIGNED_MEM_REGION_ADDR => Self::UnalignedMemRegionAddr,
169 NE_ERR_MEM_REGION_ALREADY_USED => Self::MemRegionAlreadyUsed,
170 NE_ERR_MEM_NOT_HUGE_PAGE => Self::MemNotHugePage,
171 NE_ERR_MEM_DIFFERENT_NUMA_NODE => Self::MemDifferentNumaNode,
172 NE_ERR_MEM_MAX_REGIONS => Self::MemMaxRegions,
173 NE_ERR_NO_MEM_REGIONS_ADDED => Self::NoMemRegionsAdded,
174 NE_ERR_NO_VCPUS_ADDED => Self::NoVcpusAdded,
175 NE_ERR_ENCLAVE_MEM_MIN_SIZE => Self::EnclaveMemMinSize,
176 NE_ERR_FULL_CORES_NOT_USED => Self::FullCoresNotUsed,
177 NE_ERR_NOT_IN_INIT_STATE => Self::NotInInitState,
178 NE_ERR_INVALID_VCPU => Self::InvalidVcpu,
179 NE_ERR_NO_CPUS_AVAIL_IN_POOL => Self::NoCpusAvailInPool,
180 NE_ERR_INVALID_PAGE_SIZE => Self::InvalidPageSize,
181 NE_ERR_INVALID_FLAG_VALUE => Self::InvalidFlagValue,
182 NE_ERR_INVALID_ENCLAVE_CID => Self::InvalidEnclaveCid,
183 _ => Self::Unknown(err),
184 }
185 }
186 }
187 }
188}
189
190impl fmt::Display for IoctlError {
191 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
192 let msg = match self {
193 Self::CopyToUser => "unable to copy data to/from userspace".to_string(),
194 Self::InternalMemAllocation => {
195 "memory allocation failure for internal bookkeeping variables".to_string()
196 }
197 Self::DifferentTaskMm => {
198 "current task mm is not the same as the one that created the enclave".to_string()
199 }
200 Self::InvalidFlagValue => "the value of the provided flag is invalid".to_string(),
201 Self::NoCpusAvailInPool => {
202 "no nitro enclave CPU pool set or no CPUs available in the pool".to_string()
203 }
204 Self::NotInInitState => "not in init (not yet started) state".to_string(),
205 Self::VcpuAlreadyUsed => "the provided vCPU is already used".to_string(),
206 Self::VcpuNotInCpuPool => {
207 "the provided vCPU is not available in the NE CPU pool".to_string()
208 }
209 Self::VcpuInvalidCpuCore => {
210 "the core id of the provided vCPU is invalid or out of range".to_string()
211 }
212 Self::InvalidVcpu => "the provided vCPU is not in the available CPUs range".to_string(),
213 Self::InvalidPhysicalMemRegion => {
214 "invalid physical memory region(s) (e.g. unaligned addresses)".to_string()
215 }
216 Self::InvalidMemRegionSize => {
217 "the memory size of the region is not a multiple of 2 MiB".to_string()
218 }
219 Self::InvalidMemRegionAddr => "invalid user space address given".to_string(),
220 Self::UnalignedMemRegionAddr => "unaligned user space address given".to_string(),
221 Self::MemRegionAlreadyUsed => "the memory region is already used".to_string(),
222 Self::MemNotHugePage => "the memory region is not backed by huge pages".to_string(),
223 Self::MemDifferentNumaNode => {
224 "the memory region is not from the same NUMA node as the CPUs".to_string()
225 }
226 Self::MemMaxRegions => {
227 "the number of memory regions set for the enclave reached maximum".to_string()
228 }
229 Self::InvalidPageSize => {
230 "the memory region is not backed by pages multiple of 2 MiB".to_string()
231 }
232 Self::NoMemRegionsAdded => "no memory regions are set".to_string(),
233 Self::NoVcpusAdded => "no vCPUs are set".to_string(),
234 Self::FullCoresNotUsed => "full core(s) not set for the enclave".to_string(),
235 Self::EnclaveMemMinSize => {
236 "enclave memory is less than minimum memory size (64 MiB)".to_string()
237 }
238 Self::InvalidEnclaveCid => "the provided enclave CID is invalid".to_string(),
239 Self::Unknown(e) => format!("unknown error: {e}"),
240 };
241
242 write!(f, "{}", msg)
243 }
244}
245
246#[derive(Debug)]
248pub enum MemInitError {
249 NoHugePageFound,
251
252 ImageMetadata(io::Error),
254
255 ImageRewind(io::Error),
257
258 ImageWriteIncomplete,
260
261 ImageRead(io::Error),
263
264 OffsetCheckOverflow,
266
267 ImagePlacementOverflow,
269}
270
271impl fmt::Display for MemInitError {
272 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
273 let msg = match self {
274 Self::NoHugePageFound => {
275 "a valid combination of hugepages could not be found for the requested size"
276 .to_string()
277 }
278 Self::ImageMetadata(e) => format!("unable to retrieve image metadata: {e}"),
279 Self::ImageRewind(e) => {
280 format!("unable to rewind image to beginning of image file: {e}")
281 }
282 Self::ImageWriteIncomplete => {
283 "unable to write total image file to memory regions".to_string()
284 }
285 Self::ImageRead(e) => format!("unable to read bytes from image file: {e}"),
286 Self::OffsetCheckOverflow => {
287 "overflow when checking if memory region write was greater than image offset"
288 .to_string()
289 }
290 Self::ImagePlacementOverflow => {
291 "overflow when calculating end of image region in guest memory".to_string()
292 }
293 };
294
295 write!(f, "{}", msg)
296 }
297}