Introdução do tradutor: Tendo como pano de fundo a entrada massiva de vários tipos de contêineres em nossas vidas, pode ser bastante interessante e útil descobrir com quais tecnologias tudo começou. Alguns deles podem ser usados de forma útil até hoje, mas nem todos se lembram de tais métodos (ou sabem se não foram detectados durante seu rápido desenvolvimento). Uma dessas tecnologias é o User Mode Linux. O autor do original pesquisou bastante, descobrindo quais dos desenvolvimentos antigos ainda funcionam e quais não, e reuniu algo como uma instrução passo a passo sobre como obter uma UML homebrew em 2k19. E sim, convidamos o autor do post original para Habr Cadey, então se você tiver alguma dúvida - pergunte em inglês nos comentários.
O modo de usuário no Linux é, na verdade, uma porta do kernel do Linux para si mesmo. Este modo permite executar um kernel Linux completo como um processo de usuário e é comumente usado por desenvolvedores para testar drivers. Mas este modo também é útil como ferramenta de isolamento geral, cujo princípio é semelhante ao funcionamento de máquinas virtuais. Este modo fornece mais isolamento que o Docker, mas menos que uma máquina virtual completa como KVM ou Virtual Box.
Em geral, o Modo Usuário pode parecer uma ferramenta estranha e difícil de usar, mas ainda tem sua utilidade. Afinal, este é um kernel Linux completo executado por um usuário sem privilégios. Este recurso permite que códigos potencialmente não confiáveis sejam executados sem qualquer ameaça à máquina host. E como este é um kernel completo, seus processos são isolados da máquina host, ou seja processos em execução dentro do modo de usuário não serão visíveis para o host. Não é como um contêiner Docker tradicional, no qual a máquina host sempre vê os processos dentro do armazenamento. Veja este pedaço de pstree de um dos meus servidores:
E compare isso com o pstree do kernel Linux no modo de usuário:
linux─┬─5*[linux]
└─slirp
Ao trabalhar com contêineres Docker, posso ver no host os nomes dos processos que estão em execução no convidado. Com o modo de usuário Linux, isso não é possível. O que isso significa? Isso significa que as ferramentas de monitoramento executadas no subsistema de auditoria do Linux nao vejo processos em execução no sistema convidado. Mas em algumas situações, esse recurso pode se tornar uma faca de dois gumes.
Em geral, todo o post abaixo é uma coleção de pesquisas e tentativas aproximadas de alcançar o resultado desejado. Para fazer isso, tive que usar várias ferramentas antigas, ler as fontes do kernel, fazer depuração intensiva de código escrito na época em que eu ainda estava no ensino fundamental e também mexer nas compilações do Heroku usando um binário especial para encontrar as ferramentas que precisava. . Todo esse trabalho levou o pessoal do meu IRC a me chamar de mágico. Espero que este post sirva como documentação confiável para alguém tentar a mesma coisa com kernels e versões de sistema operacional mais recentes.
Fixação
A configuração do modo de usuário Linux é feita em várias etapas:
instalar dependências no host;
baixando o kernel do Linux;
configuração de compilação do kernel;
montagem do kernel;
instalação binária;
configurar o sistema de arquivos convidado;
seleção de parâmetros de inicialização do kernel;
configurar uma rede de convidados;
iniciando o kernel convidado.
Presumo que se você decidir fazer isso sozinho, provavelmente fará tudo o que está descrito em algum sistema Ubuntu ou semelhante ao Debian. Tentei implementar todos os itens acima em minha distribuição favorita - Alpine, mas não deu em nada, aparentemente devido ao fato de o kernel Linux ter glibc-ismos de ligação rígida para drivers no modo de usuário. Pretendo relatar isso ao upstream depois de finalmente entender o problema.
Instalando dependências no host
O Ubuntu requer pelo menos os seguintes pacotes para construir o kernel Linux (assumindo uma instalação limpa):
Observe que a execução do programa de configuração do menu do kernel Linux exigirá a instalação do libncurses-dev. Certifique-se de que esteja instalado usando o seguinte comando (como root ou usando sudo):
apt-get -y install libncurses-dev
Baixando o kernel
Decida onde fazer o download e então construa o kernel. Para esta operação, você precisará alocar cerca de 1,3 GB de espaço no disco rígido, portanto, certifique-se de tê-lo.
Agora entramos no diretório criado ao descompactar o tarball:
cd linux-5.1.16
Configurando uma compilação de kernel
O sistema de compilação do kernel é um conjunto Makefiles с muitos ferramentas e scripts personalizados para automatizar o processo. Primeiro, abra o programa de configuração interativo:
make ARCH=um menuconfig
Ele irá construir e exibir parcialmente uma caixa de diálogo para você. Quando '[Select]', você poderá configurar usando as teclas Espaço ou Enter. Navegue pela janela, como de costume, com as setas do teclado “para cima” e “para baixo”, e selecione os elementos – “esquerda” ou “direita”.
O ponteiro de visualização —> significa que você está em um submenu, acessado pela tecla Enter. A saída é obviamente através de '[Exit]'.
Inclua as seguintes opções em '[Select]' e certifique-se de que eles tenham um '[*]' próximo a eles:
UML-specific Options:
- Host filesystem
Networking support (enable this to get the submenu to show up):
- Networking options:
- TCP/IP Networking
UML Network devices:
- Virtual network device
- SLiRP transport
É isso, você pode sair desta janela selecionando sucessivamente '[Exit]'. Apenas certifique-se de que você seja solicitado a salvar a configuração no final e selecione '[Yes]'.
Eu recomendo que você experimente as opções de construção do kernel depois de ler este post. Com esses experimentos, você pode aprender muito sobre como a mecânica do kernel de baixo nível funciona e como diferentes sinalizadores afetam a forma como o kernel é construído.
Construindo o kernel
O kernel do Linux é um grande programa que faz muitas coisas. Mesmo com uma configuração tão mínima em hardware antigo, a construção pode demorar um pouco. Então construa o kernel com o seguinte comando:
make ARCH=um -j$(nproc)
Para que? Este comando dirá ao nosso construtor para usar todos os núcleos e threads de CPU disponíveis no processo de construção. Equipe $(nproc) no final do Build substitui a saída do comando nproc, que faz parte coreutils em uma versão padrão do Ubuntu.
Depois de algum tempo, nosso kernel será compilado em um arquivo executável ./linux.
Instalando o binário
Como o User Mode no Linux cria um binário regular, você pode instalá-lo como qualquer outro utilitário. Veja como eu fiz isso:
mkdir -p ~/bin
cp linux ~/bin/linux
Também vale a pena ter certeza de que ~/bin está em seu $PATH:
export PATH=$PATH:$HOME/bin
Configurando o sistema de arquivos convidado
Crie um diretório para o sistema de arquivos convidado:
mkdir -p $HOME/prefix/uml-demo
cd $HOME/prefix
Abra alpinelinux.org e em seção de download encontre o link de download real MINI ROOT FILESYSTEM. No momento em que este artigo foi escrito, isso era:
Agora entre no diretório do sistema de arquivos convidado e extraia o arquivo:
cd uml-demo
tar xf ../alpine-rootfs.tgz
As ações descritas criarão um pequeno modelo de sistema de arquivos. Devido à natureza do sistema, será extremamente difícil instalar pacotes através do gerenciador apk Alpine. Mas este FS será suficiente para avaliar a ideia geral.
Também precisamos de uma ferramenta tini para reduzir o consumo de memória processos zumbis nosso kernel convidado.
wget -O tini https://github.com/krallin/tini/releases/download/v0.18.0/tini-static
chmod +x tini
Criando uma linha de comando do kernel
O kernel do Linux, como a maioria dos outros programas, possui argumentos de linha de comando que podem ser acessados especificando a chave --help.
Ele mesmo - ajuda
linux --help
User Mode Linux v5.1.16
available at http://user-mode-linux.sourceforge.net/
--showconfig
Prints the config file that this UML binary was generated from.
iomem=<name>,<file>
Configure <file> as an IO memory region named <name>.
mem=<Amount of desired ram>
This controls how much "physical" memory the kernel allocates
for the system. The size is specified as a number followed by
one of 'k', 'K', 'm', 'M', which have the obvious meanings.
This is not related to the amount of memory in the host. It can
be more, and the excess, if it's ever used, will just be swapped out.
Example: mem=64M
--help
Prints this message.
debug
this flag is not needed to run gdb on UML in skas mode
root=<file containing the root fs>
This is actually used by the generic kernel in exactly the same
way as in any other kernel. If you configure a number of block
devices and want to boot off something other than ubd0, you
would use something like:
root=/dev/ubd5
--version
Prints the version number of the kernel.
umid=<name>
This is used to assign a unique identity to this UML machine and
is used for naming the pid file and management console socket.
con[0-9]*=<channel description>
Attach a console or serial line to a host channel. See
http://user-mode-linux.sourceforge.net/old/input.html for a complete
description of this switch.
eth[0-9]+=<transport>,<options>
Configure a network device.
aio=2.4
This is used to force UML to use 2.4-style AIO even when 2.6 AIO is
available. 2.4 AIO is a single thread that handles one request at a
time, synchronously. 2.6 AIO is a thread which uses the 2.6 AIO
interface to handle an arbitrary number of pending requests. 2.6 AIO
is not available in tt mode, on 2.4 hosts, or when UML is built with
/usr/include/linux/aio_abi.h not available. Many distributions don't
include aio_abi.h, so you will need to copy it from a kernel tree to
your /usr/include/linux in order to build an AIO-capable UML
nosysemu
Turns off syscall emulation patch for ptrace (SYSEMU).
SYSEMU is a performance-patch introduced by Laurent Vivier. It changes
behaviour of ptrace() and helps reduce host context switch rates.
To make it work, you need a kernel patch for your host, too.
See http://perso.wanadoo.fr/laurent.vivier/UML/ for further
information.
uml_dir=<directory>
The location to place the pid and umid files.
quiet
Turns off information messages during boot.
hostfs=<root dir>,<flags>,...
This is used to set hostfs parameters. The root directory argument
is used to confine all hostfs mounts to within the specified directory
tree on the host. If this isn't specified, then a user inside UML can
mount anything on the host that's accessible to the user that's running
it.
The only flag currently supported is 'append', which specifies that all
files opened by hostfs will be opened in append mode.
Este painel destaca os principais parâmetros do lançamento. Vamos executar o kernel com o conjunto mínimo de opções necessário:
linux
root=/dev/root
rootfstype=hostfs
rootflags=$HOME/prefix/uml-demo
rw
mem=64M
init=/bin/sh
As linhas acima dizem ao nosso kernel o seguinte:
Suponha que o sistema de arquivos raiz seja um pseudodispositivo /dev/root.
Escolher hostfs como um driver do sistema de arquivos raiz.
Monte o sistema de arquivos convidado que criamos no dispositivo raiz.
E sim, no modo leitura-gravação.
Use apenas 64 megabytes de RAM (você pode usar muito menos dependendo do que planeja fazer, mas 64 MB parece ser a quantidade ideal).
O kernel inicia automaticamente /bin/sh como init-processo.
Execute este comando e você deverá obter algo como o seguinte:
Outra folha
Core dump limits :
soft - 0
hard - NONE
Checking that ptrace can change system call numbers...OK
Checking syscall emulation patch for ptrace...OK
Checking advanced syscall emulation patch for ptrace...OK
Checking environment variables for a tempdir...none found
Checking if /dev/shm is on tmpfs...OK
Checking PROT_EXEC mmap in /dev/shm...OK
Adding 32137216 bytes to physical memory to account for exec-shield gap
Linux version 5.1.16 (cadey@kahless) (gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #30 Sun Jul 7 18:57:19 UTC 2019
Built 1 zonelists, mobility grouping on. Total pages: 23898
Kernel command line: root=/dev/root rootflags=/home/cadey/dl/uml/alpine rootfstype=hostfs rw mem=64M init=/bin/sh
Dentry cache hash table entries: 16384 (order: 5, 131072 bytes)
Inode-cache hash table entries: 8192 (order: 4, 65536 bytes)
Memory: 59584K/96920K available (2692K kernel code, 708K rwdata, 588K rodata, 104K init, 244K bss, 37336K reserved, 0K cma-reserved)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS: 15
clocksource: timer: mask: 0xffffffffffffffff max_cycles: 0x1cd42e205, max_idle_ns: 881590404426 ns
Calibrating delay loop... 7479.29 BogoMIPS (lpj=37396480)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes)
Checking that host ptys support output SIGIO...Yes
Checking that host ptys support SIGIO on close...No, enabling workaround
devtmpfs: initialized
random: get_random_bytes called from setup_net+0x48/0x1e0 with crng_init=0
Using 2.6 host AIO
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 256 (order: 0, 6144 bytes)
NET: Registered protocol family 16
clocksource: Switched to clocksource timer
NET: Registered protocol family 2
tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
UDP hash table entries: 256 (order: 1, 8192 bytes)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
NET: Registered protocol family 1
console [stderr0] disabled
mconsole (version 2) initialized on /home/cadey/.uml/tEwIjm/mconsole
Checking host MADV_REMOVE support...OK
workingset: timestamp_bits=62 max_order=14 bucket_order=0
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
io scheduler noop registered (default)
io scheduler bfq registered
loop: module loaded
NET: Registered protocol family 17
Initialized stdio console driver
Using a channel type which is configured out of UML
setup_one_line failed for device 1 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 2 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 3 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 4 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 5 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 6 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 7 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 8 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 9 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 10 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 11 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 12 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 13 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 14 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 15 : Configuration failed
Console initialized on /dev/tty0
console [tty0] enabled
console [mc-1] enabled
Failed to initialize ubd device 0 :Couldn't determine size of device's file
VFS: Mounted root (hostfs filesystem) on device 0:11.
devtmpfs: mounted
This architecture does not have kernel memory protection.
Run /bin/sh as init process
/bin/sh: can't access tty; job control turned off
random: fast init done
/ #
As manipulações acima nos darão sistema convidado no mínimo, sem coisas como /proc ou nome de host atribuído. Por exemplo, tente os seguintes comandos:
- uname -av
- cat /proc/self/pid
- hostname
Para sair do convidado, digite exit ou pressione control-d. Isso matará o shell seguido por um kernel panic:
/ # exit
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000
fish: “./linux root=/dev/root rootflag…” terminated by signal SIGABRT (Abort)
Tivemos esse kernel panic porque o kernel do Linux pensa que o processo de inicialização está sempre em execução. Sem ele, o sistema não funciona mais e trava. Mas como este é um processo em modo de usuário, a saída resultante é enviada para SIGABRT, o que resulta em uma saída.
Configurando uma rede de convidados
E é aqui que as coisas começam a dar errado. Rede no Modo Usuário O Linux é onde todo o conceito de "modo usuário" limitado começa a desmoronar. Afinal, geralmente no nível do sistema, a rede é limitada privilegiado modos de execução por razões compreensíveis para todos nós.
Observação. per.: você pode ler mais sobre as diferentes opções para trabalhar com uma rede em UML aqui.
Jornada para Slirp
No entanto, existe uma ferramenta antiga e quase sem suporte chamada Slip, com o qual o User Mode Linux pode interagir com a rede. Ele funciona como uma pilha TCP/IP em nível de usuário e não requer nenhuma permissão do sistema para ser executado. Esta ferramenta foi lançado em 1995, e a atualização mais recente está datada Ano 2006. Slirp é muito antigo. Durante o tempo sem suporte e atualizações, os compiladores foram tão longe que agora esta ferramenta só pode ser descrita como podridão de código.
Então vamos baixar o Slirp dos repositórios do Ubuntu e tentar executá-lo:
sudo apt-get install slirp
/usr/bin/slirp
Slirp v1.0.17 (BETA)
Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.
IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)
Type five zeroes (0) to exit.
[autodetect SLIP/CSLIP, MTU 1500, MRU 1500, 115200 baud]
SLiRP Ready ...
fish: “/usr/bin/slirp” terminated by signal SIGSEGV (Address boundary error)
Ah, deuses. Vamos instalar o depurador do Slirp e ver se conseguimos descobrir o que está acontecendo aqui:
sudo apt-get install gdb slirp-dbgsym
gdb /usr/bin/slirp
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/bin/slirp...Reading symbols from /usr/lib/debug/.build-id/c6/2e75b69581a1ad85f72ac32c0d7af913d4861f.debug...done.
done.
(gdb) run
Starting program: /usr/bin/slirp
Slirp v1.0.17 (BETA)
Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.
IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)
Type five zeroes (0) to exit.
[autodetect SLIP/CSLIP, MTU 1500, MRU 1500, 115200 baud]
SLiRP Ready ...
Program received signal SIGSEGV, Segmentation fault.
ip_slowtimo () at ip_input.c:457
457 ip_input.c: No such file or directory.
O erro bate em nós está linha. Vejamos o stacktrace, talvez algo nos ajude nisso:
(gdb) bt full
#0 ip_slowtimo () at ip_input.c:457
fp = 0x55784a40
#1 0x000055555556a57c in main_loop () at ./main.c:980
so = <optimized out>
so_next = <optimized out>
timeout = {tv_sec = 0, tv_usec = 0}
ret = 0
nfds = 0
ttyp = <optimized out>
ttyp2 = <optimized out>
best_time = <optimized out>
tmp_time = <optimized out>
#2 0x000055555555b116 in main (argc=1, argv=0x7fffffffdc58) at ./main.c:95
No locals.
Aqui vemos que o travamento ocorre durante a inicialização do loop principal, quando o slirp tenta verificar os tempos limite. Neste ponto, tive que desistir de tentar depurar. Mas vamos ver se o Slirp construído a partir de classificações funciona. Baixei novamente o arquivo diretamente do site Sourceforge, porque arrastar algo de lá pela linha de comando é uma dor:
cd ~/dl
wget https://xena.greedo.xeserv.us/files/slirp-1.0.16.tar.gz
tar xf slirp-1.0.16.tar.gz
cd slirp-1.0.16/src
./configure --prefix=$HOME/prefix/slirp
make
Aqui vemos alertas sobre funções integradas indefinidas, ou seja, sobre a incapacidade de vincular o arquivo binário resultante. Parece que entre 2006 e este ponto, o gcc parou de produzir símbolos usados em funções integradas de arquivos intermediários compilados. Vamos tentar substituir a palavra-chave inline em um comentário vazio e veja o resultado:
vi slirp.h
:6
a
<enter>
#define inline /**/
<escape>
:wq
make
Não. Isso também não funciona. Ainda não consigo encontrar símbolos para essas funções.
Nesse ponto, desisti e comecei a procurar no Github Pacotes de compilação Heroku. Minha teoria era que algum pacote de compilação do Heroku conteria os binários que eu precisava. No final, a busca me levou aqui. baixei e descompactei uml.tar.gz e encontrei o seguinte:
total 6136
-rwxr-xr-x 1 cadey cadey 79744 Dec 10 2017 ifconfig*
-rwxr-xr-x 1 cadey cadey 373 Dec 13 2017 init*
-rwxr-xr-x 1 cadey cadey 149688 Dec 10 2017 insmod*
-rwxr-xr-x 1 cadey cadey 66600 Dec 10 2017 route*
-rwxr-xr-x 1 cadey cadey 181056 Jun 26 2015 slirp*
-rwxr-xr-x 1 cadey cadey 5786592 Dec 15 2017 uml*
-rwxr-xr-x 1 cadey cadey 211 Dec 13 2017 uml_run*
Este é o binário slirp! Ele trabalha?
./slirp
Slirp v1.0.17 (BETA) FULL_BOLT
Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.
IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)
Type five zeroes (0) to exit.
[autodetect SLIP/CSLIP, MTU 1500, MRU 1500]
SLiRP Ready ...
Não trava - então deve funcionar! Vamos plantar esse binário em ~/bin/slirp:
Os dois primeiros comandos de configuração /proc и /sys necessário para o trabalho ifconfig, que configura a interface de rede para se comunicar com o Slirp. Equipe route define a tabela de roteamento do kernel para forçar todo o tráfego a ser enviado através do túnel Slirp. Vamos verificar isso com uma consulta DNS:
Nota por.: Aparentemente, a postagem original foi escrita em um desktop com placa de rede com fio ou alguma outra configuração que não exigia drivers adicionais. Em um laptop com WiFi 8265 da Intel, ocorre um erro ao aumentar a rede
/ # ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
slirp_tramp failed - errno = 2
ifconfig: ioctl 0x8914 failed: No such file or directory
/ #
Aparentemente, o kernel não consegue se comunicar com o driver da placa de rede. Uma tentativa de compilar o firmware no kernel, infelizmente, não resolveu a situação. No momento da publicação não foi possível encontrar solução nesta configuração. Em configurações mais simples (por exemplo, no Virtualbox), a interface sobe corretamente.
Vamos automatizar o redirecionamento com o seguinte script de shell:
E então faremos alterações na linha de comando do kernel:
linux
root=/dev/root
rootfstype=hostfs
rootflags=$HOME/prefix/uml-demo
rw
mem=64M
eth0=slirp,,$HOME/bin/slirp
init=/init.sh
E vamos repetir:
SLiRP Ready ...
networking set up
/bin/sh: can't access tty; job control turned off
nslookup google.com 8.8.8.8
Server: 8.8.8.8
Address 1: 8.8.8.8 dns.google
Name: google.com
Address 1: 172.217.12.206 lga25s63-in-f14.1e100.net
Address 2: 2607:f8b0:4004:800::200e iad30s09-in-x0e.1e100.net
A rede está estável!
arquivo docker
Para facilitar a verificação de tudo isso, coletei dockerfile, que automatiza a maioria das etapas descritas e deve fornecer uma configuração funcional. eu também tenho kernel pré-configurado, que tem tudo o que está descrito no post. Mas é importante compreender que aqui descrevi apenas a configuração mínima.
Espero que este post tenha ajudado você a entender como criar um kernel convidado. Acabou sendo uma espécie de monstro, mas a publicação foi concebida como um guia completo sobre construção, instalação e configuração do Modo Usuário no Linux para versões modernas de sistemas operacionais desta família. As próximas etapas devem incluir a instalação de serviços e outros softwares já dentro do sistema convidado. Como as imagens de contêiner do Docker são apenas tarballs divulgados, você poderá extrair a imagem via docker exporte, em seguida, determine seu caminho de instalação na raiz do sistema de arquivos do kernel convidado. Bem, então execute o script de shell.
Agradecimentos especiais a Rkeene do #lobsters no Freenode. Sem a ajuda dele para depurar o Slirp, eu não teria chegado tão longe. Não tenho ideia de como o sistema Slackware dele funciona corretamente com o slirp, mas meus sistemas Ubuntu e Alpine não aceitavam o slirp e o binário Rkeene me sugeriu. Mas é suficiente para mim que pelo menos algo funcione para mim.