When Memory-Safe Languages Become Unsafe

Fatal bugs introduced by non-memory-safe languages (C/C++/etc.) are one of the
oldest yet persistent problems in computer security. To alleviate this issue,
there has been an emerging trend to re-implement programs using memory-safe
languages (Rust/Go/Swift/etc.). By using such languages, developers usually
have an illusion that they have obtained 100% guarantees of type soundness,
memory-safety, and thread safety.

However, through our assessment of a wide range of open-source projects, we
found that this assumption is not correct and sometimes can lead to dangerous
consequences. We collected and analyzed more than 10,000 Rust programs. All of
these programs rely on libc, and at least 25% depend on extra unsafe C/C++
libraries. These libraries break Rust's memory-safety promise and also expose
users to great threats. Unfortunately, the inclusion of C/C++ libraries are
agnostic to developers, leaving the issue unnoticed. What's more, some of the
C/C++ libraries are statically linked. This leads to fragmentation and makes it
challenging to carry out a scalable patching.

Even if a program is fully developed using memory-safe languages, memory
security issues can still occur. Rust allows developers to write unsafe code
using "unsafe" keyword, but some libraries wrap unsafe code and re-export as
"safe" functions. If developers use these "safe" functions, they are not aware
of the unsafety introduced by these libraries. Moreover, we will show that some
of the memory-safe languages fail to zero-out memory regions on object
destruction, which can lead to secret memory leakages.

To illustrate the real-world threats, we will provide a few detailed case
studies and live demos where programs developed by memory-safe languages can
still be exploited via memory bugs. Finally, we will offer suggestions and
provide tools for developers/users to achieve a sustainable ecosystem.