virtio-devices: copy VSock header from guest - #7530
Conversation
|
@alyssais Is this something you could take a look at? I think you might be the most experienced in this code. |
|
Can do, but probably not this week. |
@alyssais Happy New Year - any chance to you can take a look at this? |
alyssais
left a comment
There was a problem hiding this comment.
Looks fine. I think it would be nicer to use GuestMemory but this fix shouldn't be blocked on that since it has a security impact.
| hdr: *mut u8, | ||
| // We still hold the header address in guest memory. We need to write back the modified | ||
| // header in RX buffers. | ||
| guest_hdr_ptr: *mut u8, |
There was a problem hiding this comment.
Would be nice to use a GuestAddress here to be more robust against similar issues in future. Might also simplify from_tx_virtq_head and from_rx_virtq_head.
There was a problem hiding this comment.
guest_hdr_ptr is now guest_hdr_addr and it's a GuestAddr
Thanks for the review! I'll have the time this weekend to update with GuestMemory use |
|
@alyssais PR updated using |
|
|
||
| let hdr_ptr = | ||
| get_host_address_range(desc_chain.memory(), guest_hdr_addr, VSOCK_PKT_HDR_SIZE) | ||
| .ok_or(VsockError::GuestMemory)?; |
There was a problem hiding this comment.
How about dest_chain.memory().get_slice(guest_hdr_addr, VSOCK_PKT_HDR_SIZE), and then we avoid the unsafe?
There was a problem hiding this comment.
Much cleaner indeed. Updated
| // we need to copy the content of the header in the VMM's memory. | ||
| // After the copy, the hdr content can be trusted since the guest can't change its | ||
| // content anymore. | ||
|
|
There was a problem hiding this comment.
nit: Maybe we could maybe we could condense some of the whitespace in this block. Do we need quite so many empty lines?
There was a problem hiding this comment.
do you mean something like:
// To avoid TOCTOU issues when reading/writing the VSock packet header in guest memory,
// we need to copy the content of the header in the VMM's memory. After the copy, the
// hdr content can be trusted since the guest can't change its content anymore.
let mut hdr = [0u8; VSOCK_PKT_HDR_SIZE];
There was a problem hiding this comment.
I was referring to the whitespace on lines 143, 145, 246, 248. I like vertical whitespace when it helps group logical bits together e.g. grouping where the data is created, size calculated and then copied would make a good grouping. If you use too much whitespace it can be hard to see the logical groups (since then you can't see where another logical group of functionality is)
There was a problem hiding this comment.
Makes sense. I just remove those whitespaces
VsockPacket::hdr holds a raw pointer to the address of the VSock packet header, which is in guest memory. It opens the door to double-fetch (or TOCTOU) race conditions. Therefore, VSockPacket::hdr content can't be trusted since it can be arbitrarily changed by the guest, at any time. To mitigate this, we can copy the header content to an array in VMM's memory that the guest can't modify. Signed-off-by: Thomas Leroy <[email protected]>
|
@p4zuu Thank you for your PR. It's now 🚀 |
This issue has been reported privately to @rbradford.
VsockPacket::hdr holds a raw pointer to the address of the VSock packet header, which is in guest memory. It opens the door to double-fetch (or TOCTOU) race conditions. Therefore, VSockPacket::hdr content can't be trusted since it can be arbitrarily changed by the guest, at any time.
To mitigate this, we can copy the header content to an array in VMM's memory that the guest can't modify.
I managed to trigger this race condition by changing the
lenfield header just before this line. This triggers a slice out-of-bounds and makes the VMM process panic. Since the packet header is allocated by the guest kernel, the PoC needs a guest kernel module to scan kernel memory and change the len field. I can provide the source files for the PoC.It seems that some (maybe most) of the VSock code comes from firecracker, which had the same issue but fixed it. This PR takes some pieces of code from the firecracker codebase.
Also, I'm not a VSock expert so a more experienced reviewer would be appreciated.