|
|
Subscribe / Log in / New account

Proper Community Engagement

Proper Community Engagement

Posted Sep 2, 2024 20:22 UTC (Mon) by anthm (guest, #173221)
In reply to: Proper Community Engagement by LtWorf
Parent article: Rust-for-Linux developer Wedson Almeida Filho drops out

DARPA is pushing automated translation. The NSA has recommended against using memory unsafe languages (note they didn't push Rust, they gave a list).

Calling it "vague recommendations" is, IMO, deliberately misconstruing the situation. It's not banned becasue it's not practicable (yet) to ban it.


to post comments

Proper Community Engagement

Posted Sep 2, 2024 21:46 UTC (Mon) by LtWorf (subscriber, #124958) [Link]

I'm not aware of any ban of new C in procurement. Until that happens it's vague.

Proper Community Engagement

Posted Sep 3, 2024 1:45 UTC (Tue) by viro (subscriber, #7872) [Link] (6 responses)

DARPA might or might not be pushing anything, but result of that automated translation will be unmaintainable *AND* certain to be unsafe. Consider a program that uses a static array as a poor man's heap, with indices used instead of pointers. A separate (also static) bitmap is used to maintain the set of free elements. All perfectly expressible in Rust, _including_ an equivalent of UAF (function gets an integer argument, clears the corresponding bit in bitmap and returns; caller continues to access the corresponding element of array and then proceeds to find a clear bit in bitmap, sets it and starts using the corresponding element of array in assumption that it does not coincide with the first one). Rust will accept that as memory safe. Not pretty and (possibly) with suspicious names of primitives, but if conversion is also a mindless style corrector, results are _guaranteed_ to be broken. They could argue that the sucker is memory safe - the underlying array is not freed, after all. However, for all intents and purposes it is a use after free.

You'll get a bunch of preexisting bugs obfuscated and made harder to find.

Proper Community Engagement

Posted Sep 5, 2024 7:15 UTC (Thu) by NYKevin (subscriber, #129325) [Link] (5 responses)

Rust will not let you do that, unless you add so many restrictions that the whole thing is both completely unergonomic and also not much of a UAF.

You cannot ever have multiple mutable references to the same array element (or any other object, for that matter), because the borrow checker forbids it (and if you cheat and do it anyway with unsafe code, it is immediate UB because of noalias). Without mutable aliasing, it's not possible for two different parts of the program to both think they own the Nth slot in the array at the same time.

The lack of mutable aliasing must be provable at compile time just from the types of the arguments. It immediately follows that you cannot conjure a mutable reference out of thin air in safe code - it must come from something you already own or another mutable reference. It does not matter whether you're indexing into an array or doing some more complicated dance. Mutability is transitive, and all of the relevant loopholes are either protected by unsafe (UnsafeCell<T>) or by runtime checking (RefCell<T> and most of std::sync).

In the specific case of the static fake heap, this fails on several different grounds:

0. All interactions with mutable statics are unsafe, because of thread safety. Unsafe code can, of course, do a UAF in Rust. That's not news, so in order for this argument to be interesting, the whole thing must work in safe code. But we can just pretend you said "a long-lived boxed slice" instead of a static array, so let's ignore this and continue.
1. To get a mutable reference to the Nth element of an array (or slice/Vec/whatever-it-is), you must borrow the entire array mutably. It is sound to take out multiple non-overlapping mutable borrows against the same array, but you are limited by the API exposed by slice (see e.g. slice::split_at_mut()) unless you write your own unsafe code to do it manually. Regardless, you still cause the whole array to be borrowed mutably until all element borrows are returned.
2. Your array borrow must outlive the borrow of the individual element. This means that whatever part of the program thinks it owns the Nth slot in the array must not actually hold a reference to the element (or else it would prevent any other part of the program from using at least that slot in the array, if not the whole array). It may only hold an index into the array, it can only materialize that into a reference temporarily when needed, and it must receive a mutable reference to the array in order to do that. The latter reference must be constantly passed around pervasively throughout your entire program, or else the array must be protected by RefCell<T> (single-threaded) or a lock of some kind (multi-threaded). RefCell<T> will panic if you try to mutably alias the array at runtime (the locks will block, as you might expect, and if it deadlocks, oh well, that's your problem). This is still technically possible, but it looks very ugly and not at all like idiomatic code (which is what DARPA says they want as output).
3. It is not legal to drop anything in-place in safe code, because the dropped object would still be accessible, and someone might try to use it. So when we say that the object is "freed," we mean that the bitmap no longer considers it to belong to anyone. The object still exists and has a valid value. Some other part of the code might mutate it (through this careful dance of never holding a long-lived reference to anything as described above) or even replace it with an entirely new object, but it cannot replace it with random garbage. It must uphold all invariants of its type, which may be arbitrarily complicated, and which are enforced through the use of visibility restrictions. This can cause logic errors, sure, but it is a far cry from a "real" UAF in which random bytes are interpreted as some entirely inappropriate type.

I will admit that DARPA's goals seem (at best) extremely ambitious to me. But if they do succeed, their generated code will not look anything like what you describe (or else they won't have accomplished what they now claim to be trying to do).

Proper Community Engagement

Posted Sep 7, 2024 17:20 UTC (Sat) by SLi (subscriber, #53131) [Link] (1 responses)

It's my impression of DARPA that if it's not a bit crazy, it's not a project for them. I don't know the numbers, but it sounds to me like they only take up things that are much less likely to succeed or not, and then one in 20 does.

DARPA's mission statement

Posted Sep 8, 2024 11:57 UTC (Sun) by farnz (subscriber, #17727) [Link]

That pretty much falls out from DARPA's mission statement. They exist to fund revolutionary technology that would otherwise fail to get funded, aiming for transformational change from every success, and eating a lot of failures in the process. Hence things like Silent Talk and TRACTOR - both high-risk projects, that would transform the world if they succeed.

And going back in time a bit, the ARPANET was a high-risk project when it started; at the time, communications was circuit-switched, and telecoms companies of every stripe were uninterested in taking the gamble to find out if wide-area packet switching could be made useful, when they were quite happy with circuits. Had DARPA not funded it, ARPANET would not have existed, and we'd probably not have any global packet switched networks, since there was a belief that the size of router buffers in packet switched networks would grow with the size of the network, disproven by ARPANET not needing large packet buffers.

Proper Community Engagement

Posted Sep 8, 2024 9:13 UTC (Sun) by Wol (subscriber, #4433) [Link] (2 responses)

> You cannot ever have multiple mutable references to the same array element (or any other object, for that matter), because the borrow checker forbids it (and if you cheat and do it anyway with unsafe code, it is immediate UB because of noalias). Without mutable aliasing, it's not possible for two different parts of the program to both think they own the Nth slot in the array at the same time.

The only reason I can think of that is a simple locking algorithm - write your pid into a variable, wait a timeout, if your pid is still there you have a lock. That obviously requires everyone to have mutable access to that variable.

Am I right in thinking that would be okay in unsafe code, provided the mutable reference never escaped the unsafe block? I can think of a couple of race conditions, so the unsafe block could lie to the compiler by accident, but the approach is sound if the implementation is correct?

Cheers,
Wol

Proper Community Engagement

Posted Sep 8, 2024 9:22 UTC (Sun) by mb (subscriber, #50428) [Link]

>Am I right in thinking that would be okay in unsafe code, provided the mutable reference never escaped the unsafe block?

The unsafe block as such doesn't give you rights to violate rules.
It gives you access to deref of raw pointers, but you still have to adhere to the rules.
It does also give you access to some unsafe intrinsics, which might be what you need.
But you can't simply put an unsafe block around your data race and then hope it's fine. It's still a forbidden data race.
So you can for example use an unsafe atomic intrinsic to avoid the data race.

Proper Community Engagement

Posted Sep 8, 2024 10:16 UTC (Sun) by LtWorf (subscriber, #124958) [Link]

That algorithm doesn't work.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds