Hacker News new | ask | show | jobs
by moefh 324 days ago
I agree that there are two groups here talking past each other. I think it would help a lot to clarify this:

> the issue here is that the "Rust and Java sense" of memory safety is not the actual meaning of the term

So what is the actual meaning? Is it simply "there are no cases of actual exploited bugs in the wild"?

Because in another comment you wrote:

> a term of art was created to describe something complicated; in this case, "memory safety", to describe the property of programming languages that don't admit to memory corruption vulnerabilities, such as stack and heap overflows, use-after-frees, and type confusions. Later, people uninvolved with the popularization of the term took the term and tried to define it from first principles, arriving at a place different than the term of art.

But type confusion is exactly what has been demonstrated in the post's example. So what kind of memory safety does Go actually provide, in the term of art sense?

1 comments

It's a contrived type confusion bug. It reads 42h because that address is hardcoded, and it does something that ordinary code doesn't do.

If you were engaged to do a software security assessment for an established firm that used Go (or Python, or any of the other mainstream languages that do shared-memory concurrency and don't have Rust's type system), and you said "this code is memory-unsafe", showing them this example, you would not be taken seriously.

If people want to make PLT arguments about Rust's correctness advantages, I will step out of the way and let them do that. But this article makes a security claim, and that claim is in the practical sense false.

> It reads 42h because that address is hardcoded,

It is trivial to change this example into an arbitrary int2ptr cast.

> Go (or Python, or any of the other mainstream languages that do shared-memory concurrency and don't have Rust's type system),

As the article discusses, only Go has this issue. Python and Java and JavaScript and so on are all memory-safe. Maybe you are mixing up "language has data races" and "data races can cause the language itself to be broken"?

> If people want to make PLT arguments about Rust's correctness advantages, I will step out of the way and let them do that. But this article makes a security claim, and that claim is in the practical sense false.

This article makes a claim about the term "memory safety". You are making the claim that that's a security term. I admit I am not familiar with the full history of the term "memory safety", but I do know that "type safety" has been used in PLT for many decades, so it's not like all "safety" terms are somehow in the security domain.

I am curious what your definition of "memory safety" is such that Go satisfies the definition. Wikipedia defines it as

> Memory safety is the state of being protected from various software bugs and security vulnerabilities when dealing with memory access, such as buffer overflows and dangling pointers.

My example shows that Go does not enforce memory safety according to that definition -- and not through some sort of oversight or accident, but by design. Out-of-bounds reads and writes are possible in Go. The example might be contrived, but the entire point of memory safety guarantees is that it doesn't matter how contrived the code is.

I'm completely fine with Go making that choice, but I am not fine with Go then claiming to be memory safe in the same sense that Java or Rust are, when it is demonstrably not the case.

The problem isn't that you couldn't hardcode a scarier value; it's that you have to demonstrate a plausible scenario in realistic code where an attacker controls both the value and the address it's written to.

While you're wondering why I keep claiming Go is a memory-safe language, you can also go ask the ISRG, which says the same thing I am at (checks notes) https://www.memorysafety.org/.

> While you're wondering why I keep claiming Go is a memory-safe language, you can also go ask the ISRG, which says the same thing I am at

And yet Go violates the definition they give -- it doesn't prevent out-of-bounds accesses. (And just to be sure we're talking about the same thing, I'm specifically talking about Go here. All the other languages on their list are actually memory safe, as far as I know.)

> you have to demonstrate a plausible scenario in realistic code where an attacker controls both the value and the address it's written to.

So your definition of memory safety includes some notion of "plausible" and "realistic"? Neither https://www.memorysafety.org/docs/memory-safety/ nor Wikipedia have such a qualification in their definition. It would help if you could just spell out your definition in full, rather than having us guess.

> So your definition of memory safety includes some notion of "plausible" and "realistic"? Neither https://www.memorysafety.org/docs/memory-safety/ nor Wikipedia have such a qualification in their definition. It would help if you could just spell out your definition in full, rather than having us guess.

This is a strawman argument, you're arguing semantics here. You're a smart person, so you know exactly what he means. The perception created by your article is that people shouldn't use Go because it's not memory-safe. But the average developer hearing "not memory-safe" thinks of C/C++ level issues, with RCEs everywhere.

Unless you can show a realistic way this could be exploited for RCE in actual programs, you're just making noise. Further down the thread, you admit yourself that you're in a PLT research bubble and it shows.

You definitely shouldn’t use Go, but it’s not because of the discussion in TFA. I jest, rhetorically.

Seriously, why are we bashing a researcher for being academic? This makes no fucking sense. Nobody claimed anywhere that people should stop using Go.

Did you not notice how this started over someone saying "That's not the definition of memory safety" and then prevaricating about the bush when asked to provide their definition? Your theory that this is an argument over semantics is correct, but not fully understood.
> The perception created by your article is that people shouldn't use Go because it's not memory-safe.

