Live data from Hacker News

There is no memory safety without thread safety

ralfj.de

251–260 of 517 posts

Re: There is no memory safety without thread safety

#251
post #64

Earlier quoted context omitted.

> If you want to claim that a language is memory-unsafe, POC || GTFO. There's a POC right in the post, demonstrating type confusion due to a torn read of a fat pointer. I think it could have just as easily been an out-of-bounds write via a torn read of a slice. I don't see how you can seriously call this memory safe, even by a conservative definition. Did you mean POC against a real program? Is that your bar?

You need a non-contrived example of a memory-corrupting data race that gives attackers the ability to control memory, through type confusion or a memory lifecycle bug or something like it. You don't have to write the exploit but you have to be able to tell the story of how the exploit would actually work --- "I ran this code and it segfaulted" is not enough. It isn't even enough for C code!

The post is a demonstration that a class of problems: causing Go to treat a integer field as a pointer and access the memory behind that pointer without using any of Go's documented "unsafe.Pointer" (or other documented as unsafe operations).

We're talking about programming languages being memory safe (like fly.io does on it's security page [1]), not about other specific applications.

It may be helpful to think of this as talking about the security of the programming language implementation. We're talking about inputs to that implementation that are considered valid and not using "unsafe" marked bits (though I do note that the Go project itself isn't very clear on if they claim to be memory-safe). Then we want to evaluate whether the programming language implementation fulfills what people think it fulfills; ie: "being a memory safe programming language" by producing programs under some constraints (ie: no unsafe) that are themselves memory-safe.

The example we see in the OP is demonstrating a break in the expectations for the behavior of the programming language implementation if we expected the programming language implementation to produce programs that are memory safe (again under some conditions of not using "unsafe" bits).

[1]: https://fly.io/docs/security/security-at-fly-io/#application...

Re: There is no memory safety without thread safety

#252
post #199

Earlier quoted context omitted.

> People talk as if "memory safety" was a PLT axiom. It's not; it's a software security term of art. It's been in usage for PLT for at least twenty years[1]. You are at least two decades late to the party. Software is memory-safe if (a) it never references a memory location outside the address space allocated by or that entity, and (b) it never executes intstruction outside code area created by the compiler and linke…

...by that definition, can a C program be memory safe as long as it doesn't have any relevant bugs, despite the choice of language? (I realize that in practice, most people are not aware of every bug that exists in their program.)

Can a C program be memory safe as long as it doesn't have any relevant bugs? Yes, and you can even prove this about some C programs using tools like CBMC.

Re: There is no memory safety without thread safety

#253
post #250

This is, in my mind, the trickiest issue with Rust right now as a language project, to wit: - The above is true - If I'm writing something using a systems language, it's because I care about performance details that would include things like "I want to spawn and curate threads." - Relative to the borrow-checker, the Rust thread lifecycle static typing is much more complicated. I think it is because it's reflecting so…

I don't know what you're referring to. Rust's threads are OS threads. There's no magic runtime there. The same memory corruption gotchas caused by threads exist, regardless of whether there is a borrow checker or not. Rust makes it easier to work with non-trivial multi-threaded code thanks to giving robust guarantees at compile time, even across 3rd party dependencies, even if dynamic callbacks are used. Appeasing th…

It's not the runtime; it's how the borrow-checker interoperates with threads.

This is an aesthetics argument more than anything else, but I don't think the type theory around threads and memory safety in Rust is as "cooked" as single-thread borrow checking. The type assertions necessary around threads just get verbose and weird. I expect with more time (and maybe a new paradigm after we've all had more time to use Rust) this is a solvable problem, but I personally shy away from Rust for multi-threaded applications because I don't want to please the type-checker.

Re: There is no memory safety without thread safety

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

Zig's claims of memory safety are a bad joke. Sure, it's easier to avoid memory safety bugs in Zig than it is in C, but that's also true of C++ (which nobody claims is a memory safe language).

Re: There is no memory safety without thread safety

#255
post #249

