block: do not allow guest to not negotiate VIRTIO_BLK_F_RO
Unlike most virtio feature bits, VIRTIO_BLK_F_RO is not optional. It indicates that the host is refusing to permit write operations, and the guest must not be allowed to override it. However, the block device currently does not enforce this. If the guest does not negotiate VIRTIO_BLK_F_RO, the block device will think the device is writable and forward write requests to the backend. This is not a security problem right now because the backing device of a read-only device is always opened read-only. The kernel will thus reject the write operations with EBADF. If support is added for receiving the backing device file descriptor via SCM_RIGHTS (#7704), it will be possible to have a read-only block device backed by a writable file descriptor. This would make the bug a genuine security vulnerability. Fix the bug by explicitly checking if VIRTIO_BLK_F_RO was offered but not negotiated. In this case, log a warning and proceed as if the guest did acknowledge the feature. This always indicates a guest driver bug. Fixes: #7697 Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
This commit is contained in:
parent
80ea1fe62d
commit
ce93686ad2
1 changed files with 7 additions and 0 deletions
|
|
@ -986,6 +986,13 @@ impl VirtioDevice for Block {
|
|||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
mut queues: Vec<(usize, Queue, EventFd)>,
|
||||
) -> ActivateResult {
|
||||
// See if the guest didn't ack the device being read-only.
|
||||
// If so, warn and pretend it did.
|
||||
let original_acked_features = self.common.acked_features;
|
||||
self.common.acked_features |= self.common.avail_features & (1u64 << VIRTIO_BLK_F_RO);
|
||||
if original_acked_features != self.common.acked_features {
|
||||
warn!("Guest did not acknowledge that device is read-only, acting as if it did!");
|
||||
}
|
||||
self.common.activate(&queues, interrupt_cb.clone())?;
|
||||
|
||||
self.update_writeback();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue