Hogyan kezdjük el használni a User Mode-ot Linux alatt

Bevezetés a fordítótól: A különböző konténerek tömeges megjelenésének tükrében érdekes és hasznos lehet megismerni, hogy egyes technológiák hogyan kezdődtek egykoron. Néhányat még ma is hasznosíthatunk, de nem mindenki emlékszik ezekre a módszerekre (vagy nem tud róluk, ha nem tapasztalta meg a virágzásukat). Az egyik ilyen technológia a User Mode Linux. Az eredeti szerző alaposan utánanézett, hogy a régi megoldások közül mi működik még, és mi az, ami már nem, és összeállított egyfajta lépésről lépésre útmutatót arról, hogyan lehet saját magunknak házi UML-t beindítani 2k19-ben. Igen, meghívtuk a Habr-ra az eredeti poszt szerzőjét. Cadey, tehát ha kérdéseid vannak, tedd fel angolul a hozzászólásokban.

Hogyan kezdjük el használni a User Mode-ot Linux alatt

A Linux User Mode lényegében a Linux kernel önálló portja. Ez a mód lehetővé teszi, hogy egy teljes értékű Linux kernel felhasználói folyamatként fusson, és általában a fejlesztők használják meghajtók tesztelésére. De ez a mód hasznos eszközként is szolgál az általános elkülönítéshez, amelynek elve hasonló a virtuális gépek működéséhez. Ez a mód nagyobb elkülönítést biztosít, mint a Docker, de kevesebbet, mint egy teljes virtuális gép, mint a KVM vagy a Virtual Box.

Összességében a User Mode furcsának és bonyolultnak tűnhet, de mindenesetre van néhány területe, ahol alkalmazható. Ez a teljes értékű Linux kernel, amely nem privilegizált felhasználóként működik. Ez a jellemző lehetővé teszi potenciálisan megbízhatatlan kód futtatását anélkül, hogy fenyegetést jelentene a hoszt gépre. Mivel ez egy teljes értékű kernel, a folyamatai elkülönülnek a hoszt géptől, tehát a User Mode-on belül futó folyamatok nem lesznek láthatók a hoszt számára. Ez nem hasonlít a megszokott Docker-konténerhez, ahol a hoszt gép mindig látja a tárolón belüli folyamatokat. Nézze meg ezt a pstree darabot az egyik szerveremről:

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}]

És hasonlítsa össze ezt a Linux kernel pstree-jével felhasználói módban:

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

Docker-konténerek használatakor láthatom a hosztból azokat a folyamatneveket, amelyek a vendégrendszerben futnak. Linux felhasználói módban ez lehetetlen. Mit jelent ez? Azt jelenti, hogy a Linux audit alrendszerén keresztül működő monitorozó eszközök nem látják a vendégrendszerben végrehajtott folyamatokat. De bizonyos helyzetekben ez a jellemző kétélű fegyverré válhat.

A bejegyzés alja valójában egy kutatás és próbálkozások sorozata a kívánt eredmény elérésére. Ehhez különböző régi eszközöket kellett használnom, tanulmányozni a kernel forráskódját, intenzíven debuggolni a kódot, amelyet még akkor írtak, amikor én még általános iskolás voltam, és módosítani a Heroku buildjeit egy speciális binárissal a szükséges eszközök keresése során. Mindez oda vezetett, hogy az IRC csoportomban varázslónak (magic) neveztek. Remélem, ez a bejegyzés megbízható dokumentációval szolgál valakinek, hogy ugyanezt kivitelezhesse, de már újabb kernel verziókkal és operációs rendszerekkel.

Beállítás

A Linux Felhasználói Mód beállítása több lépésből áll:

  • függőségek telepítése a hosztra;
  • Linux kernel letöltése;
  • a kernel build beállítása;
  • a kernel összeállítása;
  • a bináris telepítése;
  • a vendég fájlrendszer beállítása;
  • a kernel indítási paramétereinek kiválasztása;
  • a vendég hálózat beállítása;
  • a vendég kernel indítása.

