Skip to content
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

Use u32 to describe vsock related buffer sizes #4637

Closed
wants to merge 3 commits into from

Conversation

brandonpike
Copy link

@brandonpike brandonpike commented Jun 10, 2024

Move to u32 for vsock module. We can translate from u32 to usize as needed.

Changes

  • Change VsockConnection::peer_avail_credit to return u32
  • Change VsockPacket::{buf_size, read_at_offset_from, write_from_offset_to} parameters & return types to u32
  • Change IoVecBuffer[Mut]::{read,write}_volatile_at to u32

Closes #4627

Reason

Follow-up to #4556.

License Acceptance

By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license. For more information on following Developer
Certificate of Origin and signing off your commits, please check
CONTRIBUTING.md.

PR Checklist

  • If a specific issue led to this PR, this PR closes the issue.
  • The description of changes is clear and encompassing.
  • Any required documentation changes (code and docs) are included in this
    PR.
  • API changes follow the Runbook for Firecracker API changes.
  • User-facing changes are mentioned in CHANGELOG.md.
  • All added/changed functionality is tested.
  • New TODOs link to an issue.
  • Commits meet
    contribution quality standards.

  • This functionality cannot be added in rust-vmm.

Move to u32 for vsock module. We can upsize from u32 to usize as needed.

Signed-off-by: brandonpike <[email protected]>
@brandonpike brandonpike marked this pull request as ready for review June 12, 2024 20:15
Copy link

codecov bot commented Jun 17, 2024

Codecov Report

Attention: Patch coverage is 96.87500% with 2 lines in your changes missing coverage. Please review.

Project coverage is 82.08%. Comparing base (8f0dcb1) to head (d514899).
Report is 302 commits behind head on main.

Files with missing lines Patch % Lines
src/vmm/src/devices/virtio/iovec.rs 94.73% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4637   +/-   ##
=======================================
  Coverage   82.08%   82.08%           
=======================================
  Files         255      255           
  Lines       31257    31262    +5     
=======================================
+ Hits        25656    25661    +5     
  Misses       5601     5601           
Flag Coverage Δ
4.14-c5n.metal 79.57% <96.87%> (+<0.01%) ⬆️
4.14-c7g.metal ?
4.14-m5n.metal 79.56% <96.87%> (+<0.01%) ⬆️
4.14-m6a.metal 78.78% <96.87%> (+<0.01%) ⬆️
4.14-m6g.metal 76.60% <96.87%> (+<0.01%) ⬆️
4.14-m6i.metal 79.55% <96.87%> (-0.01%) ⬇️
4.14-m7g.metal 76.60% <96.87%> (+<0.01%) ⬆️
5.10-c5n.metal 82.09% <96.87%> (+<0.01%) ⬆️
5.10-c7g.metal ?
5.10-m5n.metal 82.08% <96.87%> (+<0.01%) ⬆️
5.10-m6a.metal 81.38% <96.87%> (-0.01%) ⬇️
5.10-m6g.metal 79.38% <96.87%> (+<0.01%) ⬆️
5.10-m6i.metal 82.07% <96.87%> (-0.01%) ⬇️
5.10-m7g.metal 79.38% <96.87%> (+<0.01%) ⬆️
6.1-c5n.metal 82.08% <96.87%> (-0.01%) ⬇️
6.1-c7g.metal ?
6.1-m5n.metal 82.08% <96.87%> (+0.01%) ⬆️
6.1-m6a.metal 81.38% <96.87%> (+<0.01%) ⬆️
6.1-m6g.metal 79.37% <96.87%> (-0.01%) ⬇️
6.1-m6i.metal 82.07% <96.87%> (-0.01%) ⬇️
6.1-m7g.metal 79.38% <96.87%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@roypat roypat self-requested a review June 18, 2024 12:49
Copy link
Contributor

@roypat roypat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

if offset < self.len() as usize {
let expected = buf.len();
if offset < self.len() {
let expected = u32::try_from(buf.len()).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we can translate the error from try_from into some VolatileMemoryError to indicate that its impossible to read more than u32::MAX bytes from a descriptor chain

Comment on lines +149 to +151
let iov_len = u32::try_from(iov.iov_len).unwrap();
if offset >= iov_len {
offset -= iov_len;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mh, I think here its better to have a let mut offset = offset as usize in line 142, so that we do not need any casts around this arithmetic and the VolatileSlice constructor

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, however, let's do let mut offset = u32::try_into(offset).unwrap. We should also add a comment on why this is ok. Something like:

`iov.iov_len` is a `usize` but it gets assigned from `DescriptorChain::len` which is a `u32`, so the guest cannot pass to us something that is bigger than `u32`. As a result 

offset = 0;

if slice.len() > len {
slice = slice.subslice(0, len)?;
if u32::try_from(slice.len()).unwrap() > len {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if u32::try_from(slice.len()).unwrap() > len {
if slice.len() > len as usize {

Or also just a let len = len as usize; at the top of the method :). We mostly care that the API of these functions expresses the right thing, but casting up to usize inside of them is fine, since from there, the usize won't "escape" again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again agree.

if offset < self.len() as usize {
let expected = buf.len();
if offset < self.len() {
let expected = u32::try_from(buf.len()).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

let mut total_bytes_read = 0;

for iov in &self.vecs {
if len == 0 {
break;
}

if offset >= iov.iov_len {
offset -= iov.iov_len;
let iov_len = u32::try_from(iov.iov_len).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

offset = 0;

if slice.len() > len {
slice = slice.subslice(0, len)?;
if u32::try_from(slice.len()).unwrap() > len {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above

Copy link
Contributor

@bchalios bchalios left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR Brandon!

I second Patrick's comments and I left a comment regarding the use of as as opposed to into(), try_into().unwrap().

Comment on lines +119 to +120
expected: expected as usize,
completed: bytes_read as usize,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use expected.into() instead of as here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and everywhere else in this commit. We should always be able to use .into() or .try_into().unwrap() where appropriate.

Comment on lines +149 to +151
let iov_len = u32::try_from(iov.iov_len).unwrap();
if offset >= iov_len {
offset -= iov_len;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, however, let's do let mut offset = u32::try_into(offset).unwrap. We should also add a comment on why this is ok. Something like:

`iov.iov_len` is a `usize` but it gets assigned from `DescriptorChain::len` which is a `u32`, so the guest cannot pass to us something that is bigger than `u32`. As a result 

offset = 0;

if slice.len() > len {
slice = slice.subslice(0, len)?;
if u32::try_from(slice.len()).unwrap() > len {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again agree.

@roypat roypat added the Status: Awaiting review Indicates that a pull request is ready to be reviewed label Jun 20, 2024
@roypat
Copy link
Contributor

roypat commented Sep 24, 2024

Subsumed by #4788

@roypat roypat closed this Sep 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Awaiting review Indicates that a pull request is ready to be reviewed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use u32 to describe vsock related buffer sizes
3 participants