Menulis Kebijakan SELinux

Android Open Source Project (AOSP) menyediakan kebijakan dasar yang kuat untuk aplikasi dan layanan yang umum di semua perangkat Android. Kontributor AOSP secara teratur menyempurnakan kebijakan ini. Kebijakan inti diperkirakan mencapai sekitar 90–95% dari kebijakan akhir pada perangkat dengan penyesuaian khusus perangkat yang mencapai 5-10% sisanya. Artikel ini berfokus pada penyesuaian khusus perangkat ini, cara menulis kebijakan khusus perangkat, dan beberapa masalah yang harus dihindari selama prosesnya.

Pembukaan perangkat

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

Jalankan dalam mode permisif

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

  • Mode permisif memastikan bahwa pengungkapan kebijakan tidak menunda tugas peluncuran perangkat awal lainnya.
  • Penolakan yang dipaksakan dapat menutupi penolakan lainnya. Misalnya, akses file biasanya memerlukan pencarian direktori, membuka file, lalu membaca 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, konfirmasi mode permisif dengan:

adb shell getenforce

Dua minggu adalah waktu yang wajar untuk berada dalam mode permisif global. Setelah mengatasi sebagian besar penolakan, kembali ke mode penegakan dan atasi bug saat mereka masuk. Domain yang masih menghasilkan penolakan atau layanan yang masih dalam pengembangan besar dapat dimasukkan ke mode permisif untuk sementara, tetapi pindahkan kembali ke mode penegakan sesegera mungkin.

Terapkan lebih awal

Dalam mode penegakan, penolakan dicatat dan ditegakkan. Ini adalah praktik terbaik untuk memasukkan perangkat Anda ke mode penegakan sedini mungkin. Menunggu untuk membuat dan menerapkan kebijakan khusus perangkat sering kali menghasilkan produk yang bermasalah dan pengalaman pengguna yang buruk. Mulai cukup awal untuk berpartisipasi dalam dogfooding dan memastikan cakupan pengujian penuh fungsionalitas dalam penggunaan dunia nyata. Memulai lebih awal memastikan masalah keamanan menginformasikan keputusan desain. Sebaliknya, memberikan izin hanya berdasarkan penolakan yang diamati adalah pendekatan yang tidak aman. Gunakan waktu ini untuk melakukan audit keamanan perangkat dan mengajukan bug terhadap perilaku yang tidak boleh diizinkan.

Hapus atau hapus kebijakan yang ada

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

Mengatasi penolakan layanan inti

Penolakan yang dihasilkan oleh layanan inti biasanya ditangani oleh pelabelan file. Sebagai contoh:

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 /dev/kgsl-3d0 . Dalam contoh ini, tcontext adalah device . Ini mewakili konteks default di mana semua yang ada di /dev menerima label " perangkat " kecuali label yang lebih spesifik diberikan. Hanya menerima output dari audit2allow di sini akan menghasilkan aturan yang salah dan terlalu permisif.

Untuk mengatasi masalah seperti ini, beri file label yang lebih spesifik, 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 jenis yang telah ditentukan sebelumnya dalam kebijakan inti:

Secara umum, memberikan izin ke label default adalah salah. Banyak dari izin ini tidak diizinkan oleh aturan neverallow , tetapi meskipun tidak secara eksplisit dilarang, praktik terbaik adalah memberikan label tertentu.

Beri label pada layanan baru dan atasi penolakan

Layanan yang diluncurkan init harus berjalan 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 init. device .rc 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 template 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 ini ke device/ manufacturer / device-name /sepolicy/file_contexts :

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

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

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

    Gunakan penolakan untuk menentukan izin yang diperlukan. Alat audit2allow memberikan panduan yang baik, tetapi hanya menggunakannya untuk menginformasikan penulisan kebijakan. Jangan hanya menyalin output.

Beralih kembali ke mode penegakan

Tidak apa-apa untuk memecahkan masalah dalam mode permisif, tetapi beralih kembali ke mode penegakan sedini mungkin dan mencoba untuk tetap di sana.

Kesalahan Umum

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

Terlalu sering menggunakan negasi

Aturan contoh 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 cacat dalam beberapa hal. Pengecualian untrusted_app sepele untuk diatasi karena semua aplikasi secara opsional dapat menjalankan layanan di domain isolated_app . Demikian juga, jika domain baru untuk aplikasi pihak ketiga ditambahkan ke AOSP, mereka juga akan memiliki akses ke scary_debug_device . Aturannya terlalu permisif. Sebagian besar domain tidak akan mendapat manfaat dari memiliki akses ke alat debugging ini. Aturan seharusnya ditulis untuk mengizinkan hanya domain yang memerlukan akses.

Fitur debugging dalam produksi

Fitur debug tidak boleh ada pada build produksi dan juga kebijakannya.

Alternatif paling sederhana adalah 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 SEAndroid Policies in the Wild menjelaskan tren yang mengkhawatirkan dalam pertumbuhan penyesuaian kebijakan perangkat. Kebijakan khusus perangkat harus mencakup 5-10% dari keseluruhan kebijakan yang berjalan di perangkat. Penyesuaian dalam kisaran 20%+ hampir pasti mengandung lebih dari domain istimewa dan kebijakan mati.

Kebijakan besar yang tidak perlu:

  • Mendapat pukulan ganda pada memori saat kebijakan berada di ramdisk dan juga dimuat ke dalam memori kernel.
  • Membuang ruang disk dengan memerlukan bootimage yang lebih besar.
  • Mempengaruhi waktu pencarian kebijakan waktu proses.

Contoh berikut menunjukkan dua perangkat di mana kebijakan khusus produsen terdiri dari 50% dan 40% dari kebijakan pada perangkat. Penulisan ulang kebijakan 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 khusus perangkat setelah audit keamanan.

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

Dalam kedua kasus, kebijakan dikurangi secara dramatis baik dalam ukuran dan jumlah izin. Penurunan ukuran kebijakan hampir seluruhnya karena penghapusan izin yang tidak perlu, banyak di antaranya kemungkinan aturan yang dihasilkan oleh audit2allow yang ditambahkan tanpa pandang bulu ke kebijakan. Domain mati juga menjadi masalah untuk 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 hampir tidak pernah memberikan izin dac_override . Alih-alih mengubah izin unix pada file atau proses . Beberapa domain seperti init , vold , dan installd benar-benar membutuhkan kemampuan untuk mengesampingkan izin file unix untuk mengakses file proses lain. Lihat blog Dan Walsh untuk penjelasan lebih mendalam.