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

Read::read_buf mutable reference to ReadBuf #94742

Closed
nrc opened this issue Mar 8, 2022 · 3 comments
Closed

Read::read_buf mutable reference to ReadBuf #94742

nrc opened this issue Mar 8, 2022 · 3 comments
Labels
T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@nrc
Copy link
Member

nrc commented Mar 8, 2022

cc #78485

Currently, Read::read_buf takes a &mut ReadBuf. That means that a malicious Read impl could swap out the buffer for another whereas the intent is that an impl should only write into the buffer. If users rely on properties of the ReadBuf to hold for an underlying buffer, then they must check that the ReadBuf has not been changed, otherwise they risk writing code which is unsound (see ##93305 for an example. Here copy_to should make this check, but does not). Since this check is not obvious, this is a potential footgun.

This was previously discussed on Zulip: https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/Read.3A.3Abuf_read.20signature

Note that this is not a soundness issue, however, it makes it easier than it ought to be to write unsound code.

Note also that this requires an actively malicious impl of Read to be harmful since the lifetime of the ReadBuf means that the impl must use a static (or leaked) ReadBuf and that is extremely unlikely to happen by accident. IMO, this is important because a malicious impl could cause similar errors in many other ways, such as calling assume_init on the ReadBuf without in fact initializing the bytes. That does require unsafe, but IMO is no easier to audit than swapping out the ReadBuf for another (since every legitimate use of ReadBuf requires unsafe code).

Anyway, the way to fix this is to have some kind of type struct ReadBufMut<'a>(&'a mut ReadBuf); and to use ReadBufMut rather than &mut ReadBuf in read_buf's signature. The interesting question is exactly how to convert between the two types ergonomically and whether we can design things in such a way that we can expose only one type rather than two.

@nrc nrc added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Mar 8, 2022
@Darksonn
Copy link
Contributor

Darksonn commented Mar 8, 2022

The Tokio crate already uses a ReadBuf-based API in its IO traits, and my experience using the ReadBuf design there for more than a year is that this is important to fix. Pretty much everyone who writes something that can have this mistake does make the mistake until pointed out to them.

Regarding ergonomics, one way could be to have ReadBuf have an .as_mut() method that returns an ReadBufMut<'_>.

@beepster4096
Copy link
Contributor

#93359 implements this

@tmiasko
Copy link
Contributor

tmiasko commented Mar 9, 2023

Resolved by #97015.

@tmiasko tmiasko closed this as completed Mar 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants