Menulis Kebijakan SELinux

Proyek Sumber Terbuka Android (AOSP) memberikan kebijakan dasar yang kuat untuk aplikasi dan layanan yang umum di semua perangkat Android. Kontributor AOSP secara berkala menyempurnakan kebijakan ini. Kebijakan inti diperkirakan akan mencakup sekitar 90–95% dari kebijakan final pada perangkat, sedangkan penyesuaian khusus perangkat akan mencakup 5–10% sisanya. Artikel ini berfokus pada penyesuaian khusus perangkat, cara menulis kebijakan khusus perangkat, dan beberapa kendala yang harus dihindari selama prosesnya.

Munculnya perangkat

Saat menulis kebijakan khusus perangkat, ikuti langkah-langkah berikut.

Jalankan dalam mode permisif

Saat perangkat berada dalam mode permisif , penolakan dicatat tetapi tidak diterapkan. Mode permisif penting karena dua alasan:

  • Mode permisif memastikan bahwa penyampaian kebijakan tidak menunda tugas-tugas pembukaan perangkat awal lainnya.
  • Penyangkalan yang dipaksakan mungkin menutupi penyangkalan lainnya. Misalnya, akses file biasanya memerlukan pencarian direktori, pembukaan file, lalu pembacaan file. Dalam mode penegakan, hanya penolakan pencarian direktori yang akan terjadi. Mode permisif memastikan semua penolakan terlihat.

Cara paling sederhana untuk menempatkan perangkat ke mode permisif adalah menggunakan baris perintah kernel . Ini dapat ditambahkan ke file BoardConfig.mk perangkat: platform/device/<vendor>/<target>/BoardConfig.mk . Setelah memodifikasi baris perintah, lakukan make clean , lalu make bootimage , dan flash image boot baru.

Setelah itu, konfirmasikan mode permisif dengan:

adb shell getenforce

Dua minggu adalah waktu yang cukup lama untuk berada dalam mode permisif global. Setelah mengatasi sebagian besar penolakan, kembalilah ke mode penegakan dan atasi bug yang muncul. Domain yang masih menghasilkan penolakan atau layanan yang masih dalam pengembangan besar-besaran dapat dialihkan ke mode permisif untuk sementara, namun kembalikan ke mode penegakan sesegera mungkin.

Terapkan lebih awal

Dalam mode penegakan, penolakan dicatat dan diterapkan. Praktik terbaiknya adalah memasukkan perangkat Anda ke mode penerapan sedini mungkin. Menunggu untuk membuat dan menerapkan kebijakan khusus perangkat sering kali mengakibatkan produk bermasalah dan pengalaman pengguna yang buruk. Mulailah sejak dini untuk berpartisipasi dalam dogfood dan pastikan cakupan uji penuh fungsionalitas dalam penggunaan di dunia nyata. Memulai lebih awal memastikan masalah keamanan menginformasikan keputusan desain. Sebaliknya, memberikan izin hanya berdasarkan penolakan yang teramati merupakan pendekatan yang tidak aman. Gunakan waktu ini untuk melakukan audit keamanan perangkat dan melaporkan bug terhadap perilaku yang tidak diperbolehkan.

Hapus atau hapus kebijakan yang ada

Ada sejumlah alasan bagus untuk membuat kebijakan khusus perangkat dari awal pada perangkat baru, yang meliputi:

Mengatasi penolakan layanan inti

Penolakan yang dihasilkan oleh layanan inti biasanya diatasi dengan pelabelan file. Misalnya:

avc: denied { open } for pid=1003 comm=”mediaserver” path="/dev/kgsl-3d0”
dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0
tclass=chr_file permissive=1
avc: denied { read write } for pid=1003 name="kgsl-3d0" dev="tmpfs"
scontext=u:r:mediaserver:s0
tcontext=u:object_r:device:s0 tclass=chr_file permissive=1

sepenuhnya diatasi dengan memberi label dengan benar /dev/kgsl-3d0 . Dalam contoh ini, tcontext adalah device . Ini mewakili konteks default di mana segala sesuatu di /dev menerima label “ perangkat ” kecuali label yang lebih spesifik ditetapkan. Menerima keluaran dari audit2allow di sini saja akan menghasilkan aturan yang salah dan terlalu permisif.

Untuk mengatasi masalah seperti ini, beri label yang lebih spesifik pada file, yang dalam hal ini adalah gpu_device . Tidak diperlukan izin lebih lanjut karena server media sudah memiliki izin yang diperlukan dalam kebijakan inti untuk mengakses GPU_device.

File khusus perangkat lainnya yang harus diberi label dengan tipe yang telah ditentukan sebelumnya dalam kebijakan inti:

Secara umum, memberikan izin pada label default adalah salah. Banyak dari izin ini yang tidak diizinkan oleh aturan neverallow , namun meskipun tidak secara eksplisit dilarang, praktik terbaiknya adalah memberikan label tertentu.

Beri label pada layanan baru dan atasi penolakan

Layanan yang diluncurkan init harus dijalankan di domain SELinux mereka sendiri. Contoh berikut menempatkan layanan “foo” ke dalam domain SELinux-nya sendiri dan memberinya izin.

Layanan ini diluncurkan di init. device .rc file sebagai:

