mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-22 19:32:20 +00:00
vhost_rs: fix VhostUserConfig payload management
The VhostUserConfig carries a message with a payload, the contents of which depend on the kind of device being emulated. With this change, we calculate the offset of the payload within the message, check its size corresponds to the expected one, and pass it to the backend as a reference to a slice adjusted to the payload dimensions. The backend will be responsible of validating the payload, as it's the one aware of its expected contents. Signed-off-by: Sergio Lopez <slp@redhat.com>
This commit is contained in:
parent
2cc723f77b
commit
85e936d4bd
@ -265,7 +265,6 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
|
|||||||
if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 {
|
if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 {
|
||||||
return Err(Error::InvalidOperation);
|
return Err(Error::InvalidOperation);
|
||||||
}
|
}
|
||||||
self.check_request_size(&hdr, size, mem::size_of::<VhostUserConfig>())?;
|
|
||||||
self.get_config(&hdr, &buf)?;
|
self.get_config(&hdr, &buf)?;
|
||||||
}
|
}
|
||||||
MasterReq::SET_CONFIG => {
|
MasterReq::SET_CONFIG => {
|
||||||
@ -341,6 +340,10 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
|
|||||||
if !msg.is_valid() {
|
if !msg.is_valid() {
|
||||||
return Err(Error::InvalidMessage);
|
return Err(Error::InvalidMessage);
|
||||||
}
|
}
|
||||||
|
let payload_offset = mem::size_of::<VhostUserConfig>();
|
||||||
|
if buf.len() - payload_offset != msg.size as usize {
|
||||||
|
return Err(Error::InvalidMessage);
|
||||||
|
}
|
||||||
let flags = match VhostUserConfigFlags::from_bits(msg.flags) {
|
let flags = match VhostUserConfigFlags::from_bits(msg.flags) {
|
||||||
Some(val) => val,
|
Some(val) => val,
|
||||||
None => return Err(Error::InvalidMessage),
|
None => return Err(Error::InvalidMessage),
|
||||||
@ -519,6 +522,7 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
|
|||||||
fn new_reply_header<T: Sized>(
|
fn new_reply_header<T: Sized>(
|
||||||
&self,
|
&self,
|
||||||
req: &VhostUserMsgHeader<MasterReq>,
|
req: &VhostUserMsgHeader<MasterReq>,
|
||||||
|
payload_size: usize,
|
||||||
) -> Result<VhostUserMsgHeader<MasterReq>> {
|
) -> Result<VhostUserMsgHeader<MasterReq>> {
|
||||||
if mem::size_of::<T>() > MAX_MSG_SIZE {
|
if mem::size_of::<T>() > MAX_MSG_SIZE {
|
||||||
return Err(Error::InvalidParam);
|
return Err(Error::InvalidParam);
|
||||||
@ -527,7 +531,7 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
|
|||||||
Ok(VhostUserMsgHeader::new(
|
Ok(VhostUserMsgHeader::new(
|
||||||
req.get_code(),
|
req.get_code(),
|
||||||
VhostUserHeaderFlag::REPLY.bits(),
|
VhostUserHeaderFlag::REPLY.bits(),
|
||||||
mem::size_of::<T>() as u32,
|
(mem::size_of::<T>() + payload_size) as u32,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,7 +541,7 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
|
|||||||
res: Result<()>,
|
res: Result<()>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if self.reply_ack_enabled {
|
if self.reply_ack_enabled {
|
||||||
let hdr = self.new_reply_header::<VhostUserU64>(req)?;
|
let hdr = self.new_reply_header::<VhostUserU64>(req, 0)?;
|
||||||
let val = match res {
|
let val = match res {
|
||||||
Ok(_) => 0,
|
Ok(_) => 0,
|
||||||
Err(_) => 1,
|
Err(_) => 1,
|
||||||
@ -553,7 +557,7 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
|
|||||||
req: &VhostUserMsgHeader<MasterReq>,
|
req: &VhostUserMsgHeader<MasterReq>,
|
||||||
msg: &T,
|
msg: &T,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let hdr = self.new_reply_header::<T>(req)?;
|
let hdr = self.new_reply_header::<T>(req, 0)?;
|
||||||
self.main_sock.send_message(&hdr, msg, None)?;
|
self.main_sock.send_message(&hdr, msg, None)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -568,7 +572,7 @@ impl<S: VhostUserSlaveReqHandler> SlaveReqHandler<S> {
|
|||||||
T: Sized,
|
T: Sized,
|
||||||
P: Sized,
|
P: Sized,
|
||||||
{
|
{
|
||||||
let hdr = self.new_reply_header::<T>(req)?;
|
let hdr = self.new_reply_header::<T>(req, payload.len())?;
|
||||||
self.main_sock
|
self.main_sock
|
||||||
.send_message_with_payload(&hdr, msg, payload, None)?;
|
.send_message_with_payload(&hdr, msg, payload, None)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -15,7 +15,6 @@ use std::thread;
|
|||||||
use vhost_rs::vhost_user::message::{
|
use vhost_rs::vhost_user::message::{
|
||||||
VhostUserConfigFlags, VhostUserMemoryRegion, VhostUserProtocolFeatures,
|
VhostUserConfigFlags, VhostUserMemoryRegion, VhostUserProtocolFeatures,
|
||||||
VhostUserVirtioFeatures, VhostUserVringAddrFlags, VhostUserVringState,
|
VhostUserVirtioFeatures, VhostUserVringAddrFlags, VhostUserVringState,
|
||||||
VHOST_USER_CONFIG_OFFSET, VHOST_USER_CONFIG_SIZE,
|
|
||||||
};
|
};
|
||||||
use vhost_rs::vhost_user::{
|
use vhost_rs::vhost_user::{
|
||||||
Error as VhostUserError, Result as VhostUserResult, SlaveListener, VhostUserSlaveReqHandler,
|
Error as VhostUserError, Result as VhostUserResult, SlaveListener, VhostUserSlaveReqHandler,
|
||||||
@ -720,16 +719,6 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandler for VhostUserHandler<S> {
|
|||||||
size: u32,
|
size: u32,
|
||||||
_flags: VhostUserConfigFlags,
|
_flags: VhostUserConfigFlags,
|
||||||
) -> VhostUserResult<Vec<u8>> {
|
) -> VhostUserResult<Vec<u8>> {
|
||||||
if self.acked_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 {
|
|
||||||
return Err(VhostUserError::InvalidOperation);
|
|
||||||
} else if offset < VHOST_USER_CONFIG_OFFSET
|
|
||||||
|| offset >= VHOST_USER_CONFIG_SIZE
|
|
||||||
|| size > VHOST_USER_CONFIG_SIZE - VHOST_USER_CONFIG_OFFSET
|
|
||||||
|| size + offset > VHOST_USER_CONFIG_SIZE
|
|
||||||
{
|
|
||||||
return Err(VhostUserError::InvalidParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(self.backend.read().unwrap().get_config(offset, size))
|
Ok(self.backend.read().unwrap().get_config(offset, size))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,17 +728,6 @@ impl<S: VhostUserBackend> VhostUserSlaveReqHandler for VhostUserHandler<S> {
|
|||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
_flags: VhostUserConfigFlags,
|
_flags: VhostUserConfigFlags,
|
||||||
) -> VhostUserResult<()> {
|
) -> VhostUserResult<()> {
|
||||||
let size = buf.len() as u32;
|
|
||||||
if self.acked_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 {
|
|
||||||
return Err(VhostUserError::InvalidOperation);
|
|
||||||
} else if offset < VHOST_USER_CONFIG_OFFSET
|
|
||||||
|| offset >= VHOST_USER_CONFIG_SIZE
|
|
||||||
|| size > VHOST_USER_CONFIG_SIZE - VHOST_USER_CONFIG_OFFSET
|
|
||||||
|| size + offset > VHOST_USER_CONFIG_SIZE
|
|
||||||
{
|
|
||||||
return Err(VhostUserError::InvalidParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.backend
|
self.backend
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user