Android sangat menganjurkan OEM untuk menguji implementasi SELinux mereka secara menyeluruh. Saat menerapkan SELinux, produsen harus menerapkan kebijakan baru ke kumpulan perangkat pengujian terlebih dahulu.
Setelah menerapkan kebijakan baru, pastikan SELinux berjalan dalam mode yang benar di perangkat dengan mengeluarkan perintah getenforce.
Perintah ini mencetak mode SELinux global: Enforcing atau Permissive. Untuk
menentukan mode SELinux untuk setiap domain, Anda harus memeriksa file yang sesuai
atau menjalankan versi terbaru sepolicy-analyze dengan
flag yang sesuai (-p), yang ada di
/platform/system/sepolicy/tools/.
Baca penolakan
Periksa error, yang dirutekan sebagai log peristiwa ke dmesg
dan logcat serta dapat dilihat secara lokal di perangkat. Produsen
harus memeriksa output SELinux untuk dmesg di perangkat ini dan
menyesuaikan setelan sebelum rilis publik dalam mode permisif dan akhirnya beralih
ke mode penerapan. Pesan log SELinux berisi avc: sehingga dapat
ditemukan dengan mudah menggunakan grep. Anda dapat merekam log penolakan yang sedang berlangsung dengan menjalankan cat /proc/kmsg atau merekam log penolakan dari booting sebelumnya dengan menjalankan cat /sys/fs/pstore/console-ramoops.
Pesan error SELinux dibatasi lajunya setelah booting selesai untuk menghindari membanjiri log. Untuk memastikan Anda melihat semua pesan yang relevan, Anda dapat menonaktifkan fitur ini
dengan menjalankan adb shell auditctl -r 0.
Dengan output ini, produsen dapat dengan mudah mengidentifikasi kapan pengguna atau komponen sistem melanggar kebijakan SELinux. Produsen kemudian dapat memperbaiki perilaku buruk ini, baik dengan mengubah software, kebijakan SELinux, atau keduanya.
Secara khusus, pesan log ini menunjukkan proses apa yang akan gagal dalam mode penerapan dan alasannya. Berikut ini contohnya:
avc: denied { connectto } for pid=2671 comm="ping" path="/dev/socket/dnsproxyd"
scontext=u:r:shell:s0 tcontext=u:r:netd:s0 tclass=unix_stream_socket
Interpretasikan output ini seperti berikut:
-
{ connectto }di atas mewakili tindakan yang sedang dilakukan. Bersama dengantclassdi bagian akhir (unix_stream_socket), tindakan ini memberi tahu Anda secara kasar apa yang sedang dilakukan terhadap apa. Dalam hal ini, sesuatu mencoba terhubung ke soket streaming unix. -
scontext (u:r:shell:s0)memberi tahu Anda konteks yang memulai tindakan. Dalam kasus ini, ada sesuatu yang berjalan sebagai shell. -
tcontext (u:r:netd:s0)memberi tahu Anda konteks target tindakan. Dalam hal ini, itu adalah unix_stream_socket yang dimiliki olehnetd. -
comm="ping"di bagian atas memberi Anda petunjuk tambahan tentang apa yang sedang dijalankan pada saat penolakan dibuat. Dalam hal ini, petunjuknya cukup bagus.
Contoh lain:
adb shell su root dmesg | grep 'avc: '
Output:
<5> type=1400 audit: avc: denied { read write } for pid=177
comm="rmt_storage" name="mem" dev="tmpfs" ino=6004 scontext=u:r:rmt:s0
tcontext=u:object_r:kmem_device:s0 tclass=chr_file
Berikut adalah elemen utama dari penolakan ini:
- Tindakan - tindakan yang dicoba ditandai dalam tanda kurung,
read writeatausetenforce. - Aktor - Entri
scontext(konteks sumber) merepresentasikan aktor, dalam hal ini daemonrmt_storage. - Object - Entri
tcontext(konteks target) merepresentasikan objek yang sedang ditindaklanjuti, dalam hal ini kmem. - Hasil - Entri
tclass(class target) menunjukkan jenis objek yang sedang ditindaklanjuti, dalam hal inichr_file(perangkat karakter).
Mengekspor stack pengguna dan kernel
Dalam beberapa kasus, informasi yang terdapat dalam log peristiwa tidak cukup untuk menunjukkan asal penolakan. Mengumpulkan rangkaian panggilan, termasuk kernel dan userspace, sering kali berguna untuk lebih memahami alasan penolakan terjadi.
Kernel terbaru menentukan titik rekaman aktivitas bernama avc:selinux_audited. Gunakan Android
simpleperf untuk mengaktifkan titik rekaman aktivitas ini dan merekam callchain.
Konfigurasi yang didukung
- Kernel Linux >= 5.10, khususnya cabang Android Common Kernel
mainline
dan
android12-5.10
didukung.
Cabang android12-5.4
juga didukung. Anda dapat menggunakan
simpleperfuntuk menentukan apakah titik rekaman aktivitas ditentukan di perangkat Anda:adb root && adb shell simpleperf list | grep avc:selinux_audited. Untuk versi kernel lainnya, Anda dapat memilih commit dd81662 dan 30969bc. - Anda harus dapat mereproduksi peristiwa yang sedang Anda debug. Peristiwa waktu booting tidak didukung menggunakan simpleperf; namun, Anda mungkin masih dapat memulai ulang layanan untuk memicu peristiwa.
Mencatat rantai panggilan
Langkah pertama adalah mencatat peristiwa menggunakan simpleperf record:
adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"
Kemudian, peristiwa yang menyebabkan penolakan harus dipicu. Setelah itu, perekaman harus dihentikan. Dalam contoh ini, dengan menggunakan Ctrl-c, sampel seharusnya sudah diambil:
^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.
Terakhir, simpleperf report dapat digunakan untuk memeriksa stacktrace yang direkam.
Sebagai contoh:
adb shell -t "cd /data/local/tmp && su root simpleperf report -g --full-callgraph"
[...]
Children Self Command Pid Tid Shared Object Symbol
100.00% 0.00% dmesg 3318 3318 /apex/com.android.runtime/lib64/bionic/libc.so __libc_init
|
-- __libc_init
|
-- main
toybox_main
toy_exec_which
dmesg_main
klogctl
entry_SYSCALL_64_after_hwframe
do_syscall_64
__x64_sys_syslog
do_syslog
selinux_syslog
slow_avc_audit
common_lsm_audit
avc_audit_post_callback
avc_audit_post_callback
Rantai panggilan di atas adalah rantai panggilan kernel dan ruang pengguna yang terpadu. Hal ini memberi Anda tampilan alur kode yang lebih baik dengan memulai rekaman aktivitas dari ruang pengguna hingga ke kernel tempat penolakan terjadi. Untuk mengetahui informasi selengkapnya tentang simpleperf, lihat
Referensi perintah yang dapat dieksekusi Simpleperf
Beralih ke permisif
Penerapan SELinux dapat dinonaktifkan dengan adb pada build userdebug atau eng. Untuk melakukannya,
alih-alih ADB ke root terlebih dahulu dengan menjalankan adb root. Kemudian, untuk menonaktifkan penerapan SELinux, jalankan:
adb shell setenforce 0
Atau di command line kernel (selama pengaktifan awal perangkat):
androidboot.selinux=permissiveandroidboot.selinux=enforcing
Atau melalui bootconfig di Android 12:
androidboot.selinux=permissiveandroidboot.selinux=enforcing
Menggunakan audit2allow
Alat audit2allow mengambil penolakan dmesg dan
mengonversinya menjadi pernyataan kebijakan SELinux yang sesuai. Dengan demikian, fitur ini dapat
sangat mempercepat pengembangan SELinux.
Untuk menggunakannya, jalankan:
adb pull /sys/fs/selinux/policyadb logcat -b events -d | audit2allow -p policy
Namun demikian, Anda harus berhati-hati dalam memeriksa setiap potensi penambahan izin yang
berlebihan. Misalnya, memberikan penolakan audit2allow
rmt_storage yang ditampilkan sebelumnya akan menghasilkan pernyataan kebijakan SELinux yang disarankan berikut:
#============= shell ==============
allow shell kernel:security setenforce;
#============= rmt ==============
allow rmt kmem_device:chr_file { read write };
Hal ini akan memberi rmt kemampuan untuk menulis memori kernel, yang merupakan celah keamanan yang sangat jelas. Pernyataan audit2allow sering kali hanya
titik awal. Setelah menggunakan pernyataan ini, Anda mungkin perlu mengubah
domain sumber dan label target, serta menyertakan makro
yang tepat, untuk mendapatkan kebijakan yang baik. Terkadang penolakan yang sedang diperiksa tidak boleh mengakibatkan perubahan kebijakan apa pun; melainkan aplikasi yang melanggar harus diubah.