Skip to content

Commit 1cec116

Browse files
authored
Merge pull request #364 from 00xc/sev/ghcb-safebuf
sev/ghcb: fix `GHCB::write_buffer()` soundness issues and clean up `GHCBExitCode`
2 parents dcbc558 + 82f54ee commit 1cec116

File tree

1 file changed

+29
-32
lines changed

1 file changed

+29
-32
lines changed

kernel/src/sev/ghcb.rs

+29-32
Original file line numberDiff line numberDiff line change
@@ -118,18 +118,19 @@ impl From<GhcbError> for SvsmError {
118118
}
119119
}
120120

121-
enum GHCBExitCode {}
122-
123-
impl GHCBExitCode {
124-
pub const RDTSC: u64 = 0x6e;
125-
pub const IOIO: u64 = 0x7b;
126-
pub const MSR: u64 = 0x7c;
127-
pub const RDTSCP: u64 = 0x87;
128-
pub const SNP_PSC: u64 = 0x8000_0010;
129-
pub const GUEST_REQUEST: u64 = 0x8000_0011;
130-
pub const GUEST_EXT_REQUEST: u64 = 0x8000_0012;
131-
pub const AP_CREATE: u64 = 0x80000013;
132-
pub const HV_DOORBELL: u64 = 0x8000_0014;
121+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
122+
#[repr(u64)]
123+
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
124+
enum GHCBExitCode {
125+
RDTSC = 0x6e,
126+
IOIO = 0x7b,
127+
MSR = 0x7c,
128+
RDTSCP = 0x87,
129+
SNP_PSC = 0x8000_0010,
130+
GUEST_REQUEST = 0x8000_0011,
131+
GUEST_EXT_REQUEST = 0x8000_0012,
132+
AP_CREATE = 0x80000013,
133+
HV_DOORBELL = 0x8000_0014,
133134
}
134135

135136
#[derive(Clone, Copy, Debug)]
@@ -336,15 +337,15 @@ impl GHCB {
336337

337338
fn vmgexit(
338339
&mut self,
339-
exit_code: u64,
340+
exit_code: GHCBExitCode,
340341
exit_info_1: u64,
341342
exit_info_2: u64,
342343
) -> Result<(), GhcbError> {
343344
// GHCB is version 2
344345
self.set_version_valid(2);
345346
// GHCB Follows standard format
346347
self.set_usage_valid(0);
347-
self.set_exit_code_valid(exit_code);
348+
self.set_exit_code_valid(exit_code as u64);
348349
self.set_exit_info_1_valid(exit_info_1);
349350
self.set_exit_info_2_valid(exit_info_2);
350351

@@ -397,28 +398,24 @@ impl GHCB {
397398
Ok(())
398399
}
399400

400-
fn write_buffer<T>(&mut self, data: &T, offset: isize) -> Result<(), GhcbError>
401+
fn write_buffer<T>(&mut self, data: &T, offset: usize) -> Result<(), GhcbError>
401402
where
402-
T: Sized,
403+
T: Copy,
403404
{
404-
let size: isize = mem::size_of::<T>() as isize;
405-
406-
if offset < 0 || offset + size > (GHCB_BUFFER_SIZE as isize) {
405+
offset
406+
.checked_add(mem::size_of::<T>())
407+
.filter(|end| *end <= GHCB_BUFFER_SIZE)
408+
.ok_or(GhcbError::InvalidOffset)?;
409+
410+
// SAFETY: we have verified that the offset is within bounds and does
411+
// not overflow
412+
let dst = unsafe { self.buffer.as_mut_ptr().add(offset) };
413+
if dst.align_offset(mem::align_of::<T>()) != 0 {
407414
return Err(GhcbError::InvalidOffset);
408415
}
409416

410-
unsafe {
411-
let dst = self
412-
.buffer
413-
.as_mut_ptr()
414-
.cast::<u8>()
415-
.offset(offset)
416-
.cast::<T>();
417-
let src = data as *const T;
418-
419-
ptr::copy_nonoverlapping(src, dst, 1);
420-
}
421-
417+
// SAFETY: we have verified the pointer is aligned and within bounds.
418+
unsafe { dst.cast::<T>().copy_from_nonoverlapping(data, 1) }
422419
Ok(())
423420
}
424421

@@ -471,7 +468,7 @@ impl GHCB {
471468
};
472469
let pgsize = usize::from(size);
473470
let entry = self.psc_entry(paddr, op_mask, 0, size);
474-
let offset: isize = (entries as isize) * 8 + 8;
471+
let offset = usize::from(entries) * 8 + 8;
475472
self.write_buffer(&entry, offset)?;
476473
entries += 1;
477474
paddr = paddr + pgsize;

0 commit comments

Comments
 (0)