flawopen.com/Incidents/rust-unsafe-smallvec-overflow-january-2021
CVE-2021-25900: heap overflow pada smallvec Rust
SmallVec::insert_many memercayai batas bawah size_hint; jika iterator menghasilkan lebih, buffer heap terlampaui. Diperbaiki di 0.6.14 dan 1.6.1.
Sebuah gudang terkenal aman karena robot memeriksa setiap rak sebelum barang ditaruh. Untuk beberapa tugas, robot dimatikan dan seorang pekerja bekerja manual sambil berjanji berhati-hati. Salah satunya bertanya kepada sopir, "Kira-kira berapa kardus yang dibawa?", membuat rak seukuran itu, lalu mulai menumpuk. Perkiraan itu hanya tebakan, bukan jaminan, dan ketika datang lebih banyak kardus dari yang dijanjikan, tumpukannya melewati ujung rak.
Konsep Kunci & Istilah
SmallVec- Koleksi Rust yang menyimpan sedikit elemen secara inline dan pindah ke buffer heap saat membesar. Kecepatannya berasal dari kode unsafe yang mengelola buffer itu secara manual.
size_hint- Metode Iterator yang melaporkan perkiraan batas bawah dan atas jumlah item yang tersisa. Ini hanya petunjuk: kode safe boleh mengembalikan nilai apa pun, termasuk yang salah.
Rust unsafe- Kode di dalam blok unsafe boleh melakukan hal yang tidak bisa diperiksa kompiler, seperti menulis lewat pointer mentah; penulisnya wajib menjaga keamanan memori untuk setiap pemanggil safe yang mungkin.
Soundness- API safe disebut sound jika tidak ada kode safe, seaneh apa pun, yang dapat memicu perilaku tak terdefinisi melaluinya. insert_many tidak sound, karena size_hint yang sah bisa merusak memori.
Pemetaan kerangka kerja
Kronologi Insiden
Yechan Bae dan kelompok Rust di SSLab Georgia Tech melaporkan bug ini; RustSec menerbitkan RUSTSEC-2021-0003 dan smallvec 0.6.14 serta 1.6.1 membawa perbaikannya.
CVE-2021-25900 ditetapkan; cargo audit mulai menandai versi terdampak di pohon dependensi.
Alur Serangan Langkah demi Langkah
Iterator melaporkan panjang yang terlalu kecil
insert_many dipanggil dengan iterator yang batas bawah size_hint-nya lebih kecil dari jumlah item yang benar-benar dihasilkan. Kode safe diizinkan berbuat begitu.
Ruang disediakan menurut petunjuk
insert_many hanya menyediakan ruang untuk batas bawah dan menggeser elemen yang ada sebanyak itu.
Semua item tetap ditulis
Di dalam blok unsafe, perulangan menulis setiap item lewat pointer mentah, sehingga item berlebih jatuh melewati akhir alokasi.
Heap rusak
Overflow menimpa memori heap di sebelahnya. Program yang meneruskan ke insert_many iterator yang dipengaruhi masukan tak tepercaya menjadi rentan.
Kode Sumber: Rentan vs Aman
// Alokasikan berdasarkan sebuah *petunjuk*...
let (lower, _) = iter.size_hint();
self.reserve(lower);
unsafe {
let ptr = self.as_mut_ptr().add(index);
for (i, item) in iter.enumerate() {
// ...tetapi tulis sebanyak
// item yang benar-benar diterima.
ptr::write(ptr.add(i), item);
}
}// Periksa ulang kapasitas untuk setiap item.
// Jangan biarkan nilai dari kode aman
// menentukan batas yang digunakan oleh kode unsafe.
for (i, item) in iter.enumerate() {
self.reserve(1);
unsafe {
let ptr = self.as_mut_ptr()
.add(index + i);
ptr::write(ptr, item);
}
}
// Perbaikan sebenarnya juga memangkas
// cakupan unsafe secara signifikan.Daftar Periksa Penguatan Sistem Rekayasa
- ✓Jangan pernah menentukan ukuran buffer yang dipakai kode unsafe dari metode trait safe seperti size_hint, len pada trait object, atau pembanding; periksa ulang kapasitas sebelum setiap penulisan.
- ✓Tulis komentar // SAFETY: untuk setiap blok unsafe yang menyebut invarian yang diandalkannya, dan tolak tinjauan jika invarian itu bergantung pada kode safe yang tak tepercaya.
- ✓Jalankan Miri di CI pada uji yang memakai implementasi yang bermusuhan, seperti iterator yang size_hint-nya berbohong, Drop yang panik, dan pembanding yang bukan urutan total.
- ✓Buat blok unsafe sekecil mungkin; perbaikan smallvec juga mengurangi kode unsafe di insert_many agar bisa diverifikasi.
- ✓Jalankan cargo audit (atau cargo deny) di CI agar dependensi dengan imbauan RustSec, seperti smallvec sebelum 0.6.14 atau 1.6.1, menggagalkan build.
Sumber
- RustSec — RUSTSEC-2021-0003: buffer overflow di SmallVec::insert_many
- servo/rust-smallvec — issue 252
- CVE-2021-25900 — catatan CVE
- MITRE CWE-787
- Heartbleed: satu pemeriksaan batas yang hilang, separuh internet
- Baron Samedit: sepuluh tahun root tersembunyi dalam garis miring terbalik
- Citrix Bleed: bagaimana salah membaca satu nilai kembalian melumpuhkan MFA