Curiously, Go itself is unclear about its memory safety on go.dev. It has a few references to memory safety in the FAQ ( https://go.dev/doc/faq#Do_Go_programs_link_with_Cpp_programs , https://go.dev/doc/faq#unions ) implying that Go is memory safe, but never defines what those FAQ questions mean with their statements about "memory safety". There is a 2012 presentation by Rob Pike ( https://go.dev/talks/2012/splash.sl…

The definition kind of changed.

At the time Go was created, it met one common definition of "memory safety", which was essentially "have a garbage collector". And compared to c/c++, it is much safer.

Re: There is no memory safety without thread safety

#256
post #255
post #249

Curiously, Go itself is unclear about its memory safety on go.dev. It has a few references to memory safety in the FAQ ( https://go.dev/doc/faq#Do_Go_programs_link_with_Cpp_programs , https://go.dev/doc/faq#unions ) implying that Go is memory safe, but never defines what those FAQ questions mean with their statements about "memory safety". There is a 2012 presentation by Rob Pike ( https://go.dev/talks/2012/splash.sl…

The definition kind of changed. At the time Go was created, it met one common definition of "memory safety", which was essentially "have a garbage collector". And compared to c/c++, it is much safer.

That seems contrasted by Rob Pike's statement in 2012 in the linked presentation being one of the places where it's called "not purely memory safe". That would have been early, and Go is not called memory safe then. It seems like calling Go memory safe is a more recent thing rather than a historical thing.

Re: There is no memory safety without thread safety

#257

Every time this conversation comes up, I'm reminded of my team at Dropbox, where it was a rite of passage for new engineers to introduce a segfault in our Go server by not synchronizing writes to a data structure. Swift has (had?) the same issue and I had to write a program to illustrate that Swift is (was?) perfectly happy to segfault under shared access to data structures. Go has never been memory-safe (in the Rust…

Right, the issue here is that the "Rust and Java sense" of memory safety is not the actual meaning of the term. People talk as if "memory safety" was a PLT axiom. It's not; it's a software security term of art. This is just two groups of people talking past each other. It's not as if Go programmers are unaware of the distinction you're talking about. It's literally the premise of the language; it's the basis for "sha…

> But: everybody understands that.

Everybody does not understand that otherwise there would be zero of these issues in shipping code.

This is the problem with the C++ crowd hoping to save their language. Maybe they'll finally figure out some --disallow-all-ub-and-be-memory-safe-and-thread-safe flag but at the moment it's still insanely trivial to make a mistake and return a reference to some value on the stack or any number of other issues.

The answer can not be "just write flawless code and you'll never have these issues" but at the moment that's all C++, and Go, from this article has.

Re: There is no memory safety without thread safety

#258
post #91

Earlier quoted context omitted.

> And frankly, a lot of software I write is just boring, and Go does fine for a lot of that. I try Rust periodically for things, and romantically it feels like it's the closest language to "the future", but I think the future might still have a place for languages like Go. It's not so much about being "boring" or not; Rust does just fine at writing boring code once you get familiar with the boilerplate patterns (Real…

> (Real-world experience has shown that Rust is not really at a disadvantage wrt. productivity or iteration speed). I don't believe that for a second. Even just going from Python to Go drops my productivity by maybe about 50%. Rust? Forget it. Sure, if you have a project that demands correctness and high performance that requires tricky concurrency to achieve, something like Rust may make sense. Not for your run-of-t…

I believe your productivity drops as you say. I don't think it's inherent to the language though, at least not most of it. Rather it think it's a matter of familiarity and experience in each. When you're less practiced in a language, you're slower at it. I can write python fast, but im pretty slow at ruby. I've written a lot of python rust and go, and am about equally productive in them (although how that productivity is distributed through the dev cycle is different). It wasn't always this way, I was slow in each of them at first.

Re: There is no memory safety without thread safety

#259

Every time this conversation comes up, I'm reminded of my team at Dropbox, where it was a rite of passage for new engineers to introduce a segfault in our Go server by not synchronizing writes to a data structure. Swift has (had?) the same issue and I had to write a program to illustrate that Swift is (was?) perfectly happy to segfault under shared access to data structures. Go has never been memory-safe (in the Rust…

To put things in perspective, I posit to you, how many memory unsafe things can you do in Go that isn’t a variant of the same thing?

Or put another way what is the likelihood that a go program is memory unsafe?

Re: There is no memory safety without thread safety

#260
post #161

Earlier quoted context omitted.

"nice, correct numbers" end somewhere between 1/3 and sqrt(2) so in reality, it's just "pick your own poison" to various degrees...

The square root of two is still a computable Real. We choose not to cope with that, but it's not actually impossible it was merely inconvenient. I've mentioned elsewhere that my Rust care realistic is quite happy to work with these numbers e.g. take the square root of ten, and the square root of forty, multiply them together and get the quite ordinary integer twenty. The non computable reals are a huge problem becaus…

The problem with computables is that equivalence between them is only semi-decidable. (If the two numbers are different, it is decidable, but if they are not, it isn't. The problem is that you don't know if they are different a priori, so you might get lucky and find difference, but you might as well not.)

We know for sure that algebraic numbers behave nicely in terms of equivalence, and there are other, bigger number systems that are conjectured to behave nicely ( https://en.wikipedia.org/wiki/Period_(algebraic_geometry) ), but the problem with these and computers is that they are hard to represent.

Post reply on HN