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 uninitialized buffers for read and recvfrom #1606

Merged
merged 2 commits into from
Feb 19, 2025

Conversation

thaliaarchi
Copy link
Contributor

@thaliaarchi thaliaarchi commented Feb 19, 2025

Currently, when using an uninitialized buffer for read or recvfrom, as would be typical in C or required for Read::read_buf, it is casted from *mut u8 at the FFI boundary in sys_read/sys_readv/sys_recvfrom to a &[u8]. I think this is unsound. Instead, use &[MaybeUninit<u8>] internally.

I use &[u8] instead of core::io::BorrowedCursor<'_>, because there are currently no cases where the initialized portion needs to be separately tracked.

Since smoltcp::socket::tcp::Socket::recv_slice takes a &[u8], inline it and refactor. As a bonus, this avoids a copy and clear in the error case and it makes it more clear that packets are dropped when given an insufficiently large buffer.

This PR enables implementing std::io::Read::read_buf for std::fs::File and std::io::Stdin on Hermit. That effort is tracked in rust-lang/rust#136756.

Currently, when using an uninitialized buffer for `read`, as would be
typical in C or required for `Read::read_buf`, it is casted from `*mut
u8` at the FFI boundary in `sys_read`/`sys_readv` to a `&[u8]`. I think
this is unsound.

Instead, use `&[MaybeUninit<u8>]` internally. I use this instead of
`core::io::BorrowedCursor<'_>`, because there are currently no cases
where the initialized portion needs to be separately tracked.

This enables implementing `std::io::Read::read_buf` for `std::fs::File`
and `std::io::Stdin` on Hermit. That effort is tracked in
rust-lang/rust#136756.
Since `smoltcp::socket::tcp::Socket::recv_slice` takes a `&[u8]`, inline
it and refactor. As a bonus, this avoids a copy and clear in the error
case and it makes it more clear that packets are dropped when given an
insufficiently large buffer.
@thaliaarchi thaliaarchi changed the title Read to uninitialized buffer Use uninitialized buffers for read and recvfrom Feb 19, 2025
@thaliaarchi
Copy link
Contributor Author

thaliaarchi commented Feb 19, 2025

The CI failure seems likely to be unrelated:

Laplace iterations
Error: QEMU timeout

@mkroening mkroening self-requested a review February 19, 2025 07:57
@mkroening mkroening self-assigned this Feb 19, 2025
Copy link
Member

@mkroening mkroening left a comment

Choose a reason for hiding this comment

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

Thanks a lot! :)

@mkroening mkroening added this pull request to the merge queue Feb 19, 2025
Merged via the queue into hermit-os:main with commit da243b5 Feb 19, 2025
13 checks passed
@thaliaarchi
Copy link
Contributor Author

How should I coordinate with the Hermit side when I submit the PR to Rust for Read::read_buf? Does this need to be released in Hermit for a while?

@mkroening
Copy link
Member

The kernel is built separately from the application and then linked together without LTO at the moment, so I think the chances of something bad happening due to undefined behavior are really slim in this case.

So I'd say you can go ahead with that PR right away. Feel free to Tag @stlankes and me in everything Hermit-related to keep us in the loop, of course. :)

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.

2 participants