Android, OEM'leri SELinux uygulamalarını kapsamlı bir şekilde test etmeye teşvik eder. Üreticiler SELinux'u uygularken, yeni politikayı önce bir cihaz test havuzuna uygulamalıdır.
Yeni bir ilke uyguladıktan sonra getenforce
komutunu vererek SELinux'un cihazda doğru modda çalıştığından emin olun.
Bu, global SELinux modunu yazdırır: Zorlayıcı veya Müsamahakâr. Her etki alanı için SELinux modunu belirlemek için ilgili dosyaları incelemeli veya /platform/system/sepolicy/tools/
içinde bulunan uygun ( -p
) bayrağıyla sepolicy-analyze
en son sürümünü çalıştırmalısınız.
Reddetmeleri okumak
Olay günlükleri olarak dmesg
ve logcat
yönlendirilen ve cihazda yerel olarak görüntülenebilen hataları kontrol edin. Üreticiler, bu cihazlarda dmesg
yapmak için SELinux çıktısını incelemeli ve izin verme modunda genel kullanıma sunulmadan ve sonunda zorlama moduna geçmeden önce ayarları iyileştirmelidir. SELinux günlük mesajları avc:
içerir ve grep
ile kolayca bulunabilir. cat /proc/kmsg
çalıştırarak devam eden reddetme günlüklerini yakalamak veya cat /sys/fs/pstore/console-ramoops
çalıştırarak önceki önyüklemeden reddetme günlüklerini yakalamak mümkündür.
SELinux hata mesajları, günlüklerin boğulmasını önlemek için önyükleme tamamlandıktan sonra hız sınırlıdır. İlgili tüm mesajları gördüğünüzden emin olmak için bunu adb shell auditctl -r 0
çalıştırarak devre dışı bırakabilirsiniz.
Bu çıktı ile üreticiler, sistem kullanıcılarının veya bileşenlerinin ne zaman SELinux politikasını ihlal ettiğini kolayca belirleyebilir. Üreticiler daha sonra yazılımda, SELinux politikasında veya her ikisinde birden değişiklik yaparak bu kötü davranışı onarabilir.
Spesifik olarak, bu günlük mesajları, zorlama modunda hangi işlemlerin başarısız olacağını ve neden başarısız olacağını gösterir. İşte bir örnek:
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
Bu çıktıyı şu şekilde yorumlayın:
- Yukarıdaki
{ connectto }
, gerçekleştirilmekte olan eylemi temsil eder.tclass
(unix_stream_socket
) ile birlikte, neyin neye yapıldığını kabaca söyler. Bu durumda, bir şey bir unix akış soketine bağlanmaya çalışıyordu. - Bağlam
scontext (u:r:shell:s0)
, eylemi hangi bağlamın başlattığını söyler. Bu durumda bu, kabuk olarak çalışan bir şeydir. -
tcontext (u:r:netd:s0)
size eylemin hedefinin bağlamını söyler. Bu durumda, bu, netd'nin sahip olduğu birnetd
. - En üstteki
comm="ping"
, reddetme oluşturulduğu sırada neyin çalıştırıldığı hakkında size ek bir ipucu verir. Bu durumda, oldukça iyi bir ipucu.
Başka bir örnek:
adb shell su root dmesg | grep 'avc: '
Çıktı:
<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
İşte bu inkarın ana unsurları:
- Eylem - denenen eylem parantez içinde vurgulanır,
read write
veyasetenforce
. - Aktör -
scontext
(kaynak bağlamı) girişi, aktörü temsil eder, bu durumdarmt_storage
arka plan programı. - Nesne -
tcontext
(hedef bağlam) girişi, üzerinde işlem yapılan nesneyi, bu durumda kmem'i temsil eder. - Sonuç -
tclass
(hedef sınıf) girişi, üzerinde işlem yapılan nesnenin türünü, bu durumda birchr_file
(karakter aygıtı) belirtir.
Kullanıcı ve Çekirdek Yığınlarını Boşaltma
Bazı durumlarda, olay günlüğünde yer alan bilgiler, reddetmenin kaynağını kesin olarak belirlemek için yeterli değildir. Reddin neden oluştuğunu daha iyi anlamak için çekirdek ve kullanıcı alanı da dahil olmak üzere çağrı zincirini toplamak genellikle yararlıdır.
Son çekirdekler, avc:selinux_audited
adlı bir izleme noktası tanımlar. Bu izleme noktasını etkinleştirmek ve çağrı zincirini yakalamak için Android simpleperf
kullanın.
desteklenen yapılandırma
- Linux çekirdeği >= 5.10, özellikle Android Ortak Çekirdek şubeleri ana hat ve android12-5.10 desteklenir. android12-5.4 şubesi de desteklenmektedir. İzleme noktasının cihazınızda tanımlanıp tanımlanmadığını belirlemek için
simpleperf
kullanabilirsiniz:adb root && adb shell simpleperf list | grep avc:selinux_audited
. Diğer çekirdek sürümleri için, dd81662 ve 30969bc taahhütlerini seçebilirsiniz. - Hata ayıkladığınız olayı yeniden oluşturmak mümkün olmalıdır. Önyükleme zamanı olayları, simpleperf kullanılarak desteklenmez; ancak yine de olayı tetiklemek için hizmeti yeniden başlatabilirsiniz.
Çağrı zincirini yakalamak
İlk adım, olayı simpleperf record
kullanarak kaydetmektir:
adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"
Ardından, reddetmeye neden olan olay tetiklenmelidir. Bundan sonra, kayıt durdurulmalıdır. Bu örnekte, Ctrl-c
kullanılarak örnek alınmış olmalıdır:
^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.
Son olarak, yakalanan stacktrace'i incelemek için simpleperf report
kullanılabilir. Örneğin:
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
Yukarıdaki çağrı zinciri, birleşik bir çekirdek ve kullanıcı alanı çağrı zinciridir. İzi kullanıcı alanından inkarın gerçekleştiği çekirdeğe kadar başlatarak kod akışını daha iyi görmenizi sağlar. simpleperf hakkında daha fazla bilgi için simpleperf
Yürütülebilir komutlar referansına bakın
Müsamahakâr moda geçiliyor
SELinux zorlaması, userdebug veya eng derlemelerinde ADB aracılığıyla devre dışı bırakılabilir. Bunu yapmak için önce adb root
çalıştırarak ADB'yi root olarak değiştirin. Ardından, SELinux zorlamasını devre dışı bırakmak için şunu çalıştırın:
adb shell setenforce 0
Veya çekirdek komut satırında (cihazın erken getirilmesi sırasında):
androidboot.selinux=permissive
androidboot.selinux=enforcing
Veya Android 12'deki bootconfig aracılığıyla:
androidboot.selinux=permissive
androidboot.selinux=enforcing
audit2allow'u kullanma
audit2allow
aracı, dmesg
redlerini alır ve bunları karşılık gelen SELinux politika ifadelerine dönüştürür. Bu nedenle, SELinux gelişimini büyük ölçüde hızlandırabilir.
Kullanmak için şunu çalıştırın:
adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy
Bununla birlikte, aşırı erişim izinleri için her potansiyel eklemeyi incelemek için özen gösterilmelidir. Örneğin, daha önce gösterilen rmt_storage
reddinin beslenmesi audit2allow
aşağıdaki önerilen SELinux politika bildirimiyle sonuçlanır:
#============= shell ============== allow shell kernel:security setenforce; #============= rmt ============== allow rmt kmem_device:chr_file { read write };
Bu, rmt
göze batan bir güvenlik açığı olan çekirdek belleği yazma yeteneği verir. Genellikle audit2allow
ifadeleri yalnızca bir başlangıç noktasıdır. Bu ifadeleri kullandıktan sonra, iyi bir politikaya ulaşmak için kaynak etki alanını ve hedefin etiketini değiştirmeniz ve uygun makroları dahil etmeniz gerekebilir. Bazen incelenmekte olan ret, herhangi bir politika değişikliğine yol açmamalıdır; bunun yerine rahatsız edici uygulama değiştirilmelidir.