-
Notifications
You must be signed in to change notification settings - Fork 111
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
move encrypt_op{_sev} into system ioctls #259
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -682,6 +682,97 @@ impl Kvm { | |||||||||
let run_mmap_size = self.get_vcpu_mmap_size()?; | ||||||||||
Ok(new_vmfd(File::from_raw_fd(fd), run_mmap_size)) | ||||||||||
} | ||||||||||
|
||||||||||
/// Issues platform-specific memory encryption commands to manage encrypted VMs if | ||||||||||
/// the platform supports creating those encrypted VMs. | ||||||||||
/// | ||||||||||
/// Currently, this ioctl is used for issuing Secure Encrypted Virtualization | ||||||||||
/// (SEV) commands on AMD Processors. | ||||||||||
/// | ||||||||||
/// See the documentation for `KVM_MEMORY_ENCRYPT_OP` in the | ||||||||||
/// [KVM API doc](https://www.kernel.org/doc/Documentation/virtual/kvm/api.txt). | ||||||||||
/// | ||||||||||
/// For SEV-specific functionality, prefer safe wrapper: | ||||||||||
/// - [`encrypt_op_sev`](Self::encrypt_op_sev) | ||||||||||
/// | ||||||||||
/// # Safety | ||||||||||
/// | ||||||||||
/// This function is unsafe because there is no guarantee `T` is valid in this context, how | ||||||||||
/// much data kernel will read from memory and where it will write data on error. | ||||||||||
/// | ||||||||||
/// # Arguments | ||||||||||
/// | ||||||||||
/// * `fd` - the RawFd to be operated on. (`VmFd`, `VcpuFd`, etc.) | ||||||||||
/// * `op` - an opaque platform specific structure. | ||||||||||
/// | ||||||||||
/// # Example | ||||||||||
#[cfg_attr(has_sev, doc = "```rust")] | ||||||||||
#[cfg_attr(not(has_sev), doc = "```rust,no_run")] | ||||||||||
/// # extern crate kvm_ioctls; | ||||||||||
/// # extern crate kvm_bindings; | ||||||||||
/// use kvm_bindings::bindings::kvm_sev_cmd; | ||||||||||
/// # use kvm_ioctls::Kvm; | ||||||||||
/// | ||||||||||
/// let kvm = Kvm::new().unwrap(); | ||||||||||
/// let vm = kvm.create_vm().unwrap(); | ||||||||||
/// | ||||||||||
/// // Initialize the SEV platform context. | ||||||||||
/// let mut init: kvm_sev_cmd = Default::default(); | ||||||||||
/// unsafe { kvm.encrypt_op(&vm, &mut init).unwrap() }; | ||||||||||
/// ``` | ||||||||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] | ||||||||||
pub unsafe fn encrypt_op<T>(&self, fd: &impl AsRawFd, op: *mut T) -> Result<()> { | ||||||||||
let ret = ioctl_with_mut_ptr(fd, KVM_MEMORY_ENCRYPT_OP(), op); | ||||||||||
Comment on lines
+724
to
+725
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not familiar with AMD-SEV, but if this is a system ioctl, shouldn't it be issued on the KVM fd? e.g.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I believe you're right. It was brought to my attention that I was referencing stale documentation. However, the changes to the ioctl should be so that it is both a vm ioctl and a vcpu ioctl, so that requires an update on my end. |
||||||||||
if ret == 0 { | ||||||||||
Ok(()) | ||||||||||
} else { | ||||||||||
Err(errno::Error::last()) | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
/// Issue common lifecycle events of SEV guests, such as launching, running, snapshotting, | ||||||||||
/// migrating and decommissioning via `KVM_MEMORY_ENCRYPT_OP` ioctl. | ||||||||||
/// | ||||||||||
/// Kernel documentation states that this ioctl can be used for testing whether SEV is enabled | ||||||||||
/// by sending `NULL`. To do that, pass [`std::ptr::null_mut`](std::ptr::null_mut) to [`encrypt_op`](Self::encrypt_op). | ||||||||||
/// | ||||||||||
/// See the documentation for Secure Encrypted Virtualization (SEV). | ||||||||||
/// | ||||||||||
/// # Arguments | ||||||||||
/// | ||||||||||
/// * `fd` - the RawFd to be operated on. (`VmFd`, `VcpuFd`, etc.) | ||||||||||
/// * `op` - SEV-specific structure. For details check the | ||||||||||
/// [Secure Encrypted Virtualization (SEV) doc](https://www.kernel.org/doc/Documentation/virtual/kvm/amd-memory-encryption.rst). | ||||||||||
/// | ||||||||||
/// # Example | ||||||||||
#[cfg_attr(has_sev, doc = "```rust")] | ||||||||||
#[cfg_attr(not(has_sev), doc = "```rust,no_run")] | ||||||||||
/// # extern crate kvm_ioctls; | ||||||||||
/// # extern crate kvm_bindings; | ||||||||||
/// # use std::{os::raw::c_void, ptr::null_mut}; | ||||||||||
/// use kvm_bindings::bindings::kvm_sev_cmd; | ||||||||||
/// # use kvm_ioctls::Kvm; | ||||||||||
/// | ||||||||||
/// let kvm = Kvm::new().unwrap(); | ||||||||||
/// let vm = kvm.create_vm().unwrap(); | ||||||||||
/// | ||||||||||
/// // Check whether SEV is enabled, optional. | ||||||||||
/// assert!(unsafe { kvm.encrypt_op(&vm, null_mut() as *mut c_void) }.is_ok()); | ||||||||||
/// | ||||||||||
/// // Initialize the SEV platform context. | ||||||||||
/// let mut init: kvm_sev_cmd = Default::default(); | ||||||||||
/// kvm.encrypt_op_sev(&vm, &mut init).unwrap(); | ||||||||||
/// ``` | ||||||||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] | ||||||||||
pub fn encrypt_op_sev( | ||||||||||
&self, | ||||||||||
fd: &impl AsRawFd, | ||||||||||
op: &mut kvm_bindings::kvm_sev_cmd, | ||||||||||
) -> Result<()> { | ||||||||||
// SAFETY: Safe because we know that kernel will only read the correct amount of memory | ||||||||||
// from our pointer and we know where it will write it (op.error). | ||||||||||
unsafe { self.encrypt_op(fd, op) } | ||||||||||
} | ||||||||||
} | ||||||||||
|
||||||||||
impl AsRawFd for Kvm { | ||||||||||
|
@@ -979,4 +1070,15 @@ mod tests { | |||||||||
} | ||||||||||
assert_eq!(faulty_kvm.create_vm().err().unwrap().errno(), badf_errno); | ||||||||||
} | ||||||||||
|
||||||||||
#[test] | ||||||||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] | ||||||||||
#[cfg_attr(not(has_sev), ignore)] | ||||||||||
fn test_encrypt_op_sev() { | ||||||||||
let kvm = Kvm::new().unwrap(); | ||||||||||
let vm = kvm.create_vm().unwrap(); | ||||||||||
|
||||||||||
let mut init: kvm_bindings::kvm_sev_cmd = Default::default(); | ||||||||||
assert!(kvm.encrypt_op_sev(&vm, &mut init).is_ok()); | ||||||||||
} | ||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add the PR number here?