Live data from Hacker News

This shouldn't have happened: A vulnerability postmortem

googleprojectzero.blogspot.com

471–480 of 499 posts

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

#471

Earlier quoted context omitted.

How big is too big? I haven't run into any size issues writing very unoptimized Go targeting STM32F4 and RP2040 microcontrollers, but they do have a ton of flash. And for that, you use tinygo and not regular go, which is technically a slightly different language. (For some perspective, I wanted to make some aspect of the display better, and the strconv was the easiest way to do it. That is like 6k of flash! An unabas…

I have 16MB of flash and I wanted to link in some webrtc Go library and the binary was over 1MB. As I had other stuff it seemed like C was smaller.

I took a look at using github.com/pion/webrtc/v3 with tinygo, but it apparently depends on encoding/gob which depends on reflection features that tinygo doesn't implement. No idea why they need that, but that's the sort of blocker that you'll run into.

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

#472
post #452
post #433

Earlier quoted context omitted.

Just compile it all to Wasm and we'll run it in virtualization. Give us memory segments back and I think we have a shot of making this a reality.

Except WASM made the big mistake of not having bounds checking on linear memory, so attacks with input data that corrupt internal state and by it try to influence the outcome of WASM modules behaviour are still a good attack vector. Being sandboxed is good, however if one can start an internal fire from the outside, not so much.

Not sure what you were expecting, but no, Wasm doesn't magically make memory-unsafe languages internally uncorruptible, it limits all corruption to internal state. If you look at the PL research stretching back a couple decades on how to do that for C, you are looking at integer factor performance overheads in the general case. Wasm also doesn't make anything less safe than it was before (ok, ok, modulo the current lack of read-protected memory), and since we wisely chose to make the execution stack non-addressable, has CFI by default.

Wasm's sandboxing makes it impossible to escalate the privilege of a program or acquire capabilities that it didn't have before (i.e. were not explicit imported and granted). That's a strictly stronger primitive than a random userspace Unix process.

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

#473
post #312
post #275

Earlier quoted context omitted.

The whole post is a giant blinking red sign that says (or should say) "Fuzzing is a horribly ineffective workaround for a treacherous language." No offense to the many bright and capable people who have worked hard on the C/C++ language, tools, compilers, libraries, kernels, etc over the years, but we will someday look back on it as asbestos and wonder why we kept at it for so damn long .

> but we will someday look back on it as asbestos and wonder why we kept at it for so damn long. Maybe. But there is good reason for C dominance - it's low level and close to systems as in "syscalls and stuff". And we need that level of systems control, not only for max performance but also for not loosing what is available in hw and os. Asm is the other option to have full functionality :) Maybe it's just case of av…

Memory is cheap. (But not free of course!) Scala, Kotlin, and Java exist. The HotSpot VM is amazing, its JIT is mindblowing. (Probaly even TS + V8 would do the job for high level stuff.)

It's complete nonsense that C is needed for accessing the HW. High level languages can do low-level bibanging just fine.

So yes, there's a good reason, but that is inertia. Literally too big to fail, so it keeps on living. Even if we tomorrow outlawed C, drafted people to start rewriting things in a memory-managed language, and so on, it would take decades to get rid of it.

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

#474

Earlier quoted context omitted.

There’s a world of difference between ASN.1 validation and validation of cryptographic primitives. The serialization/deserialization routines for cryptographic data formats or protocols are where you typically get problems. Things like AES and ECDSA itself, less so, especially when you’re talking about the code in BoringSSL. Maybe some more obscure algorithms but I imagine BoringSSL has already stripped them and ring…

For symmetric cryptography (ciphers & hashes), I agree. I'd say as far as to say they're stupidly easy to test. Polynomial hashes, elliptic curves, and anything involving huge numbers however are more delicate. Depending on how you implement them, you could have subtle limb overflow issues, that occur so extremely rarely by chance that random test don't catch them. For those you're stuck with either proving that your…

That's a very good point. Thanks for the correction!

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

#475

Earlier quoted context omitted.

> I don't think there are any general purpose programming languages with decent performance which outright "prevent undefined behaviour" in something like NSS. Rust, for example, does not. You know what I meant by "a language that prevents UB". Your comment argues semantics. That's not nice. Please stop. > safe Rust doesn't have undefined behaviour but of course you can (and a large project like this will) use unsafe…

