SELinux e chroot system call


21

TL; DR: Questa è una domanda sul passaggio finale, in un processo di rooting portatile e orientato agli sviluppatori, che funziona su tutte le macchine Android. Non si basa su alcun exploit: è qualcosa che ci è consentito legalmente e moralmente, come sviluppatori, di utilizzare le nostre macchine. Se avrò una risposta e riuscirò a chroot all'interno del mio Debian, realizzerò un post conciso sul blog che descriverà dettagliatamente tutti i passaggi di questo processo per tutti i colleghi sviluppatori che desiderano accedere come root ai loro tablet - e non vogliono fidarsi dell'origine dubbia "root con un clic" che Dio sa-cosa-per le loro macchine (membri botnet?) ... Le uniche dipendenze saranno i sorgenti del kernel della macchina (che il produttore è legalmente obbligato a fornire) e l'immagine della partizione di avvio (boot.img), ovvero il 99% delle volte all'interno degli aggiornamenti over-the-air forniti dal produttore o scaricabili singolarmente come immagine autonoma con flash.

Quindi, è passata una settimana in cui ho trascorso tutto il mio tempo libero sul mio nuovo tablet Android.

E quasi ci sono riuscito - nella creazione di un processo portatile, orientato agli sviluppatori, per ottenere il root sul mio tablet Android 5.0.2.

Ma manca ancora una cosa: non posso fare un chroot (di cui ho bisogno per eseguire il mio debootstrapDebian!)

Quello che ho fatto finora

  1. Innanzitutto, ho fatto una piccola patch nei sorgenti del kernel del mio tablet (forniti dal produttore), quindi ho compilato il mio kernel, dove ho disabilitato i controlli per cambiare la modalità di esecuzione di SELINUX . In particolare ...

In security/selinux/selinuxfs.c:

...
if (new_value != selinux_enforcing) {
    /* Commented out by ttsiodras.
    length = task_has_security(current, SECURITY__SETENFORCE);
    if (length)
        goto out;
    */
    audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
        "enforcing=%d old_enforcing=%d auid=%u ses=%u",
        new_value, selinux_enforcing,
  1. Ho quindi modificato l'immagine della mia initrd /default.propper contenere: ro.secure=0ero.debuggable=1

  2. Poiché initrd.imgmancava il mio produttore , ho anche compilato su.cda https://android.googlesource.com/platform/system/extras/+/master/su/ e ho posizionato il binario risultante sotto /sbin/su, assicurandomi che sia impostato su SUID root ( chmod 04755 /sbin/su) .

Successivamente, ho creato il pacchetto del nuovo kernel e del nuovo initrd, come spiegato nell'episodio 2 del mio post precedente , e avviato dalla mia immagine:

adb reboot boot-loader ; fastboot boot myboot.img

Quindi, sei root?

Sì, inizialmente sembrava avere successo:

$ adb shell

shell@K01E_2:/ $ id

uid=2000(shell) gid=2000(shell) groups=1004(input),1007(log),1011(adb),
1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),
3003(inet),3006(net_bw_stats) 
context=u:r:shell:s0

shell@K01E_2:/ $ ls -l /sbin/su /sbin/_su
-rwxr-xr-x root     root          131 2015-10-03 10:44 su
-rwsr-xr-x root     root         9420 2015-10-03 01:31 _su

(the _su is the binary I compiled, set to SUID root, and "su" is
 a script I wrote to tell "su" to add me to all these groups...)

shell@K01E_2:/ $ cat /sbin/su

#!/system/bin/sh
export PATH=/system/bin:$PATH
exec /sbin/_su 0,0,1000,1028,2000,2001,1004,1007,1011,1015,\
   1028,3001,3002,3003,3006

E ora ho raggiunto il root:

shell@K01E_2:/ $ su

root@K01E_2:/ # id

uid=0(root) gid=0(root) 
groups=1000(system),1004(input),1007(log),1011(adb),
1015(sdcard_rw),1028(sdcard_r),1028(sdcard_r),2000(shell),2001(cache),
3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) 
context=u:r:shell:s0

Sono sicuro al 100% di essere root, non solo perché lo iddice, ma perché posso anche fare cose che i normali processi non possono assolutamente:

root@K01E_2:/ # ls -l /dev/block/platform/msm_sdcc.1/by-name/boot
lrwxrwxrwx root root 2015-10-03 10:47 boot -> /dev/block/mmcblk0p16

root@K01E_2:/ # dd if=/dev/block/mmcblk0p16 of=/dev/null bs=1M
16+0 records in
16+0 records out
16777216 bytes transferred in 0.569 secs (29485441 bytes/sec)

Ecco, finalmente riesco a leggere le partizioni grezze dal mio tablet!

E SELinux è davvero in modalità "down, dog":

root@K01E_2:/ # getenforce                                                     
Permissive

Ma ... ci sono ancora cose che non posso fare:

root@K01E_2:/ # mkdir /my_mnt

root@K01E_2:/ # mount -t ext4 /dev/block/mmcblk1p2 /my_mnt
mount: Operation not permitted

Cioè, non riesco a montare la mia seconda partizione formattata EXT4-fs della mia scheda SD esterna.

Inoltre non posso chroot con il mio adorabile debootstrapDebian:

root@K01E_2:/ # chroot /data/debian/ /bin/bash                             
chroot() fail
Operation not permitted

È a causa di SELinux?

Non lo so - sono nuovo (molto nuovo - una settimana fa) per SELinux. Ho pensato che quando lo mettevi a dormire ( getenforceriportando "Permissivo") non interferisce più ...

