top | item 33553668

NSA guidance on how to protect against software memory safety issues [pdf]

130 points| cpeterso | 3 years ago |media.defense.gov

103 comments

order
[+] scj|3 years ago|reply
The term "memory safe language" (also used in the "Securing Open Source Software Act") is a misnomer. The report kind of acknowledges this "Even with a memory safe language, memory management is not entirely memory safe" but then presses on with the term anyway.

I think they're trying to combine the concepts of languages that have GCs and prevent buffer overflows into a catch-all term, but "memory safe language" isn't a good choice. Non-programmers might take the term at face value.

It's kind of like using the term "safe flame thrower", except no one would be lulled into a false sense of security with that one.

Don't get me wrong, I'd rather use a "safer flame thrower" than a "flame thrower", but I also wouldn't trust anyone selling me a "safe flame thrower".

The above is my best Dijkstra impersonation.

[+] tialaramex|3 years ago|reply
The excuse that "safety" could mean a lot of things, and these languages don't solve all of those things, so therefore they shouldn't count and we should stop saying C and C++ are unsafe is really tired at this point.

The current set of papers for WG21 the "C++ Standards Committee" includes more than one taking this stance, but obviously the standout is P2687 from Bjarne Stroustrup and Gabriel Dos Reis. Bjarne and Gaby describe the situation (in which the US Federal Government has noticed that there's a problem) as an "Emergency"

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p26...

P2687R0 is an initial draft (even by R0 standards it looks very hastily thrown together) but it wrings its hands about the propensity of programmers to write bad code, and then it offers a list of eight kinds of (un)safety, including "delivering a result in 1.2ms to a device supposedly responding to an external event in 1ms". Alas, although C++ doesn't really help you with any of this list, other languages don't solve all of them and so why bother right?

It also takes pains to group together intractable problems (e.g. dynamic allocation but with assurance of no leaks) with solved problems (e.g. preventing use-after-free). The R0 draft doesn't really spend much time explaining how, if at all, they would solve the problem (beyond vaguely "static analysis" so it can't be critiqued on that basis.

I'm sure the committee (of which both Bjarne and Gaby are members) will look favourably on this sort of work, but nobody in government should take anything like this seriously until the actual problem gets solved, ie the programs stop being full of memory bugs.

[+] IshKebab|3 years ago|reply
What about safety net or safety belt or... a safe? None of those are infallible either.

"Memory safe language" is a perfectly good term for the moment since most languages fall square into "completely unsafe" or "completely safe with the ability to be unsafe in special circumstances".

I don't know of any that are "fairly safe". Maybe something like Carbon will be like that.

[+] rowanG077|3 years ago|reply
"safe" doesn't mean "cannot go wrong". See terms such as safety belt or safety shoes, no one expects those to be infallible. It's simply an extra layer of defense.
[+] zelon88|3 years ago|reply
Non programmers reading this will start throwing it around at meetings prompting some kind of explanation or response from more technical teams. This pressure on the technical teams will probably result in a net reduction of memory errors over time.
[+] mark_l_watson|3 years ago|reply
Quoting myself from a similar thread today:

Good advice. As a Lisp developer, I have used Swift and it seems like a nicely designed language, very good tooling on macOS/iPadOS and OK on Linux. Go, Rust, and others are also good.

Off topic, but I thought it sad how once 9/11 happened with the side-tracked war on terrorism, the NSA and FBI apparently (from my private citizen perspective) stopped doing much of the previous great work on public support for computer security, going after international computer crime cartels, etc. As a US taxpayer, I would like to see them prioritize that type of work.

[+] CTDOCodebases|3 years ago|reply
Maybe that was deliberate.

It doesn’t make sense to teach terrorists how to secure their systems if you need to exploit these systems to achieve your mission.

Now that Chinese, Russian and North Korean actors are putting in work and causing real economic damage in the west it looks like defence is starting to hold some value again.

[+] yazzku|3 years ago|reply
Underwhelming report. Boils down to "rewrite it in <memory safe language>; but be careful, even those allow unsafe regions". Also surprising: no mention of Ada/Spark, the language people use to guide rockets and pacemakers? Seems pretty damn safe to me, and it handles more than memory safety, such as integer arithmetic.
[+] halffaday|3 years ago|reply
To your point, you should probably not do anything the NSA tells you to do. A spy agency’s endorsement of Rust is not to its credit.
[+] bugfix-66|3 years ago|reply
TLDR: Transition from C to Go.

Go was designed by (among others) the father of Unix, Ken Thompson, with an understanding of the mistakes of C and C++. Despite getting hilariously little respect here on Hacker News, the language is (for many purposes) an excellent replacement for C.

(Yes, yes, I know you disagree. Tell me more about how C++ is necessary and all the time you spend fighting it is actually a huge win! Please tell me how slow garbage collection is, all evidence to the contrary!)

Go reads from, and writes to, variable-sized blocks of memory through (pointer, length, capacity) triples, known as "slices". A Go slice "[]int" is essentially a C struct like this, passed around in 3 registers:

  struct IntSlice {
      int* pointer;
      ssize_t length;
      ssize_t capacity;
  };
Bounds checking in Go is easily disabled (pass -B flag to the compiler) but almost nobody does so because the performance benefit is miniscule. With bounds checking and garbage collection, Go avoids almost all memory-related bugs.

You can understand Go as C redesigned for a world where parallel computing (e.g., dozens of CPU cores) is commonplace, and the benefits of safe code outweigh the tiny costs.

We're not using 80286 chips anymore. We can afford safety.

[+] pjmlp|3 years ago|reply
We could already afford safety coding for 80286 using Turbo Pascal, Turbo Basic, Quick Pascal, Quick Basic, Modula-2, Clipper.

Performance stuff was written with inline Assembly, or straight Assembly with nice macro assemblers (TASM, MASM), using C or C++ in detriment of the above selection only helped bringing UNIX stuff into MS-DOS.

EDIT: See books like "PC Intern: System Programming : The Encyclopedia of DOS Programming Know How".

EDIT2: It is available at archive.org, https://archive.org/details/pcinternsystempr0000tisc/mode/2u...

[+] kajaktum|3 years ago|reply
Oh yes, the language that STILL have null pointer dereference is a good replacement for C in this day and age. Please. Go feels like a person stuck in the 80s idea of a modern programming language. Oh and the idiom of the language is to treat zero of a value the same as nil. Brilliant, now I have a to litter a bunch of checks that time.Time{} is not a valid time because???
[+] yazzku|3 years ago|reply
> the language is (for many purposes) an excellent replacement for C.

No, it's not. The runtime wouldn't even fit on many platforms. GC pauses are similarly not acceptable on soft/real-time systems, etc.

Ada/Rust get closer to a replacement.

[+] tsujamin|3 years ago|reply
I've spent my last few weeks writing a platform in Go. Buffer management/strong typing is definitely an improvement on C. Shame about tall the null-pointer-exceptions though :')

