SELinux и системный вызов chroot

21

TL; Д.Р .: Это вопрос о последнем шаге в переносимом, ориентированном на разработчика процессе рутирования, который работает на всех машинах Android. Он не основан на каком-либо подвиге - это то, что нам, как разработчикам, разрешено делать юридически и морально на наших собственных машинах. Если я получу ответ и смогу выполнить chroot внутри своего Debian, я сделаю краткое сообщение в блоге с подробным описанием всех этапов этого процесса для всех коллег-разработчиков, которые хотят получить root-доступ к своим планшетам - и не хотят доверять сомнительному происхождению «корни в один клик», которые, как Бог знает, для своих машин (участников ботнета?) ... Единственными зависимостями будут источники ядра машины (которые юридически обязаны предоставлять производители) и образ загрузочного раздела (boot.img), что составляет 99% времени в предоставленных производителем беспроводных обновлениях, или может быть отдельно загружено как отдельное изображение с возможностью прошивки.

Итак, прошла неделя, когда я проводил все свободное время на своем новом планшете Android.

И я почти полностью преуспел - в создании портативного, ориентированного на разработчика процесса для получения root в моем планшете Android 5.0.2.

Но пока не хватает одной вещи - я не могу сделать chroot (который мне нужен для запуска моего debootstrap-ed Debian!)

Что я сделал до сих пор

  1. Сначала я сделал небольшое исправление в исходных текстах ядра моего планшета (предоставленных производителем), а затем скомпилировал свое собственное ядро, где отключил проверки для изменения режима принудительного применения SELINUX . В частности ...

В 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. Затем я изменил мое Initrd изображение это /default.propсодержать: ro.secure=0иro.debuggable=1

  2. Так как у моего производителя его не initrd.imgбыло, я также скомпилировал su.cпо адресу https://android.googlesource.com/platform/system/extras/+/master/su/ и поместил полученный бинарный файл в папку /sbin/su, убедившись, что он установлен в SUID root ( chmod 04755 /sbin/su) ,

После этого я упаковал новое ядро ​​и новый initrd, как я объяснил в Эпизоде ​​2 моего предыдущего поста, и загрузился с собственного образа:

adb reboot boot-loader ; fastboot boot myboot.img

Итак, вы рут?

Да, изначально он оказался успешным:

$ 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

И я теперь достиг 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

Я на 100% уверен, что являюсь пользователем root - не только потому, idчто так сказано, но и потому, что я могу делать то, что обычные процессы не могут:

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)

И вот, наконец, я могу читать сырые разделы из своего планшета!

И SELinux действительно находится в режиме «вниз, собака»:

root@K01E_2:/ # getenforce                                                     
Permissive

Но ... есть еще вещи, которые я не могу сделать:

root@K01E_2:/ # mkdir /my_mnt

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

То есть я не могу смонтировать отформатированный в EXT4-fs 2-й раздел моей внешней SD-карты.

Я также не могу получить доступ к моему debootstrapлюбимому Debian:

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

Это из-за SELinux?

Я не знаю - я новичок (очень новый - одна неделя) в SELinux. Я думал, что когда вы усыпляете его ( getenforceсообщая "Permissive"), это больше не мешает ...

Видимо, я был не прав. Вниз по кроличьей норе мы снова идем ...

Может ли это быть из-за моего контекста процесса?

Помните, что idвозвращено ... "uid = 0 (root) gid = 0 (root) ... context = u: r: shell: s0 "

Могу ли я изменить этот контекст? Будучи root и все, я могу отойти от shell? И если так, переходите к чему?

Ответ на первый вопрос 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

Хорошо. Но какой контекст позволит мне mountи chroot?

Читая больше о SELinux, вернувшись на свою основную машину, я анализирую /sepolicyфайл в корне 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 ...
...

ОК, ряд возможностей! Особенно то, что kernelкажется многообещающим:

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

Штопать.

Кто, черт возьми, мешает мне chroot?

Любые советы приветствуются ...

ttsiodras
источник

Ответы:

12

Кто, чёрт возьми, мешает мне использовать chroot?

Это был не SELinux - это была дикая погоня за гусем ( getenforceвозвращение «Permissive» означает, что SELinux действительно больше нет на картинке).

Виновником - после добавления целого ряда printkв исходный код ядра для отслеживания сбоев обоих chrootи mount- оказались возможности . Точнее говоря, «ограничивающий набор возможностей» Android - вы можете прочитать о них все через your man( man 7 capabilities), и, признаюсь, я никогда не удосужился взглянуть на них - мои повседневные задачи UNIX зависели от них, и я понятия не имел ... попробуйте это в свою коробку linux, чтобы убедиться в этом:

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

Видеть? Ping больше не является корнем SUID - он использует информацию, хранящуюся в расширенных атрибутах файловой системы, чтобы знать, что у него есть доступ к уровню необработанных сокетов (так что он может делать это с ICMP - на уровне IP).

Во всяком случае, я отвлекся - точка операции в моем ядре, где я остановил «отбросить мои возможности» - возможно, отвратительно, «пусть все идут в поход» - это было ( 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;
}

Это означает, что возможности НИКОГДА не падают - действительно очень безопасная конфигурация :-)

$ 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

Здравствуйте, мой сладкий Debian :-)

Да, и "Root Checker" тоже работает - я набрал "su.c", чтобы все в моем планшете могли стать 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;
  //}

Теперь, когда это работает, я должен заставить это работать должным образом - то есть разрешить только моим termuxи Terminal Emulatorпользователям вызывать suи chroot, и не пропускать всех и их бабушку :-)

ttsiodras
источник
Разве этот корневой метод не требует возможности прошивать собственное ядро? И для этого требуется разблокированный загрузчик. В этот момент вы можете просто прошить кастомное рекавери и получить root таким образом.
1110101001
@ 1110101001 Для загрузчика: очевидно, да. Для
кастомного рекавери:
1
@ 1110101001: И еще одна вещь - вы сказали , «способность вспышки» - я не блеснул мой загрузочный образ на планшете, я просто загрузиться с него: fastboot boot my.img. Я считаю, что корневое сообщество называет это привязанным рутингом :-) И, конечно, я мог бы прошить его - если бы захотел.
Циодрас