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 sendmsg on macOS when passing a zero entry cmsgs array. #623

Merged
merged 2 commits into from
Jul 11, 2017

Conversation

kinetiknz
Copy link
Contributor

@kinetiknz kinetiknz commented Jun 20, 2017

On macOS, trying to call sendmsg with a zero entry cmsgs buffer, e.g.:

sendmsg(fd, [IoVec::from_slice(buf)], &[], MsgFlags::empty(), None)

...fails with EINVAL. This occurs due to the pointer value for zero capacity Vecs being 0x1 rather than 0x0, to distinguish allocated-but-zero-size from nullptr. The kernel validates both the msghdr.msg_control and msghdr.msg_controllen fields and rejects msghdr.msg_control == 0x1 as invalid.

This doesn't show up on Linux because the kernel validates msghdr.msg_controllen first and ignores the value of msghdr.msg_control if the length was 0.

@@ -279,12 +277,18 @@ pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'
None => (0 as *const _, 0),
};

let cmsg_ptr = if capacity > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this not supposed to be len?

Copy link
Contributor Author

@kinetiknz kinetiknz Jun 20, 2017

Choose a reason for hiding this comment

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

I think, if anything, cmsg_buffer should be allocated with capacity rather than 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'm not certain on this API, so I just wanted to confirm that len was correct.

@Susurrus
Copy link
Contributor

Since you have a simple test case, can you add it as a test to the test suite? That way this will never regress after this fix.

@Susurrus
Copy link
Contributor

Also we need an entry in CHANGELOG.md under the Fixed category for this.

@kinetiknz
Copy link
Contributor Author

Thanks for the feedback. I've pushed an updated version.

Since you have a simple test case, can you add it as a test to the test suite? That way this will never regress after this fix.

Done.

Also we need an entry in CHANGELOG.md under the Fixed category for this.

Done.

@Susurrus
Copy link
Contributor

This looks pretty good to me, but right now we're blocking on a fix for #634.

@Susurrus
Copy link
Contributor

@kinetiknz I actually wanted to request that you add a summary of what's going on in your test, either inline or at the top. I don't understand this subsystem, so being able to roughly understand it without having to dig through the low-level code would be appreciated.

@kinetiknz
Copy link
Contributor Author

@kinetiknz I actually wanted to request that you add a summary of what's going on in your test, either inline or at the top. I don't understand this subsystem, so being able to roughly understand it without having to dig through the low-level code would be appreciated.

I added a bit of a description to the top of the test. Let me know if that makes sense.

I've found another couple of issues in this area of the code while updating this PR with your feedback. I'll send another PR for those soon.

@Susurrus
Copy link
Contributor

Susurrus commented Jul 4, 2017

Can you rebase this? We've fixed the mount tests and enabled some more platforms, but I think this is RTM otherwise.

@kinetiknz
Copy link
Contributor Author

Thanks for the update. Rebased patch pushed.

for _ in msg.cmsgs() {
panic!("unexpected cmsg");
}
assert_eq!(msg.flags & (MSG_TRUNC | MSG_CTRUNC), MsgFlags::empty());
Copy link
Contributor

Choose a reason for hiding this comment

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

This would be more clear if it was written as:

assert!(!msg.flags.intersects(MSG_TRUNC | MSG_CTRUNC));

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed there and in test_scm_rights, where it was copied from.

@Susurrus
Copy link
Contributor

Susurrus commented Jul 6, 2017

This LGTM, @asomers wanna take a look over this as well and merge it if so?

@Susurrus
Copy link
Contributor

Susurrus commented Jul 9, 2017

bors r+

@bors
Copy link
Contributor

bors bot commented Jul 9, 2017

Merge conflict

@asomers
Copy link
Member

asomers commented Jul 9, 2017

@kinetiknz please rebase your PR.

@kinetiknz
Copy link
Contributor Author

@kinetiknz please rebase your PR.

Done. I assume I don't have access to get bors to retry the merge.

@Susurrus
Copy link
Contributor

I don't think you could even if you specified me as a reviewer. Don't worry, though, I pay close attention to our massive backlog of PRs!

bors r+

bors bot added a commit that referenced this pull request Jul 10, 2017
623: Fix sendmsg on macOS when passing a zero entry cmsgs array. r=Susurrus

On macOS, trying to call `sendmsg` with a zero entry cmsgs buffer, e.g.:

    sendmsg(fd, [IoVec::from_slice(buf)], &[], MsgFlags::empty(), None)

...fails with `EINVAL`.  This occurs due to the pointer value for zero capacity `Vec`s being 0x1 rather than 0x0, to distinguish allocated-but-zero-size from nullptr.  The [kernel validates](https://github.com/opensource-apple/xnu/blob/dc0628e187c3148723505cf1f1d35bb948d3195b/bsd/kern/uipc_syscalls.c#L1304) both the `msghdr.msg_control` and `msghdr.msg_controllen` fields and rejects `msghdr.msg_control == 0x1` as invalid.

This doesn't show up on Linux because the [kernel validates](https://github.com/torvalds/linux/blob/9705596d08ac87c18aee32cc97f2783b7d14624e/net/core/scm.c#L139) `msghdr.msg_controllen` first and ignores the value of `msghdr.msg_control` if the length was 0.
@bors
Copy link
Contributor

bors bot commented Jul 11, 2017

Timed out

@Susurrus
Copy link
Contributor

There's just a big backlog of PRs right now which is why bors timed out. Given that builds currently take almost two hours, I'm tempted to suggest we should double our timeout for bors again. @asomers any opinion on this?

bors r+

bors bot added a commit that referenced this pull request Jul 11, 2017
623: Fix sendmsg on macOS when passing a zero entry cmsgs array. r=Susurrus

On macOS, trying to call `sendmsg` with a zero entry cmsgs buffer, e.g.:

    sendmsg(fd, [IoVec::from_slice(buf)], &[], MsgFlags::empty(), None)

...fails with `EINVAL`.  This occurs due to the pointer value for zero capacity `Vec`s being 0x1 rather than 0x0, to distinguish allocated-but-zero-size from nullptr.  The [kernel validates](https://github.com/opensource-apple/xnu/blob/dc0628e187c3148723505cf1f1d35bb948d3195b/bsd/kern/uipc_syscalls.c#L1304) both the `msghdr.msg_control` and `msghdr.msg_controllen` fields and rejects `msghdr.msg_control == 0x1` as invalid.

This doesn't show up on Linux because the [kernel validates](https://github.com/torvalds/linux/blob/9705596d08ac87c18aee32cc97f2783b7d14624e/net/core/scm.c#L139) `msghdr.msg_controllen` first and ignores the value of `msghdr.msg_control` if the length was 0.
@asomers
Copy link
Member

asomers commented Jul 11, 2017

@Susurrus I think that's reasonable. I'll open a new issue for it.

@bors
Copy link
Contributor

bors bot commented Jul 11, 2017

@bors bors bot merged commit 64815c6 into nix-rust:master Jul 11, 2017
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.

None yet

3 participants