Azt feltételezem, hogy ha magad akarod ezt elvégezni, valószínűleg mindezt valamelyik Ubuntu vagy Debian-szerű rendszeren fogod csinálni. Próbáltam megvalósítani mindazt, amit fentebb írtam, a kedvenc disztribúciómban — Alpine-ban, de nem sikerült, nyilvánvalóan azért, mert a Linux kernel szigorúan kapcsolódik a glibc-ismekhez a felhasználói módú meghajtók számára. Tervezem, hogy értesítem a fejlesztőket, miután véglegesen megértem a problémát.

A függőségek telepítése a hoszton

Az Ubuntu legalább a következő csomagokat igényli a Linux kernel fordításához (tiszta telepítés esetén):

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

Ezeket a következő parancs segítségével telepítheted (root jogosultság vagy sudo használatával):

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

Ne feledd, hogy a Linux kernel menübeállító program futtatása megköveteli a következő telepítését libncurses-dev. Kérlek, győződj meg arról, hogy telepítve van, a következő parancs segítségével (root jogosultság vagy sudo használatával):

apt-get -y install libncurses-dev

A kernel letöltése

Határozd meg a kernel letöltési és későbbi építési helyét. Ennek a műveletnek körülbelül 1,3 GB lemezterületre lesz szüksége, ezért győződj meg róla, hogy van elegendő helyed.

Ezután lépj a kernel.org -ra, és szerezzd meg az URL-t az utolsó stabil kernel verzió letöltéséhez. A bejegyzés írásának pillanatában ez: https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Töltsd le ezt a fájlt a 'wget':

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

És bontsd ki a következővel 'tar':

tar xJf linux-5.1.16.tar.xz

Most lépjünk be a kicsomagolt könyvtárba:

cd linux-5.1.16

A kernel építési beállítása

A kernel építési rendszere egy sor Make-fájlt a sokféle felhasználói eszközzel és szkripttel automatikálandó folyamatra. Az elején nyisd meg az interaktív beállító programot:

make ARCH=um menuconfig

Ez részben végigvezeti az építést, és egy párbeszédablakot fog megjeleníteni. Amikor az ablak alján megjelenik a ‘[Select]‘, a szóköz vagy az Enter billentyű segítségével tudsz beállítani. Az ablakban való navigáció a szokásos módon történik, a felfelé és lefelé nyilakkal, az elemek kiemelése pedig balra vagy jobbra billentyűkkel.

A '->' jelölés azt jelzi, hogy egy almennüben vagy, ahová az Enter billentyűvel tudsz belépni. A kilépés nyilvánvalóan a ‘[Exit]‘.

Kapcsold be a következő beállításokat a ‘[Select]‘ mellett, és győződj meg arról, hogy mellettük a ‘[*]’ jel található:

UML-specifikus lehetőségek:
  - Gazda fájlrendszer
Hálózati támogatás (engedélyezze ezt, hogy a legördülő menü megjelenjen):
  - Hálózati lehetőségek:
    - TCP/IP hálózat
UML hálózati eszközök:
  - Virtuális hálózati eszköz
  - SLiRP szállítás

Mindenből, ebből az ablakból ki lehet lépni, folyamatosan választva az ‘[Exit]‘. Csak győződjön meg róla, hogy a végén felajánlja a konfiguráció mentését, és válassza az ‘[Igen]‘.

Azt ajánlom, hogy kísérletezzen a kernel összeállítási paramétereivel, miután elolvasta ezt a bejegyzést. Ezekkel a kísérletekkel sokat tanulhat a kernel alacsony szintű mechanizmusainak működéséről és a különböző zászlók összeállításra gyakorolt hatásáról.

Kernel összeállítása

A Linux kernel egy nagy program, amely sok mindennel foglalkozik. Még egy ilyen minimális konfigurációval is a régi hardveren az összeállítása sok időt vehet igénybe. Ezért a következő paranccsal állítsa össze a kernelt:

make ARCH=um -j$(nproc)

Miért? Ez a parancs azt mondja a fordítónknak, hogy használja az összes elérhető magot és processzorszálat az összeállítás során. A parancs $(nproc) a Build végén behelyettesíti a parancs kimenetét: nproc, amely a coreutils standard Ubuntu-összeállítás része.

Néhány idő elteltével a kernelünk egy végrehajtható fájlként lesz összeállítva: ./linux.

Binaries telepítése

Mivel a Linux User Mode normál binárist hoz létre, telepítheti, akár bármely más segédeszközt. Így tettem én is:

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