Apparentemente, mi sbagliavo. Scendiamo nella tana del coniglio ...

Potrebbe essere a causa del mio contesto di processo?

Ricorda che ha idrestituito ... "uid = 0 (root) gid = 0 (root) ... context = u: r: shell: s0 "

Posso cambiare quel contesto? Essendo root e tutto, posso allontanarmi da shell? E se è così, passare a cosa?

La risposta alla prima domanda è runcon:

shell@K01E_2:/ $ runcon u:r:debuggerd:s0 /sbin/su

root@K01E_2:/ # id
uid=0(root) gid=0(root)... context=u:r:debuggerd:s0

Buono. Ma quale contesto mi permetterà mounte chroot?

Leggendo qualcosa in più su SELinux, tornando alla mia macchina principale, analizzo il /sepolicyfile sulla radice di initrd.img:

linuxbox$ $ sesearch -A sepolicy | grep chroot
allow init_shell init_shell : capability { chown sys_chroot ...
allow init init : capability { chown dac_read_search sys_chroot ...
allow kernel kernel : capability { chown dac_override sys_chroot ... 
allow asus-dbug-d asus-dbug-d : capability { chown sys_chroot ...
...

OK, un numero di possibilità! Soprattutto quello che kernelsembra promettente:

shell@K01E_2:/ $ runcon u:r:kernel:s0 /sbin/su

root@K01E_2:/ # id
uid=0(root) gid=0(root)... context=u:r:kernel:s0

root@K01E_2:/ # chroot /data/debian/ /bin/bash                             
chroot() fail
Operation not permitted

Darn.

Chi diavolo mi sta impedendo di chrooting?

Qualche consiglio più gradito ...

Risposte:


12

Chi diavolo mi sta bloccando dal chrooting?

Non era SELinux - quello era un inseguimento di oca selvatica (il getenforceritorno di "Permissive" significa che SELinux non è più nella foto).

Il colpevole - dopo aver aggiunto parecchi printknel sorgente del kernel per rintracciare i fallimenti di entrambi chroote mount- si è rivelato essere capacità . Più specificamente, il "set di limiti di capacità" di Android - puoi leggere tutto su di loro tramite il tuo man( man 7 capabilities) e confesso che non mi sono mai preoccupato di esaminarli - le mie attività quotidiane di UNIX dipendevano da loro e non avevo idea ... provalo in la tua scatola di Linux per vedere di persona:

$ getfattr -d -m - /sbin/ping
getfattr: Removing leading '/' from absolute path names
# file: sbin/ping
security.capability=0s......

Vedere? Il ping non è più SUID root: utilizza le informazioni memorizzate negli attributi estesi del filesystem per sapere che ha accesso al layer socket grezzo (quindi può fare ciò che è ICMP - a livello IP).

Ad ogni modo, sto divagando - il punto di intervento chirurgico nel mio kernel in cui ho fermato il "drop set di capacità" - in modo discutibilmente disgustoso, "lasciamo che tutti marciano in" maniera - era questo ( security/commoncap.c):

static long cap_prctl_drop(struct cred *new, unsigned long cap)
{
    if (!capable(CAP_SETPCAP))
        return -EPERM;
    if (!cap_valid(cap))
        return -EINVAL;

    // ttsiodras: come in, everyone, the water's fine!
    //cap_lower(new->cap_bset, cap);
    return 0;
}

Ciò significa che le funzionalità non vengono MAI abbandonate - una configurazione molto sicura, anzi :-)

$ adb shell

shell@K01E_2:/ $ su

root@K01E_2:/ # chroot /data/debian/ /bin/bash

root@localhost:/# export PATH=/bin:/sbin:/usr/bin:/usr/sbin:\
     /usr/local/bin:$PATH

root@localhost:/# cat /etc/issue
Debian GNU/Linux 8 \n \l

Ciao dolce Debian :-)

Oh, e anche "Root checker" funziona - ho scattato "su.c", quindi tutti nel mio tablet possono diventare root:

int main(int argc, char **argv)
{
  struct passwd *pw;
  uid_t uid, myuid;
  gid_t gid, gids[50];

  /* Until we have something better, only root and shell can use su. */
  myuid = getuid();
  //
  // ttsiodras - Oh no, you don't :-)
  //
  //if (myuid != AID_ROOT && myuid != AID_SHELL) {
  //    fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
  //    return 1;
  //}

Ora che funziona, devo farlo funzionare correttamente, vale a dire consentire solo a me termuxe Terminal Emulatoragli utenti di invocare sue chroot, e non far entrare tutti e la nonna :-)


Questo metodo di root non richiede la possibilità di eseguire il flashing del proprio kernel? E per farlo richiede un bootloader sbloccato. A quel punto puoi anche eseguire il flashing di un ripristino personalizzato e ottenere il root in quel modo.
1110101001,

@ 1110101001 Per il bootloader: ovviamente sì. Per il recupero personalizzato: non esiste (ancora) una cosa del genere per il mio tablet - Ora sono in grado di crearne uno ;-)
ttsiodras

1
@ 1110101001: E un'altra cosa - lei ha detto "capacità di flash" - non ho balenò la mia immagine di avvio alla tavoletta, io sono solo l'avvio da esso: fastboot boot my.img. Credo che la comunità del rooting lo definisca un rooting vincolato :-) E ovviamente potrei mostrarlo, se lo volessi.
ttsiodras,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.