-
Notifications
You must be signed in to change notification settings - Fork 45
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
Make read/write methods from GuestPtr unsafe, and copy_{from, to} methods from SecretsPage as well #382
Conversation
One case we cannot protect from (as we already discussed) is
As far as I can tell we already guard against this via |
You're right, I misread |
Several uses of pub fn read_caa(va: VirtAddr) -> Result<SvsmCaa, SvsmError> {
let calling_area = GuestPtr::<SvsmCaa>::new(virt_addr);
// SAFETY: HV and guests can't change VMSA's content, therefore CAA.
unsafe { calling_area.read() }
} |
No, I don't think that's how it works. First, the guest's VMSA is different from the SVSM's VMSA - the guest is allowed to update its VMSA. Second, the CA is located in a different physical page than the VMSA. When the guest sets the CA's physical address (via |
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.
Left some suggestions. On top of that, safety comments regarding the CAA should be updated based on my previous comment above.
That makes sense to me, thanks. I think there is a 3rd way to update the CA: through |
Longer term we should introduce a safe interface around this pattern, which does all the mapping and bounds checking internally and avoids the {
// Create TLB handle
tlb = tlb_gather::new();
// Create memory handle which can not outlive TLB handle
mem_handle = tlb.new_mapping(phys_addr, size);
let mut foo = mem_handle.read();
let mut bar = mem_handle::offset(1).read();
drop(mem_handle);
// mem_handle goes out of scope, unmapping the memory, TLB handle makes sure the virt range is not
// re-used until it is destroyed
mem_handle2 = tlb.new_mapping(paddr2, size2)
// ... use mem_handle2
// memhandle2 goes out of scope, mapping is removed
// tlb goes out of scope and flushes the TLB(s).
}
|
But for now it looks good to me, will merge it once @00xc approves. |
We still have some unresolved conversations. Once that's done I'll approve. |
I agree, this pattern happens in quite a few places and there is room for improvements.
Couldn't we just simply create new |
Checked with Carlos that the CA address updated in |
It wouldn't solve the fact that we would need to issue a flush for each guard. It also requires making |
There are some conflicts to resolve, please rebase. |
copy_from and coy_to methods from SecretsPage copy raw content from or to arbitrary virtual addresses. Both functions should be mark unsafe to that callers are aware that argument's correctness has to be verified. Signed-off-by: Thomas Leroy <[email protected]>
write_u8() can write arbitrary byte to abritrary address. Even though it already catches writes to unmapped memory, it doesn't prevent a malicious user to write at a dangerous place if it can control the parameters. It should be made unsafe. Signed-off-by: Thomas Leroy <[email protected]>
Once creating a GuestPtr, the read(), write() and write_ret() methods could grant arbitrary read/write if an attacker (HV or guest) can control the GuestPtr.ptr value, and the write*() parameters. We need to verify that this is not the case for the current calls, and to enforce an unsafe block for the future calls to make the caller validating the parameters. Signed-off-by: Thomas Leroy <[email protected]>
Done |
Leaving as draft because I still have doubts.
Providing partial fix for #359 (tasks 7, 8, 9).
My two interrogations are:
As already discussed with @00xc, if
start + offset
is valid butstart + offset + size_of::<T>
ends on an unmapped page or on an adjacent page belonging to another guest or the SVSM kernel (I don't really know if it's possible),read()
could raise a #PF and possibly return an error and panicking, or reading content from an unauthorized page. If such scenarii are possible, we should either:start + offset + size_of::<T>
doesn't cross the page endGuestPtr::read()/write()
for partial read/writeGuestPtr::read()/write()
to return an error that will be treated as a fatal error by the SVSM kernel (that would be valid DoS).PValidateRequest
(including the kernel memory). Moreover, the guest-provided entries suffer from the same issue, thepaddr
to pvalidate are only verified to be mapped. A guest could make the SVSM kernel pvalidate any page. For the core protocol handlers that work with guest-provided paddrs, my understanding is that we should validate that paddrs only belong to the guest's memory region. I left TODOs is some places (not all of them) to points where there is this issue.