-
Notifications
You must be signed in to change notification settings - Fork 2k
virtio-queue: Error out on invalid available ring index #3156
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
Conversation
62cbafc
to
9c71485
Compare
src/devices/src/virtio/queue.rs
Outdated
if len > self.actual_size() { | ||
// We are choosing to interrupt execution since this could be a potential malicious driver | ||
// scenario. This way we also eliminate the risk of repeatedly logging and potentially | ||
// clogging the microVM through the log system. | ||
panic!("The number of available virtio descriptors is greater than queue size!"); | ||
} |
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.
if len > self.actual_size() { | |
// We are choosing to interrupt execution since this could be a potential malicious driver | |
// scenario. This way we also eliminate the risk of repeatedly logging and potentially | |
// clogging the microVM through the log system. | |
panic!("The number of available virtio descriptors is greater than queue size!"); | |
} | |
// We are choosing to interrupt execution since this could be a potential malicious driver | |
// scenario. This way we also eliminate the risk of repeatedly logging and potentially | |
// clogging the microVM through the log system. | |
assert!(len > self.actual_size(), "The number of available virtio descriptors is greater than queue size!"); |
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.
I prefer to use panic over assert in production code.
At least, this is what we have targeted to do until now so that it is easier to track the panic branches we have in production code.
Also, we have a panic handler installed when starting Firecracker (for flushing metrics and whatnot) which I am not sure would get called if we use asssert.
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.
At least, this is what we have targeted to do until now so that it is easier to track the panic branches we have in production code.
Could you expand, how do we currently track panic branches?
Also, we have a panic handler installed when starting Firecracker (for flushing metrics and whatnot) which I am not sure would get called if we use asssert.
The docs for std::assert
specify:
This will invoke the panic! macro if the provided expression cannot be evaluated to true at runtime.
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.
At least, this is what we have targeted to do until now so that it is easier to track the panic branches we have in production code.
Could you expand, how do we currently track panic branches?
We do not have an automated process or something of the kind. But if we were to use assert
s in production code (which are extensively used throughout unit tests) is going to be quite challenging to uncover those if the need arises. That would be one of the practical aspects of it.
Also, we have a panic handler installed when starting Firecracker (for flushing metrics and whatnot) which I am not sure would get called if we use asssert.
The docs for
std::assert
specify:This will invoke the panic! macro if the provided expression cannot be evaluated to true at runtime.
Nice, thanks for looking this up!
Can you tell me is there is a strong reason for using assert over panic here?
I prefer to use panic over assert in production code. At least, this is what we have targeted to do until now so that it is easier to track the panic branches we have in production code. Also, we have a panic handler installed when starting Firecracker (for flushing metrics and whatnot) which I am not sure would get called if we use asssert.
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.
It is simpler, but beyond that, no strong reasons.
src/devices/src/virtio/queue.rs
Outdated
if len > self.actual_size() { | ||
// We are choosing to interrupt execution since this could be a potential malicious driver | ||
// scenario. This way we also eliminate the risk of repeatedly logging and potentially | ||
// clogging the microVM through the log system. | ||
panic!("The number of available virtio descriptors is greater than queue size!"); | ||
} |
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.
if len > self.actual_size() { | |
// We are choosing to interrupt execution since this could be a potential malicious driver | |
// scenario. This way we also eliminate the risk of repeatedly logging and potentially | |
// clogging the microVM through the log system. | |
panic!("The number of available virtio descriptors is greater than queue size!"); | |
} | |
// We are choosing to interrupt execution since this could be a potential malicious driver | |
// scenario. This way we also eliminate the risk of repeatedly logging and potentially | |
// clogging the microVM through the log system. | |
assert!(len > self.actual_size(), "The number of available virtio descriptors is greater than queue size!"); |
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.
See above (#3156 (comment)).
9c71485
to
59bddd2
Compare
for j in 0..4 { | ||
vq.dtable[j].set( | ||
0x1000 * (j + 1) as u64, | ||
0x1000, | ||
VIRTQ_DESC_F_NEXT, | ||
(j + 1) as u16, | ||
); | ||
} |
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.
Nit: It is always safe to cast a u64
into a usize
but it is not always safe to do the reverse (with stricter linting this would currently raise a warning).
for j in 0..4 { | |
vq.dtable[j].set( | |
0x1000 * (j + 1) as u64, | |
0x1000, | |
VIRTQ_DESC_F_NEXT, | |
(j + 1) as u16, | |
); | |
} | |
for j in 0u64..4u64 { | |
vq.dtable[usize::from(j)].set( | |
0x1000 * (j + 1), | |
0x1000, | |
VIRTQ_DESC_F_NEXT, | |
(u16::from(j) + 1), | |
); | |
} |
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.
This is a good point @JonathanWoollett-Light! However, this applies to all queue tests in this file. Can you please open an issue for this? Thanks!
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.
With a wider context, maybe an issue should relate to adding #![warn(clippy::as_conversions)]
(https://rust-lang.github.io/rust-clippy/master/)?
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.
Or maybe modify add this restriction in the cargo clippy
command directly if possible.
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.
Created basic issue #3161
for j in 0..4 { | ||
vq.dtable[j].set( | ||
0x1000 * (j + 1) as u64, | ||
0x1000, | ||
VIRTQ_DESC_F_NEXT, | ||
(j + 1) as u16, | ||
); | ||
} |
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.
Nit: It is always safe to cast a u64 into a usize but it is not always safe to do the reverse (with stricter linting this would currently raise a warning).
for j in 0..4 { | |
vq.dtable[j].set( | |
0x1000 * (j + 1) as u64, | |
0x1000, | |
VIRTQ_DESC_F_NEXT, | |
(j + 1) as u16, | |
); | |
} | |
for j in 0u64..4u64 { | |
vq.dtable[usize::from(j)].set( | |
0x1000 * (j + 1), | |
0x1000, | |
VIRTQ_DESC_F_NEXT, | |
(u16::from(j) + 1), | |
); | |
} |
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.
Applies to all virtio queue unit tests. We need to open an issue for this.
We would also take into account newlines when checking that lines following co-author are only additional co-authors. Signed-off-by: Diana Popa <dpopa@amazon.com>
The number of descriptor chain heads to process should always be smaller or equal to the queue size, as the driver should never ask the VMM to process a available ring entry more than once. Checking and reporting such incorrect driver behavior can prevent potential hanging and Denial-of-Service from happening on the VMM side. Issue reported in rust-vmm/vm-virtio and fixed in rust-vmm/vm-virtio#196. Signed-off-by: Diana Popa <dpopa@amazon.com> Co-authored-by: Bo Chen <chen.bo@intel.com>
59bddd2
to
35d1abe
Compare
The number of descriptor chain heads to process should always be smaller or equal to the queue size, as the driver should never ask the VMM to process a available ring entry more than once. Checking and reporting such incorrect driver behavior can prevent potential hanging and Denial-of-Service from happening on the VMM side.
Issue reported in rust-vmm/vm-virtio and fixed in
rust-vmm/vm-virtio#196.
Signed-off-by: Diana Popa dpopa@amazon.com
Co-authored-by: Bo Chen chen.bo@intel.com
Fixes #3149.
License Acceptance
By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license.
PR Checklist
git commit -s
).unsafe
code is documented.CHANGELOG.md
.rust-vmm
.