Chamada do sistema SELinux e chroot

21

TL; DR: Esta é uma pergunta sobre a etapa final, em um processo de root portátil, orientado ao desenvolvedor, que funciona em todas as máquinas Android. Não se baseia em nenhuma exploração - é algo que nos é permitido legal e moralmente, como desenvolvedores, em nossas próprias máquinas. Se eu receber uma resposta e conseguir fazer um chroot dentro do meu Debian, farei um post conciso no blog detalhando todas as etapas deste processo para todos os colegas desenvolvedores que desejam acesso root aos seus tablets - e não querem confiar na origem duvidosa "raízes de um clique" que Deus sabe o que faz com suas máquinas (membros de botnet?) ... As únicas dependências serão as fontes de kernel da máquina (que o fabricante é legalmente obrigado a fornecer) e a imagem da partição de inicialização (boot.img), que é 99% das vezes dentro das atualizações over-the-air fornecidas pelo fabricante ou que podem ser baixadas individualmente como uma imagem autônoma com capacidade de flash.

Então, passou uma semana em que passei todo o meu tempo livre no meu novo tablet Android.

E quase consegui - criando um processo portátil, orientado ao desenvolvedor, para obter raiz no meu tablet Android 5.0.2.

Mas há uma coisa que falta ainda - eu não posso fazer um chroot (que eu preciso para rodar meu debootstrapDebian!)

O que eu fiz até agora

  1. Primeiro, fiz um pequeno patch nas fontes de kernel do meu tablet (fornecidas pelo fabricante) e compilei meu próprio kernel - onde desabilitei as verificações para alterar o modo de imposição do SELINUX . Especificamente...

Em 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. Eu então mudei minha imagem initrd /default.proppara conter: ro.secure=0ero.debuggable=1

  2. Como o meu fabricante initrd.imgestava ausente, eu também compilei su.cem https://android.googlesource.com/platform/system/extras/+/master/su/ e coloquei o binário resultante em baixo /sbin/su, certificando-me de que ele esteja definido como SUID root ( chmod 04755 /sbin/su) .

Depois disso, empacotei o novo kernel e o novo initrd, como expliquei no episódio 2 do meu post anterior - e inicializei a partir da minha própria imagem:

adb reboot boot-loader ; fastboot boot myboot.img

Então, você é root?

Sim, inicialmente parecia ter sucesso:

$ 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

E agora consegui raiz:

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

Tenho 100% de certeza de que sou raiz - não apenas porque iddiz isso, mas porque também posso fazer coisas que processos normais definitivamente não podem:

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)

Eis aqui - finalmente posso ler partições brutas no meu tablet!

E o SELinux está realmente no modo "baixo, cachorro":

root@K01E_2:/ # getenforce                                                     
Permissive

Mas ... ainda há coisas que não posso fazer:

root@K01E_2:/ # mkdir /my_mnt

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

Ou seja, não consigo montar minha segunda partição no formato EXT4-fs do meu cartão SD externo.

Eu também não posso chroot para o meu adorável debootstrapDebian:

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

É por causa do SELinux?

Não sei - sou novo (muito novo - uma semana) no SELinux. Eu pensei que quando você colocá-lo para dormir ( getenforcerelatando "Permissivo"), ele não interfere mais ...

Aparentemente, eu estava errado. Abaixo da toca do coelho, vamos novamente ...

Poderia ser por causa do meu contexto de processo?

Lembre-se que idretornou ... "uid = 0 (root) gid = 0 (root) ... contexto = u: r: shell: s0 "

Posso mudar esse contexto? Sendo raiz e tudo, posso me afastar shell? E se sim, vá para o que?

A resposta para a primeira pergunta é 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

Boa. Mas que contexto me permitirá mounte chroot?

Lendo um pouco mais sobre o SELinux, de volta à minha máquina principal, analiso o /sepolicyarquivo na raiz do 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, várias possibilidades! Especialmente esse kernelparece promissor:

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

Droga.

Quem diabos está me impedindo de chrooting?

Qualquer conselho muito bem-vindo ...

ttsiodras
fonte

Respostas:

12

Quem diabos está me impedindo de chrooting?

Não foi o SELinux - isso foi uma loucura ( getenforceretornar "Permissivo" significa que o SELinux não está mais na imagem).

O culpado - depois de adicionar um número considerável printkna fonte do kernel para rastrear as falhas de ambos chroote mount- acabou sendo recursos . Mais especificamente, o "conjunto de limites de recursos" do Android - você pode ler tudo sobre eles através do seu man( man 7 capabilities) e confesso que nunca me preocupei em procurá-los - minhas tarefas diárias do UNIX dependiam deles e eu não tinha ideia ... tente isso em sua caixa linux para ver por si mesmo:

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

Vejo? O ping não é mais a raiz do SUID - ele usa as informações armazenadas nos atributos estendidos do sistema de arquivos para saber que ele tem acesso à camada de soquetes brutos (para que possa executar o seu ICMP - no nível do IP).

De qualquer forma, discordo - o ponto da cirurgia no meu kernel onde parei o "abandono do conjunto de minhas capacidades" - de uma maneira indiscutivelmente repugnante ", deixe todos marcharem de maneira" - era este ( 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;
}

Isso significa que os recursos NUNCA são descartados - uma configuração muito segura, de fato :-)

$ 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

Olá, meu doce Debian :-)

Ah, e o "Verificador de raiz" também funciona - cortei "su.c", para que todos no meu tablet possam se tornar 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;
  //}

Agora que funciona, devo fazê-lo funcionar corretamente - ou seja, permitir que apenas eu termuxe os Terminal Emulatorusuários invoquem sue chroot, e não permita que todos e sua avó entrem :-)

ttsiodras
fonte
Esse método raiz não requer a capacidade de exibir seu próprio kernel? E para fazer isso, é necessário um gerenciador de inicialização desbloqueado. Nesse ponto, você também pode apenas exibir uma recuperação personalizada e obter raiz dessa maneira.
1110101001
@ 1110101001 Para o carregador de inicialização: obviamente, sim. Para a recuperação personalizado: não existe tal coisa (ainda) para o meu tablet - Eu estou em uma posição agora para criar um, embora ;-)
ttsiodras
11
@ 1110101001: E mais uma coisa - você disse "capacidade de Flash" - Eu não brilhou minha imagem de inicialização para o tablet, estou apenas iniciar a partir deste: fastboot boot my.img. Acredito que a comunidade de torcedores o chame de torcedor :-) E é claro que eu poderia exibi-lo - se quisesse.
ttsiodras