Azt is érdemes megbizonyosodni arról, hogy ~\/bin a következő helyen található: $PATH:

export PATH=$PATH:$HOME/bin

Vendég fájlrendszer beállítása

Hozzon létre egy könyvtárat a vendég fájlrendszer számára:

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

Nyissa meg az alpinelinux.org oldalt, és a letöltési részben keresse meg a legfrissebb letöltési linket KIS RENDSZER FÁJLRÉSZ. A bejegyzés írásakor ez volt:

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

Töltse le ezt a tarballt a wget használatával:

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

Most lépjen a vendég fájlrendszer könyvtárába, és csomagolja ki az archívumot:

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

A leírt lépések egy kis fájlrendszer sablont hoznak létre. A rendszer működési jellemzői miatt nehéz lesz csomagokat telepíteni az Alpine apk kezelőjén keresztül. De ez a fájlrendszer elegendő lesz az általános ötlet megértéséhez.

Szükségünk lesz a tini eszközre is, hogy megakadályozza a memóriafogyasztást zombi folyamatok által

a vendég kernelünkből.

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

A Linux kernel, like most other programs, has command line arguments that can be found by using the key --help.

self --help

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=,
Configure  as an IO memory region named .

mem=
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=
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=
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]*=
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]+=,
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=
The location to place the pid and umid files.

quiet
Turns off information messages during boot.

hostfs=,,...
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.

Ez a dokumentum bemutatja a futtatás fő paramétereit. Indítsuk el a kernelt a minimálisan szükséges opciókkal:

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

A fenti sorok azt mondják a kernelünknek:

  • Tegyük fel, hogy a gyökér fájlrendszer egy ál-eszköz /dev/root.
  • Válassz hostfs mint root fájlrendszer meghajtójaként.
  • Csatold a vendég fájlrendszert, amelyet a root meghajtóra hoztunk létre.
  • Igen, írási-olvasási módban.
  • Használjon csak 64 megabájt RAM-ot (sokkal kevesebb is elegendő lehet a tervezett feladatokhoz, de a 64 MB optimális mennyiségnek tűnik).
  • A kernel automatikusan indítja el /bin/sh hogyan init-folyamatot.

Futtasd ezt a parancsot, és valami ilyesmit kell kapnod:

Még egy huzat

Core dump korlátok:
        soft - 0
        hard - NINCS
