Remix.run Logo
Thaxll 5 days ago

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.

zozbot234 5 days ago | parent | next [-]

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

SkiFire13 5 days ago | parent | next [-]

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.

jlouis 5 days ago | parent | prev | next [-]

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

Segfaults has nothing to do with the properties. There's some languages or some contexts in which segfaults is part of the discussion, but in general, the theory doesn't care about segfaults.

sapiogram 5 days ago | parent | next [-]

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

I don't know what you're trying to say here. C would also be memory-safe if the program just simply stopped after violating memory safety, but it doesn't necessarily do that, so it's not memory safe. And neither is Go.

uecker 5 days ago | parent [-]

The point is that a segfault is not an indication for memory unsafety. It is the opposite: The OS stops some unsafe access. The problem with C implementations is that it often comes to late and the segfault does not stop a prior unsafe read or write. But this is also an implementation property, you can implement C in a memory safe way as many have shown. Rust has, unfortunately, changed the narrative so that people now believe memory safety is a property of the language, when it is one of the implementation. (there are, of course, language properties that make it harder to implement C in a memory safe way without sacrificing performance and/or breaking ABI).

ralfj 4 days ago | parent | next [-]

(EDIT: removed the first part since I realized you were replying to some comment further up, not my example.)

> Rust has, unfortunately, changed the narrative so that people now believe memory safety is a property of the language, when it is one of the implementation.

I am not sure I agree with that (the concept of memory-safe languages looong predates Rust), but you can just define a memory-safe language as one where all conforming implementations are memory-safe -- making it a feature of the language itself, not just a feature of a particular implementation.

uecker 4 days ago | parent [-]

I am not really saying the term is not useful, the idea that it is the only legitimate way of memory safety is what I am questioning.

SkiFire13 5 days ago | parent | prev [-]

The segfault seen here is not a property of the language implementation, it's just a consequence of the address chosen by the attacker: 42. If you replicated this code in C you would get the same result, and if you used an address pointing to mapped memory in Go then the program would continue executing like in similar exploits in C.

The only reason this isn't a more critical issue is because data races are hard to exploit and there aren't lot of concurrent Go programs/system libraries that accept lot of attacker controlled inputs.

uecker 4 days ago | parent [-]

Whether you can a segfault if you access an out-of-bounds address or not is part of the language implementation. An implementation that guarantees a segfault for out-of-bounds accesses is memory safe.

zozbot234 4 days ago | parent | next [-]

You can't really guarantee that all out-of-bounds accesses will segfault, because memory protection mechanisms are not that granular. (And actual memory segmentation, that did have the required granularity, has fallen out of use - though CHERI is an attempt to revive it.) That's why a segfault is treated as something to be avoided altogether, not as a reliable error mechanism.

What you can say though (and the point I made upthread) is that if a language manages to provably never segfault, then it must have some sort of true language-enforced safety because the difference between segfaulting or not is really just a matter of granularity.

uecker 4 days ago | parent [-]

How granular the memory protection mechanism is is part of the implementation.

zozbot234 4 days ago | parent [-]

It's part of the broader system, not the language implementation. And in practice, systems that achieve this are not in common use.

uecker 4 days ago | parent [-]

You are using a narrower definition than me. The language implementation builds on the functionality of the a larger system. An implementation can utilize the functionality of the overall system and close the loopholes. For example, using sanitizer you can turn out-of-bounds accesses to arrays into traps. This is not a segmentation fault but SIGILL, but it also builds on the trapping mechanism to achieve bounds safety (if you limit yourself to arrays).

2 days ago | parent | prev [-]
[deleted]
zozbot234 5 days ago | parent | prev [-]

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.

dylnuge 5 days ago | parent | prev | next [-]

I've never heard anyone define memory safety that way. You can segfault by overflowing stack space and hitting the guard page or dereferencing a null pointer. Those are possible in languages that don't even expose their underlying pointers like Java. You can make Python segfault if you set the recursion limit too high. Meanwhile a memory access bug or exploit that does not result in a segfault would still be a memory safety issue.

Memory safe languages make it harder to segfault but that's a consequence, not the primary goal. Segfaults are just another memory protection. If memory bugs only ever resulted in segfaults the instant constraints are violated, the hardware protections would be "good enough" and we wouldn't care the same way about language design.

Thaxll 5 days ago | parent | prev [-]

I don't know the NSA with their white house paper about memory safe language mentioned Go, maybe you should tell that there are wrong.

Sesse__ 5 days ago | parent [-]

https://en.wikipedia.org/wiki/Argument_from_authority

Thaxll 5 days ago | parent [-]

So NSA does not have the relevant authority to qualify a language as memory safe, is it what you're saying?

The document is backed by foreign government as well.

https://media.defense.gov/2023/Dec/06/2003352724/-1/-1/0/THE...

SkiFire13 5 days ago | parent [-]

> NSA does not have the relevant authority

You did not even read the link the parent comment provided and are continuing with the same flawed argument.

Yoric 5 days ago | parent | prev [-]

Segfaults are just the simplest way of exposing a memory issue. It's quite easy to use a race condition to reproduce a state that isn't supposed to be reachable, and that's much worse than a segfault, because it means memory corruption.

Now the big question, as you mention, is "can it be exploited?" My assumption is that it can, but that there are much lower-hanging fruits. But it's just an assumption, and I don't even know how to check it.