flawopen.com/보안 사고/Rust unsafe & smallvec

Rust가 메모리 안전하지 않을 때: unsafe 블록과 smallvec 힙 오버플로우의 진실

Critical — CVSS 9.8 CWE-787: Out-of-bounds Write RUSTSEC-2021-0003 · CVE-2021-25900
쉬운 설명 (ELI5)

로봇이 모든 선반의 무게를 철저히 검사해 절대 사고가 안 나는 물류창고가 있습니다. 특수 작업을 위해 로봇을 끄고 직원이 맨손으로 일합니다. 직원이 트럭 기사에게 '대충 몇 상자쯤 되나요?'라고 묻고 대충 선반을 만들어 쌓기 시작했습니다. 기사의 대답은 어림짐작이었고, 상자가 넘쳐 선반이 무너져 내렸습니다.

Illustrative reconstruction of the pattern, not the crate's literal source. The upstream fix reserved additional space per inserted item and simplified the implementation specifically so its correctness would be easier to verify.

What this says about Rust's guarantee

Rust's memory-safety guarantee is real but conditional, and the condition is usually stated imprecisely. The accurate formulation is: safe Rust cannot cause undefined behaviour, provided every unsafe block it depends on is sound.

That shifts where the risk lives rather than eliminating it. In C, memory-safety bugs can appear anywhere in millions of lines. In Rust, they can only originate inside unsafe blocks — typically a very small fraction of a codebase. This is an enormous practical improvement: it makes the auditable surface small enough to actually audit. But "small" is not "zero", and a soundness bug inside that surface is exploitable exactly like its C equivalent, as the CVSS 9.8 here reflects.

There is a second, subtler point. unsafe is not locally contained. An unsound unsafe block poisons every safe API built on top of it — which is why this bug affected callers who never wrote the keyword.

The rules for writing unsafe correctly

FAQ

Does this mean Rust's safety claims are overstated?

No — it means they are conditional in a way worth understanding precisely. Rust confines memory-safety defects to a small, explicitly marked, auditable portion of a codebase, which is a substantial structural improvement over a language where any line can contain one. The claim that survives scrutiny is "dramatically smaller attack surface", not "no attack surface".

Is there a way to make a trait trustworthy for unsafe code?

Yes — that is what unsafe trait is for. Implementing one is an explicit promise that carries safety obligations, which lets unsafe code rely on it. The standard library's TrustedLen exists for exactly this iterator-length problem, though it remains unstable.

How do I find unsafe code in my dependencies?

cargo geiger reports unsafe usage across a dependency tree, and cargo audit flags known advisories. Neither proves soundness, but together they show you where the risk is concentrated.

Related reading

출처 및 공식 보안 권고