Convalida SELinux

Android consiglia vivamente agli OEM di testare attentamente le loro implementazioni di SELinux. Quando i produttori implementano SELinux, devono applicare il nuovo a un pool di dispositivi di test.

Dopo aver applicato un nuovo criterio, assicurati che SELinux sia in esecuzione nella modalità corretta sul dispositivo emettendo il comando getenforce.

Viene stampata la modalità SELinux globale: Enforcing o Permissive (Applicabile). Per determinare la modalità SELinux per ogni dominio, devi esaminare i file corrispondenti o eseguire la versione più recente di sepolicy-analyze con il flag (-p) appropriato, presente in /platform/system/sepolicy/tools/.

Leggi rifiuti

Verifica la presenza di errori, che vengono indirizzati come log eventi a dmesg e logcat e sono visualizzabili localmente sul dispositivo. I produttori devono esaminare l'output di SELinux su dmesg su questi dispositivi e perfezionare le impostazioni prima del rilascio pubblico in modalità permissiva ed eventualmente passare alla modalità di applicazione. I messaggi di log di SELinux contengono avc: e quindi potrebbero può essere trovata facilmente con grep. È possibile acquisire l'andamento denial log eseguendo cat /proc/kmsg o acquisisci i log di rifiuto. dall'avvio precedente eseguendo cat /sys/fs/pstore/console-ramoops.

I messaggi di errore SELinux hanno una frequenza limitata dopo il completamento dell'avvio per evitare lo swamping nei log. Per assicurarti di vedere tutti i messaggi pertinenti, puoi disattivare questa opzione eseguendo adb shell auditctl -r 0.

Con questo output, i produttori possono identificare facilmente quando gli utenti del sistema violano il criterio SELinux. I produttori possono quindi correggere questo comportamento scorretto modificando il software, le norme SELinux o entrambi.

In particolare, questi messaggi di log indicano i processi che potrebbero avere esito negativo di applicazione forzata e perché. Ecco un esempio:

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

Interpreta questo output nel seguente modo:

  • Il valore { connectto } riportato sopra rappresenta l'azione intrapresa. Insieme al tclass alla fine (unix_stream_socket), indica approssimativamente cosa è stato fatto a cosa. In questo caso, qualcosa stava tentando di connettersi a una socket stream Unix.
  • scontext (u:r:shell:s0) indica il contesto che ha avviato l'azione. In questo caso, si tratta di un programma in esecuzione come shell.
  • tcontext (u:r:netd:s0) indica il contesto del target dell'azione. In questo caso, si tratta di un unix_stream_socket di proprietà di netd.
  • Il simbolo comm="ping" in alto fornisce un ulteriore suggerimento su cosa veniva eseguito al momento della generazione del rifiuto. In questo caso, è un suggerimento piuttosto buono.

Un altro esempio:

adb shell su root dmesg | grep 'avc: '

Uscita:

<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

Ecco gli elementi chiave di questo rifiuto:

  • Azione: l'azione tentata è evidenziata tra parentesi, read write o setenforce.
  • Attore: la voce scontext (contesto di origine) rappresenta l'attore, in questo caso il daemon rmt_storage.
  • Oggetto: la voce tcontext (contesto di destinazione) rappresenta l'oggetto su cui viene eseguito l'intervento, in questo caso kmem.
  • Risultato: la voce tclass (classe di destinazione) indica il tipo di oggetto su cui viene eseguito l'intervento, in questo caso un chr_file (dispositivo di caratteri).

Esegui il dump degli stack utente e del kernel

In alcuni casi, le informazioni contenute nel log eventi non sono sufficienti per individuare la provenienza del rifiuto. Spesso è utile raccogliere la catena di chiamate, inclusi kernel e per comprendere meglio perché il rifiuto è avvenuto.

I kernel recenti definiscono un tracepoint denominato avc:selinux_audited. Usa Android simpleperf per abilitare questo tracepoint e acquisire la callchain.

Configurazione supportata

  • Kernel Linux >= 5.10, in particolare rami del kernel Linux comune principale e Android12-5.10 sono supportati. L'app android12-5.4 è supportato anche il ramo. Puoi utilizzare simpleperf per determinare se il tracepoint è definiti sul tuo dispositivo: adb root && adb shell simpleperf list | grep avc:selinux_audited. Per altre versioni del kernel, puoi scegliere i commit dd81662 e 30969bc.
  • Dovrebbe essere possibile riprodurre l'evento in cui stai eseguendo il debug. Gli eventi al momento di avvio non sono supportato usando simpleperf; ma potresti comunque riuscire a riavviare il servizio per attivare l'evento.

Acquisire la catena di chiamate

Il primo passaggio consiste nel registrare l'evento utilizzando simpleperf record:

adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"

Quindi dovrebbe essere attivato l'evento che ha causato il rifiuto. Dopodiché, la registrazione l'arresto anomalo. In questo esempio, utilizzando Ctrl-c, il campione dovrebbe essere stato acquisito:

^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.

Infine, è possibile utilizzare simpleperf report per ispezionare lo stacktrace acquisito. Ad esempio:

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

La catena di chiamate riportata sopra è una catena unificata di chiamate kernel e spazio utente. Ti offre una migliore visualizzazione del flusso di codice avviando la traccia dallo spazio utente fino al kernel dove avviene il rifiuto. Per ulteriori informazioni su simpleperf, consulta Riferimento per i comandi SimplePerf Executable

Passare a modalità permissiva

L'applicazione di SELinux può essere disattivata con adb nelle build userdebug o eng. Per farlo, innanzitutto passa ad ADB come utente root eseguendo adb root. Quindi, per disattivare SELinux applicazione forzata, esegui:

adb shell setenforce 0

Oppure dalla riga di comando del kernel (durante il lancio anticipato del dispositivo):

androidboot.selinux=permissive
androidboot.selinux=enforcing

In alternativa, tramite bootconfig in Android 12:

androidboot.selinux=permissive
androidboot.selinux=enforcing

Utilizzare audit2allow

Lo strumento audit2allow prende i rifiuti dmesg e li converte in istruzioni del criterio SELinux corrispondenti. Di conseguenza, può accelerare notevolmente lo sviluppo di SELinux.

Per utilizzarlo, esegui:

adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy

Tuttavia, è necessario esaminare attentamente ogni potenziale aggiunta per verificare che non siano presenti autorizzazioni eccessive. Ad esempio, se fornisci a audit2allow il divieto rmt_storage mostrato in precedenza, il risultato è la seguente istruzione del criterio SELinux suggerita:

#============= shell ==============
allow shell kernel:security setenforce;
#============= rmt ==============
allow rmt kmem_device:chr_file { read write };

Questo concede a rmt la possibilità di scrivere la memoria del kernel, buca di sicurezza sgargiante. Spesso le istruzioni audit2allow sono solo un punto di partenza. Dopo aver utilizzato queste istruzioni, potrebbe essere necessario modificare il dominio di origine e l'etichetta del target, nonché incorporare le macro appropriate per ottenere un criterio valido. A volte il rifiuto in esame non comportino alcuna modifica alle norme; ma l'app in questione modifiche.