Ellenőrzés, hogy a ptrace képes-e megváltoztatni a rendszerhívások számát...OK
Ellenőrzés a Syscall emulációs patch számára ptrace esetén...OK
Ellenőrzés az előrehaladott syscall emulációs patch számára ptrace esetén...OK
Ellenőrzés, hogy a környezeti változók között van-e tempdir...nem található
Ellenőrzés, hogy a /dev/shm tmpfs-en van-e...OK
Ellenőrzés PROT_EXEC mmap-en a /dev/shm...OK
32137216 byte hozzáadása a fizikai memóriához az exec-shield rés pótlására
Linux verzió 5.1.16 (cadey@kahless) (gcc verzió 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #30 2019. július 7. 18:57:19 UTC
1 zonelista épített, mobilitáscsoportosítás engedélyezve. Összes oldal: 23898
Kernel parancssor: root=/dev/root rootflags=/home/cadey/dl/uml/alpine rootfstype=hostfs rw mem=64M init=/bin/sh
Dentry cache hash táblabejegyzések: 16384 (rend: 5, 131072 byte)
Inode-cache hash táblabejegyzések: 8192 (rend: 4, 65536 byte)
Memória: 59584K/96920K elérhető (2692K kernel kód, 708K rwdata, 588K rodata, 104K init, 244K bss, 37336K fenntartva, 0K cma-fenntartva)
SLUB: HWalign=64, Rendelés=0-3, MinObjects=0, CPU=1, Csomópont=1
NR_IRQS: 15
Clocksource: timer: maszk: 0xffffffffffffffff max_cycles: 0x1cd42e205, max_idle_ns: 881590404426 ns
Késleltetési hurok kalibrálása... 7479.29 BogoMIPS (lpj=37396480)
pid_max: alapértelmezett: 32768 minimum: 301
Mount-cache hash táblabejegyzések: 512 (rend: 0, 4096 byte)
Mountpoint-cache hash táblabejegyzések: 512 (rend: 0, 4096 byte)
Ellenőrzés, hogy a gazda pty-k támogatják-e a SIGIO kimenetet...Igen
Ellenőrzés, hogy a gazda pty-k támogatják-e a SIGIO-t bezáráskor...Nem, workaround engedélyezve
devtmpfs: inicializálva
random: get_random_bytes hívása a setup_net+0x48/0x1e0-ból crng_init=0 esetén
2.6-os gazda AIO használata
Clocksource: jiffies: maszk: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash táblabejegyzések: 256 (rend: 0, 6144 byte)
NET: Regisztrált protokollcsalád 16
Clocksource: Átváltva clocksource timer-re
NET: Regisztrált protokollcsalád 2
tcp_listen_portaddr_hash hash táblabejegyzések: 256 (rend: 0, 4096 byte)
TCP megalapozott hash táblabejegyzések: 1024 (rend: 1, 8192 byte)
TCP bind hash táblabejegyzések: 1024 (rend: 1, 8192 byte)
TCP: Hash táblák konfigurálva (megalapozott 1024 bind 1024)
UDP hash táblabejegyzések: 256 (rend: 1, 8192 byte)
UDP-Lite hash táblabejegyzések: 256 (rend: 1, 8192 byte)
NET: Regisztrált protokollcsalád 1
console [stderr0] letiltva
mconsole (2. verzió) inicializálva a /home/cadey/.uml/tEwIjm/mconsole helyen
Ellenőrzés, hogy a gazda MADV_REMOVE támogatás...OK
workingset: timestamp_bits=62 max_order=14 bucket_order=0
Block layer SCSI general (bsg) driver verzió 0.4 betöltve (major 254)
io ütemező no-op regisztrálva (alapértelmezett)
io ütemező bfq regisztrálva
loop: modul betöltve
NET: Regisztrált protokollcsalád 17
Inicializált stdio konzol driver
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen az 1-es eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 2-es eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 3-as eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 4-es eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen az 5-ös eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 6-os eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 7-es eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 8-as eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 9-es eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 10-es eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 11-es eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 12-es eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 13-as eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 14-es eszköz esetén: A konfiguráció sikertelen
Olyan csatornatípust használ, amely UML-en kívül van konfigurálva
setup_one_line sikertelen a 15-ös eszköz esetén: A konfiguráció sikertelen
Konzol inicializálva a /dev/tty0-n
console [tty0] engedélyezve
console [mc-1] engedélyezve
Nem sikerült inicializálni az ubd 0 eszközt: Nem lehetett meghatározni az eszköz fájljának méretét
VFS: Gyökér csatlakoztatva (hostfs fájlrendszer) a 0:11 eszközön.
devtmpfs: csatlakoztatva
Ez az architektúra nem rendelkezik kernel memória védelemmel.
Futtassa a /bin/sh-t mint az init folyamatot
/bin/sh: nem tud hozzáférni a tty-hez; a feladatvezérlés letiltva
random: gyors init kész
/ # 

A fenti manipulációk segítenek nekünk egy minimalista vendég rendszert létrehozni, olyan dolgok nélkül, mint például /proc vagy a hozzárendelt hostnév. Például próbálja meg végrehajtani az alábbi parancsokat:

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

A vendég rendszerből való kilépéshez írja be exit vagy nyomja meg a control-d gombot. Ez megölni fogja a shell-t, ami kernel pánikot idéz elő:

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

Ezt a kernel pánikot azért tapasztaltuk, mert a Linux magja úgy ítéli meg, hogy az inicializáló folyamat mindig fut. Enélkül a rendszer már nem tud működni, és leáll. Mivel ez egy felhasználói módbeli folyamat, a kapott eredmény önmagát küldi el a SIGABRT, ami kilépéshez vezet.

Vendég hálózat beállítása

Itt emelkednek a bonyodalmak. A User Mode Linux hálózat ott van, ahol az egész korlátozott "felhasználói mód" koncepció kezd szétesni. Hiszen általában a rendszer szintjén a hálózatot privilegizált végrehajtási módok korlátozzák, mindenki által jól ismert okokból.

Megjegyzés: többet olvashat a UML hálózati működésének különböző változatairól itt.

Utazás a slirp-be

Viszont létezik egy régi és gyakorlatilag nem támogatott eszköz, amelyet Slirp, amellyel a User Mode Linux kapcsolatba léphet a hálózattal. Ez körülbelül úgy működik, mint egy TCP/IP verem felhasználói szinten, és nem igényel semmiféle rendszerszintű engedélyt a futtatásához. Ezt az eszközt 1995-ben adták ki, és az utolsó frissítése 2006-ra datálódik.A Slirp nagyon régi. A támogatás és frissítések hiánya miatt a fordítók annyira elmentek, hogy ezt az eszközt csak «kód bomlásnak».

tudjuk jellemezni. Most telepítsük a Slirp-t az Ubuntu repókból, és próbáljuk meg futtatni:

sudo apt-get install slirp
/usr/bin/slirp
Slirp v1.0.17 (BETA)

Copyright (c) 1995,1996 Danny Gasparovski és mások.
Minden jog fenntartva.
Ez a program szerzői jogvédelem alatt áll, szabad szoftver.
Kérjük, olvassa el a Slirp
csomaggal együtt érkező COPYRIGHT fájlt a szerzői jogi feltételekről.

A Slirp gazdagép IP-címe: 127.0.0.1
A DNS címe(i): 1.1.1.1, 10.77.0.7
Az ön címe: 10.0.2.15
(vagy bármi más, amit akar)

Írjon be öt nullát (0) a kilépéshez.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500, 115200 baud]

