Live data from Hacker News

This shouldn't have happened: A vulnerability postmortem

googleprojectzero.blogspot.com

261–270 of 499 posts

Re: This shouldn't have happened: A vulnerability postmortem

#261

Earlier quoted context omitted.

Swift uses automatic reference counting. From some cursory reading, the major difference from Rust in this regard is that Swift references are always tracked atomically, whereas in Rust they may not be atomic in a single-owner context. To my mind (again, with admittedly limited familiarity), I would think: - Atomic operations in general don’t necessarily provide deterministic timing, but I'm assuming (maybe wrongly?)…

Incrementing an atomic counter every time a reference is copied is a significant amount of overhead, which is why most runtimes prefer garbage collection to reference counting (that, and the inability of referencing counting to handle cycles elegantly). Rust doesn't rely on reference counting unless explicitly used by the program, and even then you can choose between atomically-reference-counted pointers (Arc) vs non…

I promise I’m not trying to be obtuse or argumentative, but I think apart from cycles your response restates exactly what I took from my reading on the subject and tried to articulate. So I’m not sure if what I should take away is:

- ARC is generally avoided by GC languages, which puts Swift in a peculiar position for a language without manual memory management (without any consideration of Swift per se for the case I asked about)

- Swift’s atomic reference counting qualitatively eliminates it from consideration because it’s applied even in single threaded workloads, negating determinism in a way I haven’t understood

- It’s quantitatively eliminated because that overhead has such a performance impact that it’s not worth considering

Re: This shouldn't have happened: A vulnerability postmortem

#262
post #224

Earlier quoted context omitted.

> In Rust every non-trivial library pulls in 10s or even 100s of dependencies. You're exaggerating here. The most recent project I've been working on pulls in 6 dependencies. The anyhow crate has no dependencies, regex 3 (recursively!), clap and csv each 8. Only handlebars and palette pull in 10s of dependencies, and I can trim a fair few dependencies of palette by opting out of named color support (dropping the phf…

It's typical for very large C projects to have perhaps 2-5 dependencies that aren't libc, often something very basic such as zlib, curl or openssl. A rust CSV parser has 8 dependencies?

Three of those dependencies are not entirely unreasonable: one is the actual "core" CSV implementation (with one recursive dependency), one is the dependency for the standard "this interface allows you to serialize/deserialize arbitrary data to arbitrary formats", and one crate that adds traits to make &[u8]/Vec work much more like &str/String (which has 4 recursive dependencies, although two of those are already mentioned). The last two dependencies are crates that provide accelerated routines for serializing integers and floating points, which are IMHO somewhat excessive, but if it's easy to pull in such dependencies, why not? It would be helpful in places where CSV serialization might actually be a bottleneck.

There are two key differences between large projects in ecosystems that have working package managers and those in C/C++. For starters, the basic working 'package' tends to be smaller. Consider something like LLVM (just LLVM itself, none of its subprojects like Clang). This you'd count as "one project" without any dependencies (at least, no required dependencies that aren't vendored, liked zlib and googletest). But if you were to make it in something like Rust, it would likely consist of a dozen or more packages: the core IR, analysis passes, command-line tools, transformations, codegen (with each target likely being its own package!). With such fragmentation, you'd have dozens of dependencies that are essentially nothing more than the 'project' itself.

But more importantly is that, because dependencies are hard to add, code duplication is the norm; it's only when what you want to do is too impossible to duplicate that you resort to a dependency. For any large C++ project, I can virtually guarantee that there will exist some form of 'standard library++' dependency in the code that will contain at least an intrusive linked list, better hashtable implementation, std::vector-lookalike that avoids heap allocation for small lists, replacement for iostream, helpers for process creation, custom string formatting routines, and something to make dealing with segfaults sane. In a package ecosystem, each of those kinds of things would be a separate dependency. Is it really necessary for everybody who wants to write something dealing with graphs to have write their own graph-based data structure, as opposed to just using the ecosystem-standard graph library (e.g., networkx in Python, or petgraph in Rust)? Or to have everybody that wants to use a hashtable to have to write their own implementation of a notoriously tricky data structure?

Re: This shouldn't have happened: A vulnerability postmortem

#263
post #66

Earlier quoted context omitted.

Also, far, far easier to build than all of these C programs with their own bespoke build systems and implicit dependency management. The more of the software stack that can be built by mere mortals, the better.

> far, far easier to build than all of these C programs One of my friends who work on AIX machines without direct Internet access does not share the same view, though.

If the trade is getting proper memory safety for the 99.99% of code which never has to be built directly on a mainframe without internet access in exchange for the code that does have to be built on mainframes without internet access a bit harder, I think I'm fine with that.

Re: This shouldn't have happened: A vulnerability postmortem

#264

Earlier quoted context omitted.

> Suggesting a tabula rasa rewrite of NSS would more likely be met with genuine concern for your mental well-being, than by incredulity or skepticism. In my experience, porting code more or less directly from one language to another is faster and easier than people assume. Its certainly way faster than I assumed. I hand ported chipmunk2d to javascript a few years ago. Its ~30k LOC and it took me about a month to get…

> In my experience, porting code more or less directly from one language to another is faster and easier than people assume Converting code to Rust while keeping the logic one-to-one wouldn't work. Rust isn't ensuring memory safety by just adding some runtime checks where C/C++ aren't. It (the borrow checker) relies on static analysis that effectively tells you that the way you wrote the code is unsound and needs to…