In all seriousness though it does seem to mitigate a lot of exploitable memory corruption vulns, perhaps not memory-corruption-caused Denial-of-Service vulnerabilities as well as Rust et all maybe.

[+] djbusby|3 years ago|reply
Go gets little respect on HN? We're not reading the same threads.
[+] pclmulqdq|3 years ago|reply
I think go would have gotten a lot more love from C and C++ users if they weren't so resistant to having an optimizing compiler. I'm not referring to removing bounds checks - I'm referring to things like stack-passed function arguments and the normal optimization passes that you get from -O2 in gcc. Sometimes you want a slow compiler that does a lot of heavy lifting.

Now, Rust is the new hotness and it doesn't make a lot of sense to use other things if you care about both safety and speed.

[+] zozbot234|3 years ago|reply
Note that Go is not memory safe for concurrent programs. Memory safety is ensured for sequential code only.
[+] eternityforest|3 years ago|reply
I say we jump straight to Rust. Rust goes farther in terms of stopping bugs even beyond memory safety issues.
[+] rowanG077|3 years ago|reply
I think Ken Thompson gets little respect precisely because he designed Go. It's a large stain on his legacy that has single handedly set back the field of Software Development.

I think that if Go didn't exist he would be considered "one of the greats".

[+] deafpolygon|3 years ago|reply
This is the NSA here.

Chances are you probably don't want to use memory safe languages now.

[+] felipemesquita|3 years ago|reply
RubyTM is a registered trademark of O’Reilly Media Inc. in the United States and/or other countries
[+] DSingularity|3 years ago|reply
Amazing how little things have changed. Till today, ASLR and some basic CFI is all we have?
[+] rodgerd|3 years ago|reply
To steal a comment by Matthew Garret, "No way to prevent this, says users of only programming language where this happens regularly".
[+] helloooooooo|3 years ago|reply
Stack cookies, CET(shadow stack) on Windows, XFG in some cases, non-deterministic heaps etc…
[+] pornel|3 years ago|reply

[deleted]

[+] tsujamin|3 years ago|reply
Don't let the [victim memory-spaces] win!
[+] midislack|3 years ago|reply

[deleted]

[+] nix23|3 years ago|reply
Also linux and ghidra... have fun with your windows-stack.