SLiRP Kész ...
fish: “/usr/bin/slirp” megszakítva a SIGSEGV jellel (Címhatár hiba)

Ó, istenem. Telepítsünk egy hibakeresőt a Slirp-hez, és nézzük meg, tudunk-e rájönni, mi történik itt:

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 
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:
.
Find the GDB manual and other documentation resources online at:
.
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.

Hiba történt a következő sorban: ebben a sorban. Nézzük meg a stacktrace-t, hátha segít nekünk:

(gdb) bt full
#0  ip_slowtimo () at ip_input.c:457
        fp = 0x55784a40
#1  0x000055555556a57c in main_loop () at ./main.c:980
        so = 
        so_next = 
        timeout = {tv_sec = 0, tv_usec = 0}
        ret = 0
        nfds = 0
        ttyp = 
        ttyp2 = 
        best_time = 
        tmp_time = 
#2  0x000055555555b116 in main (argc=1, argv=0x7fffffffdc58) at ./main.c:95
No locals.

Itt látjuk, hogy a hiba a fő ciklus indítása közben történik, amikor a slirp megpróbálja ellenőrizni az időtúllépéseket. Ekkor kellett volna feladnom a hibakeresést. De nézzük meg, működik-e a Slirp, ami forráskódból készült. Közvetlenül a weboldalról töltöttem le az archívumot Sourceforge, mert valamit onnan parancssoron keresztül letölteni fájdalmas:

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

Itt figyelmeztetéseket látunk a meghatározatlan beépített függvényekről, ami azt jelzi, hogy nem lehet a keletkező bináris fájlt linkelni. Úgy tűnik, hogy 2006 és e pillanat között a gcc leállította a használt szimbólumok létrehozását a köztesen lefordított fájlokban. Próbáljuk meg kicserélni a kulcsszót inline üres kommentre, és nézzük meg az eredményt:

vi slirp.h
:6
a

#define inline /**/

:wq
make

Nem. Ez sem működik. Még mindig nem találom ennek a funkciónak a szimbólumait.

Ezen a ponton feladtam, és elkezdtem keresni a Githubon Heroku build csomagokat. Az elméletem abból indult ki, hogy egy Heroku build csomagban megtalálhatók a szükséges bináris fájlok. Végül a keresés ide vezetett ide. Letöltöttem és kicsomagoltam uml.tar.gz és a következőt találtam:

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*

Ez a slirp bináris fájl! Működik?

. /slirp
Slirp v1.0.17 (BETA) FULL_BOLT

Copyright (c) 1995,1996 Danny Gasparovski és mások.
Minden jog fenntartva.
Ez a program szerzői jogi védelem alatt áll, ingyenes szoftver.
Kérjük, olvassa el a Slirp csomaggal együtt járó COPYRIGHT fájlt a szerzői jogi feltételekről.

