SELinux dan chroot system call

21

TL; DR: Ini adalah pertanyaan tentang langkah terakhir, dalam proses rooting portabel, yang berorientasi pada pengembang, yang bekerja di semua mesin Android. Itu bukan berdasarkan eksploitasi apa pun - itu adalah sesuatu yang secara hukum dan moral kita boleh lakukan, sebagai pengembang, ke mesin kita sendiri. Jika saya mendapatkan jawaban dan berhasil melakukan chroot di dalam Debian saya, saya akan membuat posting blog singkat yang merinci semua langkah dari proses ini untuk semua sesama pengembang yang ingin mengakses root ke tablet mereka - dan tidak ingin mempercayai asal yang meragukan. "one-click-root" yang melakukan yang Tuhan tahu-apa pada mesin mereka (anggota botnet?) ... Satu-satunya ketergantungan adalah sumber kernel mesin (yang secara hukum wajib diberikan oleh produsen) dan gambar partisi boot (boot.img), yang merupakan 99% dari waktu di dalam pembaruan Over-the-air yang disediakan pabrikan, atau dapat diunduh secara individu sebagai gambar yang dapat di-flash sendiri.

Jadi, seminggu berlalu di mana saya menghabiskan semua waktu luang saya di tablet Android baru saya.

Dan saya hampir sepenuhnya berhasil - dalam menciptakan proses portabel, yang berorientasi pada pengembang, untuk mencapai root di tablet Android 5.0.2 saya.

Tapi ada satu hal yang hilang - Saya tidak bisa melakukan chroot (yang saya perlukan untuk menjalankan debootstrapDebian -ed saya !)

Apa yang saya lakukan sejauh ini

  1. Pertama, saya melakukan patch kecil pada sumber-sumber kernel tablet saya (yang disediakan oleh produsen), dan kemudian mengkompilasi kernel saya sendiri - di mana saya menonaktifkan pemeriksaan untuk mengubah mode penegakan SELINUX . Secara khusus...

Dalam 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. Saya kemudian mengubah gambar initrd saya /default.propuntuk mengandung: ro.secure=0danro.debuggable=1

  2. Karena pabrikan saya initrd.imgmelewatkannya, saya juga mengkompilasi su.cdari https://android.googlesource.com/platform/system/extras/+/master/su/ dan menempatkan biner yang dihasilkan di bawah /sbin/su, memastikannya disetel ke root SUID ( chmod 04755 /sbin/su) .

Setelah itu, saya mengemas kernel baru dan initrd baru, seperti yang saya jelaskan di Episode 2 dari posting saya sebelumnya - dan boot dari gambar saya sendiri:

adb reboot boot-loader ; fastboot boot myboot.img

Jadi, apakah Anda root?

Ya, awalnya tampaknya berhasil:

$ 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

Dan sekarang saya telah mencapai 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

Saya 100% yakin saya root - bukan hanya karena idmengatakannya, tetapi karena saya juga bisa melakukan hal-hal yang proses normal pasti tidak bisa:

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)

Lihatlah, akhirnya aku bisa membaca partisi mentah dari tabletku!

Dan SELinux memang dalam mode "turun, anjing":

root@K01E_2:/ # getenforce                                                     
Permissive

Tapi ... masih ada hal-hal yang tidak bisa saya lakukan:

root@K01E_2:/ # mkdir /my_mnt

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

Yaitu, saya tidak bisa memasang partisi ke-2 EXT4-fs saya yang diformat dari kartu SD eksternal saya.

Saya juga tidak bisa melakukan chroot ke debootstrapDebian saya yang cantik :

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

Apakah karena SELinux?

Saya tidak tahu - Saya baru (sangat baru - berusia satu minggu) untuk SELinux. Saya berpikir bahwa ketika Anda menidurkannya ( getenforcemelaporkan "Permisif") itu tidak lagi mengganggu ...

Ternyata saya salah. Turun lubang kelinci kita pergi lagi ...

Mungkinkah karena konteks proses saya?

Ingat yang iddikembalikan ... "uid = 0 (root) gid = 0 (root) ... konteks = u: r: shell: s0 "

Bisakah saya mengubah konteks itu? Menjadi root dan semuanya, bisakah saya menjauh shell? Dan jika demikian, pindah ke apa?

Jawaban untuk pertanyaan pertama adalah 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

Baik. Tetapi konteks apa yang akan memungkinkan saya untuk mountdan chroot?

Membaca lebih banyak tentang SELinux, kembali ke mesin utama saya, saya mem-parsing /sepolicyfile pada root 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 ...
...

OKE, sejumlah kemungkinan! Terutama yang kerneltampaknya menjanjikan:

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

Menisik.

Siapa sih yang menghalangi saya dari chrooting?

Semua saran sangat disambut ...

ttsiodras
sumber

Jawaban:

12

Siapa sih yang menghalangi saya melakukan chroot?

Itu bukan SELinux - itu adalah pengejaran angsa liar ( getenforcemengembalikan "Permissive" berarti SELinux memang tidak lagi dalam gambar).

Pelakunya - setelah menambahkan cukup banyak printkdi sumber kernel untuk melacak kegagalan keduanya chrootdan mount- ternyata adalah kemampuan . Lebih khusus lagi, "batasan kemampuan" Android - Anda dapat membaca semua tentang mereka melalui man( man 7 capabilities) dan saya akui saya belum pernah repot-repot melihatnya - tugas UNIX sehari-hari saya bergantung padanya dan saya tidak tahu ... coba ini di kotak linux Anda untuk melihatnya sendiri:

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

Lihat? Ping bukan lagi SUID root - ia menggunakan informasi yang disimpan dalam atribut extended filesystem untuk mengetahui bahwa ia memiliki akses ke lapisan soket mentah (sehingga dapat melakukan hal ICMP - pada tingkat IP yang ada).

Ngomong-ngomong, saya ngelantur - titik operasi di kernel saya di mana saya menghentikan "jatuhkan kemampuan saya" - dengan cara yang bisa dibilang menjijikkan, "biarkan mereka semua berbaris dalam cara" - adalah ini ( 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;
}

Ini berarti bahwa kemampuannya TIDAK PERNAH turun - konfigurasi yang sangat aman, memang :-)

$ 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

Halo, Debianku yang manis :-)

Oh, dan "Root checker" juga berfungsi - saya memotong "su.c", sehingga semua orang di tablet saya bisa menjadi 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;
  //}

Sekarang ini berfungsi, saya harus membuatnya bekerja dengan benar - yaitu hanya mengizinkan saya termuxdan Terminal Emulatorpengguna untuk memohon sudan chroot, dan tidak membiarkan semua orang dan nenek mereka masuk :-)

ttsiodras
sumber
Bukankah metode root ini membutuhkan kemampuan untuk mem-flash kernel Anda sendiri? Dan untuk melakukan itu diperlukan bootloader yang tidak dikunci. Pada titik mana Anda mungkin juga mem-flash pemulihan kustom dan mendapatkan root dengan cara itu.
1110101001
@ 1110101001 Untuk bootloader: jelas, ya. Untuk pemulihan khusus: belum ada hal seperti itu untuk tablet saya - saya berada dalam posisi sekarang untuk membuatnya, meskipun ;-)
ttsiodras
1
@ 1110101001: Dan satu hal lagi - Anda mengatakan "kemampuan untuk flash" - Saya belum berkelebat boot image saya ke tablet, saya hanya boot dari itu: fastboot boot my.img. Saya percaya komunitas rooting menyebut ini rooting tertambat :-) Dan tentu saja saya bisa mem-flashnya - jika saya mau.
ttsiodras