TL; DR: Dies ist eine Frage zum letzten Schritt in einem tragbaren, entwicklerorientierten Rooting-Prozess, der auf allen Android-Geräten funktioniert. Es basiert nicht auf einem Exploit – es ist etwas, was wir als Entwickler rechtlich und moralisch auf unseren eigenen Maschinen tun dürfen. Wenn ich eine Antwort erhalte und es schaffe, in meinem Debian zu chrooten, werde ich einen prägnanten Blog-Beitrag erstellen, der alle Schritte dieses Prozesses für alle anderen Entwickler aufführt, die Root-Zugriff auf ihre Tablets wünschen - und nicht auf zweifelhafte Herkunft vertrauen wollen "Ein-Klick-Roots", die Gott-weiß-was mit ihren Maschinen machen (Botnet-Mitglieder?) ... Die einzigen Abhängigkeiten sind die Kernelquellen der Maschine (zu deren Bereitstellung der Hersteller gesetzlich verpflichtet ist) und das Boot-Partitions-Image (boot.img
), das zu 99 % in den vom Hersteller bereitgestellten Over-the-Air-Updates enthalten ist oder einzeln als eigenständiges Flash-fähiges Image heruntergeladen werden kann.
So verging eine Woche, in der ich meine gesamte Freizeit auf meinem neuen Android-Tablet verbrachte.
Und es ist mir fast vollständig gelungen, einen tragbaren, entwicklerorientierten Prozess zu erstellen, um Root in meinem Android 5.0.2-Tablet zu erreichen.
Aber eine Sache fehlt noch – ich kann keine Chroot erstellen (die ich brauche, um mein debootstrap
-ed Debian auszuführen!)
Was ich bisher gemacht habe
Im 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,
Ich habe dann meine initrd-Images so geändert, dass sie Folgendes /default.prop
enthalten: ro.secure=0
undro.debuggable=1
Da es bei meinem Hersteller initrd.img
fehlte, habe ich auch su.c
von https://android.googlesource.com/platform/system/extras/+/master/su/ kompiliert und die resultierende Binärdatei unter platziert /sbin/su
, wobei ich darauf geachtet habe, dass sie auf SUID root ( chmod 04755 /sbin/su
) gesetzt ist. .
Danach habe ich den neuen Kernel und die neue initrd gepackt, wie ich es in Episode 2 meines vorherigen Posts erklärt habe - und von meinem eigenen Image gebootet:
adb reboot boot-loader ; fastboot boot myboot.img
Also bist du root?
Ja, es schien zunächst erfolgreich zu sein:
$ 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
Und ich habe jetzt root erreicht:
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
Ich bin mir zu 100% sicher, dass ich root bin - nicht nur, weil id
es so steht, sondern weil ich auch Dinge tun kann, die normale Prozesse definitiv nicht können:
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)
Und siehe da – endlich kann ich Raw-Partitionen aus meinem Tablet auslesen!
Und SELinux ist tatsächlich im "down, dog"-Modus:
root@K01E_2:/ # getenforce
Permissive
Aber ... es gibt immer noch Dinge, die ich nicht tun kann:
root@K01E_2:/ # mkdir /my_mnt
root@K01E_2:/ # mount -t ext4 /dev/block/mmcblk1p2 /my_mnt
mount: Operation not permitted
Das heißt, ich kann meine EXT4-fs-formatierte zweite Partition meiner externen SD-Karte nicht mounten.
Ich kann auch nicht zu meinem schönen debootstrap
-ed Debian chrooten:
root@K01E_2:/ # chroot /data/debian/ /bin/bash
chroot() fail
Operation not permitted
Liegt es an SELinux?
Ich weiß nicht - ich bin neu (sehr neu - eine Woche alt) bei SELinux. Ich dachte, wenn Sie es in den Ruhezustand versetzen (mit getenforce
"Permissive" melden), stört es nicht mehr ...
Anscheinend lag ich falsch. Wir gehen wieder in den Kaninchenbau ...
Könnte es an meinem Prozesskontext liegen?
Denken Sie daran, dass id
zurückgegeben wurde ... "uid=0(root) gid=0(root)... context=u:r:shell:s0 "
Kann ich diesen Kontext ändern? Kann ich mich als Root und so von wegbewegen shell
? Und wenn ja, wozu wechseln?
Die Antwort auf die erste Frage lautet 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
Gut. Aber welcher Kontext erlaubt es mir, mount
und chroot
?
Wenn ich etwas mehr über SELinux lese, analysiere ich auf meinem Hauptcomputer die /sepolicy
Datei im Stammverzeichnis von 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, mehrere Möglichkeiten! Besonders das kernel
scheint vielversprechend zu sein:
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
Verflixt.
Wer zum Teufel hindert mich daran chroot
?
Jeder Ratschlag ist willkommen...
Wer zum Teufel hindert mich am Chrooten?
Es war nicht SELinux - das war eine wilde Gänsejagd ( getenforce
die Rückkehr von "Permissive" bedeutet, dass SELinux tatsächlich nicht mehr im Bild ist).
Der Übeltäter – nach dem Hinzufügen einer ganzen Reihe von in den Kernel-Quellen, um die Fehler von beiden und printk
nachzuvollziehen – stellte sich als Capabilities heraus . Genauer gesagt, das "Capability Bounding Set" von Android - Sie können alles über Ihr ( ) lesen und ich gestehe, ich habe mich noch nie damit beschäftigt - meine alltäglichen UNIX-Aufgaben hingen davon ab und ich hatte keine Ahnung ... probieren Sie es aus Ihre Linux-Box, um es selbst zu sehen:chroot
mount
man
man 7 capabilities
$ getfattr -d -m - /sbin/ping
getfattr: Removing leading '/' from absolute path names
# file: sbin/ping
security.capability=0s......
Sehen? Ping ist nicht länger SUID-Root - es verwendet Informationen , die in den erweiterten Attributen des Dateisystems gespeichert sind, um zu wissen, dass es Zugriff auf die Raw-Sockets-Schicht hat (damit es seine ICMP-Sache ausführen kann - also auf IP-Ebene).
Wie auch immer, ich schweife ab – der Operationspunkt in meinem Kernel, an dem ich das „Drop My Capabilities Set“ gestoppt habe – in einer wohl ekelhaften „Lasst sie alle einmarschieren“-Manier – war dies ( 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;
}
Das bedeutet, dass Fähigkeiten NIEMALS verloren gehen - in der Tat eine sehr sichere Konfiguration :-)
$ 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
Hallo, mein süßer Debian :-)
Oh, und "Root checker" funktioniert auch - ich habe "su.c" ausgeschnitten, damit jeder in meinem Tablet root werden kann:
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;
//}
Jetzt, wo es funktioniert, muss ich dafür sorgen, dass es richtig funktioniert - dh nur meinen termux
und Terminal Emulator
Benutzern erlauben, und aufzurufen su
, chroot
und nicht alle und ihre Großmutter hereinzulassen :-)
1110101001
tsiodras
tsiodras
fastboot boot my.img
. Ich glaube, die Rooting-Community nennt das ein Tethering -Rooting :-) Und natürlich könnte ich es flashen - wenn ich wollte.