3 poin oleh GN⁺ 2024-07-31 | 1 komentar | Bagikan ke WhatsApp
  • TRACTOR dari DARPA adalah program riset yang bertujuan mengonversi otomatis kode C lama ke Rust untuk menghilangkan kategori kerentanan keamanan memori pada program C
  • Masalah keamanan memori pada C dan C++ telah dibahas selama lebih dari 20 tahun, tetapi muncul kesadaran bahwa alat pendeteksi bug saja tidak cukup
  • Alternatifnya adalah memindahkan kode yang ada ke bahasa pemrograman aman yang menolak program tidak aman pada waktu kompilasi
  • Hasil konversi menargetkan kualitas dan gaya yang setara dengan kode yang ditulis pengembang Rust berpengalaman, dengan menggabungkan analisis statis, analisis dinamis, dan pembelajaran mesin berbasis model bahasa besar
  • MIT Lincoln Laboratory bertanggung jawab atas pengujian dan evaluasi, dan benchmark, proyek milestone, serta alat dipublikasikan di halaman terbuka

Tujuan TRACTOR

  • TRACTOR adalah program “Translating All C to Rust” yang bertujuan mengonversi otomatis kode C lama ke Rust
  • Dari sisi keamanan, program ini berupaya menghapus seluruh kategori kerentanan keamanan keamanan memori yang ada pada program C
  • Kode hasil konversi tidak hanya ditujukan agar sekadar berjalan, tetapi juga mengarah pada kualitas dan gaya yang sama dengan kode buatan pengembang Rust berpengalaman

Mengapa konversi ke Rust diperlukan

  • Masalah keamanan memori pada C dan C++ adalah tantangan yang telah ditangani komunitas rekayasa perangkat lunak selama lebih dari 20 tahun
  • Telah terbentuk kesepakatan bahwa mengandalkan alat pendeteksi bug saja sulit menyelesaikan masalah ini secara memadai
  • Pendekatan yang lebih disukai adalah menggunakan bahasa pemrograman aman yang dapat menolak program tidak aman pada waktu kompilasi
  • TRACTOR menggunakan Rust sebagai bahasa targetnya

Teknologi yang digunakan untuk konversi otomatis

  • TRACTOR menggabungkan berbagai teknik analisis perangkat lunak dan pembelajaran mesin untuk memindahkan kode C lama ke Rust
  • Teknik analisis

    • Menggunakan analisis statis dan analisis dinamis secara bersamaan
    • Teknik pembelajaran mesin, termasuk model bahasa besar, juga menjadi bagian dari kombinasi ini
    • Kombinasi ini merupakan poros teknologi inti yang diperlukan untuk memahami struktur dan perilaku kode C, lalu mengonversinya otomatis menjadi kode Rust

Pengujian, evaluasi, dan materi publik

