Cumu cumincià à utilizà u Modu User in Linux

Introduzione da u traduttore: In u sfondate di l'entrata massiva in a nostra vita di varii tipi di cuntenituri, pò esse abbastanza interessante è utile per sapè cù quale tecnulugia tuttu hà cuminciatu una volta. Qualchidunu di elli ponu esse utili à questu ghjornu, ma micca tutti si ricordanu di tali metudi (o sà s'ellu ùn anu micca pigliatu durante u so rapidu sviluppu). Una di queste tecnulugia hè User Mode Linux. L'autore di l'uriginale hà fattu assai di scavà, capì quale di i vechji sviluppi travaglianu sempre è quali ùn sò micca, è hà riunitu qualcosa cum'è una struzzioni passu à passu nantu à cumu uttene un UML homebrew in 2k19. È sì, avemu invitatu l'autore di u post originale à Habr Cadey, dunque s'è vo avete qualchì quistione - dumandate in inglese in i cumenti.

Cumu cumincià à utilizà u Modu User in Linux

U Modu d'Usuariu in Linux hè, in fattu, un portu di u kernel Linux à ellu stessu. Stu modu permette di eseguisce un kernel Linux cumpletu cum'è un prucessu d'utilizatore è hè comunmente utilizatu da i sviluppatori per pruvà i driver. Ma questu modu hè ancu utile cum'è strumentu d'isolazione generale, u principiu di quale hè simile à l'operazione di macchine virtuali. Stu modu furnisce più isolamentu di Docker, ma menu di una macchina virtuale cum'è KVM o Virtual Box.

In generale, u Modu d'Usuariu pò parè un strumentu stranu è difficiule à aduprà, ma hà u so usu. Dopu tuttu, questu hè un kernel Linux cumpletu chì funziona cum'è un utilizatore senza privilegi. Questa funzione permette à u codice potenzalmentu micca fiduciale per eseguisce senza alcuna minaccia per a macchina host. E postu chì questu hè un kernel cumpletu, i so prucessi sò isolati da a macchina host, vale à dì I prucessi in esecuzione in u Modu d'Usuariu ùn saranu micca visibili à l'ospite. Questu ùn hè micca cum'è u solitu cuntainer Docker, in quale casu a macchina host sempre vede i prucessi in u repository. Fighjate stu pezzu di pstree da unu di i mo servitori:

containerd─┬─containerd-shim─┬─tini─┬─dnsd───19*[{dnsd}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─aerial───21*[{aerial}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─s6-svscan───s6-supervise
           │                 │      └─surl
           │                 └─9*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─h───13*[{h}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─goproxy───14*[{goproxy}]
           │                 └─9*[{containerd-shim}]
           └─32*[{containerd}]

È paragunate questu cù u pstree di u kernel Linux in Modu User:

linux─┬─5*[linux]
      └─slirp

Quandu u travagliu cù cuntenituri Docker, possu vede da l'ospitu i nomi di i prucessi chì sò in esecuzione in l'invitatu. Cù Linux User Mode, questu ùn hè micca pussibule. Cosa significa? Questu significa chì l'arnesi di monitoraghju chì passanu attraversu u sottosistema di auditu di Linux ùn vecu micca prucessi in esecuzione in u sistema invitatu. Ma in certi situazioni, sta funzione pò diventà una spada à doppia tagliu.

In generale, tuttu u postu sottu hè una cullizzioni di ricerca è tentativi grossi per ottene u risultatu desideratu. Per fà questu, aghju avutu aduprà diverse arnesi antichi, leghje e fonti di u kernel, fà una debugging intensiva di codice scrittu in i ghjorni chì era sempre in a scola elementaria, è ancu sbattà cù Heroku builds cù un binariu speciale per truvà l'arnesi chì avia bisognu. . Tuttu stu travagliu hà purtatu i picciotti nantu à u mo IRC per chjamà mi magia. Spergu chì questu post serve cum'è documentazione affidabile per qualchissia per pruvà a stessa cosa cù i kernels più recenti è e versioni OS.

cutter

A cunfigurazione di u Modu d'Usuariu Linux hè fatta in parechji passi:

  • installà dipendenze nantu à l'ospite;
  • scaricamentu di u kernel Linux;
  • cunfigurazione di custruzzione di u kernel;
  • assemblea di u kernel;
  • installazione binariu;
  • cunfigurà u sistema di schedari invitati;
  • selezzione di i paràmetri di lanciu di u kernel;
  • crià una reta di invitati;
  • principià u kernel d'ospiti.

Supponu chì se decide di fà da sè stessu, probabilmente farà tuttu ciò chì hè descrittu in qualchì Ubuntu o sistema Debian-like. Aghju pruvatu à implementà tuttu ciò chì sopra in a mo distribuzione preferita - Alpine, ma nunda ùn hè vinutu da questu, apparentemente per u fattu chì u kernel Linux hà un glibc-isms hard-binding per i drivers in User Mode. Pensu di rapportà questu à upstream dopu avè finalmente capitu u prublema.

Installazione di dipendenze nantu à l'ospite

Ubuntu richiede almenu i seguenti pacchetti per custruisce u kernel Linux (assumendu una installazione pulita):

- 'build-essential'
- 'flex'
- 'bison'
- 'xz-utils'
- 'wget'
- 'ca-certificates'
- 'bc'
- 'linux-headers'

Pudete installà cù u cumandimu seguitu (cum'è root o cù sudo):

apt-get -y install build-essential flex bison xz-utils wget ca-certificates bc 
                   linux-headers-$(uname -r)

Nota chì l'esecuzione di u prugramma di configurazione di menu di u kernel Linux richiederà l'installazione di libncurses-dev. Per piacè assicuratevi chì hè stallatu cù u cumandimu seguitu (cum'è root o cù sudo):

apt-get -y install libncurses-dev

Scaricamentu di u kernel

Decidite induve scaricà è poi custruisce u kernel. Per sta operazione, avete bisognu di assignà circa 1,3 GB di spaziu di discu duru, cusì assicuratevi di avè.

Dopu andà à kernel.org è uttene l'URL per scaricà l'ultimu kernel stabile. À u mumentu di a scrittura, questu hè: https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Scaricate stu schedariu usendu 'wget':

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

È estrae cù 'tar':

tar xJf linux-5.1.16.tar.xz

Avà entremu in u cartulare creatu quandu unpacking u tarball:

cd linux-5.1.16

Configurazione di a creazione di u kernel

U sistema di creazione di u kernel hè un set Makefiles с tanti Strumenti persunalizati è scripts per automatizà u prucessu. Prima, apre u prugramma di cunfigurazione interattiva:

make ARCH=um menuconfig

Custruirà parzialmente è mostra una finestra di dialogu per voi. quannu '[Select]', puderete cunfigurà usendu i tasti Space o Enter. Navigate a finestra, cum'è solitu, cù e frecce di u teclatu "up" è "down", è selezziunate elementi - "left" o "right".

L'indicatore di vista -> significa chì site in un submenu, accessu premendu a chjave Enter. A via d'uscita hè ovviamente attraversu '[Exit]'.

Includite e seguenti opzioni in '[Select]' è assicuratevi chì anu un '[*]' accantu à elli:

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

Hè questu, pudete esce da sta finestra selezziunate successivamente '[Exit]'. Solu assicuratevi di esse dumandatu à salvà a cunfigurazione à a fine è selezziunate '[Yes]'.

Vi cunsigliu di ghjucà cù l'opzioni di creazione di u kernel dopu avè lettu stu post. Per mezu di sti esperimenti, pudete amparà assai in quantu à capisce u travagliu di a meccanica di u kernel di livellu bassu è l'impattu di diverse bandiere nantu à a so assemblea.

Custruì u kernel

U kernel Linux hè un grande prugramma chì face assai cose. Ancu cun una cunfigurazione cusì minima nantu à u hardware anticu, pò piglià un bellu pezzu per custruisce. Allora custruite u kernel cù u cumandimu seguitu:

make ARCH=um -j$(nproc)

Perchè? Stu cumandamentu diciarà à u nostru custruttore di utilizà tutti i nuclei è i fili di CPU dispunibili in u prucessu di creazione. squadra $(nproc) à a fine di Build sustituisci l'output di u cumandimu nproc, chì face parte di coreutils in una versione standard di Ubuntu.

Dopu qualchì tempu, u nostru kernel serà cumpilatu in un schedariu eseguibile ./linux.

Stallà u binariu

Siccomu u Modu d'Usuariu in Linux crea un binariu regulare, pudete installà cum'è qualsiasi altra utilità. Eccu cumu l'aghju fattu:

mkdir -p ~/bin
cp linux ~/bin/linux

Hè ancu vale a pena di assicurà chì ~/bin hè in u vostru $PATH:

export PATH=$PATH:$HOME/bin

Configurazione di u sistema di schedarii invitati

Crea un repertoriu per u sistema di schedari invitati:

mkdir -p $HOME/prefix/uml-demo
cd $HOME/prefix

Aprite alpinelinux.org è in sezione di scaricamentu truvate u ligame di scaricamentu attuale MINI ROOT FILESYSTEM. À u mumentu di a scrittura, questu era:

http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.0-x86_64.tar.gz

Scaricate stu tarball cù wget:

wget -O alpine-rootfs.tgz http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.0-x86_64.tar.gz

Avà entre in u cartulare di u sistema di schedari invitati è estrae l'archiviu:

cd uml-demo
tar xf ../alpine-rootfs.tgz

L'azzioni descritte creanu un picculu mudellu di sistema di fugliale. A causa di a natura di u sistema, serà estremamente difficiuli di installà pacchetti attraversu u gestore apk Alpine. Ma questu FS serà abbastanza per valutà l'idea generale.

Avemu ancu bisognu di un strumentu tini per frenà u cunsumu di memoria prucessi zombie u nostru kernel d'ospiti.

wget -O tini https://github.com/krallin/tini/releases/download/v0.18.0/tini-static
chmod +x tini

Crià una linea di cummanda di kernel

U kernel di Linux, cum'è a maiò parte di l'altri prugrammi, hà argumenti di linea di cummanda chì ponu accede specificando a chjave. --help.

Iddu stessu - aiutu

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.

Stu pannellu mette in risaltu i paràmetri principali di u lanciu. Eseguimu u kernel cù u minimu set di opzioni necessarii:

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  init=/bin/sh

I linii sopra dicenu à u nostru kernel u seguente:

  • Assumimu chì u sistema di filesystem root hè un pseudo-dispositivu /dev/root.
  • Sceglite hostfs cum'è un driver di filesystem root.
  • Munta u sistema di filesystem d'ospiti chì avemu creatu nantu à u dispusitivu radicali.
  • È iè, in modu di lettura-scrittura.
  • Aduprate solu 64 MB di RAM (pudete aduprà assai menu secondu ciò chì pensa à fà, ma 64 MB pari a quantità ottima).
  • U kernel principia automaticamente /bin/sh quantu init- prucessu.

Eseguite stu cumandamentu è duvete ottene qualcosa cum'è u seguente:

Un altru fogliu

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
/ # 

I manipulazioni sopra ci daranu sistema di ospiti à u minimu, senza cose cum'è /proc o un nome di host assignatu. Per esempiu, pruvate i seguenti cumandamenti:

- uname -av
- cat /proc/self/pid
- hostname

Per esce da l'invitatu, scrivite exit o appughjà u cuntrollu-d. Questu ucciderà a cunchiglia seguita da un panicu di u kernel:

/ # exit
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000
fish: “./linux root=/dev/root rootflag…” terminated by signal SIGABRT (Abort)

Avemu avutu stu panicu di u kernel perchè u kernel Linux pensa chì u prucessu di inizializazione hè sempre in esecuzione. Senza ellu, u sistema ùn pò più funziunà è crashs. Ma postu chì questu hè un prucessu in u modu di l'utilizatori, u risultatu risultatu si manda à SIGABRT, chì si traduce in un output.

Configurazione di a rete di ospiti

Ma questu hè quì chì e cose cumincianu à sbaglià per noi. A rete in u Modu d'Usuariu Linux hè induve u cuncettu tutale di un "modu d'utilizatore" limitatu cumencia à fallu. Dopu tuttu, a reta hè generalmente limitata à u livellu di u sistema privilegiatu modi d'esekzione per tutti noi ragioni capisci.

Nota. per .: pudete leghje più nantu à e diverse opzioni per travaglià cù una reta in UML ccà.

Viaghju à Slirp

Tuttavia, ci hè un strumentu anticu è quasi senza supportu chjamatu Slirp, cù quale User Mode Linux pò interagisce cù a reta. Funziona à pocu pressu cum'è una pila TCP / IP à livellu d'utilizatore è ùn necessita micca permessi di u sistema per eseguisce. Stu strumentu era liberatu in u 1995, è l'ultima aghjurnazione hè datata 2006. Slirp hè assai vechju. Duranti u tempu senza supportu è aghjurnamenti, i compilatori sò andati tantu luntanu chì avà stu strumentu pò esse discrittu solu cum'è "codice rot".

Allora scarichemu Slirp da i repositori Ubuntu è pruvate à eseguisce:

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)

Oh dii. Stallà u debugger di Slirp è vede s'ellu pudemu capisce ciò chì succede quì:

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.

L'errore batte in noi sta linea. Fighjemu a stacktrace, forse qualcosa ci aiuterà quì:

(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.

Quì vedemu chì u crash succede durante u principiu di u ciclu principale quandu slirp prova di verificà i timeouts. À questu puntu, aghju avutu da rinunzià à pruvà à debug. Ma vedemu se Slirp custruitu da sorte funziona. Aghju scaricatu l'archiviu direttamente da u situ Sourceforge, perchè trascinà qualcosa da quì attraversu a linea di cummanda hè un dolore:

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

Quì vedemu alerti nantu à e funzioni integrate indefinite, vale à dì, nantu à l'incapacità di ligà u schedariu binariu risultatu. Sembra chì trà u 2006 è questu puntu, gcc hà cessatu di pruduce simboli utilizati in funzioni integrate di schedarii compilati intermedi. Pruvemu di rimpiazzà a keyword inline à un cumentu viotu è fighjate u risultatu:

vi slirp.h
:6
a
<enter>
#define inline /**/
<escape>
:wq
make

Innò. Questu ùn funziona ancu. Ùn si pò ancu truvà simboli per queste funzioni.

À questu puntu, aghju rinunziatu è cuminciatu à circà in Github Heroku custruisce pacchetti. A mo teoria era chì un pacchettu di creazione Heroku cuntene i binari chì avia bisognu. In fine, a ricerca m'hà purtatu quì. Aghju scaricatu è sbulicatu uml.tar.gz è truvò i seguenti:

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*

Questu hè u binariu slirp! U travagliu ?

./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 crash - cusì deve travaglià! Piantemu stu binariu in ~/bin/slirp:

cp slirp ~/bin/slirp

In casu chì u creatore di u pacchettu l'elimina, I hà fattu un specchiu.

Cunfigurazione di rete

Avà stallà a reta nantu à u nostru kernel d'ospiti. Aghjurnate l'opzioni di lanciu:

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  eth0=slirp,,$HOME/bin/slirp 
  init=/bin/sh

Avà accendemu a reta:

mount -t proc proc proc/
mount -t sysfs sys sys/

ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
route add default gw 10.0.2.2

I primi dui cumandamenti di cunfigurazione /proc и /sys necessariu per u travagliu ifconfig, chì stabilisce l'interfaccia di rete per cumunicà cù Slirp. squadra route stabilisce a tabella di routing di u kernel per furzà tuttu u trafficu per esse mandatu à traversu u tunnel Slirp. Cuntrollamu questu cun una dumanda DNS:

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:4006:81b::200e lga25s63-in-x0e.1e100.net

U travagliu!

Nota per .: Apparentemente, u post originale hè statu scrittu nantu à un desktop cù una carta di rete cablata, o qualchì altra cunfigurazione chì ùn hà micca bisognu di driver supplementari. Nant'à un laptop cù WiFi 8265 da Intel, un errore si trova quandu si alza a reta

/ # 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
/ #

Apparentemente, u kernel ùn pò micca cumunicà cù u driver di a carta di rete. Un tentativu di cumpilà u firmware in u kernel, sfurtunatamenti, ùn hà micca riparatu a situazione. À u mumentu di a publicazione, ùn era micca pussibule di truvà una suluzione in questa cunfigurazione. Nant'à e cunfigurazioni più simplici (per esempiu, in Virtualbox), l'interfaccia s'arrizza currettamente.

Automatizemu a redirezzione cù u seguente script di shell:

#!/bin/sh
# init.sh

mount -t proc proc proc/
mount -t sysfs sys sys/
ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
route add default gw 10.0.2.2

echo "networking set up"

exec /tini /bin/sh

È marcate eseguibile:

chmod +x init.sh

E poi faremu cambiamenti à a linea di cummanda di u kernel:

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  eth0=slirp,,$HOME/bin/slirp 
  init=/init.sh

È ripetemu :

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 reta hè stabile!

u schedariu docker

Per fà più faciule per voi per verificà tuttu questu, aghju cullatu dockerfile, chì automatizeghja a maiò parte di i passi descritti è deve dà una cunfigurazione di travagliu. Aghju ancu kernel preconfiguratu, chì hà tuttu ciò chì hè descrittu in u post. Ma hè impurtante di capisce chì quì aghju delineatu solu u paràmetru minimu.

Spergu chì questu post vi hà aiutatu à capisce cumu fà cresce un kernel d'ospiti. Risultava esse un tipu di mostru, ma a publicazione hè stata cuncipita cum'è una guida cumpleta nantu à a custruzzione, a stallazione è a cunfigurazione di u Modu d'Usuariu in Linux sottu versioni muderni di sistemi operativi di sta famiglia. I prossimi passi duveranu include l'installazione di servizii è altri software digià in u sistema di ospiti. Siccomu l'imaghjini di u containeru Docker sò solu tarballs publicitarii, duvete esse capace di estrae l'imaghjini via docker export, è dopu stabilisce a so strada di installazione in a radica di u sistema di schedari di u kernel invitatu. Ebbè, allora eseguite u script di shell.

Un ringraziu speciale à Rkeene da #lobsters nantu à Freenode. Senza u so aiutu per debugging Slirp, ùn saria micca ghjuntu cusì luntanu. Ùn aghju micca idea di cumu u so sistema Slackware funziona bè cù slirp, ma i mo sistemi Ubuntu è Alpine ùn anu micca accettatu slirp è u binariu Rkeene m'hà suggeritu. Ma hè abbastanza per mè chì almenu qualcosa funziona per mè.

Source: www.habr.com

Add a comment