SELinux'u doğrulama

Android, OEM'leri SELinux uygulamalarını kapsamlı bir şekilde test etmeye teşvik ediyor. Üreticiler SELinux'u uygularken, yeni politikayı önce bir test havuzuna uygulamalılar.

Yeni bir ilke uyguladıktan sonra, getenforce komutunu vererek SELinux'un aygıtta doğru modda çalıştığından emin olun.

Bu, global SELinux modunu yazdırır: Zorlayıcı veya İzinli. Her etki alanı için SELinux modunu belirlemek için, karşılık gelen dosyaları incelemeli veya sepolicy-analyze en son sürümünü /platform/system/sepolicy/tools/ içinde bulunan uygun ( -p ) işaretle çalıştırmalısınız.

inkar okuma

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 için SELinux çıktısını incelemeli ve izinli modda genel kullanıma sunulmadan ve nihai olarak zorlama moduna geçmeden önce ayarları düzeltmelidir. SELinux günlük mesajları avc: içerir ve bu nedenle grep ile kolayca bulunabilir. cat /proc/kmsg çalıştırarak devam eden ret günlüklerini yakalamak veya cat /sys/fs/pstore/console-ramoops çalıştırarak önceki önyüklemeden ret günlüklerini yakalamak mümkündür.

Bu çıktı ile üreticiler, sistem kullanıcılarının veya bileşenlerinin SELinux politikasını ne zaman ihlal ettiğini kolayca belirleyebilir. Üreticiler daha sonra bu kötü davranışı yazılımda, SELinux politikasında veya her ikisinde yapılan değişikliklerle onarabilir.

Spesifik olarak, bu günlük mesajları, zorlama modunda hangi işlemlerin başarısız olacağını ve nedenini belirtir. İş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. tclass ( unix_stream_socket ) ile birlikte, size ne için ne 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) size 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 bir netd .
  • Üstteki comm="ping" , reddin oluşturulduğu sırada nelerin yürütülmekte olduğu 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 temel unsurları:

  • Eylem - denenen eylem parantez içinde vurgulanır, read write veya setenforce .
  • Aktör - bağlam (kaynak bağlam) girişi, aktörü temsil eder, bu durumda scontext arka rmt_storage programı.
  • Nesne - tcontext (hedef bağlam) girişi, üzerinde işlem yapılan nesneyi temsil eder, bu durumda kmem.
  • Sonuç - tclass (hedef sınıf) girişi, üzerinde işlem yapılan nesnenin türünü, bu durumda bir chr_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ı saptamak için yeterli değildir. Reddetmenin neden oluştuğunu daha iyi anlamak için, çekirdek ve kullanıcı alanı dahil olmak üzere çağrı zincirini toplamak genellikle yararlıdır.

En 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 dalları ana hat ve android12-5.10 desteklenir. android12-5.4 dalı da desteklenir. İ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 seçim taahhütlerini kullanabilirsiniz.
  • Hata ayıkladığınız olayı yeniden oluşturmak mümkün olmalıdır. Önyükleme zamanı olayları simpleperf kullanılarak desteklenmez; ancak olayı tetiklemek için hizmeti yeniden başlatabilirsiniz.

Çağrı zincirini yakalama

İ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"

Daha sonra, reddine 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 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. İzi kullanıcı alanından, reddin gerçekleştiği çekirdeğe kadar başlatarak size kod akışının daha iyi bir görünümünü verir. Simpleperf hakkında daha fazla bilgi için simpleperf Executable komutları referansına bakın.

izin verene geçiş

SELinux zorlaması, 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 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 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 reddetmelerini alır ve bunları karşılık gelen SELinux ilke 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

Yine de, izinleri aşmak için her potansiyel eklemeyi incelemeye özen gösterilmelidir. Örneğin, daha önce gösterilen audit2allow reddini besleme rmt_storage aşağıdaki önerilen SELinux ilke bildiriminde 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. audit2allow ifadeleri genellikle sadece 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 ayrıca uygun makroları dahil etmeniz gerekebilir. Bazen incelenmekte olan ret, herhangi bir politika değişikliği ile sonuçlanmamalıdır; bunun yerine rahatsız edici uygulama değiştirilmelidir.