[TOSEM'21] Hui Xu*, Zhuangbin Chen+, Mingshen Sun-, Yangfan Zhou*, Michael R. Lyu+
*Fudan, +CHUHK, -Baidu Security
Rust, memory safety
To understand real-world Rust memory safety bugs.
- All memory-safety bugs except compiler bugs involve unsafe Rust code.
- All CVEs are library bugs. Notably,
... an important phenomenon of these bugs is that many of them do not contain errors inside but merely introduce unsoundness that violates the memory-safety design of Rust.
- The trend of new unsoundness issues seems stable.
(Section 5.1)
- Bad Drop at Normal Execution Block:
- If a raw pointer in an unsafe block is used to construct something from an existing object and that object is dropped later, and if the pointer is converted to a reference which may survive the object and be used later. UAF or double free may happen because the compiler does not consider raw pointers when doing lifetime and ownership inferences (e.g., Code 1 in the paper).
- If a raw pointer of a
struct
is turned into a reference, thestruct
may drop memory that it does not own. - Freeing uninitialized memory (invalid free).
- Bad Drop at Cleanup Block. When a program panics and stack unwinding is happening, the cleanup routine may drop dangling or invalid pointers.
(Section 5.2)
- Bad Function Signatures.
- Falsely declaring an unsafe function as safe
- Interior mutability (e.g., by FFI)
- Lack of or incorrect lifetime bound
- Unsoundness of FFI. There may be undefined behaviors in a called foreign
function. There are also memory alignment and data layout issues, e.g., unsafe
Rust code assuming a certain data layout of a
struct
in a lib which might be changed without the awareness of the Rust developers.
(Section 5.3)
- Insufficient Bound of Generic. Most are due to lack of
Send/Sync
bound. - Unsound Trait. Derived or reimplemented safe trait may be incorrect. For
example: incorrectly reimplemented
Error::type_id
.
Our analysis reveals that a major difference between Rust and other programming languages lies in the soundness promise of APIs.
- Summarizing several best practices to assist developers to avoid the pitfalls.
- Extending the current static analysis of the compiler to detect more bugs.
One important suggestion made by this paper:
Note that although general pointer analysis is hard, this problem can be simplified in two ways. Firstly, considering only the pointers related to unsafe constructors can simplify the analysis problem and should still be effective for most bugs in our dataset.
In particular, auto memory reclaim uncovers the side effect of Rust OBRM, unsound function unveils the essential challenge of Rust development for avoiding unsoundness, and unsound generic or trait reveals the advanced challenge for developers to ensure soundness when using polymorphism and inheritance.
- Analysis on real-world Rust memory safety bugs.
- Many helpful examples to illustrate the problems.
- Mainly focusing on automatic memory management bugs and ignoring buffer overflows.
- Some explanations are not as clear as possible.
- Deep analysis of real-world Rust memory safety bugs.
The three 2020 unsafe Rust survey paper (OOPSLA, PLDI, ICSE).
- Unsoundness of API is a serious issue of Rust.
- Correctly understanding and using Rust's lifetime rules is challenge for programmers.
There are several typos and minor writing issues.