1 komentar

 
GN⁺ 2024-07-31
Komentar Hacker News
  • Sebagai referensi, https://sam.gov/opp/1e45d648886b4e9ca91890285af77eb7/view juga layak dilihat

    • Tautan langsung ke PDF informasi sesi penjelasan untuk pengusul: https://sam.gov/api/prod/opps/v3/opportunities/resources/fil...
      Disebutkan bahwa tujuan acara ini adalah menjelaskan tujuan dan tantangan teknis TRACTOR, menjawab pertanyaan dari calon pengusul, serta memberi kesempatan untuk meninjau bagaimana riset masing-masing dapat selaras dengan tujuan program TRACTOR
  • Ini terlihat sangat sulit. Terutama karena Rust idiomatis yang ditulis oleh orang berpengalaman sama sekali tidak mirip dengan C, dan sebagian besar kode yang menarik ditulis dalam C++
    Pada akhirnya, sepertinya ini sama saja dengan menentukan secara statis seluruh masa hidup alokasi dalam program C. Termasuk alokasi yang diteruskan ke allocator buatan pengguna atau library proprietari. Riset di bidang seperti ini sudah lama ada, tetapi belum banyak yang sangat berhasil, dan program C/C++ dapat mengaitkan masa hidup alokasi dengan tombol apa yang ditekan pengguna tanpa pengaman seperti reference counting. Itu bukan ide yang bagus, tetapi bisa dilakukan
    Masalah jelas lainnya adalah bahwa program yang dianalisis, menurut definisinya, adalah kode yang memiliki bug. Jika masa hidupnya masuk akal, tidak akan ada kerentanan memory safety dan tidak perlu diganti. Riset yang secara statis mendeteksi “bagaimana seharusnya masa hidupnya” biasanya berasumsi bahwa kode yang dianalisis pada awalnya sudah benar. Mungkin bisa menargetkan program yang menemukan titik-titik ketika masa hidup tidak dapat ditentukan lalu meminta bantuan developer

    • Ini pekerjaan yang sangat sulit, dan DARPA suka mendanai hal-hal sulit[1]
      Namun ini bukan pertama kalinya DARPA mencoba penerjemahan program otomatis atau penerjemahan otomatis ke Rust[2]
      [1]: https://www.urbandictionary.com/define.php?term=DARPA%20hard
      [2]: https://c2rust.com/
    • Karena membahas hal sulit, DOE juga mendanai proyek bernama ROSE yang sudah berjalan lebih dari 20 tahun. Proyek ini mencakup analisis statis dan penerjemahan otomatis antara C/C++/Cuda, serta bahasa tingkat tinggi seperti Python dan varian C/C++ untuk HPC
      Proyek ini cukup keren karena memiliki abstract syntax tree terpadu yang mendukung bahasa-bahasa tersebut pada dasarnya dengan kumpulan tipe node yang sama. Saat magang di Livermore pada musim panas 2014, saya sempat berkesempatan mengerjakannya
      Ini juga open source: http://rosecompiler.org/ROSE_HTML_Reference/index.html
    • Dalam kasus umum, sepertinya hasilnya akan diterjemahkan menjadi unsafe Rust, dan sesekali hanya node daun yang terisolasi diterjemahkan menjadi Rust yang aman
      Jika bergulat dengan borrow checker saja sudah terasa sulit, menerjemahkan otomatis seluruh ruang program C yang mungkin, beserta undefined behavior-nya yang terkenal, menjadi kode yang disetujui borrow checker jauh lebih sulit. Salah satu masalah klasik dalam penulisan compiler adalah bahwa ruang program yang valid jauh lebih besar daripada ruang program yang dapat dikompilasi
      Dengan pencarian singkat, ada juga upaya seperti c2rust[1]. Saya penasaran apa perbedaan TRACTOR
      [1] https://github.com/immunant/c2rust
    • Ada alasan mengapa tantangan DARPA disebut DARPA-hard
    • Pendekatannya mungkin kira-kira seperti “AI merangkum fungsi program dalam suatu bahasa deskriptif, lalu mensintesis kode Rust yang mencakup kumpulan fungsi yang sama”
      Akan lebih menarik jika caranya memasukkan manual program itu, alih-alih program aslinya. Namun manual jarang memuat semua perilaku halus sebuah program, jadi setidaknya untuk mendapatkan nilai acuan yang sebenarnya kemungkinan besar tetap perlu melihat source code
  • Inisiatif yang diusulkan ini sudah saya ketahui cukup lama, dan menarik melihatnya kini diumumkan ke publik. Ini proposal yang sangat ambisius, dan saya rasa tingkat ambisi seperti ini sesuai dengan misi DARPA, jadi saya berharap berhasil
    Sebagai pihak yang mendukung Rust di bidang ini, saya selama ini berusaha menurunkan ekspektasi orang-orang yang mendorong proposal ini terhadap kemungkinan penerjemahan otomatis dari C ke Rust. Hambatan mendasar yang saya lihat adalah bahwa kode sumber C memuat lebih sedikit informasi daripada kode sumber Rust. Untuk menerjemahkan kode C ke kode Rust, seseorang atau sesuatu harus menciptakan informasi yang hilang itu. Dengan alasan yang sama seperti memperbesar gambar tidak bisa menghasilkan bit informasi yang tidak tertangkap dalam gambar asli tanpa kesalahan, mudah dibuktikan bahwa mustahil menghasilkan informasi yang hilang ini secara sempurna. Pada akhirnya, informasi yang hilang dari kode sumber yang ada harus diekstrapolasi, atau dengan kata lain diciptakan. Mengekstrapolasi dengan benar membutuhkan penilaian, dan terutama ketika dilakukan dalam skala besar oleh model bahasa tanpa supervisi, proses itu pasti akan menghasilkan kesalahan. Saya pernah mengusulkan solusi yang menurut saya bisa meredakan masalah ini sampai batas tertentu, tetapi saya tidak akan membahas detailnya
    Pada akhirnya saya pikir proyek ini bisa meraih keberhasilan sampai tingkat tertentu, tetapi harus dijalankan dengan ekspektasi yang hati-hati dan terkendali. Pada saat yang sama, ada juga kemungkinan tidak ada hasil publik sama sekali, jadi saya ingin mengatakan agar jangan menafsirkannya berlebihan pada tahap ini. Secara khusus, pemerintah bukanlah satu entitas tunggal, jadi proyek ini tidak boleh ditafsirkan sebagai penolakan total terhadap C atau restu penuh bagi Rust. Tiap lembaga akan menentukan sendiri arah dan jadwal adopsi teknologi keamanan memori. Misalnya, NIST merekomendasikan bukan hanya Rust, tetapi juga Ada SPARK dan beberapa dialek C/C++ yang diperkuat

    • Apa hubungannya dengan upaya CRAM dari Grammatech?
      https://cpp-rust-assisted-migration.gitlab.io/blog/
    • Jika tidak berusaha mempertahankan makna formal kode C, dan menganggap cukup selama setelah diterjemahkan ia tetap lolos test suite, ruang gerak untuk penerjemahan menjadi jauh lebih besar
      Proyek Rust-ifikasi nyata sering berjalan seperti ini. Fuzzer juga bisa membantu membuat data uji tambahan untuk meningkatkan branch coverage
  • Secara pribadi saya tidak menyukai pola pikir “mari tulis ulang seluruh dunia dengan Rust”. Meski begitu, jika hendak mem-porting suatu proyek ke bahasa atau platform baru, penerjemahan mekanis adalah cara yang buruk
    Kita perlu meluangkan waktu untuk merencanakan arsitektur yang lebih baik dan merancang sistem perangkat lunak yang lebih baik, lalu mencari cara menggantinya bagian demi bagian. Kalau membangun istana di atas awan, ia tidak akan pernah menyentuh tanah. Jika memutuskan memakai Rust untuk sistem ini, itu tidak masalah, tetapi harus ditulis dengan gaya Rust. Jangan mencoba mem-backport C ke Rust
    Menurut saya proses yang jauh lebih baik dan matang adalah memperbarui C menjadi C modern, lalu memverifikasi keamanan memori, sumber daya, dan operasi integer dengan model checker seperti CBMC. Dengan begitu kita bisa memperoleh keamanan yang sama seperti penulisan ulang bertahap ke Rust, sambil tetap mempertahankan codebase, basis pengetahuan, dan para pengembang

    • Tidak mungkin. CBMC memang luar biasa, tetapi pernahkah Anda memverifikasi secara formal program “nyata”?
      Saya setuju bahwa menggantinya dengan versi Rust yang arsitekturnya dirancang manual jelas merupakan solusi yang lebih baik, tetapi biayanya juga lebih besar. Di sini tampaknya targetnya adalah produk ala RLBox yang “meningkatkan keamanan secara besar dengan hampir tanpa usaha”. Kalau ada sumber daya, bukan berarti jangan melakukan penulisan ulang manual sepenuhnya, tetapi maksudnya ini lebih baik daripada tidak melakukan apa-apa
    • C modern pun memiliki kerentanan keamanan yang sama pada array dan string seperti C klasik, dan tidak ada yang berubah selama 50 tahun
    • Ini jelas merupakan tantangan DARPA yang mengawang-awang yang mungkin menyenangkan untuk dimiliki saat keluar dari sistem legacy. Namun bahkan jika kita memasukkan fungsi atau metode dari satu bahasa ke ChatGPT dan memintanya menerjemahkan ke bahasa lain, hasilnya umumnya tidak bagus
      Jika menanyakan masalah awal yang ingin dipecahkan kepada ChatGPT, jawabannya memang lebih sering benar, tetapi tetap saja umumnya tidak bagus. Untuk membuat hal-hal dasar dari output-nya saja bisa berjalan, masih perlu banyak perbaikan dan pemikiran
    • Untuk kode dorman yang berjalan di mana-mana tetapi tidak disentuh siapa pun, pendekatan “terjemahkan dulu ke Rust yang jelek sebelum disentuh lagi” memang punya daya tarik tertentu
      Bukan daya tarik sebagai ide yang jelas bagus. “Rust jelek” hasil terjemahan kemungkinan jauh lebih buruk untuk dikerjakan daripada C dengan noise latar berupa bug. Berkat terjemahan yang setia, bug-bug itu juga akan tetap ada di “Rust jelek” tersebut. Di C, orang-orang setidaknya cukup tahu cara menangani masalahnya, tetapi “Rust jelek” benar-benar jelek karena orang Rust tidak terbiasa dengan hal semacam itu
      Meski begitu, peluang seseorang mengembangkan teknik untuk membersihkannya berulang kali hingga menjadi cukup bisa ditoleransi bukanlah nol. Selain itu, sebagai keluaran non-tujuan proyek, bisa saja muncul umpan balik linter seperti “tidak dapat diterjemahkan menjadi Rust yang bisa ditoleransi karena x, y, z”. Pengembang C dapat meninjaunya, dan jika kodenya sudah bisa diterjemahkan menjadi Rust yang baik, alasan untuk menerjemahkannya pun berkurang
      Jika hasil seperti ini muncul, bagi sebagian orang mungkin akan lebih mudah menjelaskan solusi dalam C yang dapat dijalankan dan membiarkan “translator/linter” mengarahkan mereka ke pendekatan yang tidak rusak. Saya menganggap hasil-hasil positif seperti ini kemungkinannya cukup rendah, tetapi sesekali memasang taruhan dark horse tampaknya memang mendekati deskripsi pekerjaan DARPA
    • Tidak ada pola pikir “mari tulis ulang seluruh dunia dengan Rust” di mana pun. Ada sangat banyak perangkat lunak yang jauh lebih baik dibiarkan dalam bahasa dinamis atau bahasa statically typed dengan garbage collection seperti Go. Insinyur yang baik memahami gagasan bahwa kita harus memakai alat yang sesuai untuk pekerjaan
      Intinya adalah mulai mengurangi CVE keamanan memori yang terbukti berkali-kali benar-benar menjadi masalah
      Saya setuju bahwa jika terjemahan otomatis dan andal dari C/C++ ke Rust memang bisa dilakukan, itu sudah akan terjadi. Namun di suatu titik dalam proses merencanakan arsitektur dan sistem yang lebih baik lalu menggantinya bagian demi bagian, orang bisa merasa percaya diri bahwa “sekarang kita sudah menulis C jauh lebih baik, jadi bukankah kita tidak akan membuat bug keamanan memori lagi, mungkin berhenti di sini saja?”, dan dalam praktiknya mereka memang akan begitu. Lalu 6 bulan kemudian muncul lagi CVE buffer overflow yang tragik sekaligus menggelikan
      Memperbarui C menjadi C modern dan memverifikasinya dengan CBMC juga merupakan investasi yang sangat besar. Kalau sudah sejauh itu, lebih baik sekalian pindah ke Rust. Klaim bahwa kita bisa memperoleh keamanan yang sama seperti penulisan ulang bertahap ke Rust mungkin saja benar, tetapi tampaknya cukup tidak pasti atau jauh dari kesimpulan yang jelas
  • Banyak orang membaca ini sebagai permintaan atau perintah untuk menerjemahkan semua kode C dan C++ ke Rust, tetapi terlepas dari nama proyeknya yang mencolok, abstraknya tidak terbaca seperti itu. Ada dua paragraf yang saling terkait tetapi berbeda
    Pertama, C dan C++ tidak cukup aman dalam skala besar. Meski kita memprogram dengan hati-hati dan memakai alat yang bagus, desain yang pada dasarnya tidak aman menimbulkan terlalu banyak kerentanan. Karena itu, sebanyak mungkin kode harus diterjemahkan atau ditulis ulang dalam bahasa yang “aman”, khususnya bahasa yang menjamin keamanan memori
    Kedua, mereka akan mendanai dan mengadakan kompetisi untuk software yang menerjemahkan kode C yang ada ke Rust
    Ini bukan konsensus untuk menulis ulang dunia dalam Rust. Ini adalah konsensus untuk bermigrasi ke bahasa yang aman, Rust adalah salah satu contohnya, dan ada program dalam migrasi ini yang menargetkan Rust

    • Jika bahasa-bahasa seperti itu memiliki konstruksi unsafe, bagaimana aturan untuk memakainya? Tanpa sekumpulan aturan yang terdefinisi untuk digunakan di sini, pada akhirnya kita hanya kembali ke titik awal
      Rust memiliki mode aman. Bukan berarti Rust adalah bahasa yang aman. Untuk melakukan hal-hal menarik, diperlukan blok unsafe. Dengan ini kita tidak mendapatkan banyak hal
      Di sisi lain, ada banyak bahasa dengan garbage collection yang bahkan tidak membiarkan programmer menyentuh pointer. Mengapa bahasa-bahasa itu tidak dipertimbangkan? Alasannya adalah performa. Karena para programmer Rust begitu “mementingkan” performa, bahasa itu tidak akan pernah bisa menyelesaikan masalah mendasarnya
      Mau performa, atau mau keamanan? Keduanya tidak bisa didapat sekaligus
  • Sungguh mengejutkan kalau ini bisa bekerja lewat bentuk otomasi apa pun. Program C biasa tidak bisa ditranskripsikan baris demi baris ke Rust
    Dalam program C, pointer dan aliasing ada di mana-mana, dan Rust secara eksplisit mencegah konsep seperti itu. Kecuali seluruhnya dibungkus dengan unsafe, menulis ulang program C ke Rust mengharuskan banyak struktur khas dipikirkan ulang pada level yang lebih tinggi

    • Terjemahan baris demi baris memang mustahil, jadi untuk melakukan penalaran semantik yang lebih besar harus memakai AI
      Tidak perlu menerjemahkan semuanya sekaligus juga. Salah satu nilai compiler Rust adalah ia memberi banyak informasi konkret yang bisa dimasukkan kembali ke LLM untuk iterasi
      Di startup saya, grit.io, kami sudah menangani masalah serupa, dan saya melihat C -> Rust akan cukup bisa ditangani dalam waktu dekat. Jelas tidak mudah, tetapi ini masalah yang dapat diselesaikan
    • Jika program multithread dikecualikan, apakah aliasing jangka panjang benar-benar ada di mana-mana dalam program C secara umum? Saya memperkirakan pada banyak program, sebagian besar terjadi di dalam cakupan satu fungsi, atau melintasi pemanggilan fungsi di dalamnya. Dalam kasus itu, bukankah bisa diselesaikan dengan borrowing?
      Jika demikian, itu bisa diperlakukan sebagai satu submasalah, dan mendeteksi bagaimana data dibagikan antar-thread bisa dijadikan masalah lain. Untuk kasus terakhir, banyak program mungkin memiliki aturan ownership implisit seperti “thread T1 memasukkan ke queue Q, lalu thread T2 mengambilnya”. Ini bisa diterjemahkan menjadi “saat dimasukkan ke queue, ownership berpindah”
      Mendeteksi aturan seperti ini tentu tidak mudah, tetapi juga tidak tampak sepenuhnya di luar jangkauan, dan sebagai proyek riset bisa cukup bermakna
    • Bertanya dari sudut pandang pemula yang naif: tidak bisakah kita berjalan baris demi baris, membungkus semuanya dengan unsafe, mengompilasinya menjadi binary yang sama, lalu pelan-pelan melepas unsafe sambil terus memverifikasi ekuivalensinya?
      Dengan begitu, setidaknya sebanyak mungkin bagian bisa dibawa ke Rust, dan hanya konsep yang perlu dipikirkan ulang oleh engineer yang ditangani terpisah
    • Terjemahan baris demi baris juga tidak membutuhkan banyak “AI”. Rasanya mungkin membuat terjemahan Rust yang kasar dan sebagian besar unsafe
      Saya berasumsi agar AI benar-benar menghasilkan program yang berguna dan valid, ia harus memahami lifetime dan sebagainya. Kalau benar-benar bisa begitu, itu akan mengesankan
    • Saya terutama penasaran bagaimana ini akan berjalan pada codebase yang banyak memakai macro
  • Jika mengikuti praktik coding yang sangat ketat dan mengintegrasikan alat verifikasi statis pihak ketiga yang mengharuskan banyak anotasi proprietari dalam kode, hasil serupa memang bisa didapat dengan C/C++
    Atau cukup pakai Rust

    • Cukup lucu melihat komunitas C/C++ menolak Rust. Puluhan tahun upaya dan pengalaman bersama bahasa-bahasa itu jelas telah menimpa rangkaian penalaran mereka
      Siapa yang waras akan membela bahasa dengan cacat desain sebesar dan sejelas itu ketika ada alternatif nyata
    • Maksud saya menulis anotasi proprietari, bukan “situasi monopoli”. Gara-gara autocorrect ponsel
  • Sepertinya ini tidak akan berjalan baik. C memiliki abstraksi yang tidak bisa direplikasi di Rust tanpa perubahan besar
    Di C, dua struktur data berbeda yang menyimpan pointer yang sama dan menulis ke pointer itu adalah hal umum. Ini tidak bisa direplikasi secara sepele di Rust, dan membutuhkan intervensi yang cukup cerdik

    • Saya rasa mereka bisa membuat sesuatu yang bisa dikompilasi, sekaligus “Rust” dan “AI”. Itu memenuhi dua kali syarat buzzword, jadi bagus juga untuk membenarkan proyek riset
      Namun mereka tidak akan mendapatkan output dengan bug lebih sedikit, atau proses otomatis yang menghasilkan struktur program yang menciptakan keandalan Rust
  • Apakah ini harus otomatis? Jika ya, bukankah program yang bisa mem-porting C ke Rust secara otomatis niscaya harus mencakup semua fungsi untuk membuat kode C itu sendiri aman?

    • Jika kalimat itu dibaca secara wajar, sulit mengartikannya sebagai otomasi penuh, dan jika begitu jawaban atas pertanyaannya adalah tidak
      Sebagian kode C bukan sekadar “kebenarannya tidak bisa diverifikasi”, melainkan “benar-benar salah dari sisi keamanan memori”. Kode seperti itu tidak akan diterjemahkan otomatis tanpa campur tangan manusia. Bagaimana mungkin, kalau tidak ada kode ekuivalen yang benar. Alatnya perlu jalan keluar untuk berkata, “Saya tidak tahu kode ini bermaksud melakukan apa, dan yang benar-benar dilakukannya adalah melanggar janji dengan compiler, jadi saya juga tahu itu bukan maksudnya. Manusia, tolong bantu”
      Secara teoretis, mustahil membuat jalan keluar itu hanya dipakai ketika undefined behavior benar-benar terjadi. Ini karena teorema Rice. Secara praktis pun, kita tidak boleh menerjemahkan kode yang terlalu sulit dipahami secara membabi buta, jadi upaya melakukan itu sendiri kemungkinan besar tidak diinginkan
      Pada akhirnya saya membayangkan alatnya akan menjadi semacam alat interaktif yang melakukan sebagian besar pekerjaan tetapi dipandu manusia. Dan sebagai hasil dari panduan manusia itu, yang keluar bukan kode yang persis ekuivalen, melainkan kode yang menjalankan tujuan yang sama
  • Jika 1) Rust tidak memiliki bug memori dan 2) C dapat diterjemahkan otomatis ke Rust, itu berarti semua bug memori bisa diperbaiki secara otomatis
    Ini hampir pasti tidak benar. Pekerjaan ini kemungkinan besar sepenuhnya mustahil dalam kasus umum

    • Karena tidak dinyatakan bahwa semua perilaku kode C ingin dipertahankan, masalah ini punya solusi sepele
      Misalnya, semua alokasi memori dinamis bisa diganti dengan buffer tetap yang ditentukan saat penerjemahan, lalu semua input yang tidak muat dalam buffer tersebut ditolak