A Slirp host IP címe: 127.0.0.1
Az Ön DNS címe(i): 1.1.1.1, 10.77.0.7
Az Ön címe: 10.0.2.15
(vagy bármi más, amit szeretne)

Írja be öt nullát (0) a kilépéshez.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500]

SLiRP Kész ...

Nem omlik össze — ez tehát működni fog! Csatlakoztassuk ezt a bináris fájlt a ~ /bin /slirp:

cp slirp ~ /bin /slirp

Azért, hogy ha a csomag készítője eltávolítja, tükör másolatot készítettem.

Hálózat beállítása

Most állítsuk be a hálózatot a vendég kernelünknél. Frissítsük a indulási paramétereket:

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

Most engedjük aktiválni a hálózatot:

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

Az első két beállító parancs /proc és /sys szükséges a működéshez ifconfig, amely beállítja a hálózati interfészt a Slirppel való kommunikációhoz. A parancs route beállítja a kernel routing táblát, hogy kényszerítse az összes forgalmat a Slirp alagúton keresztül. Ellenőrizzük ezt egy DNS lekérdezéssel:

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

Működik!

Megjegyzés: Úgy tűnik, az eredeti poszt egy vezetékes hálózati kártyával rendelkező asztali számítógépen készült, vagy egy másik konfigurációban, amely nem igényel további illesztőprogramokat. A 8265-ös Intel WiFi laptopon viszont a hálózat aktiválásakor hiba lép fel.

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

Nyilvánvalóan a kernel nem tud kapcsolódni a hálózati kártya illesztőprogramjához. Az, hogy a firmware-t bevezettük a kernelbe, sajnos nem oldotta meg a problémát. A kiadás idején ennél a konfigurációnál nem találtunk megoldást. Egyszerűbb konfigurációkban (például Virtualboxban) az interfész helyesen emelkedik.

Automatizáljuk az átirányítást a következő shell script segítségével:

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

És jelöljük meg végrehajthatónak:

chmod +x init.sh

Ezután módosítsuk a kernel parancssorát:

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

És ismételjük meg:

SLiRP Készen ...
hálózat beállítva
\/bin\/sh: nem elérhető tty; a feladatvezérlés kikapcsolva

nslookup google.com 8.8.8.8
Szerver:    8.8.8.8
Cím 1: 8.8.8.8 dns.google

Név:      google.com
Cím 1: 172.217.12.206 lga25s63-in-f14.1e100.net
Cím 2: 2607:f8b0:4004:800::200e iad30s09-in-x0e.1e100.net

A hálózat stabilan működik!

Docker fájl

A könnyebb átláthatóság érdekében készítettem egy Dockerfile, amely automatizálja a legtöbb leírt lépést, és működő konfigurációt kell biztosítania Ön számára. Továbbá van egy kész kernel konfigurációm, amely tartalmazza mindazt, ami a bejegyzésben szerepel. De fontos megérteni, hogy itt csak a minimális beállítást foglaltam össze.

Remélem, ez a bejegyzés segített megérteni, hogyan lehet elindítani egy vendég kernelt. Egyfajta szörnyeteg lett belőle, de a publikálás eredetileg egy átfogó útmutatónak szánták a User Mode összeállításáról, telepítéséről és konfigurálásáról a Linux modern operációs rendszereihez. A további lépéseknek tartalmazniuk kell a szolgáltatások és más szoftverek telepítését a vendég rendszeren belül. Mivel a Docker tartalomképek egyszerűen kicsomagolt tar archívumok, képesnek kell lennie a képet kicsomagolni a docker export, majd meg kell határoznia az installációs útvonalát a vendég kernel fájlrendszerének gyökérében. Ezután futtassa a shell scriptet.

Külön köszönet Rkeene-nek a #lobsters-nél Freenoden. Az ő segítsége nélkül a Slirp hibakeresésében nem jutottam volna ilyen messzire. Fogalmam sincs, hogyan működik az ő Slackware rendszere slirp-vel, de az Ubuntu és Alpine rendszereim nem fogadták el a slirp-t és a Rkeene által javasolt binárist. De elég, ha működik valami.

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster