Berdasarkan Clang untuk bahasa C, mode untuk memeriksa batas buffer telah diterapkan

Insinyur dari Apple telah mengumumkan bahwa mereka siap menguji mode "-fbounds-safety" untuk kompiler Clang, yang memberikan jaminan untuk pekerjaan yang aman dengan buffer dalam kode C. Mode ini disertakan dalam fork LLVM yang dikelola oleh Apple untuk proyek Swift. Di masa depan, kami berencana untuk secara bertahap mentransfer fungsionalitas β€œ-fbounds-safety” ke basis kode utama LLVM/Clang.

Perlu dicatat bahwa mekanisme perlindungan yang diusulkan sudah digunakan secara aktif di produk Apple, seperti kernel XNU, firmware, perpustakaan untuk bekerja dengan dekoder suara dan gambar. Mengaktifkan mode "-fbounds-safety" mengurangi kinerja aplikasi rata-rata 5% (kisaran -1% hingga 29%), meningkatkan ukuran kode sebesar 9.1% (kisaran -1.4% hingga 38%), dan memperlambat kompilasi sebesar 11 %.

Menggunakan mode "-fbounds-safety" untuk secara otomatis mendeteksi memori di luar batas yang terkait dengan pointer memerlukan penambahan anotasi khusus ke kode dan menyertakan file header "ptrcheck.h". Inti dari metode perlindungan yang diusulkan adalah lampiran otomatis pemeriksaan kepatuhan terhadap batas yang dapat diterima, ditambahkan berdasarkan anotasi atau ukuran yang ditetapkan secara manual yang diketahui oleh penyusun.

Berbeda dengan penggunaan wide pointer pada kode yang selain alamatnya berisi informasi tentang batas atas dan bawah buffer, penggunaan mode β€œ-fbounds-safety” tidak melanggar ABI (Application Binary Interface), tidak mengubah format pointer yang diekspor, dan tidak memerlukan pengerjaan ulang untuk keseluruhan proyek sekaligus. Dalam mode "-fbounds-safety", penunjuk yang diperluas hanya digunakan di area yang tidak tumpang tindih dengan ABI, dan untuk penunjuk yang memengaruhi ABI, penunjuk biasa digunakan dengan pemeriksaan substitusi yang dihasilkan dari anotasi dengan informasi batas.

Anotasi harus dilampirkan ke pointer di bidang struktur dan parameter fungsi yang menunjuk ke array objek, serta ke variabel global dengan pointer. Tidak perlu menambahkan anotasi untuk pointer dalam variabel lokal, karena mereka secara otomatis diperlakukan sebagai pointer yang diperluas, yang sudah menyertakan informasi tentang batasan yang valid. Petunjuk tentang konstruksi dalam kode yang memerlukan anotasi disediakan oleh kompiler ketika dijalankan dengan tanda "-fbounds-safety".

Model keamanan "-fbounds-safety" dapat diterapkan secara bertahap, file demi file, tanpa mengganggu pengembangan keseluruhan proyek. Menambahkan perlindungan ke suatu proyek berarti menentukan anotasi dalam file kode tertentu, menghilangkan peringatan kompiler dan menguji program, setelah itu langkah-langkah ini diulangi untuk file berikutnya. Kode dengan anotasi tambahan tetap kompatibel dengan kode C biasa dan kompiler yang tidak mendukung β€œ-fbounds-safety” (jika dibuat dengan kompiler lain atau jika dibuat tanpa tanda β€œ-fbounds-safety”, pemeriksaan batas tambahan tidak akan ditambahkan) .

Saat program sedang berjalan, jika akses di luar batas yang diizinkan terdeteksi, pengecualian akan dihasilkan dan program menghentikan eksekusinya. Kerusakan juga dapat terjadi ketika anotasi yang salah ditentukan, jadi ketika menggunakan β€œ-fbounds-safety” pengujian tambahan terhadap operasi program diperlukan.

Pada contoh di bawah, parameter "int *p" memiliki anotasi "__counted_by(n)" yang ditambahkan untuk menambahkan pemeriksaan batas waktu proses tambahan. Jika Anda mencoba mengkompilasi kode dalam mode "-fbounds-safety" tanpa menentukan anotasi ini, kompiler akan mengeluarkan peringatan tentang hilangnya informasi batas array saat memproses ekspresi "p[i] = 0". #termasuk void init_buf(int *__counted_by(n) p, int n) { untuk (int i = 0; i < n; ++i) p[i] = 0; // pada mode β€œ-fbounds-safety”, compiler sendiri akan memasukkan tanda centang yang mirip dengan kode β€œif (i < 0 || i >= n) trap();” }

Untuk variabel lokal dengan pointer, cek dilampirkan secara otomatis, misalnya: void foo(int i){ char *buf = (char *)malloc(10); // informasi tentang batas akan disimpan untuk penunjuk buf buf[i] = 0xff; // tanda centang β€œif (buf + i < buf || buf + i >= buf + 10) trap();” akan otomatis dimasukkan }

Kapan pun memungkinkan, kompiler mengoptimalkan dan menghilangkan penambahan kode yang tidak perlu jika kode tersebut sudah memiliki pemeriksaan yang diperlukan. Misalnya: for (size_t i = 0; i < count; ++i) { buf[i] = i; // tanda centang "if (i < 0 || i >= count) trap()" tidak akan ditambahkan, karena kondisi "i < count" sudah ada di atas dan i tidak boleh kurang dari 0. }

Anotasi dasar:

  • "__counted_by(N)" - mendefinisikan ukuran buffer dalam elemen tipe target.
  • "__sized_by(N)" - menentukan ukuran buffer dalam byte.
  • "__ended_by(P)" - menetapkan batas atas buffer.
  • "__null_terminated" - menganggap karakter null sebagai akhir buffer.
  • "__single" - mengikat penunjuk ke satu objek. Ini adalah default untuk pointer yang memengaruhi ABI kecuali jika anotasi disetel secara eksplisit.
  • "__bidi_indexable" adalah indeks yang diperluas dengan informasi tentang batas atas dan bawah. Ini adalah default untuk pointer yang tidak mempengaruhi ABI.
  • "__indexable" adalah indeks yang diperluas dengan informasi batas atas.
  • "__unsafe_indexable" - pemeriksaan penunjuk tanpa batas (untuk portabilitas dengan kode yang tidak dilindungi, misalnya, untuk mendapatkan penunjuk dari kode eksternal).

Sumber: opennet.ru

Beli hosting yang andal untuk situs dengan perlindungan DDoS, server VPS VDS πŸ”₯ Beli hosting website andal dengan perlindungan DDoS, server VPS VDS | ProHoster