Skip to content

Applying the Rust Programming Language in ICS

Adam Crane

Security researchers examine technical aspects of Applying the Rust Programming Language in ICS.

Summary

Overview Adam Crane argues that Rust represents a critical modernization path for industrial control systems programming. Rather than blaming developers, he attributes persistent security bugs to using tools fundamentally ill-suited to contemporary requirements—specifically, C, which has remained essentially unchanged since 1972. Crane positions Rust adoption as inevitable, driven primarily by the massive productivity benefits developers gain when using a language designed for both safety and systems programming.

Key Topics Rust sits alongside C, C++, and Go as a compiled-to-machine-code language but uniquely offers both memory and thread safety without performance overhead. Crane catalogs five categories of C vulnerabilities—dangling references, use-after-free, null pointer dereferences, buffer overflows, and data races—and explains how Rust's compiler catches most of these at compile time through the borrow checker and ownership model, or enforces them at runtime via type constraints. The Rust ecosystem provides Cargo (integrated package management and build system), comprehensive documentation, and LLVM backend support for embedded architectures including ARM, MIPS, and PowerPC. Concretely, Crane presents Rod Bus, a Modbus client library released alongside the talk and available via crates.io, which includes a zero-cost C API shim enabling seamless integration with existing C/C++ codebases.

Technical Details Rod Bus achieves 200,000 Modbus requests per second while consuming less than 1 megabyte of RAM. Rust's ownership model prevents dangling references and use-after-free at compile time through the borrow checker; the compiler uses lifetimes (denoted with apostrophes, e.g., 'a) to statically verify that references cannot outlive their referents. For multi-threaded safety, Rust employs Arc (atomic reference counting) for thread-safe shared ownership and Mutex for coordinated access, preventing data races through type system constraints rather than runtime checks. Code examples demonstrate the compiler rejecting unsafe patterns; for instance, after moving a variable's ownership, attempting to reference it triggers a detailed error message explaining the violation. Performance comparisons show Rustls, a Rust implementation of TLS, using less than half the memory of OpenSSL in most scenarios.

Practical Deployment in ICS Rust is most suitable for new greenfield systems with real-time and low-memory constraints. More pragmatically for existing vendors, Rust's C ABI compatibility enables gradual replacement of legacy components—an approach exemplified by Suricata IDS incrementally replacing protocol parsers with Rust and Mozilla replacing high-risk Firefox components. Crane plans to enhance Rod Bus by integrating Rustls and implementing X.509 certificate-based access control for secure Modbus, allowing vendors to enforce role-based permissions through certificate validation.

When Rust Does Not Fit Adoption is impractical for vendors with large Windows-based deployments of Java, C#, or Go applications, or where critical library dependencies lack Rust implementations. The learning curve, while gentler than C++, exceeds that of Go or Java, presenting onboarding challenges for teams unfamiliar with ownership and borrowing concepts.

Takeaways Rust stabilized in 2018 with a commitment to backward compatibility going forward. Adoption is accelerating in major technology projects (Microsoft, Firefox, Suricata) though ICS-specific deployments remain nascent. University computer science curricula increasingly include Rust. Rather than replacing all C codebases overnight, Rust enables pragmatic incremental hardening of legacy systems and rapid secure development of new critical components, all enabled by C interoperability and measurably improved developer confidence in correctness.

Related talks