Android, OEM'leri SELinux uygulamalarını kapsamlı bir şekilde test etmeye şiddetle teşvik eder. Üreticiler SELinux'u uygularken yeni politikayı öncelikle cihazların test havuzuna uygulamalıdır.
Yeni bir politika uyguladıktan sonra getenforce
komutunu vererek SELinux'un cihazda doğru modda çalıştığından emin olun.
Bu, genel SELinux modunu yazdırır: Zorlayıcı veya İzin Veren. Her etki alanı için SELinux modunu belirlemek için ilgili dosyaları incelemeniz veya sepolicy-analyze
en son sürümünü /platform/system/sepolicy/tools/
dosyasında bulunan uygun ( -p
) işaretiyle çalıştırmanız gerekir.
İnkarları 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
yönelik SELinux çıkışını incelemeli ve izin verilen modda genel kullanıma sunulmadan ve sonunda zorlama moduna geçmeden önce ayarları iyileştirmelidir. SELinux günlük mesajları avc:
içerir ve bu nedenle 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 doldurulması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 adb shell auditctl -r 0
komutunu çalıştırarak bunu devre dışı bırakabilirsiniz.
Bu çıktıyla üreticiler, sistem kullanıcılarının veya bileşenlerinin SELinux politikasını ne zaman ihlal ettiğini kolaylıkla tespit edebilir. Üreticiler daha sonra bu kötü davranışı yazılımda, SELinux politikasında veya her ikisinde değişiklik yaparak onarabilirler.
Özellikle bu günlük mesajları, zorlama modunda hangi işlemlerin başarısız olacağını ve nedenini 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ştirilen eylemi temsil eder. Sondakitclass
(unix_stream_socket
) ile birlikte, size kabaca ne yapıldığını, neye yapıldığını anlatır. Bu durumda, bir şey unix akış soketine bağlanmaya çalışıyordu. -
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 içeriğini anlatır. Bu durumda bu,netd
sahip olduğu bir unix_stream_socket'tir. - Üstteki
comm="ping"
reddin oluşturulduğu sırada neyin çalıştırıldığına dair 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 temel unsurları:
- Eylem - denenen eylem parantez içinde vurgulanır,
read write
veyasetenforce
. - Aktör -
scontext
(kaynak bağlamı) girişi, aktörü, bu durumdarmt_storage
arka plan programını temsil eder. - 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ü belirtir; bu durumda birchr_file
(karakter aygıtı).
Kullanıcı ve Çekirdek Yığınlarının Silinmesi
Bazı durumlarda olay günlüğünde yer alan bilgiler, reddin kaynağını belirlemek için yeterli olmayabilir. Reddetmenin 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.
Yeni çekirdekler avc:selinux_audited
adında 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 dalları ana hattı ve android12-5.10 desteklenmektedir. Android12-5.4 dalı da desteklenmektedir. İzleme noktasının cihazınızda tanımlı olup olmadığı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 yakalama
İlk adım, simpleperf record
kullanarak olayı kaydetmektir:
adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"
Daha sonra redde sebep olan olayın tetiklenmesi gerekmektedir. Bundan sonra kayıt durdurulmalıdır. Bu örnekte Ctrl-c
kullanılarak numunenin yakalanması gerekirdi:
^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.
Son olarak, yakalanan yığın izini 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. İzlemeyi kullanıcı alanından reddin 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.
İzin vericiye geçiliyor
SELinux uygulaması, userdebug veya eng yapılarında 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 uygulaması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 açılması 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
reddini alır ve bunları karşılık gelen SELinux politika bildirimlerine 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 açısından her potansiyel eklemenin incelenmesine özen gösterilmelidir. Örneğin, daha önce gösterilen audit2allow
rmt_storage
reddinin beslenmesi, 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 çarpan bir güvenlik açığı olan çekirdek belleği yazma yeteneği verecektir. audit2allow
ifadeleri çoğunlukla 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ştirmenizin yanı sıra uygun makroları da dahil etmeniz gerekebilir. Bazen incelenmekte olan inkarın herhangi bir politika değişikliğine yol açmaması gerekir; bunun yerine rahatsız edici uygulamanın değiştirilmesi gerekir.