Peningkatan Analisis Statis di GCC 14
(developers.redhat.com)-fanalyzerdi GCC 14 mengikuti berbagai jalur eksekusi kode C dengan eksekusi simbolik, dan berfokus menemukan cacat yang sulit ditangkap sebelum runtime pada waktu kompilasi- Peningkatan kali ini terbagi menjadi deteksi loop tak berhingga, visualisasi buffer overflow, pelacakan string C, dan pengaktifan default analisis taint, dengan fokus membuat hasil diagnostik lebih mudah dipahami
-Wanalyzer-out-of-boundsmelampaui peringatan sederhana dengan menampilkan hubungan antara buffer dan posisi penulisan melalui diagram teks, serta menunjukkan di bagian tengah karakter mana overflow terjadi pada string UTF-8- Atribut baru
null_terminated_string_arg(PARAM_IDX)memberi tahu analyzer dan pembaca kode tentang syarat API yang mengharapkan string berterminasi null, sehingga jalur yang meneruskan buffer yang tidak berterminasi null lebih mudah terlihat - Analisis taint kini aktif secara default saat
-fanalyzerdipilih, sehingga alur ketika nilai yang dikendalikan penyerang digunakan sebagai ukuran, indeks, offset, dan lainnya tanpa pemeriksaan batas atas dapat lebih mudah diperiksa
Cakupan masalah yang ditangani -fanalyzer
-fanalyzeradalah pass analisis statis GCC yang mencoba menemukan cacat pada waktu kompilasi dengan mengeksekusi secara simbolik berbagai jalur eksekusi dalam kode sumber C- Peningkatan GCC 14 dirangkum menjelang rilis resmi pada April 2024, dan pada saat artikel ditulis, rilis GCC 14.1 diperkirakan hadir pada April 2024
- Prarilis GCC 14.0 sudah digunakan di Fedora 40 Beta
- Contoh-contohnya dapat dicoba di Compiler Explorer dengan opsi compiler baru
Deteksi loop tak berhingga sederhana
- GCC 14 menambahkan peringatan baru
-Wanalyzer-infinite-loop - Kode contoh berbentuk
forbersarang, dengan kondisi loop keduaj < ntetapi ekspresi increment masihi++- Ini merupakan kesalahan setelah menyalin pernyataan
forpertama lalu lupa menggantiipada ekspresi increment menjadij - Analyzer mengikuti cabang true dari
j < nterus-menerus pada jalur ini dan memperingatkan pengulangan loop
- Ini merupakan kesalahan setelah menyalin pernyataan
- Output diagnostik saat ini lebih mudah dipahami jika dibaca berurutan dari nomor peristiwa
(1)hingga(5) - Di GCC 15, upaya meningkatkan keterbacaan dengan cara seperti seni ASCII yang menyorot jalur aliran kontrol masih menjadi harapan
- Kode tersebut dapat dijalankan di contoh Compiler Explorer
Memvisualisasikan buffer overflow dengan teks
- Di GCC 13, analyzer mulai mendukung pemeriksaan batas melalui
-Wanalyzer-out-of-bounds - Di GCC 14, hubungan spasial dari buffer overflow yang diprediksi dapat ditampilkan sebagai diagram berbasis teks
- Pada contoh yang menjalankan
strcpy(buf, "hello")padachar buf[10], lalu memanggilstrcat(buf, " world!"), terdeteksi stack-based buffer overflow- Pesan sebelumnya menunjukkan kapasitas
bufadalah 10 byte dan terjadi penulisan di luar batas dari byte 10 hingga byte 12 - Diagram GCC 14 menampilkan buffer tujuan yang diisi oleh
strcpybersama byte terminatorNULyang sudah ada dan menjadi titik awalstrcat
- Pesan sebelumnya menunjukkan kapasitas
- Pada contoh string non-ASCII, analyzer juga mengikuti representasi UTF-8 dan menunjukkan posisi overflow
- Kode yang menyalin
"サツキ"kechar buf[11]lalu menambahkan"メイ"digunakan sebagai contoh - Diagram menunjukkan overflow terjadi di tengah karakter
メ, yaitu U+30E1
- Kode yang menyalin
- Kode terkait dapat dilihat di contoh string ASCII dan contoh string non-ASCII
Penguatan pelacakan operasi string C
- Analyzer GCC 14 meningkatkan pelacakan operasi string C dengan menyimulasikan API yang memindai buffer untuk mencari byte terminator null
- Jika pointer menunjuk ke buffer yang tidak berterminasi null dan ada jalur yang meneruskannya ke API tersebut, analyzer akan memperingatkannya
- Atribut fungsi baru
null_terminated_string_arg(PARAM_IDX)memberi tahu analyzer dan pembaca kode bahwa parameter tertentu harus berupa string berterminasi null - Dalam contoh,
example_fn(const char *p)diberi atributnull_terminated_string_arg(1)dannonnullchar str[3] = "abc";tidak memiliki ruang untuk byte terminator null- Saat memanggil
example_fn(str), analyzer memperingatkan stack-based buffer over-read yang membaca 1 byte setelah akhirstr - Diagnostik juga menampilkan note bahwa argumen pertama
example_fnharus berupa pointer ke string berterminasi null
- Contoh ini dapat dijalankan di Compiler Explorer
Analisis taint aktif secara default
- Analisis taint pada analyzer melacak input yang dikendalikan penyerang, titik sanitasi, dan titik penggunaan tanpa sanitasi
- Pada rilis GCC sebelumnya, fitur ini tidak diaktifkan secara default karena bug dan banyak false positive, dan disembunyikan di balik argumen command-line terpisah
- Di GCC 14, setelah berbagai perbaikan bug, analisis taint aktif secara default ketika
-fanalyzerdipilih - Perubahan ini juga mengaktifkan enam peringatan berbasis taint berikut
Kasus analisis kernel melalui CVE-2011-2210
- Cuplikan contoh dari CVE-2011-2210 di kernel Linux digunakan sebagai kasus analisis taint
- Dengan menambahkan
__attribute__((tainted_args))ke makro__SYSCALL_DEFINEx, analyzer diberi tahu bahwa argumenosf_getsysinfoadalah nilai yang berasal dari luar batas kepercayaan dan harus diperlakukan sebagai nilai ter-taint - Analyzer GCC 14 memperingatkan bahwa di
copy_to_user(buffer, hwrpb, nbytes), nilainbytesyang dikendalikan penyerang digunakan sebagai ukuran tanpa pemeriksaan batas atas- Diagnostik menunjukkan bahwa
nbyteshanya menjalani pemeriksaan batas bawah diif (nbytes < sizeof(*hwrpb)) - Parameter ketiga
copy_to_userditandai sebagai parameter ukuran melalui atributaccess(write_only, 1, 3)
- Diagnostik menunjukkan bahwa
- Masalahnya adalah kondisi sanitasi ditulis sebagai
if (nbytes < sizeof(*hwrpb))- Kondisi yang dimaksud adalah bentuk
if (nbytes > sizeof(*hwrpb)) - Pada versi yang kondisinya diperbaiki, analyzer tidak mengeluarkan peringatan
- Kondisi yang dimaksud adalah bentuk
- Pekerjaan menjalankan analyzer pada kernel untuk menemukan kerentanan dan memperbaiki false positive analyzer masih terus berlangsung
1 komentar
Komentar Hacker News
Bagi saya, fanalyzer adalah salah satu fitur pembeda utama GCC dibanding Clang. Karena ia menjelaskan error, pemrograman C jadi jauh lebih mudah, dan pesan error-nya mulai terasa mirip Rust dalam hal ramah terhadap pengembang
Salah satu alasan terbesar orang berhenti mempelajari teknologi adalah error yang menjengkelkan atau tidak jelas. Agak keluar topik, tapi maksud saya: saya suka C, dan saya akan lebih menyukainya lagi kalau punya pesan error setingkat Rust
error: missing semicolon, sering kali yang keluar adalah lebih dari 1000 baris pesan error tentang instansiasi templateSaya sudah beberapa kali mencoba analyzer GCC, tetapi belum menemukan frontend yang bagus untuk membuat output-nya nyaman dibaca. Clang punya beberapa opsi seperti output HTML yang lumayan bagus, CodeChecker, integrasi Xcode, dan lain-lain; jadi saya penasaran orang membaca output GCC dengan cara apa. Selain itu, saya merasa GCC menghasilkan jauh lebih banyak false positive daripada Clang
Ada 36 komentar lagi di thread lain: https://news.ycombinator.com/item?id=39918278
“GCC 14 Boasts Nice ASCII Art for Visualizing Buffer Overflows (phoronix.com)”, diposting 2 jam lalu
Beberapa bulan lalu saya membuat utilitas Linux kecil. Itu adalah shim drop-in untuk menggantikan executable apa pun; saat dipanggil, ia berpura-pura menjadi program asli, lalu melakukan fork terhadap aslinya dan terhubung ke stdout/stderr
Output error dikirim ke asisten GPT kustom yang memahami konteks program tersebut, lalu asisten itu mengubah error asli menjadi bentuk yang lebih mudah dibaca manusia dan mengeluarkannya ke stderr milik shim. Saya memakainya karena lelah melihat dump compiler GCC/Clang yang bertumpuk untuk concept/template, tetapi sebenarnya bisa dipakai untuk program apa pun kalau diinginkan. Itu bekerja dengan baik, tetapi saya jatuh sakit parah dan tidak bisa melanjutkannya; rasanya ini bisa jadi proyek yang bagus kalau ada yang mau membuat ulang dengan benar dan menggeneralisasikannya
Akan bagus kalau hasil analisis punya format output yang lebih baik. Bentuk sekarang adalah neraka bagi screen reader
Contoh output bisa dilihat di sini: https://godbolt.org/z/aan6Kfxds
Itu adalah contoh pertama dari artikel dengan opsi command line
-fdiagnostics-format=sarif-stderrditambahkan. Saya juga bereksperimen dengan menghasilkan diagram sebagai SVG, tetapi belum cukup dipoles untuk dimasukkan ke GCC 14Kode aslinya berbentuk mengembalikan
-1jikanbytes < sizeof(*hwrpb), dan mengembalikan-2jikacopy_to_user(buffer, hwrpb, nbytes)gagal. Perbaikan yang diterapkan adalah pemeriksaannbytes > sizeof(*hwrpb), tetapi menurut saya perbaikan yang benar adalahcopy_to_user(buffer, hwrpb, sizeof(*hwrpb))Menyalin keluar ukuran dari pointer
hwrpbselainsizeof(*hwrpb)tidak masuk akalnbytes = 4dansizeof(hwrpb)adalah 16 byte, maka kita akan menyalin berlebihan 12 byte dari buffer pemanggil dan bisa membaca memori yang bukan miliknya. Menurut saya itu harus dihindariSolusi yang lebih baik adalah menyalin hanya jumlah byte minimum yang didukung oleh pemanggil dan yang dipanggil. Misalnya,
nbytes = MIN(nbytes, sizeof(hwrpb));. Dengan asumsi informasi versi dihwrpb->sizeditaati, ini bisa menjamin kompatibilitas mundur/maju meskipun sebagian struct belum diinisialisasinbytesSangat hebat. Jumlah kerja yang masuk terlihat luar biasa. Tingkat kesulitannya tampak sebanding dengan menambahkan fat pointer/array view ke pustaka standar dan standar C
-Wstringop-overflowpunya terlalu banyak false positive sehingga itu adalah warning pertama yang saya nonaktifkan. Saya ragu variannya di analyzer akan lebih baikKeren sekali. Saya tidak terlalu banyak menulis C akhir-akhir ini, jadi saya penasaran seberapa sering
strcpydanstrcatmasih dipakai. Terakhir kali saya cek, keduanya hampir termasuk hal-hal yang ditabukan sepertigotoTentu saya tahu bahwa dalam pengembangan kernel,
gotojustru sering dipilih. Saya penasaran seberapa membantu sebenarnya analisis string C inigotojelas merupakan pilihan yang benar dan elegan. Jika dihindari secara mutlak, hasilnya bisa menjadi kode yang jelek, berbelit, dan sulit dirawat. Memang tidak sering, tetapi ada penggunaan yang validFungsi seperti
strcpymemang kurang disarankan, tetapi ada juga situasi di mana penggunaannya dijamin benar selama invarian yang lebih kuat—misalnya invarian di tingkat bahasa—tidak dilanggar. Jika kasus seperti itu rusak, berarti sudah ada masalah yang jauh lebih besar. Jarang terjadi, tetapi bisa saja diperdebatkan bahwa alternatif yang secara nominal lebih aman sedikit kurang efisien tanpa memberi manfaatgotomasih idiomatis di C. Tetap harus hati-hati, tetapi ya, ini CNamun saya sama sekali tidak suka
longjmpgotoyang sederhana. Sebaliknya, keluarga strxcpy benar-benar berantakan dan tidak boleh dipakai dengan alasan apa pun. Fakta bahwa itu dipakai di kernel itu mengerikanFungsi-fungsi itu dan semua upaya gagal untuk “memperbaikinya” seharusnya dibuang ke luar orbit
gototidak masalah jika dipakai dengan hati-hati.strcpydanstrcatjuga “tidak masalah” dalam arti Anda tahu kodenya benar dan kalau salah, akibatnya akan besar. Sayangnya, deskripsi itu berlaku untuk sebagian besar Cgotosetabustrcatdanstrcpy.gotoitu oke, sedangkanstrcatdanstrcpyyang dipakai tanpamallocberukuran tepat dalam scope yang sama lebih mendekati bau kodeSangat bagus. Senang melihat semua laporan terperinci yang menjelaskan apa yang salah disertakan