Uh, where exactly am I saying or implying that? I am, in fact, saying that Go is much closer to memory-safe languages than to C, safety-wise.

But I am arguing that the term "memory safe" should only be used for languages that actually went through the effort of thinking this problem through to the end and plugging all the holes through which memory safety violates can sneak in. Go is 99% there, but it's falling slightly short of the goal. I think that's a useful distinction, and I am disappointed that it is regularly swept under the rug, which is why I wrote this blog post. You are free to disagree, I never expected to convince everyone. But I think I gave some people some new food for thought, and that's all I can hope for.

> you're arguing semantics here

Yes, semantics — what do things mean, exactly? — is the subject of the discussion here and is actually quite important in general.

You're just wrong about this. The ability to write contrived code that does an out-of-bounds write, or to induce crashes, doesn't violate the notion of "memory safety" as an ordinary term of art.
Yeah I understand that that's how you like to use the term, you've been very clear about that. What I am curious about is whether that's just you. Because the source you gave last time, https://www.memorysafety.org/docs/memory-safety/, doesn't agree with what you are saying, and neither does Wikipedia.

I am honestly curious here. I am a PLT researcher so I am in a bubble where people use the term consistently with how I use it. You are the first person I meet (for some notion of "meet" ;) that uses the term differently. But without external sources it's hard to judge how wide-spread your definition (that you still haven't spelled out...) is.

Did you consider that the organization can be wrong?

> Memory safety is a property of some programming languages that prevents programmers from introducing certain types of bugs related to how memory is used. Since memory safety bugs are often security issues, memory safe languages are more secure than languages that are not memory safe.

That is the definition they give. Since Go does not "prevent programmers from introducing certain types of bugs related to how memory is used." it does not fall under this definition. They can list go as memory safe, but then either they disagree with their own definition or made the mistake of adding Go to that list. Memory safety is not a spectrum. You are either memory safe or unsafe. The spectrum is in the unsafety. Go is obviously less unsafe than C for example.

Then the "security" definition is totally useless, because even C can be memory safe. What about pointers, malloc(), free(), unchecked enums etc. etc.? Oh, those are just "contrived" language features you're not really supposed to use. You can write FORTRAN in any language!
You are however replying to thread where a Dropbox engineer calls it "a right of passage" to introduce such bugs to their codebase. Which suggests that it is by no means unheard of for these problems to crop up in real-world code.
Again: introducing surprising correctness bugs? Crashing programs? Absolutely. I don't know how many different ways I can say that my concern here is the misuse of a security term of art. Dropbox engineers do not have as a rite of passage introducing or finding RCE vulnerabilities in Go code. Would that it were so! My job would be much more interesting.
> correctness bugs? Crashing programs? Absolutely.

Denial of service can absolutely be a security issue, as can any correctness bug if it leads to unintended behavior or corrupted data.

If that's where we're at, where unhandled exceptions are the security issues we're hanging on, I'll consider my argument won.
That might be a reasonable argument if you were guaranteed an unhandled exception in this instance. Unfortunately that's not the case.
Doesn't Dropbox write a lot of Python extensions in C for speedup?
Excuse me, but in this thread we are bashing go, not making logical arguments.
What is the argument?
That Dropbox is very happy with unsafe languages despite the top-level comment.
Many FAANG & co engineers are overrated. If every new hire is introducing concurrency bugs in a Golang codebase, refactor, do better review and maybe use concurrency questions instead of leetcode.

I’ll take tptacek’s word over most FAANG type on such topics if we’re doing appeals to authority. The guy is very practical, unlike the Rust community which is incredibly focused on theoretical correctness instead of real-world experiences.

I have recently come to the conclusion that everything I ever thought was "contrived" is currently standard practice in some large presently existing organization.
Take that to the Apple bounty program with your crasher bug and tell them they should pay out as if you'd confirmed RCE, see how it goes. This is an engineering question; it's not about vibes.

It's not even always the case that corrupted data structures (or even pointers) in C code are exploitable. You need attacker control of data and where it goes in memory. It's far less often the case in Python or Go --- in fact, it's basically never the case. As evidence for that claim: the zero memory corruption RCEs in all of shipping Go code, of which there is a lot.

Dunno about Apple, but goog sometimes pays out bugs that are "theoretical" in the way you describe. That is, you show that there's a bug somewhere, but you can't "reach" it from user data. They'll pay less than a PoC, obviously, but will pay. YMMV, etc.
My own takeaway after looking at corporate codebases for four decades is that the state of the art in software development at banks, governments, insurance companies, airlines, health care and so on is such that I long for the time before the internet.

Sure, those mainframes from the 80's weren't bullet proof either. But you first had to get to them. And even if the data traveled in plain text on leased lines (point-to-point but not actually point-to-point (that would require a lot of digging), no multiplexing) you had to physically move to the country where they were located to eavesdrop on them, and injecting data into the stream was a much harder problem.