Linux é um interpretador
(astrid.tech)- Define o initrd como uma unidade de programa que o kernel interpreta e executa diretamente, reinterpretando o Linux como uma espécie de interpretador
- Usa
kexec,base64ecpiopara montar uma distribuição Linux recursiva que reinicia a si mesma, em que o initrd executa a si próprio novamente - Se o script
/initfor configurado para emitir sua própria imagem cpio, forma-se um initrd autorreplicante no estilo Quine - Explica, por meio da estrutura de execução ELF, do
ld.soe dobinfmt_misc, uma arquitetura em camadas de interpretadores que se estende até o kernel - Com
kexecou QEMU, é possível executar outro Linux sobre o Linux em recursão de cauda, expandindo experimentalmente as fronteiras entre kernel, virtualização e interpretadores
Engenharia reversa de rkx.gz e a estrutura de initrd autorrecursiva
- O comando
curl https://astrid.tech/rkx.gz | gunzip | sudo shbaixa e executa um script shell de 20 MB codificado em base64- O script verifica privilégios de root e confirma a presença de
kexec,base64ecpio - Decodifica os dados em base64 para criar um arquivo cpio chamado
re, a partir dele, extrai uma imagem de kernel chamadak - Usa
kexecpara carregar e executarkcomo kernel ercomo ramdisk
- O script verifica privilégios de root e confirma a presença de
- Dentro de
r.cpiohá os arquivos/bin,/initek;ké uma imagem do kernel Linux 6.18.18, e/inité um script shell- O
/initmonta/proc, empacota o sistema de arquivos atual em cpio em/re então usakexecpara executar novamente/ke/r - O resultado é uma distribuição Linux recursiva que continua reiniciando a si mesma
- O
A perspectiva de ver o kernel Linux como um interpretador
- O initrd não é apenas um ramdisk de boot, mas pode ser visto como um programa que o kernel Linux interpreta e executa
- Assim como
curl | shoupython3 script.py, o initrd também é uma forma de programa de entrada executada pelo kernel - Portanto, o kernel Linux funciona como um interpretador do initrd
- Assim como
- Essa estrutura é semelhante à otimização de recursão de cauda (tail-call optimization)
- O
kexeccarrega e executa o novo kernel em um novo espaço de memória, sem sobrescrever o kernel anterior - Cada kernel não preserva o estado anterior e é substituído por um novo “stack frame”
- O
Quine e a autorreplicação do initrd
- Quine significa um programa que imprime a si mesmo
- Se o script
/initexecutarcat /rao final, ele produzirá um cpio idêntico a si próprio - Nesse caso, forma-se um Quine do interpretador initrd do Linux
- Como todos os arquivos existem em
tmpfsna RAM, não ocorre I/O real em disco
- Se o script
ELF, ld.so e as camadas do interpretador
- Executáveis ELF incluem no cabeçalho o caminho do interpretador (
ld-linux-x86-64.so.2)- Na execução, o kernel inicia primeiro o
ld.so, e old.socarrega as bibliotecas dinâmicas do ELF antes de executar o programa - Portanto, o ELF também pode ser visto como uma espécie de linguagem interpretada
- Na execução, o kernel inicia primeiro o
- O
/bin/shé interpretado pelold.so, e old.soé interpretado diretamente pelo kernel- Como o
ld.soé um ELF com linkagem estática, o kernel pode executá-lo diretamente - Assim se forma o caso-base (base case) da hierarquia de interpretadores
- Como o
Execução de CPIO com binfmt_misc
- Com
binfmt_misc, é possível executar arquivos com determinados magic bytes por meio de um interpretador especificado- Exemplo de comando de registro:
echo ':cpio:M::\x30\x37\x30\x37\x30\x31::/path/to/my/script.sh:' > /proc/sys/fs/binfmt_misc/register - Com essa configuração, arquivos CPIO com
chmod +xpodem ser executados diretamente
- Exemplo de comando de registro:
- É possível registrar como interpretador um script que usa QEMU para executar o CPIO como initrd
- O QEMU inicializa uma máquina virtual com o kernel e o initrd especificados
- Como resultado, o interpretador do arquivo CPIO passa a ser o kernel Linux executado pelo QEMU
Interpretadores recursivos e o “loop mais estranho”
- Um interpretador baseado em QEMU cria um novo stack frame de ambiente Linux
- É uma estrutura que executa outro Linux sobre o Linux, podendo aninhar-se até o limite de memória
- Se for substituído por um interpretador baseado em
kexec, torna-se possível uma execução Linux recursiva com otimização de chamada de cauda
- Se o
/initfor configurado para registrarbinfmt_misce executar/r, completa-se um initrd que executa a si mesmo- O
/ré o próximo processo init em formato CPIO e, ao ser executado, interpreta a si próprio novamente
- O
Conclusão
- O initrd não é apenas uma ferramenta de boot, mas uma unidade de programa interpretada pelo kernel Linux
- Com
kexecebinfmt_misc, é possível executar o próprio Linux recursivamente como se fosse um interpretador - Essa estrutura é um conceito experimental que desfaz as fronteiras entre kernel, virtualização, interpretadores e programas autorreplicantes
- O código-fonte relacionado está disponível no repositório GitHub ifd3f/rekexec
2 comentários
Dizem que a ignorância traz coragem... espero que evitemos esse tipo de texto.
Comentários do Hacker News
Sofri ao ler este texto por causa de equívocos demais
Um arquivo cpio não é um sistema de arquivos. O autor usa initramfs, que é baseado em tmpfs. O Linux consegue extrair um cpio para tmpfs. Um arquivo de arquivos e diretórios não é, por si só, um programa
Só porque algo parece semelhante não quer dizer que seja a mesma coisa. Um programa binário é executado na CPU e, se existe um interpretador, ele está escondido no ambiente de hardware. Isso está fora do escopo do kernel
Para executar um shell script, é preciso um shell que interprete esse script. O autor omite essa parte e confunde o kernel com o programa shell
O Linux pode ser compilado sem initramfs ou ramdisk e ainda assim executar o userland de um sistema de arquivos
A expressão “Linux initrd interpreter” é realmente uma descrição errada
ld.sodescompactar um ELF na memória e executar o ponto de entrada, e o kernel descompactar um initramfs e executar o ponto de entrada, são conceitos parecidosTodo sistema operacional não acaba funcionando como um interpretador de código de máquina com privilégios de kernel?
Este texto funciona se você entender “Linux é um interpretador” como um modelo mental, mas está errado se levado ao pé da letra
Faz mais sentido vê-lo não como interpretação no nível de instruções da CPU, mas como o papel do kernel em orquestrar formatos executáveis como ELF, scripts com shebang e initramfs. A confusão parece vir da mistura de dois sentidos diferentes de “interpretador”
O ponto central não é se a analogia está certa, mas mostrar o quanto o conceito de “execução” depende do ambiente
“Tudo é um interpretador?”
O Theta Combinator de Turing
Num texto anterior da série, o autor disse que criou a própria imagem de VPS porque não queria usar o object storage da Contabo
Acho que existe um ponto de equilíbrio entre gastar 50 horas para economizar US$ 1,50 por mês e gastar US$ 250 mil em tokens.
Se você não consegue arcar com os custos de infraestrutura, talvez o problema seja mais social do que técnico. Ficar obcecado em rodar Doom via curl não me parece produtivo
Em
man ld.so, está explícito que o linker dinâmico armazenado na seção.interpdo ELF é executado. O nome da própria seção é interessanteO Linux é muito útil como uma interface programável. O Windows também permite isso, mas sinto que o Linux é mais adequado
Acho a GUI do Windows melhor, mas também não gosto de GNOME nem KDE. Por isso uso fluxbox, icewm e, às vezes, xfce ou mate-desktop. Hoje em dia prefiro ambientes simples e rápidos. Faço a maior parte do trabalho na linha de comando e editando código