Live data from Hacker News

There is no memory safety without thread safety

ralfj.de

111–120 of 517 posts

Re: There is no memory safety without thread safety

#111
post #68

Earlier quoted context omitted.

Rust can yield a higher quality solution, but we can't make a perfect solution, we can only approach perfection. If we want to go further, we could introduce formally-proven code, too. Personally I'm interested in the intersection of proof assistants and Rust, like creusot-rs, and have been investigating it. But as much as I love LARPing about correctness (believe me I do,) it's just simply the case that we won't rig…

A lot of sass people i know are more and more choosing rust for boring code. This includes several people who said things like "go is good enough, i don't want to deal with all the rust completely". Once your sass products get enough users, and you're dealing with millions or billions of requests per day, those rare bugs start showing up quite often... And it turns out programming towards correctness is desirable, if…

But correctness is not binary, it's more like a multidimensional spectrum. Your choice of programming language has some influence, as does standards and conventions, the ecosystem of your programming language, use of automated tooling like linting and testing, or even just ol' unreliable, discipline. Being a relatively greenfield language, Go is not in a terrible place when it comes to most of those things. Tons of automated tooling, including tools like the Checklocks analyzer or the many tools bundled with golangci-lint. Uber has done a pretty good job enumerating the challenges that remain, and even working at improving those issues too, such as with NilAway.

The question isn't "wouldn't you prefer more correctness?" it's "how much would you pay for how much of an improvement in correctness?".

Rust is still growing rapidly though, whereas Go is probably not growing rapidly anymore, I think Go has at least saturated it's own niche more than 50% and is on the other end of the curve by now. Last I checked Rust is the trendiest language by far, the one that people most wish they were writing, and the one that you want to be able to say your project is written in. So it would be extremely surprising to hear if there wasn't a growing Rust presence basically everywhere, SaaS's included.

Re: There is no memory safety without thread safety

#112
post #81

Go is memory safe by the most common definition, does not matter if you have segfault in some scenario. How many exploits or security issues have there been related to data race on dual word values? I work with Go for the last 10 years and I never heard of such issues. Not a single time.

The most common definition of memory safe is literally "cannot segfault" (unless invoking some explicitly unsafe operation - which is not the case here unless you think the "go" keyword should be unsafe).

TBH segfaults are not necessarily a sign of memory unsafety, but _unexpected_ segfaults are.

For some examples, Rust (although this is not specific to it) uses stack guard pages to detect stack overflows by _forcing_ a segfault (as opposed to reading/writing arbitrary memory after the usual stack). Some JVMs also expect and handle segfaults when dereferencing null pointers, to avoid always paying the cost for checking them.

Re: There is no memory safety without thread safety

#113
post #79
post #55

