Live data from Hacker News

There is no memory safety without thread safety

ralfj.de

171–180 of 517 posts

Re: There is no memory safety without thread safety

#171

I have never seen real Go code (i.e. not code written purposefully to be exploitable) that was exploitable due to a data race. This doesn’t prove a negative, but is probably a good hint that this risk is not something worth prioritizing for Go applications from a security point of view. Compare this with C/C++ where 60-75% of real world vulnerabilities are memory safety vulnerabilities. Memory safety is definitely a…

I have! What do i win?

Re: There is no memory safety without thread safety

#172
post #138

Earlier quoted context omitted.

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).

The definition has to do with certain classes of spatial and temporal memory errors. Ie., the ability to access memory outside the bounds of an array would be an example of a spatial memory error. Use-after-free would be an example of a temporal one. The violation occurs if the program keeps running after having violated a memory safety property. If the program terminates, then it can still be memory safe in the defi…

Both spatial and temporal memory unsafety can lead to segfaults, because that's how memory protection is intended to work in the first place. I don't believe it's feasible to write a language that manages to provably never trip a memory protection fault in your typical real-world system, yet still fails to be memory safe, at least in some loose sense. For example, such a language could never be made to execute arbitrary code, because arbitrary code can just trip a segfault. You'd be left with the sort of type confusion logical error that happens all the time anyway in all sorts of "weakly typed" languages - that's not what "memory safety" is about.

Re: There is no memory safety without thread safety

#173
post #142

Earlier quoted context omitted.

Crashing on shared access is the safe thing to do

An intentional exit by a runtime is a safe crash. A segfault is not, and is here a clear sign that memory safety has been violated.

I guess I was thinking specifically of the swift case where values have exclusive access enforcement. Normally caught by a compiler, they will safely crash if the compiler didn’t catch it. I think the only way to segfault would be by using Unsafe*Pointer types, which are explicitly marked unsafe

Re: There is no memory safety without thread safety

#174
post #149
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…

Rust does have loop counter overflow.

This is irrelevant on 64-bit platforms [^1] [^2]. For platforms with smaller `usize`, enable overflow-checks in your release builds.

[^1]: https://www.reddit.com/r/ProgrammerTIL/comments/4tspsn/c_it_...

[^2]: https://stackoverflow.com/questions/69375375/is-it-safe-to-a...

Re: There is no memory safety without thread safety

#175
post #34

Earlier quoted context omitted.

https://github.com/golang/go/issues/34902 https://www.cloudfoundry.org/blog/cve-2020-15586/ I don’t see any evidence that anyone wrote an RCE exploit for this, but I also don’t see any evidence of anyone even trying to rule it out.

What about this particular bug do you think makes it likely to be exploitable? I'm not asking you to write an RCE POC, just to tell a story of the sequence of events involving this bug that results in attacker-controlled code. What does the attacker control here, and how do they use that control to divert execution?

As a general heuristic, a corrupted data structure in a network server results in RCE. This is common in languages like C and C++.

On first glance, it looks like the bug can (at least) result in the server accessing a slice object where the various fields don’t all come from the same place. So the target server can end up accessing some object out of bounds (or as the wrong type or both), which can easily end up writing some data (possibly attacker controlled) to an inappropriate place. In standard attack, the attacker might try to modify the stack or a function pointer to set up a ROP chain or something similar, which is close enough to arbitrarily code to eventually either corrupt something to directly escalate privileges or to do appropriate syscalls to actually execute code.

Re: There is no memory safety without thread safety

#176
False.

Java got this right. Fil-C gets it right, too. So, there is memory safety without thread safety. And it’s really not that hard.

Memory safety is a separate property unless your language chooses to gate it on thread safety. Go (and some other languages) have such a gate. Not all memory safe languages have such a gate.

Re: There is no memory safety without thread safety

#177
post #142

Earlier quoted context omitted.

Crashing on shared access is the safe thing to do

An intentional exit by a runtime is a safe crash. A segfault is not, and is here a clear sign that memory safety has been violated.

Yeah it's not the segfault that's bad, it's when it's when the write to address 0x20001854 succeeds and now some hapless postal clerk is going to jail.

Re: There is no memory safety without thread safety

#178
post #175

Earlier quoted context omitted.

What about this particular bug do you think makes it likely to be exploitable? I'm not asking you to write an RCE POC, just to tell a story of the sequence of events involving this bug that results in attacker-controlled code. What does the attacker control here, and how do they use that control to divert execution?

As a general heuristic, a corrupted data structure in a network server results in RCE. This is common in languages like C and C++. On first glance, it looks like the bug can (at least) result in the server accessing a slice object where the various fields don’t all come from the same place. So the target server can end up accessing some object out of bounds (or as the wrong type or both), which can easily end up writ…

No, that doesn't work. Lots of (maybe even most) corrupted data structures aren't exploitable (past DOS). Where does the attacker-controlled data come from. What path does it take to get to where the attacker wants it to go. You have to be able to answer those two questions.

Re: There is no memory safety without thread safety

#179

False. Java got this right. Fil-C gets it right, too. So, there is memory safety without thread safety. And it’s really not that hard. Memory safety is a separate property unless your language chooses to gate it on thread safety. Go (and some other languages) have such a gate. Not all memory safe languages have such a gate.

I would recommend reading beyond the title of a post before leaving replies like this, as your comment is thoroughly addressed in the text of the article:

> At this point you might be wondering, isn’t this a problem in many languages? Doesn’t Java also allow data races? And yes, Java does allow data races, but the Java developers spent a lot of effort to ensure that even programs with data races remain entirely well-defined. They even developed the first industrially deployed concurrency memory model for this purpose, many years before the C++11 memory model. The result of all of this work is that in a concurrent Java program, you might see unexpected outdated values for certain variables, such as a null pointer where you expected the reference to be properly initialized, but you will never be able to actually break the language and dereference an invalid dangling pointer and segfault at address 0x2a. In that sense, all Java programs are thread-safe.

And:

> Java programmers will sometimes use the terms “thread safe” and “memory safe” differently than C++ or Rust programmers would. From a Rust perspective, Java programs are memory- and thread-safe by construction. Java programmers take that so much for granted that they use the same term to refer to stronger properties, such as not having “unintended” data races or not having null pointer exceptions. However, such bugs cannot cause segfaults from invalid pointer uses, so these kinds of issues are qualitatively very different from the memory safety violation in my Go example. For the purpose of this blog post, I am using the low-level Rust and C++ meaning of these terms.

Java is in fact thread-safe in the sense of the term used in the article, unlike Go, so it is not a counterexample to the article's point at all.

Re: There is no memory safety without thread safety

#180
post #76

Earlier quoted context omitted.

You’re a cryptography person. So you know that most theoretically interesting cryptography vulnerabilities, even the ones that are exploitable in PoCs, are too obscure and/or difficult to get used by actual attackers. Same goes for hardware vulnerabilities. Rowhammer and speculative execution attacks are often shown to be able to corrupt and leak memory, respectively, but AFAIK there are no famous cases of them actua…

There's lots of clientside Go, too!

Where? Within, as I said, “the type of consumer OS or client-side application that typically gets attacked”. It has to be a component of either a big application or a big OS, or something with comparable scope. Otherwise it would not likely be targeted by real-world memory corruption attacks (that we hear about) no matter the language. At least that’s my impression.
Post reply on HN