Sounds like a feature of the porting process. Not a bug. And I’d like to think that BoringSSL would be designed well enough internally to make that less of an issue.

I agree that this might slow down the process of porting the code though. I wonder how much by?

Re: This shouldn't have happened: A vulnerability postmortem

#265
post #211

Earlier quoted context omitted.

If it can really guarantee single-digit microsecond pauses in my realtime thread no matter what happens in other threads of my application, that is indeed a game changer. But I'll believe it when I see it with my own eyes. I've never even used a garbage collector that can guarantee single-digit millisecond pauses.

Not sure current state of the art, but Go's worst-case pause time five years ago was 100µs: https://groups.google.com/g/golang-dev/c/Ab1sFeoZg_8

Discord was consistently seeing pauses in the range of several hundred ms every 2 minutes a couple years ago.

https://blog.discord.com/why-discord-is-switching-from-go-to...

Re: This shouldn't have happened: A vulnerability postmortem

#266
post #46

The sooner we can rewrite our programs in Go and Rust, the more secure we will be. Our shells, coreutils, mail readers and web browsers have to be written in safer languages.

A century ago, buildings were quite dangerous, and likely to kill you in all sorts of situations. Wood burns, and concrete and brick don't. Clearly wood is an "unsafe material". But just changing the material didn't result in safer buildings. Buildings made of brick and concrete still killed people. It turns out that there are a lot of factors that go into building safety. The material is one vulnerability, sure. But…

> A century ago, buildings were quite dangerous, and likely to kill you in all sorts of situations. Wood burns, and concrete and brick don't. Clearly wood is an "unsafe material". But just changing the material didn't result in safer buildings. Buildings made of brick and concrete still killed people.

This will seem trite, but I think it's just literally easier to figure out how to build wooden buildings that are fire resistant than it is to write memory safe code in C/C++.

Re: This shouldn't have happened: A vulnerability postmortem

#267

When will we switch to memory safe (but reasonably performant) languages like Go/Rust/C#? Performance critical sections could remain in C/C++, but MOST code doesn’t need the kind of performance C/C++ provides. Hopefully C/C++ will go the way of assembly: present in TINY doses.

I don't think you need to explain to Mozilla about Just Rewriting It to Rust

Re: This shouldn't have happened: A vulnerability postmortem

#268
post #179

Earlier quoted context omitted.

BoringSSL started as a stripped down OpenSSL. That's very different from a ground-up replacement. The closest attempt here is https://github.com/briansmith/ring but even that borrows heavily the cryptographic operations from BoringSSL. Those algorithms themselves are generally considered to be more thoroughly vetted than the pieces like ASN.1 validation.

Ring would be cool if not for https://github.com/briansmith/ring#versioning--stability

This sounds like a nightmare for any downstream users of this library. Any one of those bullet points in that section would be a major concern for me using it in anything other than a hobby project, but all of them together seem almost willfully antagonistic to users.

This is especially true given it’s a security library, which perhaps more than any other category I would want to be stable, compatible, and free of surprises.

“You must upgrade to the latest release the moment we release it or else you risk security vulnerabilities and won’t be able to link against any library that uses a different version of ring. Also, we don’t ‘do’ stable APIs and remove APIs the instant we create a new one, so any given release may break your codebase. Good luck have fun!”

Re: This shouldn't have happened: A vulnerability postmortem

#269

Earlier quoted context omitted.

To provide some context for my answer, I’ve seen, first hand, plenty of insecure code written in python, JavaScript and ruby, and a metric ton - measured in low vulnerabilities/M LoC - of secure code written in C for code dating from the 80s to 2021. I personally don’t like the mental burden of dealing with C any more and I did it for 20+ years, but the real problem with vulnerabilities in code once the low hanging f…

C vulnerabilities do have a nasty habit of giving the attacker full code execution though, which doesn’t tend to be nearly so much of a problem in other languages (and would likely be even less so if they weren’t dependant on foundations written in C)

I don’t disagree with you. But just before writing that message I was code reviewing some python that was vulnerable a to the most basic SQL injection. Who needs or wants execution authority when you can dump the users table of salted sha passwords?

Re: This shouldn't have happened: A vulnerability postmortem

#270
post #238

Earlier quoted context omitted.

>"1kloc / day is a reasonable ballpark figure, landing us at about one person-year to port boringssl to rust." Porting 1k lines a day, testing and catching and fixing errors to language with incompatible memory model and doing it for a year is insanity. Programmers who propose this kind of productivity most likely have no idea about real world.

There’s an old saying attributed to Abe Lincoln: “Give me six hours to chop down a tree and I will spend the first four sharpening the axe.” I contend that most software engineers (and most engineering houses) don’t spend any time sharpening the axe. Certainly not when it comes to optimizing for development speed. Nobody even talks about deliberate practice in software. Isn’t that weird? 1000 lines of code is way too…

I'm also really skeptical that one could maintain 1K/lines per day for more than a couple weeks if that.

There have been a lot of studies that measure average output of new code at only ~15 or so LOC/day. One can manage more on small projects for a short amount of time.

I could believe porting between two C-like languages is 1 order of magnitude easier, but not 2. Std library differences, porting idioms, it adds up.

Even just reading and really understanding 1K lines/day is a lot.

Post reply on HN