NSA recommends secure memory management

This article is part of TechXchange: Rusty Programming

What you will learn

  • What is Memory Safety?
  • Why is this important?
  • What does the NSA recommend?

Poor memory management practices are the root of more than 70% of vulnerabilities found in software today. This can lead to a host of problems from programs that fail or degrade to provide attackers a hook into systems.

“Memory management issues have been exploited for decades and are still all too common today,” said Neal Ziring, CTO of cybersecurity. “We must consistently use memory-safe languages ​​and other protections when developing software to eliminate these weaknesses of malicious cyber actors.”

The challenge with embedded programs these days is that a large majority are written in C and C++. C++ can more easily mitigate some memory management issues, but not all. C, on the other hand, depends on the watchful eye of the programmer to prevent these kinds of problems. Unfortunately, it’s too easy to include bugs in an application and difficult to identify them, especially when looking at someone else’s code.

NSA Software Memory Security Fact Sheet

To address these issues, the US National Security Agency (NSA) has just released the “Software Memory Safety” Cybersecurity Fact Sheet, which you can download. The NSA recommends using compiler options that would harden the code, but the challenge is knowing what can be done with a particular compiler. This is normally based on the programming language.

C compilers can check for things like uninitialized variables. However, it takes a language like Rust or Ada to provide more robust checks. It’s better for the compiler to do the checking, because it’s more consistent, won’t forget something that’s programmed to check, and it can force programmers to specify what requirements they have that should be applied regardless the app.

According to the NSA, “Examples of memory-safe languages ​​include C#, Go, Java, Ruby, Rust, and Swift.” I find it interesting that Ada and SPARK, a provable version of Ada, weren’t included in the list, especially given Ada’s government heritage.

What about Ada and Rust?

There are many myths about Ada, but it remains a production language although less popular than most other languages. It is also used in new applications like NVIDIA’s security processor. A more detailed AdaCore case study is available for download.

The reason SPARK was used for this application was that the code could be proven to work as specified through contracts included in the application code. SPARK’s verification helps eliminate many runtime checks since things are checked at compile time.

From an embedded perspective, C++, Rust, and Ada tend to be languages ​​that can meet the needs of embedded applications because they don’t use garbage collection. Garbage collection can solve a number of memory safety issues. This is why languages ​​like Java and Ruby are often mentioned as improvements over C due to their support for garbage collection, which prevents dangling pointers.

The paper notes that “memory security can be costly in terms of performance and flexibility. Most memory-safe languages ​​require some sort of garbage collection to reclaim memory that has been allocated but is no longer needed by the program. There is also a considerable performance overhead associated with checking the boundaries of every access to the array that could potentially be outside of the array.

This is an interesting statement and applies to languages ​​like Java which require garbage collection. It’s also not true that memory-safe languages ​​require garbage collection, since Rust and Ada/SPARK don’t have this “feature”.

Static and Dynamic

The document also states that “several mechanisms can be used to harden non-memory-safe languages ​​to make them more memory-safe. Software analysis using static and dynamic application security testing (SAST and DAST) can identify memory usage issues in software.

What’s fascinating is that they talk about security, because security and safety are two different yet related programming topics. Static and dynamic analysis tools are also useful for secure memory usage. They have been the backbone of supporting most security-related standards like ISO 26262, where companies need to “prove” application security and trustworthiness.

These applications have usually been written in C and C++, but they also require significant verification by humans, which is not as reliable as software when it performs many of these verifications repeatedly. Of course, we tend to be better at finding more complex logical errors compared to the simpler memory manipulation problems handled by languages ​​like Rust and Ada/SPARK.

I also looked at some Slashdot comments on the NSA document. I was surprised by the amount of discussion about Rust and Ada/SPARK. And I noticed a lot of misinformation and misunderstandings in many answers. Likewise, the perspective of non-embedded programmers was also interesting, but that tends to be typical on sites where readers with varying degrees of expertise add to the discussion.

Paving the way to high-quality software

We have been covering high quality software development for quite some time as well as Ada/SPARK and Rust.

Part of the challenge of any solution involving more than one programming language is interfacing, as well as finding or developing skilled programmers. Interfacing is the more difficult of the two – the differences are forced by the languages ​​themselves, which change slowly and see interfacing between systems as a side issue.

Differences in language support can also be significant. For example, Rust uses strokes to provide object-oriented styling support. Using C++ objects directly with Rust can be a challenge for this reason. Even mixing C++ and Ada can be a challenge in this area due to differences in their similar but not identical class/object hierarchy.

Adding additional compilers and tools as well as training programmers in a new language will incur additional costs; however, you have to look at the cost as well as the return on investment. Remember that the very reason for discussing memory-safe languages ​​is to reduce errors, prevent error-based attacks, and provide software.

An interesting aspect is that software can often be delivered faster because fewer errors are found in the code. This is because the language and compilers prevent programmers from ignoring these issues.

If you haven’t considered any of the safer programming alternatives but want to check them out, I have two recommendations online. One is the Rust Playground. This provides a web-based development system for trying out simple Rust apps.

The other is learn.adacore.com, which is a tutorial-based introduction to Ada and SPARK. It includes a similar web interface for testing Ada/SPARK code, but it is a simpler interface designed to run sample code that is provided but can be modified. Content can also be downloaded as a PDF or EPUB e-book, and there are sections specifically for C, MISRA C, C++, and Java developers. Open source tools for both languages ​​are available.

Read more articles in TechXchange: Rusty Programming

About Thomas Brown

Check Also

CHRONICLE: Four stories I’m following this Lady Raiders basketball season

History links MURFRESBORO, Tenn. — After two exhibition wins, the Lady Raiders …