tree borrows: implicit writes#4947
Conversation
|
Thank you for contributing to Miri! A reviewer will take a look at your PR, typically within a week or two. |
|
r? @RalfJung |
|
@rustbot author |
|
Reminder, once the PR becomes ready for a review, use |
|
While looking over the code, an issue came forward which is mentioned in #4947 (comment). 29d5336 tries to address this issue by "constraining" the outside permission to Reserved if it is Unique. A test that currently breaks (but should not), but with the changes not anymore, has been implemented in |
de4a6ef to
d44b84c
Compare
|
I have pushed a refactor of the permission logic that is a bit longer than what you had but IMO also easier to follow. Please let me know what you think. |
add llvm writable attribute conditionally This PR tries to address rust-lang/unsafe-code-guidelines#584 (comment). It is part of a bachelor thesis supervised by @JoJoDeveloping and @RalfJung, for more information, see: [Project_Description.pdf](https://github.com/user-attachments/files/26537277/Project_Description.pdf). If the new `-Zllvm-writable` flag is set, the [llvm writable attribute](https://llvm.org/docs/LangRef.html#writable) is inserted for all mutable borrows. This can be conditionally turned off on a per-function basis using the `#[rustc_no_writable]` attribute. The new Undefined Behaviour introduced by this can detected by Miri, which is implemented here: rust-lang/miri#4947. Two library functions already received the `#[rustc_no_writable]` attribute, as they are known to cause problems under the Tree Borrows aliasing model with implicit writes enabled.
add llvm writable attribute conditionally This PR tries to address rust-lang/unsafe-code-guidelines#584 (comment). It is part of a bachelor thesis supervised by @JoJoDeveloping and @RalfJung, for more information, see: [Project_Description.pdf](https://github.com/user-attachments/files/26537277/Project_Description.pdf). If the new `-Zllvm-writable` flag is set, the [llvm writable attribute](https://llvm.org/docs/LangRef.html#writable) is inserted for all mutable borrows. This can be conditionally turned off on a per-function basis using the `#[rustc_no_writable]` attribute. The new Undefined Behaviour introduced by this can detected by Miri, which is implemented here: rust-lang/miri#4947. Two library functions already received the `#[rustc_no_writable]` attribute, as they are known to cause problems under the Tree Borrows aliasing model with implicit writes enabled.
|
All requested changes should be implemented now. |
|
I will try to have another look over the entire code soon ™️ but it's a very busy week for me. |
| // `noalias` would not be sound. | ||
| Permission::new_reserved_frz() | ||
| } else { | ||
| Permission::new_reserved_im() |
There was a problem hiding this comment.
@RalfJung I don't think it makes sense to mark Boxes as ReservedIM, does it? It's what the logic was doing before and we likely didn't notice... (Note that Minirust does the same).
There was a problem hiding this comment.
Why does it not make sense? Box<T> as a function argument should be treated the same as &mut T, just without the protector.
There was a problem hiding this comment.
this is about Box in non-function-argument position, i.e. when moved inside a method.
There was a problem hiding this comment.
What is your proposal for what their initial state should be?
There was a problem hiding this comment.
just Reserved. For mutable references we have ReservedIM because of the safe code in this test, but I don't think that is possible with boxes.
There was a problem hiding this comment.
Interesting. We figured it'd be like &mut because "why not".
I'd say lets leave this unchanged for now, but please open an issue or PR (depending on what you have time for) specifically for this change, also including an example of code that you think should have UB but currently doesn't because of this.
There was a problem hiding this comment.
@RalfJung We added the tree_iwrites revision to some of the fail tests. There are many more fail tests that we could add this to. Is there a reason why not to do so?
Specifically, this should probably be on all tests in fail/both_borrows and on selected tests in fail/tree_borrows even outside the fail/tree_borrows/implicit_writes folder...
There was a problem hiding this comment.
You already added this is more than enough places I think. The pass tests are more critical since the flag makes TB less permissive.
I had another look at it and am now happy with it 🎉 (except for the things noted above) |
There was a problem hiding this comment.
Thanks! Just a few more comments for the tests, the rest looks good. :)
@rustbot author
| @@ -0,0 +1,30 @@ | |||
| // Tests that accessing the same array using disjoint pointers does not cause UB under Tree Borrows. | |||
| // The pointer will access the memory range using the outside permission, thus testing if it has been set correctly. | |||
There was a problem hiding this comment.
| // The pointer will access the memory range using the outside permission, thus testing if it has been set correctly. | |
| // The pointer will access the memory range using the outside permission, thus testing if it has been set correctly. | |
| // In particular, in implicit_writes mode we used to set the "outside" permissions to | |
| // `Unique`, which caused an ICE. | |
| // Put differently, this checks the absence of subobject provenance for arrays. |
|
|
||
| fn main() { | ||
| let mut x: Box<u8> = Box::new(0u8); | ||
| let ptr = &mut *x as *mut u8; |
There was a problem hiding this comment.
There's still a mutable reference here. If that isn't relevant, maybe use &raw mut *x instead?
| @@ -1,4 +1,6 @@ | |||
| //@compile-flags: -Zmiri-tree-borrows | |||
There was a problem hiding this comment.
You can keep this line so that all revisions use TB.
There was a problem hiding this comment.
This is quite confusing to be in this folder as this test is about not having implicit writes.
Maybe call it tests/pass/tree_borrows/no_implicit_writes.rs?
There was a problem hiding this comment.
This can be merged with tests/pass/tree_borrows/implicit_writes/ptr_write.rs.
There was a problem hiding this comment.
Maybe make this just a function in tests/pass/tree_borrows/tree-borrows.rs? That's where we have most of these kinds of tests.
There was a problem hiding this comment.
can you rename this test into retag_is_data_race.rs or something like that? The current name is in praticular wrong as it is not a "read" retag.
| thread::yield_now(); // force other thread to read first | ||
|
|
||
| fn write(y: &mut u8, v: u8, barrier: &Arc<Barrier>) { | ||
| //~^ ERROR: Data race detected |
There was a problem hiding this comment.
can you make the error message more specific, to match on the retag being called a write?
This PR tries to address rust-lang/unsafe-code-guidelines#584 (comment). It is part of a bachelor thesis supervised by @JoJoDeveloping and @RalfJung, for more information, see: Project_Description.pdf.
This implements the checking for implicit writes for Tree Borrows. It is disabled by default but can be enabled using the
-Zmiri-tree-borrows-implicit-writesflag.When it is enabled, Miri inserts a write for all mutable borrows on function entry. This enables the optimization implemented here: rust-lang/rust#155207