service foo /system/bin/foo
    class core
  1. Buat domain baru "foo"

    Buat file device/ manufacturer / device-name /sepolicy/foo.te dengan isi sebagai berikut:

    # foo service
    type foo, domain;
    type foo_exec, exec_type, file_type;
    
    init_daemon_domain(foo)
    

    Ini adalah templat awal untuk domain foo SELinux, di mana Anda dapat menambahkan aturan berdasarkan operasi spesifik yang dilakukan oleh executable tersebut.

  2. Label /system/bin/foo

    Tambahkan yang berikut ke device/ manufacturer / device-name /sepolicy/file_contexts :

    /system/bin/foo   u:object_r:foo_exec:s0
    

    Hal ini memastikan executable diberi label dengan benar sehingga SELinux menjalankan layanan di domain yang tepat.

  3. Bangun dan flash image boot dan sistem.
  4. Sempurnakan aturan SELinux untuk domain tersebut.

    Gunakan penolakan untuk menentukan izin yang diperlukan. Alat audit2allow memberikan panduan yang baik, namun hanya digunakan sebagai informasi dalam penulisan kebijakan. Jangan hanya menyalin hasilnya.

Beralih kembali ke mode penegakan

Tidak masalah untuk memecahkan masalah dalam mode permisif, namun beralihlah kembali ke mode penegakan sedini mungkin dan cobalah untuk tetap berada di sana.

Kesalahan Umum

Berikut beberapa solusi untuk kesalahan umum yang terjadi saat menulis kebijakan khusus perangkat.

Penggunaan negasi secara berlebihan

Contoh aturan berikut ini seperti mengunci pintu depan tetapi membiarkan jendela terbuka:

allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms

Tujuannya jelas: semua orang kecuali aplikasi pihak ketiga mungkin memiliki akses ke perangkat debug.

Aturan ini memiliki kelemahan dalam beberapa hal. Pengecualian untrusted_app mudah untuk diatasi karena semua aplikasi dapat menjalankan layanan secara opsional di domain isolated_app . Demikian pula, jika domain baru untuk aplikasi pihak ketiga ditambahkan ke AOSP, domain tersebut juga akan memiliki akses ke scary_debug_device . Aturan tersebut terlalu permisif. Sebagian besar domain tidak akan mendapat manfaat dari akses ke alat debugging ini. Aturan tersebut seharusnya ditulis untuk mengizinkan hanya domain yang memerlukan akses.

Men-debug fitur dalam produksi

Fitur debug tidak boleh ada pada build produksi, begitu pula kebijakannya.

Alternatif paling sederhana adalah dengan hanya mengizinkan fitur debug ketika SELinux dinonaktifkan pada build eng/userdebug, seperti adb root dan adb shell setenforce 0 .

Alternatif aman lainnya adalah dengan menyertakan izin debug dalam pernyataan userdebug_or_eng .

Ledakan ukuran kebijakan

Mengkarakterisasi Kebijakan SEAndroid di Alam Liar menggambarkan tren yang mengkhawatirkan dalam pertumbuhan penyesuaian kebijakan perangkat. Kebijakan khusus perangkat harus mencakup 5–10% dari keseluruhan kebijakan yang berjalan pada perangkat. Penyesuaian dalam kisaran 20%+ hampir pasti berisi domain yang memiliki hak istimewa dan kebijakan mati.

Kebijakan besar yang tidak perlu:

  • Mengambil pukulan ganda pada memori saat kebijakan berada di ramdisk dan juga dimuat ke dalam memori kernel.
  • Membuang-buang ruang disk karena memerlukan bootimage yang lebih besar.
  • Mempengaruhi waktu pencarian kebijakan runtime.

Contoh berikut menunjukkan dua perangkat yang kebijakan khusus produsennya mencakup 50% dan 40% kebijakan pada perangkat. Penulisan ulang kebijakan ini menghasilkan peningkatan keamanan yang substansial tanpa kehilangan fungsionalitas, seperti yang ditunjukkan di bawah ini. (Perangkat AOSP Shamu dan Flounder disertakan untuk perbandingan.)

Gambar 1: Perbandingan ukuran kebijakan spesifik perangkat setelah audit keamanan.

Gambar 1 . Perbandingan ukuran kebijakan spesifik perangkat setelah audit keamanan.

Dalam kedua kasus tersebut, kebijakan tersebut dikurangi secara drastis baik dalam hal ukuran maupun jumlah izin. Penurunan ukuran kebijakan hampir seluruhnya disebabkan oleh penghapusan izin yang tidak perlu, yang sebagian besar kemungkinan merupakan aturan yang dihasilkan oleh audit2allow yang ditambahkan tanpa pandang bulu ke dalam kebijakan. Domain mati juga menjadi masalah bagi kedua perangkat.

Memberikan kemampuan dac_override

Penolakan dac_override berarti bahwa proses yang melanggar mencoba mengakses file dengan izin pengguna/grup/dunia unix yang salah. Solusi yang tepat adalah hampir tidak pernah memberikan izin dac_override . Sebaliknya ubah izin unix pada file atau proses . Beberapa domain seperti init , vold , dan installd benar-benar memerlukan kemampuan untuk mengganti izin file unix untuk mengakses file proses lain. Lihat blog Dan Walsh untuk penjelasan lebih mendalam.