SELinux- und Chroot-Systemaufruf

21

TL; DR: Dies ist eine Frage zum letzten Schritt eines portablen, entwicklerorientierten Root-Prozesses, der auf allen Android-Computern funktioniert. Es basiert nicht auf einem Exploit - es ist etwas, das wir als Entwickler legal und moralisch mit unseren eigenen Maschinen machen dürfen. Wenn ich eine Antwort bekomme und es schaffe, in meinem Debian-System zu chrooten, werde ich einen kurzen Blog-Beitrag verfassen, in dem alle Schritte dieses Prozesses für alle anderen Entwickler aufgeführt sind, die Root-Zugriff auf ihre Tablets wünschen - und nicht auf zweifelhaften Ursprung vertrauen möchten "One-Click-Roots", die Gott-weiß-was für ihre Maschinen tun (Botnet-Mitglieder?) ... Die einzigen Abhängigkeiten sind die Kernel-Quellen der Maschine (zu deren Bereitstellung der Hersteller gesetzlich verpflichtet ist) und das Boot-Partitions-Image (boot.img), der zu 99% in den vom Hersteller bereitgestellten Over-the-Air-Updates enthalten ist oder als eigenständiges, flashfähiges Image einzeln 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 portablen, entwicklerorientierten Prozess zu erstellen, um auf meinem Android 5.0.2-Tablet root zu werden.

Aber eines fehlt noch - ich kann kein chroot ausführen (was ich brauche, um mein debootstrap-ed Debian auszuführen !)

Was ich bisher gemacht habe

  1. Zuerst habe ich einen kleinen Patch in den (vom Hersteller bereitgestellten) Kernel-Quellen meines Tablets durchgeführt und dann meinen eigenen Kernel kompiliert. Dabei habe ich die Überprüfungen zum Ändern des SELINUX-Erzwingungsmodus deaktiviert . Speziell...

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. Ich änderte dann meine initrd Bilder, um /default.propzu enthalten: ro.secure=0undro.debuggable=1

  2. Da es bei meinem Hersteller initrd.imgfehlte, habe ich es auch su.cvon https://android.googlesource.com/platform/system/extras/+/master/su/ kompiliert und die resultierende Binärdatei darunter platziert /sbin/su, um sicherzustellen, dass sie auf SUID root ( chmod 04755 /sbin/su) gesetzt ist. .

Danach habe ich den neuen Kernel und die neue initrd gepackt, wie ich 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 Wurzel 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 id, weil ich das sage, sondern auch, weil ich 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 - ich kann endlich rohe Partitionen von meinem Tablet lesen!

Und SELinux befindet sich 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 mit EXT4-fs formatierte zweite Partition meiner externen SD-Karte nicht mounten.

Ich kann auch nicht zu meinem liebenswürdigen debootstrapDebian 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 ( getenforce"Permissive" melden), stört es nicht mehr ...

Anscheinend habe ich mich geirrt. Das Kaninchenloch runter gehen wir wieder ...

Könnte es an meinem Prozesskontext liegen?

Denken Sie daran, dass idzurückgegeben ... "uid = 0 (root) gid = 0 (root) ... context = u: r: shell: s0 "

Kann ich diesen Kontext ändern? Kann ich mich als Root davon entfernen shell? Und wenn ja, wohin?

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 wird es mir ermöglichen mountund chroot?

Wenn ich etwas mehr über SELinux lese, analysiere ich die /sepolicyDatei auf meinem Hauptcomputer 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, eine Reihe von Möglichkeiten! Besonders das kernelscheint vielversprechend:

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

Verdammt.

Wer zum Teufel hindert mich daran chroot?

Ratschläge herzlich willkommen ...

ttsiodras
quelle

Antworten:

12

Wer zum Teufel hindert mich daran zu chrooten?

Es war nicht SELinux - das war eine wilde Gänsejagd ( getenforce"Permissive" bedeutet, dass SELinux tatsächlich nicht mehr auf dem Bild ist).

Der Täter - nach der Zugabe eine ganze Reihe von printkin der Quelle des Kernels die Fehler von beiden zu verfolgen chrootund mount- erwies sich als Fähigkeiten . Genauer gesagt, das "Capability Bounding Set" von Android - Sie können alles über Ihr man( man 7 capabilities) lesen, und ich gestehe, ich habe mich noch nie darum gekümmert - meine täglichen UNIX-Aufgaben hingen von ihnen ab und ich hatte keine Ahnung ... probieren Sie es aus Ihre Linux-Box, um selbst zu sehen:

$ 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 ICMP-fähig ist - auf der IP-Ebene also).

Wie auch immer, ich schweife ab - der Operationspunkt in meinem Kernel, an dem ich das "Drop my Capabilities Set" gestoppt habe - auf eine wohl widerliche Art und Weise, "Lass sie alle marschieren" - 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;
}

Dies bedeutet, dass die Funktionen NIEMALS verloren gehen - 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üßes Debian :-)

Oh, und "Root checker" funktioniert auch - ich habe "su.c" abgeschnitten, 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;
  //}

Nun , da es funktioniert, muss ich es richtig funktioniert - also erlauben nur meine termuxund Terminal EmulatorBenutzer aufrufen suund chroot, und nicht zulassen , jeder und ihre Großmutter in :-)

ttsiodras
quelle
Erfordert diese Root-Methode nicht die Fähigkeit, Ihren eigenen Kernel zu flashen? Und dazu benötigen Sie einen nicht gesperrten Bootloader. An diesem Punkt können Sie auch einfach eine benutzerdefinierte Wiederherstellung durchführen und auf diese Weise Wurzel schlagen.
1110101001
@ 1110101001 Für den Bootloader: natürlich ja. Für die benutzerdefinierte Wiederherstellung: Für mein Tablet gibt es (noch) keine solche Funktion - ich bin jedoch jetzt in der Lage, eine zu erstellen
;-)
1
@ 1110101001: Und noch eine Sache - sagte Sie „ability to flash“ - Ich habe mein Boot - Image nicht auf die Tablette geflasht, ich es nur am Booten: fastboot boot my.img. Ich glaube, die Rooting-Community nennt dies ein angebundenes Rooting :-) Und natürlich könnte ich es flashen - wenn ich wollte.
Ttsiodras