TL; DR: Esta es una pregunta sobre el paso final, en un proceso de enraizamiento portátil y orientado al desarrollador, que funciona en todas las máquinas Android. No se basa en ningún exploit: es algo que, como desarrolladores, estamos legal y moralmente autorizados a hacer con nuestras propias máquinas. Si obtengo una respuesta y me las arreglo para hacer chroot dentro de mi Debian, haré una publicación de blog concisa que detallará todos los pasos de este proceso para todos los compañeros desarrolladores que quieren acceso de root a sus tabletas, y no quieren confiar en el origen dudoso. "raíces de un clic" que hacen Dios sabe qué a sus máquinas (¿miembros de botnet?)... 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 está el 99 % de las veces dentro de las actualizaciones inalámbricas proporcionadas por el fabricante, o se puede descargar individualmente como una imagen flash independiente.
Entonces, pasó una semana en la que pasé todo mi tiempo libre en mi nueva tableta Android.
Y lo he logrado casi por completo: crear un proceso portátil orientado al desarrollador para lograr la raíz en mi tableta Android 5.0.2.
Pero todavía falta una cosa: no puedo hacer un chroot (¡que necesito para ejecutar mi debootstrap
-ed Debian!)
lo que hice hasta ahora
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é mi imagen initrd /default.prop
para contener: ro.secure=0
yro.debuggable=1
Como a mi fabricante initrd.img
le faltaba, también compilé su.c
desde https://android.googlesource.com/platform/system/extras/+/master/su/ y coloqué el binario resultante en /sbin/su
, asegurándome de que esté configurado como raíz SUID ( chmod 04755 /sbin/su
) .
Después de eso, empaqueté el nuevo kernel y el nuevo initrd, como expliqué en el Episodio 2 de mi publicación anterior , y arranqué desde mi propia imagen:
adb reboot boot-loader ; fastboot boot myboot.img
Entonces, ¿eres root?
Sí, inicialmente pareció 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 logrado la raíz:
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 solo 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 finalmente puedo leer particiones en bruto de mi tableta.
Y SELinux está de hecho en modo "abajo, perro":
root@K01E_2:/ # getenforce
Permissive
Pero... todavía hay 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 segunda partición con formato EXT4-fs de mi tarjeta SD externa.
Tampoco puedo hacer chroot en mi encantador debootstrap
-ed Debian:
root@K01E_2:/ # chroot /data/debian/ /bin/bash
chroot() fail
Operation not permitted
¿Es por SELinux?
No sé, soy nuevo (muy nuevo, una semana) en SELinux. Pensé que cuando lo pones a dormir ( getenforce
reportando "Permisivo") ya no interfiere...
Aparentemente, estaba equivocado. Por la madriguera del conejo vamos de nuevo...
¿Podría ser debido al contexto de mi proceso?
Recuerde que id
devolvió... "uid=0(root) gid=0(root)... context=u:r:shell:s0 "
¿Puedo cambiar ese contexto? Siendo root y todo, ¿puedo alejarme de shell
? Y si es así, ¿mover a qué?
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á hacer mount
y chroot
?
Leyendo un poco más sobre SELinux, de vuelta en mi máquina principal, analizo el /sepolicy
archivo en la raíz de 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 número de posibilidades! Especialmente ese kernel
que 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
Maldito.
¿Quién diablos me está bloqueando de chroot
ing?
Cualquier consejo bienvenido...
¿Quién diablos me está impidiendo hacer chroot?
No fue SELinux, fue una persecución inútil ( getenforce
devolver "Permisivo" significa que SELinux ya no está en la imagen).
El culpable, después de agregar un buen número de printk
código fuente del kernel para rastrear las fallas de ambos chroot
, mount
resultó ser las capacidades . Más específicamente, el "conjunto de límites de capacidad" de Android: puede leer todo sobre ellos a través de su man
( man 7 capabilities
) y confieso que nunca antes me había molestado en investigarlos: mis tareas diarias de UNIX dependían de ellos y no tenía ni idea ... intente esto en su caja de linux para ver por sí mismo:
$ getfattr -d -m - /sbin/ping
getfattr: Removing leading '/' from absolute path names
# file: sbin/ping
security.capability=0s......
¿Ver? Ping ya no es raíz SUID: utiliza información almacenada en los atributos extendidos del sistema de archivos para saber que tiene acceso a la capa de sockets sin procesar (para que pueda hacer lo que hace ICMP, en el nivel de IP).
De todos modos, me estoy desviando: el punto de cirugía en mi kernel donde detuve el "conjunto de soltar mis capacidades" - de una manera posiblemente repugnante, "dejemos que todos marchen" - fue esto ( 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;
}
Esto significa que las capacidades NUNCA se eliminan; una configuración muy segura, de hecho :-)
$ 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
Hola, mi dulce Debian :-)
Ah, y "Root checker" también funciona: corté "su.c", para que todos en mi tableta puedan convertirse en 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;
//}
Ahora que funciona, debo hacer que funcione correctamente, es decir, permitir que solo mis usuarios termux
y yo invoquemos y , y no dejar entrar a todos ni a su abuela :-)Terminal Emulator
su
chroot
1110101001
ttsiodras
ttsiodras
fastboot boot my.img
. Creo que la comunidad de enraizamiento llama a esto un enraizamiento atado :-) Y, por supuesto, podría flashearlo, si quisiera.