The Office of the National Cyber Director (ONCD) Calls to Reduce Memory Safety Vulnerabilities

March 15, 2024

Using Formal Methods to Address the Challenges of Transitioning Codebases to Memory-Safe Languages

The office of the national cyber

Key Points:

  • Transitioning entire codebases to memory-safe programming languages presents several challenges. 
  • Memory-safe languages are not the sole solution for securing codebases, formal methods can help bridge the gap. 
  • Types of formal methods techniques that provide a rigorous framework for verifying the correctness of software systems where traditional testing methods fall short. 

This is the second installment of our three-part blog series, focusing on the critical aspect of memory safety within cybersecurity based on the report “Back to the Building Blocks: A Path Toward Secure and Measurable Software” published by the Office of the National Cyber Director (ONCD) that delves into industry changes needed to reduce memory safety vulnerabilities. Here, we will delve deeper into challenges related to moving entire codebases to memory-safe languages and how using formal methods can guarantee the correctness and security of code. 

Reread blog one here

Challenges of Transitioning Codebases to Memory-Safe Languages

Transitioning entire codebases to memory-safe programming languages presents several challenges. First, there’s the sheer scale of legacy systems written in languages like C or C++. These languages, while powerful, are prone to memory safety vulnerabilities due to their low-level nature. Transitioning such vast amounts of code to memory-safe languages like Rust or Go is a monumental task involving rewriting entire systems, which is time-consuming and costly. 

Moreover, there’s a significant skill gap to address. Developers proficient in C or C++ may not have experience with memory-safe languages, requiring extensive retraining. Additionally, there’s the potential for performance trade-offs. Memory-safe languages, while safer, can introduce performance overheads that are unacceptable in some high-performance computing environments. 

However, it’s not all doom and gloom. The transition to memory-safe languages, while challenging, represents a significant advancement in reducing memory-related vulnerabilities. Memory safety issues such as buffer overflows and use-after-free errors, which have been the root cause of numerous security breaches, can be significantly mitigated by employing memory-safe languages. 

Advantages of Formal Methods in Cybersecurity

While transitioning to memory-safe languages is beneficial, it’s not the sole solution for securing codebases. This is where formal methods come into play. Unlike traditional testing methods, formal methods offer mathematical guarantees on the correctness and security of code. This means they can systematically and exhaustively verify that software meets specified properties, significantly reducing the risk of undetected vulnerabilities, like the recent VMware sandbox escape

Formal methods, as detailed in the “Delivering Safety-Critical Software Faster and Cheaper with Exhaustive Static Analysis” white paper, have proven their worth in critical software industries. They increase operational efficiency in development and verification processes and can even ensure cybersecurity beyond memory safety. For example, the “most dangerous bugs” lists such as CWE Top 25 and CWE Top 10 of known exploited vulnerabilities are memory safety-related undefined behaviors.  

Different Types of Formal Methods: Enhancing the Developer Toolchain

In the realm of software development, ensuring code correctness and security is paramount. As systems grow increasingly complex, traditional testing methods often fall short. Formal methods provide a rigorous framework for verifying the correctness of software systems, directly integrating into the developer toolchain for automatic verification as software is built, tested, and deployed.  

  • Verifiable C: Verifiable C is specifically designed for the C programming language, providing a logical framework that ensures the correctness of C code against its operational semantics. Integrated with the CompCert verified optimizing C compiler, Verifiable C guarantees that the generated machine code adheres to the intended behavior defined at the source-code level.  
  • B Method: The B Method offers a comprehensive approach covering the entire software development life-cycle. It models software systems as abstract machines, which are then refined step by step to ensure correctness and security. By splitting the software into manageable components and validating each against mathematical models, the B Method can be directly incorporated into the development toolchain, facilitating early fault detection and reducing the overall testing effort. 
  • Z Notation: Z Notation provides an abstract, model-based specification language most suitable for object-oriented programming. While it excels at defining system requirements and design specifications, its real strength lies in integrating these specifications directly into the development process, enabling developers to verify design-level decisions automatically against formal models. 
  • Event-B: Building on the B Method, Event-B focuses on system state transitions, modeling them through events that alter system states under certain conditions. By directly incorporating Event-B models into the developer toolchain, software specifications can be automatically verified against these state models, ensuring that system behaviors align with the defined requirements. 

Advantages of Integrating Formal Methods into the Developer Toolchain:

  • Enhanced Reliability: By grounding software development in mathematical proofs, formal methods ensure that systems behave precisely as intended under all conditions, significantly reducing the risk of bugs or security vulnerabilities. Including but not limited to the memory safety vulnerabilities highlighted as being the most disruptive and critical in the report.
  • Early Fault Detection: Formal methods allow for the detection of faults at the earliest stages of development, minimizing the cost and effort associated with later-stage debugging and rework. 
  • Comprehensive Verification: Unlike traditional testing, which can only cover a subset of all possible scenarios, formal methods provide exhaustive verification, covering all conceivable states and interactions within a system. 

Disadvantages of Formal Methods:

  • Steep Learning Curve: Formal methods require a deep understanding of mathematical principles and logic, posing a significant learning curve for developers unaccustomed to such rigorous approaches. 
  • Increased Initial Effort: Setting up formal verification can be time-consuming and resource-intensive, particularly for large or complex systems. 
  • Toolchain Integration Challenges: Integrating formal methods into existing development environments and workflows can present technical and organizational challenges. 

Ensuring Software Quality, Robustness, Security, and Safety:

The incorporation of formal methods into the developer toolchain marks a significant evolution in software development practices. While challenges remain, the advantages—particularly in terms of reliability, security, and overall system quality—make them an invaluable asset for modern software engineering. By adopting these rigorous verification techniques, developers can ensure that their systems meet the highest standards of correctness and security, paving the way for a new era of trustworthy software. 

TrustInSoft Analyzer is not your average static analyzer, it epitomizes the power of formal methods. By providing exhaustive static analysis powered by mathematical precision of formal methods, TrustInSoft Analyzer allows developers to detect all undefined behaviors in C and C++ code, boosting test coverage up to 100% while reducing time and effort. It integrates seamlessly into both Agile and V-model workflows, empowering developers to secure their code with unparalleled accuracy and efficiency.  

Request a demo today and take a proactive step towards enhancing your software’s security.  

Note: This blog is part of a three-part series aimed at addressing the critical aspects of memory safety in software development. 

Newsletter