157787561 © Wutthichai Luemuang | Dreamstime.com
Programmer Dreamstime 157787561

NSA Recommends Safe Memory Management

Nov. 14, 2022
The U.S. National Security Agency recently published the “Software Memory Safety” Cybersecurity Information Sheet.

This article is part of TechXchange: Rusty Programming

What you’ll learn

  • What is memory safety?
  • Why is it important?
  • What does the NSA recommend?

Poor memory-management practices have been the cause of over 70% of the vulnerabilities found in today’s software. This can lead to a host of problems from programs that fail or degrade to providing attackers with a hook into the systems.

“Memory-management issues have been exploited for decades and are still entirely too common today,” said Neal Ziring, Cybersecurity Technical Director. “We have to consistently use memory safe languages and other protections when developing software to eliminate these weaknesses from malicious cyber actors.”

The challenge with embedded programs these days is a vast majority are written in C and C++. C++ can more easily mitigate some memory-management problems 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’s Software Memory Safety Info Sheet

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

C compilers can check a few things like uninitialized variables. However, it takes a language like Rust or Ada to provide more robust checks. It’s preferable to have the compiler do the checking, since it’s more consistent, will not overlook something that’s programmed to check, and it can force programmers to specify what requirements they have that should be applied regardless of the application.

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

What About Ada and Rust?

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

The reason SPARK was used for this application was that the code could be proven to work as specified through contracts included as part of the application code. SPARK’s checking enables many runtime checks to be eliminated since things are checked at compile time.

From an embedded perspective, C++, Rust, and Ada tend to be languages that can address embedded application needs because they don’t use garbage collection. Garbage collection can address a number of memory safety issues. That’s why languages like Java and Ruby are often mentioned as improvements over C because of their garbage-collection support, which prevents dangling pointers.

The paper notes that “Memory safety can be costly in 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 considerable performance overhead associated with checking the bounds on every array access that could potentially be outside of the array.”

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

Static and Dynamic

The paper also says that “Several mechanisms can be used to harden non-memory-safe languages to make them more memory safe. Analyzing the software using static and dynamic application security testing (SAST and DAST) can identify memory use issues in software.”

What’s intriguing is that they’re talking about security, because security and safety are two different although related programming topics. Static- and dynamic-analysis tools are useful in address safe memory use, too. They’ve been the backbone for supporting much of the safety-related standards like ISO 26262, where companies need to “prove” the safety and reliability of the application.

Such applications have typically been written in C and C++, but they also require significant checking by humans, which isn’t as reliable as software when repeatedly doing many of these checks. Of course, we tend to be better at finding more complex logic errors versus the more straightforward memory manipulation problems being addressed by languages like Rust and Ada/SPARK.

I also checked out some Slashdot feedback on the NSA paper. I was surprised by the amount of discussion of Rust and Ada/SPARK. And I noticed a large amount of misinformation and misunderstandings in many of the responses. Likewise, the point of view from non-embedded programmers was interesting as well, but this tends to be typical on sites where readers with varying degrees of expertise add to the discussion.

Carving a Path to High-Quality Software

We’ve been covering development of high-quality software for some time as well as Ada/SPARK and Rust.

Part of the challenge with any solution involving more than one programming language is interfacing, as well as finding or developing qualified programmers. Interfacing is the more challenging of the two—the differences are forced by the languages themselves, which change slowly and look at interfacing between systems as a secondary issue.

The differences in language support also can be significant. For example, Rust uses traits to provide object-oriented-style support. Direct use of C++ objects with Rust can be a challenge for this reason. Even mixing C++ and Ada may be a challenge in this area because of differences in their similar but not identical class/object hierarchy.

Adding more compilers and tools as well as training programmers in a new language will incur further costs; however, one must look at the cost as well as the payback. Remember, the reason for even discussing memory-safe languages is to reduce errors, prevent attacks due to errors, and deliver software.

One interesting aspect is that software often can be delivered faster because fewer errors are in the code. That’s because the language and compilers prevent programmers from overlooking these problems.

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

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

Read more articles in TechXchange: Rusty Programming

Sponsored Recommendations


To join the conversation, and become an exclusive member of Electronic Design, create an account today!