The sad thing is that most languages with threads have a default of global variables and unrestricted shared memory access. This is the source of the vast majority of data corruption and races. Processes are generally a better concurrency model than threads, but they are unfortunately too heavyweight for many use cases. If we defaulted to message passing all required data to each thread (either by always copying or t…

> The sad thing is that most languages with threads have a default of global variables and unrestricted shared memory access. This is the source of the vast majority of data corruption and races. Processes are generally a better concurrency model than threads Modern languages have the option of representing thread-safety in the type system, e.g. what Rust does, where working with threads is a dream (especially when y…

Originally Rust is something altogether different. Graydon has written about that extensively. Graydon wanted tail calls, reflection, more "natural" arithmetic with Python style automatic big numbers, decimal for financial work and so on.

The Rust we have from 1.0 onwards is not what Graydon wanted at all. Would Graydon's language have been broadly popular? Probably not, we'll never know.

Re: There is no memory safety without thread safety

#114
post #27

Earlier quoted context omitted.

There's enormous incentive to construct those exploits. Why don't they exist?

I'm not sure that's correct. Yes, this is an enormous effort to construct exploits, but constructing exploits for C/C++ code is much much easier and gives not less, or even more, benefit. Therefore it makes sense the efforts are focused on that. If/when most C/C++ code in the world will be gone, I assume we'll see more exploits of Go code.

I can show you a trivial POC in C/C++ where someone opens a socket and ends up with a buffer overflow or UAF, both cases leading to memory corruption due to sloppy programming, and both easily exploitable for RCE.

Can you show me any reasonable proof of concept (without using unsafe etc.) in Go that leads to similar memory corruption and is exploitable for RCE?

Re: There is no memory safety without thread safety

#115
post #75

This is one of the things that I'm also looking on at Zig like a slow moving car crash about: they claim they are memory safe (or at least "good enough" memory safe if you use the safe optimization level, which is it's own discussion), but they don't have the equivalent to Rust's Send/Sync types. It just so happens that in practice no one was writing enough concurrent Zig code to get bitten by it a lot, I guess...exc…

IIUC even single-threaded Zig programs built with ReleaseSafe are not guaranteed to be free of memory corruption vulnerabilities; for example, dereferencing a pointer to a local variable that's no longer alive is undefined behavior in all optimization modes.

Re: There is no memory safety without thread safety

#116
post #88

Earlier quoted context omitted.

Interestingly, at least in C++, this was changed in the recent past. It used to be that evaluation of arguments was not sequenced at all and if any evaluation touched the same variable, and at least one was a write, it was UB. It was changed as part of the C++11 memory model and now, as you said, there is a sequenced-before order, it is just unspecified which one it is. I don't know much about C, but I believe it was…

Yes, but that's just a subset of expressions where unspecified sequencing applied. For instance, the example with two `print()` as parameters would have a sequence point (in pre-C++11 terminology) separating any reads/writes inside the `print` due to the function calls. It would never be UB even though the order in which the prints are called is still unspecified.

IIRC the point was that there was no sequence point between argument evaluation, so for example f(++i, ++i) was UB. Or maybe it was only for builtin operators?

Cppreference is not authoritative[1], but seems to support my recollection. In fact it states that the f(++i, ++i) was UB till C++17.

[1] https://en.cppreference.com/w/cpp/language/eval_order.html, Pre C++11 Ordering Rules, point (2).

Re: There is no memory safety without thread safety

#117

Earlier quoted context omitted.

Interestingly, at least in C++, this was changed in the recent past. It used to be that evaluation of arguments was not sequenced at all and if any evaluation touched the same variable, and at least one was a write, it was UB. It was changed as part of the C++11 memory model and now, as you said, there is a sequenced-before order, it is just unspecified which one it is. I don't know much about C, but I believe it was…

Sure, prior to the C++ 11 memory model there just isn't a memory ordering model in C++ and all programs in either C or C++ which would need ordering for correctness did not have any defined behaviour in the language standard. This is very amusing because that means in terms of the language standard Windows and Linux, which both significantly pre-date C++ 11 and thus its memory model, were technically relying on Undef…

It is not so much that windows and linux were relying on UB, but that these platforms, with their compilers, provided guarantees beyond the standard. e.g. GCC not only aims for C/C++ standard compliance, but also POSIX.

Of course these guarantees were often not fully written down nor necessarily self consistent (but then again, neither is the current standard).

Re: There is no memory safety without thread safety

#118
post #102
post #95

Earlier quoted context omitted.

On the flip side, what would be the point? There are already a million other languages that have everything and the kitchen sink. Not going down the same road is the only reason it didn't end up on the pile of obscure languages nobody uses.

The only reason it didn't end on pile of obscure languages nobody uses, it called Google, followed by luck with Docker and Kubernetes adoption on the market, after they decided to rewrite from Python and Java respectively into Go, after Go heads joined their teams. Case in point, Limbo and Oberon-2, the languages that influenced its design, and authors were involved with.

> The only reason it didn't end on pile of obscure languages nobody uses, it called Google

Dart ended up on the pile of languages nobody uses. And Carbon? What's Carbon? Exactly!

> Case in point, Limbo and Oberon-2, the languages that influenced its design

Agreed. Limbo and Oberon-2, as primitive as they may look now, had the kitchen sinks of their time. Why wouldn't they have ended up on the pile of languages nobody uses?

Re: There is no memory safety without thread safety

#119
post #58
post #23

Earlier quoted context omitted.

It took months to finally solve a data race in Go. No race detector would see anything. Nobody understood what was happening. It ultimately resulted in a loop counter overflowing, which recomputed the same thing a billion of time (but always the same!). So the visible effect was a request would randomly take 3 min instead of 100ms. I ended up using perf in production, which indirectly lead me to understand the data r…

It is very unfortunate that we use fixed width numbers by default in most programming languages and that common ops will silently overflow. Smarter compilers can work with richer numeric primitives and either automatically promote machine words to big numbers or throw an error on overflow. People talk a lot about the productivity gains of ai, but fixing problems like this at the language level could have an even bigg…

The situation with numbers in basically every widely used programming language is kind of an indictment of our industry. Silent overflow for incorrect results, no convenient facilities for units, lossy casts everywhere. It's one of those things where standing in 1975 you'd think surely we'll spend some of the next 40 years of performance gains to give ourselves nice, correct numbers to work with, but we never did.

Re: There is no memory safety without thread safety

#120

Memory safety is a big deal because many of the CVEs against C programs are memory safety bugs. Thread safety is not a major source of CVEs against Go programs. It’s a nice theoretical argument but doesn’t hold up in practice.

A typical memory safety issue in a C program is likely to generate an RCE. A thread-safety issue that leads to a segfault can likely only lead to a DoS attack, unpleasant but much less dangerous. A race condition can theoretically lead to more powerful attacks, but triggering it should be much harder.
Post reply on HN