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

Fix panic on dropping RecvAncillaryBuffer after failed recvmsg #676

Merged
merged 2 commits into from
Jun 10, 2023

Conversation

ids1024
Copy link
Contributor

@ids1024 ids1024 commented May 22, 2023

Calling drain on RecvAncillaryBuffer, including in its Drop implementation was failing, with an "attempted to subtract with overflow" error in cvt_msg.

If recvmsg returns -1, msg_controllen will not be updated by the call. So it had a non-zero value as passed into the function, despite there not being any control messages to parse.

Copy link
Contributor

@notgull notgull left a comment

Choose a reason for hiding this comment

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

notgull code after spending five minutes in production:

robot fallx299

Comment on lines +39 to +44
if res.is_ok() {
unsafe {
control.set_control_len(msghdr.msg_controllen.try_into().unwrap_or(usize::MAX));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if the contents of the control buffer are defined on error. I think it would be safest to set the buffer's length to zero on error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

set_control_len just sets the length (and read) field of the RecvAncillaryBuffer, which isn't part of the buffer that libc will be touching so it won't be changed by the recvmsg call if this set_control_len line isn't run.

And for a newly allocated RecvAncillaryBuffer, it will already be 0. So there's no need to set it, in that case.

If the same RecvAncillaryBuffer is re-used in multiple calls, I'm not sure how that works currently. Should check that doesn't leak file descriptors or anything.

Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably be clearing out all of the inner data before we do anything with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a commit that clears the RecvAncillaryBuffer at the start of the recv operation.

Comment on lines +52 to 58
if res.is_ok() {
unsafe {
control.set_control_len(msghdr.msg_controllen.try_into().unwrap_or(usize::MAX));
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto here.

Calling drain on `RecvAncillaryBuffer`, including in its `Drop`
implementation was failing, with an "attempted to subtract with
overflow" error in `cvt_msg`.

If `recvmsg` returns `-1`, `msg_controllen` will not be updated by the
call. So it had a non-zero value as passed into the function, despite
there not being any control messages to parse.
This should prevent leaks of file descriptors if the `RecvAncillaryBuffer`
is re-used for multiple reads.
@sunfishcode
Copy link
Member

@notgull Do you have any further comments here?

@sunfishcode
Copy link
Member

@notgull Is this ready to merge?

Copy link
Contributor

@notgull notgull left a comment

Choose a reason for hiding this comment

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

Looks good to me!

@sunfishcode sunfishcode merged commit dc56e0f into bytecodealliance:main Jun 10, 2023
@sunfishcode
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants