Judging by the three commits added by the android-9.0.0_r53 tag in the platform/system/bt android subcomponent, the vulns seem to be UAF + OOB write. All vulnerabilities thus belong into the class of vulnerabilities that safe Rust eliminates.
https://android.googlesource.com/platform/system/bt/+/1d788d...
https://android.googlesource.com/platform/system/bt/+/c20f24...
https://android.googlesource.com/platform/system/bt/+/abc302...
It's an 8-bit counter... just allocate a fixed 256 entries and be done with it. That reads like code written by people without any embedded/low-level experience.
Keeping code simple and without unnecessary abstraction is a far more valuable skill than $safe-language-trend-of-the-day.
It's a valuable skill for sure, but there apparently isn't enough people with this skill on the market, which is why $safe-language-trend-of-the-day is being developed and gains momentum.
How long must a language be around and prove it’s staying power before people will stop brushing it aside with the “$safe-language-trend-of-the-day“ quip? 1 year? 2 years? 5 years? 50?
How many people must use it? 1k? 10k? 100k?
It’s pointless to argue with someone who throws Rust into that category at this point because it means nothing. It’s a slight to allow them to feel ok, that eventually this language too will pass, and so it will be ignored.
> there apparently isn't enough people with this skill on the market
Judging by the number of memory vulnerabilities found each year in mainstream operating systems (which are developed by some of the best programmers around), there aren't any people on the market with this skill. This is very likely because all programmers are human beings.
Manually managing memory isn't difficult, it has been proven to be practically impossible. I wouldn't care if it were Linus claiming otherwise, it's ignoring incredible amounts of evidence to the contrary and is much like flat-earther.
As someone who both writes C and Rust I don't think the two contradict each other. Rust is very nice to write stable, fast and well tested libraries in that can interface with C code in.
Learning Rust and with its concepts improved my C code. Even if Rust would vanish over night I wouldn't regret learning it.
People who know how to do that are expensive, and they still make mistakes. Rust enables junior-level JavaScript programmers to write kernel/bare-metal level code without fear of making these kinds of errors. If you've spent a career programming in C and you're complaining about Rust, you're right. Rust isn't for you, it's for your replacement.
"Rust enables junior-level JavaScript programmers to write kernel/bare-metal level code without fear of making these kinds of errors. If you've spent a career programming in C and you're complaining about Rust, you're right. Rust isn't for you, it's for your replacement."
That's a pretty silly thing to say.
Writing code that doesn't crash isn't the hardest thing about writing low-level code. Sure, it's a problem, even an important problem, but there's a ton of other knowledge that no JS developer would have. Unless by "write" you mean write 2 lines per day with lots of searching in-between that has to be thrown away in the end.
The way I see it it: With C/C++, you have to to have a team of 5 senior devs, and they have to cross-check each other work all the time. With Rust, you could have 1 senior Rust dev, and 4 junior devs, and they would arrive in a better place anyway, just by the virtue of compiler doing 90% of the boring checks and tutoring.
You can't build a quality project only with juniors supervised by a senior no matter what technology you use. This is such a common programming fallacy, it's surprising to see it here.
But at least with Rust it won't have out of bounds and use after free bugs even if being crap otherwise.
> People who know how to do that are expensive
Good programmers are expensive. The notion that better tools are going to change that is naive.
Rust is good. Use it for things. But the idea that it can let people who don't know what they're doing write secure code is dangerous. For example, what does Rust do about Spectre? Does your junior-level JavaScript programmer know how to address that? What about other timing attacks, or knowing which crypto to use in which context?
People still have to know what they're doing.
> Rust enables junior-level JavaScript programmers to write kernel/bare-metal level code without fear of making these kinds of errors
I've used Rust for a while, and this isn't really true. At the lowest level you still have to build good abstractions with judicious use of `unsafe`. It also comes across as incredibly hostile, you're not doing Rust any favors with this.
If by "write kernel/bare-metal level code" you mean blinking an LED, sure. Writing low level doesn't have to do anything with C or any language for that matter. It requires a deep understanding of the architecture that you're writing code for. Junior JS devs don't have enough experience or the skills to do that.
"Junior-level JavaScript programmers" "kernel/bare-metal level code"
Can't see how that can be. Only a small minority of programmers can code low level systems. Only those that truly enjoy it, go through the pains necessary to have adequate grasp of it.
> If you've spent a career programming in C and you're complaining about Rust, you're right. Rust isn't for you, it's for your replacement.
LOL, I wish. I've been told I was going to be replaced every 5 years for the last 20 years of my career. I fucking wish they did so I could finally retire but I keep being given money and cool problems so I stay waiting for this fangled replacement who will come and take my job.
> It's an 8-bit counter... just allocate a fixed 256 entries and be done with it. That reads like code written by people without any embedded/low-level experience.
I guess you are talking about the first commit I linked. The problem here seems to be that some events of the kind HCI_READ_RMT_EXT_FEATURES_COMP_EVT can be shorter than the assumed 13 bytes. The code contains no check for that and if the events are shorter, it would read data from after the allocation. It would use that data to index inside arrays, etc.
Now, if you just allocate a buffer of 256 entries but don't do anything else, it wouldn't read data from outside the allocation, yes, but it would still read uninitialized data, as nothing would be written after the end of the valid data. That uninitialized data could e.g. come from previous freed allocations. This would hardly be an improvement. You'd have to allocate and zero-initialize it, and then you'd still have the problem whether zero is invalid data or part of the allocation... Even if code would figure that out, it would be extremely smelly code and I'd never merge it in any projects I maintain.
The approach done by the patch to just check the length is much much better. The length is sent as part of the event.
> Keeping code simple and without unnecessary abstraction is a far more valuable skill than $safe-language-trend-of-the-day.
This code almost directly maps to the bluetooth host controller interface which is part of the published Bluetooth standard. So you can't change the core concepts of it. There are a few abstraction layers which copy the data for some reason from a new/delete managed hidl_vec to a malloc/free managed array (check hciEventReceived function in hci/src/hci_layer_android.cc). Yes, I'd say that some of those layers are indeed unnecessary. But those abstraction layers are not where the vulnerability occurs. It occurs in the code that parses the message, and the bug is that the code does not check the length of the input data. This is a classic bug that can occur in C/C++ codebases.
Safe Rust prevents OOB writes/reads by performing bounds checks when you index into a slice.
The issue with languages like C is that verifying that code is safe is extremely hard, even harder than writing it in the first place. This codebase seems to have not been written by Google but by Broadcom, so Google would have to verify whether what Broadcom wrote is actually safe. With Rust, such verification is easy. If your code makes little use of unsafe, and most code doesn't actually have to, it's easy to verify its safety (at least for the classes of bugs that Rust eliminates). Due to the strong typing, other types of bugs are made harder to write as well.
I appreciate this comment, because it demonstrates a solid approach to simplify the code.
That said, regarding:
> safe-language-trend-of-the-day.
I agree that rust advocacy can sometimes be a bit misguided and over-enthusiastic - however how often is an out of bounds write not a bug (or a too clever by far hack)?
We've had pretty efficient ways to deal with this in c like languages for a long time (eg Pascal, Ada).
(c-like in the sense of being relatively low-overhead, close to the hardware wrt memory layout etc).
Just in general, you can never take for granted the length of the data you're referencing via a pointer unless you absolutely control the whole input path and it's amazing to see that happening in code written at this level
This is not a constructive comment. Saying an entire OS "would have been safer on this language" is just trolling. Comment should be reported IMO.
The entire raison d'etre of Rust is that it can be safer in exactly these cases where C or C++ is unsafe, and aims towards their eventual replacement.
This will take a couple of decades, but it's a worthwhile effort.
Sure but until someone demonstrates at least a basic PoC using Rust to replace some Android C code, suggesting that it can is just speculation at best.
Google has: https://en.wikipedia.org/wiki/Google_Fuchsia
I'm certain that you cannot simply drop-replace an Android OS component with a Fuschia component.
My point is, of course Rust is a memory safe language, and of course it would theoretically prevent overflow exploits, but throwing in "you should've used Rust" when this news is announced isn't helping anything. I am certain that Android devs are at least aware of Rust and it's benefits.
> I am certain that Android devs are at least aware of Rust and it's benefits.
There is still not a single Android ROM component that's written in Rust. Cuttlefish uses crosvm which is Rust based, but it's a VM for Android testing rather than a ROM component. So they aren't even ready yet to experiment with shipping small components in Rust. Same goes for Chrome btw, it currently has a "no Rust allowed" policy, which is IMO very sad.
So yeah I think it's worthwhile to talk about why AOSP doesn't have Rust components yet, especially as patching is sadly not available (yet) for most deployed devices. Large fleets of devices will have the bug for eternity. Therefore, prevention of vulnerabilities becomes even more important, which Rust helps doing. Your program won't be free of them, but as I pointed out above, these bluetooth vulns fall into the class that safe Rust eliminates.
This is userspace code, it's a legit point to criticise use of a memory-unsafe language here. It's 2020 after all, 24 years after "Smashing the stack for fun and profit" and 24 years into the golden age of C exploits while safer practical systems languages have existed. And also a legit point to promote Rust, even if it's a little too new for this codebase.
The transition in perception of UNIX and C from being buggy, inconsistent, foot-gun-laden corporate messes to being treated like the immutable ancient ways has certainly been a trip.
Isn't that because Os's based on Linux don't share a single LOC with commercial Unices?
I mean, they did link to a bunch of source code spots... so it's not completely unconstructive.
...especially when the large majority of HN readers are already aware of rust "thanks" to the rust evangelism strikeforce.
A day or two ago there was an embedded software developer here claiming that low-level C developers "know what they're doing", so any languages with built-in safety features impose unnecessary safety restrictions, and that since any software can have bugs, there is no reason to use anything but C. Once that kind of stubborn attitude dies out, maybe we'll stop seeing people leave comments saying "This could have been prevented if they had used language X".
The downvotes are really telling.
I've said nowhere that all of Android should be written in Rust. I've only said that had this specific component been written in Rust, the issues wouldn't have shown up. Of course the code base is old and predates Rust.
But I think this vulnerability serves as an important lesson about which language to choose for new projects in the embedded area. Thus I'm very glad that Google uses Rust for its new OpenSK security key firmware. I hope that future versions of Android will adopt Rust, at least in newly written components. Some Google developed Android related projects are already using Rust, like Cuttlefish which uses crosvm.
Since Android includes a deeply integrated Java implementation that they've put a lot of work into, which includes an AOT compiler, why wouldn't they write services like this one in Java?
Or Java, or Go, or one of the other 10 or so languages that have bounds checking.
I think it's extremely silly that every time buffer length vulnerabilities get discovered, people start immediately jumping how rewriting everything in rust would have stopped it.
Yes, that's not wrong, but a sane (ptr, len) "slice"/"buffer" type would have prevented this in any language, not just rust. These things happen not because C and C++ lack sophisticated ownership semantics, but because without such a type, passing a pointer and hoping the buffer is always big enough is just easier than doing the right thing.
If this was something funky like a cross-thread race-condition dangling-pointer double-free, you'd have a great point. Only Rust's unique safety model can prevent that. But with things like this, as much as I love Rust and it's community, I sometimes feel like many rust fans are much more interested in being smug than making real-world progress towards safer software today.
The point is that the sane, correct choice is also the easy, default choice in Rust. We've been able to implement (ptr,len) buffer types in C for as long as we've had C, but uint8_t* is both baked into many APIs, and the path of least resistance.
We've spent decades pushing the limits of security improvements we can get through asking people to please try harder and do better with C, but we still see a high rate of high-impact errors like this.
Rust's safety model isn't the only valuable thing about Rust. Another big valuable part of Rust is that instead of giving the programmer a box of unsafe tools and a post-it reminding them to be careful, Rust provides sane, safe default tools that have been built based on what we've learned from the past several decades.
The argument isn't "Only Rust can save you", but that Rust is a good choice that both meets the same performance requirements, and avoids these problems by default.
If you've got a better solution to persuade C and C++ developers to consistently and reliably always wrap their use of pointers from other APIs into (ptr,len) buffer types, I'd love to hear it!
With comments like this, I sometimes feel like many developers are much more interested in smugly dismissing a group that's made significant real-world progress in making it easy to do the right thing than they are in actually helping real developers to reliably make safer software today.
Android accepts contributions and your complete rust rewrite of bluedroid would be most welcome