> A large Rust project uses unsafe only because its authors don't care enough. This is not true at all. There are plenty of reasons to occasionally use unsafe code, even if your bar for "is it really worth it" is quite high. One reason, if you're writing a crypto library, is that certain kinds of timing attacks are pretty much impossible to prevent without inline assembly.

Preventing timing leaks requires unsafe code because the Rust compiler lacks support for constant-runtime code [0]. Adding that support is one step in making it "good enough to use for everything".

What are several more of the "plenty of reasons to occasionally use unsafe code"? I can think of only one: interfacing with hardware or unsafe OSes that control access to the hardware.

[0] https://github.com/rust-lang/rfcs/issues/2533

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

#476
post #472
post #452

Earlier quoted context omitted.

Except WASM made the big mistake of not having bounds checking on linear memory, so attacks with input data that corrupt internal state and by it try to influence the outcome of WASM modules behaviour are still a good attack vector. Being sandboxed is good, however if one can start an internal fire from the outside, not so much.

Not sure what you were expecting, but no, Wasm doesn't magically make memory-unsafe languages internally uncorruptible, it limits all corruption to internal state. If you look at the PL research stretching back a couple decades on how to do that for C, you are looking at integer factor performance overheads in the general case. Wasm also doesn't make anything less safe than it was before (ok, ok, modulo the current l…

I was expecting that people don't oversell WebAssbemly as some kind of magic pixie dust of security, anyone that knows a bit about security spots those flaws.

You know what is also sandboxed? An OS process.

Ah, but an OS process has a wider syscalls surface, well lets than bring WASI or JavaScript bindings into the picture.

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

#477
post #356

Earlier quoted context omitted.

> Why is indirect Internet access less of a problem for C than Rust/Go/etc? Because C codes tend to have less dependencies and shallow/more "clustered" dependency graph. To be fair, that's more or less due to dependency management being a 100% pain 0 fun experience.

I agree with your characterization of the dependency graphs, but I don't see how that changes the calculus. Let's say in both cases you're copying a tarball of dependencies onto your friend's AIX machine--why is it harder to copy a tarball with a few large dependencies rather than a tarball with more small dependencies (I also posit that the Rust tarball would be smaller because you're less likely to be bringing in t…

> a few large dependencies

Unfortunately this does not match my experience :( Rust projects tend to depend on a lot of smaller, single-purposed (or, npm-y) dependencies, for example, Debian's ripgrep package has a X-Cargo-Built-Using saying:

X-Cargo-Built-Using: rust-aho-corasick (= 0.7.10-1), rust-atty (= 0.2.14-2), rust-base64 (= 0.12.1-1), rust-bitflags (= 1.2.1-1), rust-bstr (= 0.2.12-1), rust-bytecount (= 0.6.0-1), rust-byteorder (= 1.3.4-1), rust-cfg-if-0.1 (= 0.1.10-2), rust-clap (= 2.33.3-1), rust-crossbeam-utils (= 0.7.2-2), rust-encoding-rs (= 0.8.22-1), rust-encoding-rs-io (= 0.1.6-2), rust-fnv (= 1.0.6-1), rust-globset (= 0.4.5-1), rust-grep-cli (= 0.1.5-1), rust-grep (= 0.2.7-1), rust-grep-matcher (= 0.1.4-1), rust-grep-pcre2 (= 0.1.4-2), rust-grep-printer (= 0.1.5-1), rust-grep-regex (= 0.1.8-1), rust-grep-searcher (= 0.1.7-1), rust-ignore (= 0.4.16-2), rust-itoa (= 0.4.3-1), rust-lazy-static (= 1.4.0-1), rust-libc (= 0.2.80-1), rust-log (= 0.4.11-2), rust-memchr (= 2.3.3-1), rust-memmap (= 0.7.0-1), rust-num-cpus (= 1.13.0-1), rust-pcre2 (= 0.2.3-1), rust-pcre2-sys (= 0.2.2-1), rust-regex-automata (= 0.1.8-2), rust-regex (= 1.3.7-1), rust-regex-syntax (= 0.6.17-1), rust-ryu (= 1.0.2-1), rust-same-file (= 1.0.6-1), rust-serde (= 1.0.106-1), rust-serde-json (= 1.0.41-1), rust-strsim (= 0.9.3-1), rust-termcolor (= 1.1.0-1), rust-textwrap (= 0.11.0-1), rust-thread-local (= 1.0.1-1), rust-unicode-width (= 0.1.8-1), rust-walkdir (= 2.3.1-1), rustc (= 1.48.0+dfsg1-2)

Building it using cargo with Internet access is a breeze. Figuring out how to `cargo vendor` is not. And the sheer number of the dependencies makes it not practical to manually do stuff.

In short, what cargo actively supports and everyone uses are great, otherwise it's disaster.

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

#478

Earlier quoted context omitted.

Hard to say without more details, but those graphs look very similar to nproc numbers of goroutines interacting with the Linux-of-the-time's CFS CPU scheduler. I've seen significant to entire improvement to latency graphs simply by setting GOMAXPROC to account for the CFS behavior. Unfortunately the blog post doesn't even make a passing mention to this.

Anecdotally, the main slowdown we saw of Go code running in Kubernetes at my previous job was not "GC stalls", but "CFS throttling". By default[1], the runtime will set GOMACSPROCS to the number of cores on the machine, not the CPU allocation for the cgroup that the container runs in. When you hand out 1 core, on a 96-core machine, bad things happen. Well, you end up with a non-smooth progress. Setting GOMACPROCS to…

Ah, note, said program also had one goroutine trying the stupidest-possible way of finidng primes in one goroutine (then not actyakly doing anything with the found primes, apart from appending them to a slice). It literally trial-divided (well, modded) all numbers between 2 and isqrt(n) to see if it was a multiple. Not designed to be clever, explicitly designed to suck about one core.

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

#479
post #453

Earlier quoted context omitted.

In Rust, or any other systems programming language with unsafe code blocks, all the way back to JOVIAL and ESPOL, one can search for those code blocks. At very least they provide an initial searching point. On C, C++ and Objective-C, any line of code is a possible cause for memory corruption, integer overflow, or implicit conversions that lead to data loss.

This is starting from the point of knowing it is a memory corruption issue though. From my experience, memory corruption usually manifests in logic or data behaviour changes. In a Rust program you'd probably spend a few days pulling your hair out trying to understand why some data structure doesn't do what it's supposed to before considering that it's one of the unsafe blocks.

Yeah, but at least you know where to start searching afterwards.

This applies to other languages with unsafe code blocks, note that JOVIAL and ESPOL were the first ones offering such capability.

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

#480
post #143

Earlier quoted context omitted.

I don't think the exact URL is the problem, it is the fact that it is so easy to include dependencies from external repository that is the problem. In Rust every non-trivial library pulls in 10s or even 100s of dependencies. I don't think anyone can expect that all of these libraries are of good quality but how would one even try to verify that? And you have to verify it every time you update your project. Then there…

> 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…

druid v0.7.0 (\druid\druid) druid-derive v0.4.0 (proc-macro) (\druid\druid-derive) proc-macro2 v1.0.32 unicode-xid v0.2.2 quote v1.0.10 proc-macro2 v1.0.32 () syn v1.0.81 proc-macro2 v1.0.32 () quote v1.0.10 () unicode-xid v0.2.2 [dev-dependencies] druid v0.7.0 (\druid\druid) () float-cmp v0.8.0 trybuild v1.0.52 glob v0.3.0 lazy_static v1.4.0 serde v1.0.130 serde_derive v1.0.130 (proc-macro) proc-macro2 v1.0.32 () quote v1.0.10 () syn v1.0.81 () serde_json v1.0.69 itoa v0.4.8 ryu v1.0.5 serde v1.0.130 () termcolor v1.1.2 winapi-util v0.1.5 winapi v0.3.9 winapi-x86_64-pc-windows-gnu v0.4.0 toml v0.5.8 serde v1.0.130 () druid-shell v0.7.0 (\druid\druid-shell) anyhow v1.0.45 cfg-if v1.0.0 instant v0.1.12 cfg-if v1.0.0 keyboard-types v0.5.0 bitflags v1.3.2 kurbo v0.8.2 arrayvec v0.7.2 lazy_static v1.4.0 piet-common v0.5.0-pre1 cfg-if v1.0.0 piet v0.5.0-pre1 kurbo v0.8.2 () unic-bidi v0.9.0 matches v0.1.9 unic-ucd-bidi v0.9.0 unic-char-property v0.9.0 unic-char-range v0.9.0 unic-char-range v0.9.0 unic-ucd-version v0.9.0 unic-common v0.9.0 piet-direct2d v0.5.0-pre1 associative-cache v1.0.1 dwrote v0.11.0 lazy_static v1.4.0 libc v0.2.107 winapi v0.3.9 () wio v0.2.2 winapi v0.3.9 () piet v0.5.0-pre1 () utf16_lit v2.0.2 winapi v0.3.9 () wio v0.2.2 () png v0.17.2 bitflags v1.3.2 crc32fast v1.2.1 cfg-if v1.0.0 deflate v0.9.1 adler32 v1.2.0 encoding v0.2.33 encoding-index-japanese v1.20141219.5 encoding_index_tests v0.1.4 encoding-index-korean v1.20141219.5 encoding_index_tests v0.1.4 encoding-index-simpchinese v1.20141219.5 encoding_index_tests v0.1.4 encoding-index-singlebyte v1.20141219.5 encoding_index_tests v0.1.4 encoding-index-tradchinese v1.20141219.5 encoding_index_tests v0.1.4 miniz_oxide v0.4.4 adler v1.0.2 [build-dependencies] autocfg v1.0.1 scopeguard v1.1.0 time v0.3.5 tracing v0.1.29 cfg-if v1.0.0 pin-project-lite v0.2.7 tracing-attributes v0.1.18 (proc-macro) proc-macro2 v1.0.32 () quote v1.0.10 () syn v1.0.81 () tracing-core v0.1.21 lazy_static v1.4.0 winapi v0.3.9 () wio v0.2.2 () [dev-dependencies] piet-common v0.5.0-pre1 () static_assertions v1.1.0 test-env-log v0.2.7 (proc-macro) proc-macro2 v1.0.32 () quote v1.0.10 () syn v1.0.81 () tracing-subscriber v0.2.25 ansi_term v0.12.1 winapi v0.3.9 () chrono v0.4.19 libc v0.2.107 num-integer v0.1.44 num-traits v0.2.14 [build-dependencies] autocfg v1.0.1 [build-dependencies] autocfg v1.0.1 num-traits v0.2.14 () winapi v0.3.9 () lazy_static v1.4.0 matchers v0.0.1 regex-automata v0.1.10 regex-syntax v0.6.25 regex v1.5.4 regex-syntax v0.6.25 serde v1.0.130 () serde_json v1.0.69 () sharded-slab v0.1.4 lazy_static v1.4.0 smallvec v1.7.0 thread_local v1.1.3 once_cell v1.8.0 tracing v0.1.29 () tracing-core v0.1.21 () tracing-log v0.1.2 lazy_static v1.4.0 log v0.4.14 cfg-if v1.0.0 tracing-core v0.1.21 () tracing-serde v0.1.2 serde v1.0.130 () tracing-core v0.1.21 () unicode-segmentation v1.8.0 fluent-bundle v0.15.2 fluent-langneg v0.13.0 unic-langid v0.9.0 unic-langid-impl v0.9.0 tinystr v0.3.4 fluent-syntax v0.11.0 thiserror v1.0.30 thiserror-impl v1.0.30 (proc-macro) proc-macro2 v1.0.32 () quote v1.0.10 () syn v1.0.81 () intl-memoizer v0.5.1 type-map v0.4.0 rustc-hash v1.1.0 unic-langid v0.9.0 () intl_pluralrules v7.0.1 tinystr v0.3.4 unic-langid v0.9.0 () rustc-hash v1.1.0 self_cell v0.10.1 smallvec v1.7.0 unic-langid v0.9.0 () fluent-langneg v0.13.0 () fluent-syntax v0.11.0 () fnv v1.0.7 instant v0.1.12 () tracing v0.1.29 () tracing-subscriber v0.2.25 () unic-langid v0.9.0 () unicode-segmentation v1.8.0 xi-unicode v0.3.0 [dev-dependencies] float-cmp v0.8.0 open v1.7.1 winapi v0.3.9 () piet-common v0.5.0-pre1 () pulldown-cmark v0.8.0 bitflags v1.3.2 memchr v2.4.1 unicase v2.6.0 [build-dependencies] version_check v0.9.3 tempfile v3.1.0 cfg-if v0.1.10 rand v0.7.3 getrandom v0.1.16 cfg-if v1.0.0 rand_chacha v0.2.2 ppv-lite86 v0.2.15 rand_core v0.5.1 getrandom v0.1.16 () rand_core v0.5.1 () remove_dir_all v0.5.3 winapi v0.3.9 () winapi v0.3.9 () test-env-log v0.2.7 (proc-macro) () tracing-subscriber v0.2.25 ()

druid-derive v0.4.0 (proc-macro) (\druid\druid-derive) ()

druid-shell v0.7.0 (\druid\druid-shell) ()

Post reply on HN