Menulis kebijakan SELinux

Project Open Source Android (AOSP) menyediakan kebijakan dasar yang solid untuk aplikasi dan layanan yang umum di semua perangkat Android. Kontributor AOSP secara rutin meningkatkan kualitas kebijakan ini. Kebijakan inti diharapkan akan mencakup sekitar 90–95% kebijakan akhir di perangkat dengan penyesuaian khusus perangkat yang mencakup 5–10% sisanya. Artikel ini berfokus pada penyesuaian khusus perangkat ini, cara menulis kebijakan khusus perangkat, dan beberapa masalah yang harus dihindari.

Pembuatan perangkat

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

Menjalankan dalam mode permisif

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

  • Mode permisif memastikan bahwa pembahasan kebijakan tidak menunda tugas pembersihan perangkat awal lainnya.
  • Penolakan yang diberlakukan dapat menyamarkan penolakan lainnya. Misalnya, akses file biasanya memerlukan penelusuran direktori, pembukaan file, lalu pembacaan file. Dalam mode penerapan, hanya penolakan penelusuran direktori yang akan terjadi. Mode permisif memastikan semua penolakan terlihat.

Cara paling sederhana untuk mengalihkan perangkat ke mode permisif adalah menggunakan command line kernel. Ini dapat ditambahkan ke file BoardConfig.mk perangkat: platform/device/<vendor>/<target>/BoardConfig.mk. Setelah mengubah command line, jalankan make clean, lalu make bootimage, dan flash image booting 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 penerapan dan atasi bug saat muncul. Domain yang masih menghasilkan penolakan atau layanan yang masih dalam pengembangan berat dapat dimasukkan ke dalam mode permisif untuk sementara, tetapi pindahkan kembali ke mode penerapan sesegera mungkin.

Terapkan lebih awal

Dalam mode penerapan, penolakan dicatat ke dalam log dan diterapkan. Praktik terbaiknya adalah menyetel perangkat Anda ke mode penerapan 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 pastikan cakupan pengujian penuh fungsionalitas dalam penggunaan di dunia nyata. Memulai sejak awal akan memastikan masalah keamanan menjadi pertimbangan dalam pengambilan keputusan desain. Sebaliknya, memberikan izin hanya berdasarkan penolakan yang diamati adalah pendekatan yang tidak aman. Gunakan waktu ini untuk melakukan audit keamanan perangkat dan melaporkan bug terhadap perilaku yang tidak boleh diizinkan.

Menghapus atau menghapus 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 dengan pelabelan file. 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 dengan benar. Dalam contoh ini, tcontext adalah device. Ini mewakili konteks default saat segala sesuatu di /dev menerima label “ perangkat” kecuali jika label yang lebih spesifik ditetapkan. Hanya menerima output dari audit2allow di sini akan menghasilkan aturan yang salah dan terlalu permisif.

Untuk mengatasi masalah semacam ini, beri file label yang lebih spesifik, yang dalam hal ini adalah gpu_device. Tidak diperlukan izin lebih lanjut karena mediaserver 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 dalam kebijakan inti:

Secara umum, memberikan izin ke label {i>default<i} merupakan suatu kesalahan. Banyak izin ini tidak diizinkan oleh aturan neverallow, tetapi meskipun tidak secara eksplisit tidak diizinkan, praktik terbaiknya adalah memberikan label tertentu.

Memberi label pada layanan baru dan penolakan alamat

Layanan yang diluncurkan Init harus berjalan di domain SELinux-nya sendiri. Contoh berikut menempatkan layanan “foo” ke dalam domain SELinux-nya sendiri dan memberikan izin.

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

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

    Buat file device/manufacturer/device-name/sepolicy/foo.te dengan konten 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, tempat Anda dapat menambahkan aturan berdasarkan operasi spesifik yang dilakukan oleh file yang dapat dieksekusi tersebut.

  2. Label /system/bin/foo

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

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

    Tindakan ini memastikan file yang dapat dieksekusi diberi label dengan benar sehingga SELinux menjalankan layanan di domain yang sesuai.

  3. Build dan flash image booting dan sistem.
  4. Pertajam aturan SELinux untuk domain.

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

Beralih kembali ke mode penerapan

Tidak masalah untuk memecahkan masalah dalam mode permisif, tetapi beralihlah kembali ke mode penerapan sedini mungkin dan cobalah untuk tetap menggunakannya.

Kesalahan umum

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

Penggunaan negasi yang berlebihan

Contoh aturan berikut 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 dapat memiliki akses ke perangkat debug.

Aturan ini memiliki beberapa kesalahan. Pengecualian untrusted_app mudah 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 memiliki akses ke scary_debug_device. Aturannya terlalu permisif. Sebagian besar domain tidak akan mendapatkan manfaat dari akses ke alat proses debug ini. Aturan harus ditulis untuk hanya mengizinkan domain yang memerlukan akses.

Men-debug fitur dalam produksi

Fitur debug tidak boleh ada di build produksi, begitu juga di kebijakannya.

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

Alternatif aman lainnya adalah menyertakan izin debug dalam pernyataan userdebug_or_eng.

Ledakan ukuran kebijakan

Characterizing SEAndroid Policies in the Wild menjelaskan tren yang mengkhawatirkan dalam pertumbuhan penyesuaian kebijakan perangkat. Kebijakan khusus perangkat harus memperhitungkan 5–10% dari keseluruhan kebijakan yang berjalan di perangkat. Penyesuaian dalam rentang 20%+ hampir pasti berisi domain dengan hak istimewa dan kebijakan yang tidak berlaku.

Kebijakan yang terlalu besar:

  • Melakukan hit ganda pada memori karena kebijakan berada di ramdisk dan juga dimuat ke dalam memori kernel.
  • Mengurangi kapasitas disk dengan mengharuskan bootimage yang lebih besar.
  • Memengaruhi waktu pencarian kebijakan runtime.

Contoh berikut menunjukkan dua perangkat dengan kebijakan khusus produsen yang terdiri dari 50% dan 40% kebijakan di perangkat. Penulisan ulang kebijakan menghasilkan peningkatan keamanan yang signifikan tanpa kehilangan fungsi, seperti yang ditunjukkan di bawah. (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 tersebut, kebijakan dikurangi secara drastis baik dari segi ukuran maupun jumlah izin. Penurunan ukuran kebijakan hampir sepenuhnya disebabkan oleh penghapusan izin yang tidak diperlukan, yang sebagian besar kemungkinan adalah aturan yang dihasilkan oleh audit2allow yang ditambahkan secara sembarangan ke kebijakan. Domain yang tidak aktif 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 hampir tidak pernah memberikan izin dac_override. Sebagai gantinya, ubah izin unix pada file atau proses. Beberapa domain seperti init, vold, dan installd benar-benar memerlukan kemampuan untuk mengganti izin file unix guna mengakses file proses lainnya. Lihat blog Dan Walsh untuk penjelasan yang lebih mendalam.