TL; DR: Esta es una pregunta sobre el paso final, en un proceso de rooting portátil, orientado a los desarrolladores, que funciona en todas las máquinas Android. No se basa en ningún exploit - es algo que se nos permite hacer legal y moralmente, como desarrolladores, a nuestras propias máquinas. Si obtengo una respuesta y consigo hacer chroot dentro de mi Debian, haré una entrada de blog concisa detallando todos los pasos de este proceso para todos los compañeros desarrolladores que quieran acceso Root a sus tabletas - y no quieran confiar en "one-click-roots" de dudoso origen que hacen Dios sabe qué a sus máquinas (¿miembros de botnets?)... Las únicas dependencias serán las fuentes del kernel de la máquina (que el fabricante está legalmente obligado a proporcionar) y la imagen de la partición de arranque ( boot.img
), que el 99% de las veces se encuentra dentro de las actualizaciones Over-the-air proporcionadas por el fabricante, o se puede descargar individualmente como una imagen independiente que se puede flashear.
Así, pasó una semana en la que pasé todo mi tiempo libre en mi nueva tablet Android.
Y lo he conseguido casi por completo: crear un proceso portátil, orientado a los desarrolladores, para conseguir el Root en mi tablet Android 5.0.2.
Pero aún falta una cosa: no puedo hacer un chroot (que necesito para ejecutar mi debootstrap
-ed Debian!)
Lo que he hecho hasta ahora
- Primero, hice un parche menor en las fuentes del kernel de mi tablet (proporcionadas por el fabricante), y luego compilé mi propio kernel - donde deshabilité las comprobaciones para cambiar Modo de aplicación de SELINUX . En concreto...
En 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,
-
Luego cambié la imagen de mi initrd
/default.prop
para contener:ro.secure=0
yro.debuggable=1
-
Desde que mi fabricante
initrd.img
se lo perdió, también compilésu.c
de https://Android.googlesource.com/platform/system/extras/+/master/su/ y colocamos el binario resultante en/sbin/su
asegurándose de que está configurado como SUID Root (chmod 04755 /sbin/su
).
Después de eso, empaqué el nuevo kernel y el nuevo initrd, como expliqué en el episodio 2 de mi post anterior - y arrancado de mi propia imagen:
adb reboot boot-loader ; fastboot boot myboot.img
Entonces, ¿eres Root?
Sí, inicialmente parecía tener éxito:
$ 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
Y ahora he conseguido 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
Estoy 100% seguro de que soy Root - no sólo porque id
lo dice, sino porque también puedo hacer cosas que los procesos normales definitivamente no pueden:
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)
He aquí que por fin puedo leer las particiones en bruto de mi tablet.
Y SELinux está, efectivamente, en modo "abajo, perro":
root@K01E_2:/ # getenforce
Permissive
Pero... hay todavía cosas que no puedo hacer:
root@K01E_2:/ # mkdir /my_mnt
root@K01E_2:/ # mount -t ext4 /dev/block/mmcblk1p2 /my_mnt
mount: Operation not permitted
Es decir, no puedo montar mi 2ª partición formateada en EXT4-fs de mi tarjeta SD externa.
También no puedo chroot a mi encantadora debootstrap
-ed Debian:
root@K01E_2:/ # chroot /data/debian/ /bin/bash
chroot() fail
Operation not permitted
¿Es por culpa de SELinux?
No sé - soy nuevo (muy nuevo - una semana) en SELinux. Pensé que cuando se pone a dormir ( getenforce
reportando "Permiso") ya no interfiere...
Aparentemente, estaba equivocado. Bajando por la madriguera del conejo vamos de nuevo...
¿Podría ser por el contexto de mi proceso?
Recuerda que id
devuelve... "uid=0(Root) gid=0(Root)... context=u:r:shell:s0 "
¿Puedo cambiar ese contexto? Siendo Root y todo eso, ¿puedo alejarme de shell
? Y si es así, ¿a qué se traslada?
La respuesta a la primera pregunta es 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
Bien. Pero qué contexto me permitirá mount
y chroot
?
Leyendo un poco más sobre SELinux, de vuelta en mi máquina principal, analizo el /sepolicy
en root del 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 ...
...
Vale, ¡una serie de posibilidades! Especialmente que kernel
uno parece prometedor:
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
Maldita sea.
¿Quién diablos me está bloqueando chroot
¿?
Cualquier consejo será bienvenido...