Comment by tptacek

Comment by tptacek 10 days ago

21 replies

Right, it's a cool trick. It's just not material to real threat models, which is what people imply when they say "Go isn't memory safe".

tialaramex 10 days ago

The fact Go has UB under data races has practical implications for sufficiently complex concurrent software. If you can induce a race on a non-trivial object, that's UB instantly - you can probably blow up the Go runtime and all bets are off.

I would not characterise this fact, which is a design choice in Go, as similar to say a Rust soundness bug, which will sooner or later just get fixed. They aren't going to somehow magically fix this problem in Go, it's part of the design.

  • adonovan 10 days ago

    > They aren't going to somehow magically fix this problem in Go, it's part of the design.

    I wouldn't be entirely pessimistic.

    Russ's post https://research.swtch.com/gorace mentions a conservative representation for Go's data structures (essentially: more indirection) that would make it possible to implement them in a way that was robust to races, at an obvious large performance cost.

    More recently others have been investigating the possibility of using 128-bit atomic writes (on ARM and x86) to reduce the cost. Go's strings and interfaces are both 2-word structures. Slices are three words but by changing the field order atomicity can be achieved with 2-word writes. Of course it would break a lot of code that assumes the representation or the ABI.

    • wbl 10 days ago

      That code is usually internal.

    • kaba0 9 days ago

      I mean, C is also memory safe when run within valgrind.. at an obvious large performance cost.

      • tialaramex 9 days ago

        To make this work you need to re-define "memory safety" to the point where it loses any value in a discussion about programming

        Valgrind has no way to detect trivial global or local array bounds misses so long as they don't stray out of the defined memory. It can't spot this because the resulting executable (the only thing Valgrind sees) is not doing anything that's prohibited - it's nonsense because you used a non-MSL, but the actual executable has some defined behaviour.

  • tptacek 10 days ago

    My point has nothing to do with whether the language will achieve "soundness". It's that this is behavior that has not over the last 15 years produced exploitable vulnerabilities, despite extremely high incentives for those vulnerabilities to be unearthed.

    • pkolaczk 10 days ago

      You don’t need to blow up the runtime to cause a vulnerability due to a data race in Go:

      https://security.snyk.io/vuln/SNYK-DEBIAN13-GOLANGGITHUBGORE...

      • arp242 10 days ago

        That's a completely different type of vulnerability than the UB that's being talked about.

        > The call to sync.Pool.Get will then return a bytes.Buffer that hasn't had bytes.Buffer.Reset called on it. This dirty buffer will contain the HTTP request body from an unrelated request.

        This is just a good ol' logic error, that just so happens to also be a race.

  • arp242 10 days ago

    I think these are "if a tree falls in a forest and no one is around to hear it, does it make a sound?"-type musings.

    Whatever the case, it doesn't really affect anyone and it doesn't really matter.

    • pkolaczk 10 days ago

      It’s a matter of time. Spectre / meltdown were also considered extremely hard to use in practice. Yet they are considered vulnerabilities.

      In Golang case the data race window to corrupt memory is extremely narrow, so it makes it very hard to trigger it. That together with Go being still quite a niche language results in the fact we see no exploits… yet.

      • vacuity 10 days ago

        I note that of the Spectre/Meltdown and similar hardware vulns, even the hard-to-swallow kinds of mitigations for Spectre primarily prevent user-to-kernel hijacking only, which is the most important single property but doesn't cover inter-process hijacking. We can more or less patch these vulns completely, but there is a (huge) performance penalty to be weighed as a drawback. I do not know enough to say whether the Go data race bugs are an acceptable risk. Although, not everyone may accept it, namely if it strikes them just once.

      • arp242 10 days ago

        Even if some sort of security bug is discovered tomorrow, then we're talking about one issue every 15 years or so. Whoop die doo. That barely even registers in the noise.

        That it "may" lead to a problem and that it's not "sound" is basically just meaningless.

        • pkolaczk 9 days ago

          How many spectre / meltdown related vulnerabilities were detected between 1990 and 2010? Zero. So those chip vendors must be paranoid they patch them - were talking about one issue per 20 years xD Similarly how many hashmap collision attacks existed prior to 2010? Zero, but once people learned they are not just a theoretical problem, suddenly plenty of vulnerabilities were found.

          Seriously, it doesn’t work like that. It’s not linear. During the first half of those 15 years almost no one heard about Go, and forget about using it in critical systems where vulnerabilities would matter. Even at Google it was (still is?) very niche compared to Java, Python and C++ and is used mostly for userspace clis and orchestration, not the core stuff. There is simply very little incentive to attack systems written Go, when there exist 100x more less secure networked systems written in C or C++.

          Considering this memory unsafety thing in Go is fortunately very hard to exploit, there is no doubt why attackers don’t target this weakness and it has been so far only a technical curiosity. Also data races in Go are easy to make and can lead to vulnerabilities in a much more direct way, without corrupting the heap. I bet those are exploited first (and there exist CVEs caused by races in Go).

Yoric 10 days ago

Well, time will tell. As Go usage increases, it becomes a more tempting target, which means that more malicious third-parties will start poring over the code of the std library and the frameworks looking exactly for this kind of vulnerability.

The same goes for Rust, Swift or Zig, of course.

kaba0 10 days ago

How is it not material? You only need to accidentally write and read a map at the same time in language that is supposedly for concurrency (which is why not the same as parallelism, in its case it does largely correlate).

This is a ridiculous design issue with big ramifications.