EinfĂŒhrung des Ăbersetzers: Angesichts des massiven Einzugs verschiedener Container in unser Leben kann es ziemlich interessant und nĂŒtzlich sein, herauszufinden, mit welchen Technologien das alles einmal begonnen hat. Einige von ihnen können bis heute nĂŒtzlich angewandt werden, aber viele erinnern sich nicht mehr an solche Methoden (oder wissen es nicht, wenn sie in der Zeit ihrer rasanten Entwicklung nicht dabei waren). Eine solche Technologie ist User Mode Linux. Die Autorin des Originals hat grĂŒndlich recherchiert, was von den alten Entwicklungen noch funktioniert und was nicht mehr so gut ist, und hat eine Art Schritt-fĂŒr-Schritt-Anleitung zusammengestellt, wie man sich im Jahr 2k19 ein selbstgebautes UML einrichten kann. Und ja, wir haben die Autorin des ursprĂŒnglichen Beitrags zu Habr eingeladen. , also wenn es Fragen gibt â stellt sie auf Englisch in den Kommentaren.

User Mode in Linux ist praktisch ein Port des Linux-Kernels auf sich selbst. Dieser Modus ermöglicht es, einen vollstĂ€ndigen Linux-Kernel als Benutzerprozess auszufĂŒhren und wird normalerweise von Entwicklern zum Testen von Treibern verwendet. Aber dieser Modus ist auch als Werkzeug zur allgemeinen Isolation nĂŒtzlich, dessen Prinzip dem von virtuellen Maschinen Ă€hnelt. Dieser Modus bietet mehr Isolation als Docker, aber weniger als eine vollwertige virtuelle Maschine wie KVM oder Virtual Box.
Insgesamt mag User Mode wie ein seltsames und kompliziertes Werkzeug erscheinen, hat aber dennoch seine Anwendungsbereiche. SchlieĂlich handelt es sich um einen vollstĂ€ndigen Linux-Kernel, der von einem nicht privilegierten Benutzer betrieben wird. Dieser Umstand erlaubt das AusfĂŒhren von potenziell unsicherem Code, ohne die Host-Maschine zu gefĂ€hrden. Und da es sich um einen vollstĂ€ndigen Kernel handelt, sind seine Prozesse von der Host-Maschine isoliert, d. h. Prozesse, die innerhalb des User Mode laufen, werden fĂŒr den Host nicht sichtbar sein. Dies unterscheidet sich von einem herkömmlichen Docker-Container, bei dem die Host-Maschine immer die Prozesse im Container sieht. Schaut euch diesen Ausschnitt von pstree von einem meiner Server an:
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}]Und vergleichen Sie dies mit pstree des Linux-Kernels im Benutzer-Modus:
linuxââŹâ5*[linux]
ââslirpBei der Arbeit mit Docker-Containern kann ich vom Host aus die Prozessnamen sehen, die im Gastbetriebssystem ausgefĂŒhrt werden. Mit dem Linux-Benutzermodus ist dies nicht möglich. Was bedeutet das? Das bedeutet, dass Monitoring-Tools, die ĂŒber das Auditsystem von Linux arbeiten, sehen nicht die Prozesse, die im Gastbetriebssystem ausgefĂŒhrt werden. In einigen Situationen kann diese Eigenschaft jedoch ein zweischneidiges Schwert sein.
Der gesamte nachfolgende Beitrag ist eine Sammlung von Studien und groben Versuchen, die gewĂŒnschten Ergebnisse zu erzielen. Dazu musste ich verschiedene alte Werkzeuge verwenden, Quellcodes des Kernels lesen, intensiv an einem Code debuggen, der zur Zeit, als ich noch in der Grundschule war, geschrieben wurde, und in den Heroku-Bauten mit einem speziellen Binary nach den benötigten Werkzeugen suchen. All diese Arbeit fĂŒhrte dazu, dass die Jungs in meinem IRC mich eine Zauberin (magic) nannten. Ich hoffe, dass dieser Beitrag jemandem als zuverlĂ€ssige Dokumentation dienen kann, um dasselbe zu erreichen, jedoch mit neueren Kernen und Betriebssystemversionen.
Einstellungen
Die Konfiguration des Linux-Benutzermodus erfolgt in mehreren Schritten:
- Installation der AbhÀngigkeiten auf dem Host;
- Herunterladen des Linux-Kernels;
- Konfiguration des Kernel-Baus;
- Bau des Kernels;
- Installation des Binaries;
- Konfiguration des Gast-Dateisystems;
- Festlegung der Kernel-Startparameter;
- Konfiguration des Gast-Netzwerks;
- Start des Gast-Kerns.
Ich nehme an, dass Sie, wenn Sie das Ganze selbst durchfĂŒhren möchten, dies wahrscheinlich in einem Ubuntu- oder Debian-Ă€hnlichen System tun werden. Ich habe versucht, alles oben Beschriebene in meiner bevorzugten Distribution â Alpine â umzusetzen, aber es hat nicht geklappt, vermutlich weil der Linux-Kernel eine strikte Bindung an glibc-isms fĂŒr Treiber im User Mode hat. Ich plane, dies upstream zu melden, nachdem ich das Problem endgĂŒltig verstanden habe.
Installation der AbhÀngigkeiten auf dem Host
Ubuntu benötigt mindestens die folgenden Pakete zum Bauen des Linux-Kernels (bei einer sauberen Installation):
- 'build-essential'
- 'flex'
- 'bison'
- 'xz-utils'
- 'wget'
- 'ca-certificates'
- 'bc'
- 'linux-headers'
Sie können diese mit folgendem Befehl installieren (als Root oder mit sudo):
apt-get -y install build-essential flex bison xz-utils wget ca-certificates bc
linux-headers-$(uname -r) Bitte beachten Sie, dass das AusfĂŒhren des MenĂŒkonfigurationsprogramms fĂŒr den Linux-Kernel die Installation von libncurses-deverfordert. Bitte stellen Sie sicher, dass es mit folgendem Befehl installiert ist (als Root oder mit sudo):
apt-get -y install libncurses-devHerunterladen des Kernels
Bestimmen Sie den Speicherort fĂŒr den Download und das anschlieĂende Bauen des Kernels. FĂŒr diese Operation benötigen Sie etwa 1,3 GB Speicherplatz auf der Festplatte, stellen Sie also sicher, dass dieser verfĂŒgbar ist.
Gehen Sie nun zu und holen Sie sich die URL zum Herunterladen der neuesten stabilen Version des Kernels. Zum Zeitpunkt der Erstellung dieses Beitrags ist das:
Laden Sie diese Datei mit 'wget':
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz Und extrahieren Sie sie mit 'tar':
tar xJf linux-5.1.16.tar.xzGehen Sie nun in das Verzeichnis, das beim Entpacken des Tarballs erstellt wurde:
cd linux-5.1.16Konfiguration des Kernel-Baus
Das System zum Bauen des Kernels besteht aus c vielen benutzerdefinierten Werkzeugen und Skripten zur Automatisierung des Prozesses. Ăffnen Sie zunĂ€chst das interaktive Konfigurationsprogramm:
make ARCH=um menuconfig Es wird teilweise den Bauprozess anstoĂen und Ihnen ein Dialogfenster anzeigen. Wenn unten im Fenster '[Select]' angezeigt wird, können Sie mit den Tasten Leertaste oder Eingabe mit der Konfiguration beginnen. Die Navigation im Fenster erfolgt wie gewohnt mit den Pfeiltasten âhochâ und ârunterâ, und das AuswĂ€hlen von Elementen erfolgt mit âlinksâ oder ârechtsâ.
Ein Hinweis wie â> bedeutet, dass Sie sich im UntermenĂŒ befinden, das mit der Eingabetaste betreten werden kann. Der Ausstieg erfolgt offensichtlich ĂŒber '[Exit]'.Aktivieren Sie die folgenden Optionen in '[Select]' und stellen Sie sicher, dass neben ihnen ein Symbol '[*]' steht:â.
â[Select]â
UML-spezifische Optionen:
- Host-Dateisystem
NetzwerkunterstĂŒtzung (aktivieren Sie dies, um das UntermenĂŒ anzuzeigen):
- Netzwerkauswahl:
- TCP/IP-Netzwerk
UML-NetzwerkgerÀte:
- Virtuelles NetzwerkgerÀt
- SLiRP-Transport Sie können aus diesem Fenster herausgehen, indem Sie nacheinander 'Aktivieren Sie die folgenden Optionen in '[Select]' und stellen Sie sicher, dass neben ihnen ein Symbol '[*]' steht:â wĂ€hlen. Nur sollten Sie sicherstellen, dass Ihnen am Ende angeboten wird, die Konfiguration zu speichern, und wĂ€hlen Sie '[Ja]â.
Ich empfehle Ihnen, nach dem Lesen dieses Beitrags mit den Kernel-Bauoptionen zu experimentieren. Dank dieser Experimente werden Sie viel ĂŒber das VerstĂ€ndnis der Funktionsweise der Low-Level-Mechaniken des Kernels und den Einfluss verschiedener Flags auf dessen Erstellung lernen.
Kernel-Bau
Der Linux-Kernel ist ein groĂes Programm, das viele Dinge verwaltet. Selbst mit einer so minimalen Konfiguration kann das Erstellen auf alter Hardware ausreichend Zeit in Anspruch nehmen. Daher erstellen Sie den Kernel mit dem folgenden Befehl:
make ARCH=um -j$(nproc) Warum? Dieser Befehl sagt unserem Compiler, alle verfĂŒgbaren Kerne und Prozessor-Threads wĂ€hrend des Bauprozesses zu nutzen. Der Befehl $(nproc) am Ende von Build ersetzt das Ergebnis des Befehls nproc, der Teil von coreutils in der Standardinstallation von Ubuntu ist.
Nach einiger Zeit wird unser Kernel in eine ausfĂŒhrbare Datei erstellt ./linux.
Installation des BinÀrdatei
Da der User Mode in Linux ein normales BinÀrformat erstellt, können Sie es wie jede andere Utility installieren. So habe ich das gemacht:
mkdir -p ~/bin
cp linux ~/bin/linux Es ist auch wichtig sicherzustellen, dass ~/bin in Ihrem $PATH:
export PATH=$PATH:$HOME/binEinrichtung des Gast-Dateisystems
Erstellen Sie ein Verzeichnis fĂŒr das Gast-Dateisystem:
mkdir -p $HOME/prefix/uml-demo
cd $HOME/prefix
Besuchen Sie alpinelinux.org und suchen Sie im nach dem aktuellen Download-Link fĂŒr MINI ROOT FILESYSTEM. Zum Zeitpunkt der Veröffentlichung dieses Beitrags war das:
http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.0-x86_64.tar.gzLaden Sie dieses Tarball mit wget herunter:
wget -O alpine-rootfs.tgz http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.0-x86_64.tar.gzJetzt wechseln Sie in das Verzeichnis des Gast-Dateisystems und entpacken das Archiv:
cd uml-demo
tar xf ../alpine-rootfs.tgzDie beschriebenen Schritte erstellen ein kleines Vorlagen-Dateisystem. Aufgrund der Eigenschaften des Systems wird es Ă€uĂerst schwierig sein, Pakete ĂŒber den apk-Manager von Alpine zu installieren. Aber dieses FS wird ausreichen, um die allgemeine Idee zu bewerten.
Wir benötigen auch ein Werkzeug um den Speicherverbrauch unseres Gastkernels zu stoppen.
wget -O tini https://github.com/krallin/tini/releases/download/v0.18.0/tini-static
chmod +x tiniErstellen einer Kernel-Befehlszeile
Im Linux-Kernel, wie in den meisten anderen Programmen, gibt es Kommandozeilenargumente, die Sie einsehen können, indem Sie den SchlĂŒssel --help.
Selbst âhelp
linux --help
User Mode Linux v5.1.16
verfĂŒgbar unter http://user-mode-linux.sourceforge.net/
--showconfig
Gibt die Konfigurationsdatei aus, aus der dieses UML-BinÀrdatei generiert wurde.
iomem=,
Konfigurieren Sie als einen IO-Speicherbereich namens .
mem=
Dies steuert, wie viel "physischer" Speicher der Kernel fĂŒr das System reserviert.
Die GröĂe wird als eine Zahl gefolgt von einem der Buchstaben 'k', 'K', 'm', 'M' angegeben, die offensichtlich sind.
Dies steht nicht im Zusammenhang mit der Menge an Speicher im Host. Es kann mehr sein, und der Ăberschuss, falls er jemals verwendet wird, wird einfach ausgelagert.
Beispiel: mem=64M
--help
Gibt diese Nachricht aus.
debug
Dieses Flag ist nicht erforderlich, um gdb im UML im skas-Modus auszufĂŒhren.
root=
Dies wird tatsĂ€chlich vom generischen Kernel auf genau die gleiche Weise verwendet wie in jedem anderen Kernel. Wenn Sie eine Anzahl von BlockgerĂ€ten konfigurieren und von etwas booten möchten, das nicht ubd0 ist, wĂŒrden Sie etwas verwenden wie:
root=/dev/ubd5
--version
Gibt die Versionsnummer des Kernels aus.
umid=
Dies wird verwendet, um dieser UML-Maschine eine eindeutige IdentitĂ€t zuzuweisen und wird fĂŒr die Benennung der PID-Datei und des Verwaltungskonsolensockets verwendet.
con[0-9]*=
SchlieĂt eine Konsole oder serielle Leitung an einen Hostkanal an. Siehe
http://user-mode-linux.sourceforge.net/old/input.html fĂŒr eine vollstĂ€ndige Beschreibung dieses Schalters.
eth[0-9]+=,
Konfigurieren Sie ein NetzwerkgerÀt.
aio=2.4
Dies wird verwendet, um UML zu zwingen, 2.4-Stil AIO zu verwenden, selbst wenn 2.6 AIO verfĂŒgbar ist. 2.4 AIO ist ein einzelner Thread, der einen Antrag auf einmal synchron verarbeitet. 2.6 AIO ist ein Thread, der die 2.6 AIO-Schnittstelle verwendet, um eine beliebige Anzahl von ausstehenden Anfragen zu verarbeiten. 2.6 AIO ist nicht im tt-Modus, auf 2.4-Hosts oder wenn UML mit /usr/include/linux/aio_abi.h nicht verfĂŒgbar gebaut wurde. Viele Distributionen beinhalten aio_abi.h nicht, daher mĂŒssen Sie es aus einem Kernelbaum nach /usr/include/linux kopieren, um ein AIO-fĂ€higes UML zu bauen.
nosysemu
Deaktiviert den Systemaufruf-emulations-Patch fĂŒr ptrace (SYSEMU).
SYSEMU ist ein Leistungspatch, der von Laurent Vivier eingefĂŒhrt wurde. Es Ă€ndert das Verhalten von ptrace() und hilft, die Kontextwechselraten des Hosts zu reduzieren.
Damit es funktioniert, benötigen Sie auch einen Kernel-Patch fĂŒr Ihren Host.
Siehe http://perso.wanadoo.fr/laurent.vivier/UML/ fĂŒr weitere Informationen.
uml_dir=
Der Ort, um die PID- und umid-Dateien abzulegen.
quiet
Schaltet Informationsnachrichten wÀhrend des Bootvorgangs aus.
hostfs=,,...
Dies wird verwendet, um hostfs-Parameter festzulegen. Das Argument fĂŒr das Root-Verzeichnis wird verwendet, um alle Hostfs-Mounts auf den angegebenen Verzeichnisbaum im Host zu beschrĂ€nken. Wenn dies nicht angegeben wird, kann ein Benutzer innerhalb von UML alles auf dem Host einhĂ€ngen, das fĂŒr den Benutzer, der es ausfĂŒhrt, zugĂ€nglich ist.
Das einzige derzeit unterstĂŒtzte Flag ist 'append', was angibt, dass alle von hostfs geöffneten Dateien im Anhang-Modus geöffnet werden.Dieses Banner zeigt die grundlegenden Startparameter. Lassen Sie uns den Kernel mit dem minimal notwendigen Satz an Optionen starten:
linux
root=/dev/root
rootfstype=hostfs
rootflags=$HOME/prefix/uml-demo
rw
mem=64M
init=/bin/shDie obigen Zeilen sagen unserem Kernel Folgendes:
- Angenommen, das Root-Dateisystem ist ein Pseudo-GerÀt.
/dev/root. - WĂ€hle als Treiber des Root-Dateisystems.
- Binde das Gast-Dateisystem ein, das wir im Root-GerÀt erstellt haben.
- Und ja, im Lese- und Schreibmodus.
- Verwende nur 64 Megabyte RAM (du kannst viel weniger verwenden, je nachdem, was du vorhast, aber 64 MB erscheinen optimal).
- Der Kernel startet automatisch
/bin/shalsinit-Prozess.
FĂŒhre diesen Befehl aus und du solltest etwas wie Folgendes erhalten:
Noch ein Blatt
Kerneltabellen:
weich - 0
hart - KEINE
ĂberprĂŒfung, ob ptrace Systemaufrufnummern Ă€ndern kann...OK
ĂberprĂŒfung des Syscall-Emulationspatches fĂŒr ptrace...OK
ĂberprĂŒfung des erweiterten Syscall-Emulationspatches fĂŒr ptrace...OK
ĂberprĂŒfung der Umgebungsvariablen fĂŒr ein tempdir...keines gefunden
ĂberprĂŒfung, ob /dev/shm auf tmpfs ist...OK
ĂberprĂŒfung von PROT_EXEC mmap in /dev/shm...OK
32137216 Bytes zum physischen Speicher hinzugefĂŒgt, um die LĂŒcke des exec-shields auszugleichen
Linux-Version 5.1.16 (cadey@kahless) (gcc-Version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #30 So Jul 7 18:57:19 UTC 2019
1 Zonelisten erstellt, MobilitÀtsgruppierung aktiv. Gesamtseiten: 23898
Kernel-Befehlszeile: root=/dev/root rootflags=/home/cadey/dl/uml/alpine rootfstype=hostfs rw mem=64M init=/bin/sh
Dentry-Cache-Hash-TabelleneintrÀge: 16384 (Ordnung: 5, 131072 Bytes)
Inode-Cache-Hash-TabelleneintrÀge: 8192 (Ordnung: 4, 65536 Bytes)
Speicher: 59584K/96920K verfĂŒgbar (2692K Kernelcode, 708K rwdata, 588K rodata, 104K init, 244K bss, 37336K reserviert, 0K cma-reserviert)
SLUB: HWalign=64, Ordnung=0-3, MinObjects=0, CPUs=1, Knoten=1
NR_IRQS: 15
Uhrzeitquelle: timer: Maske: 0xffffffffffffffff max_cycles: 0x1cd42e205, max_idle_ns: 881590404426 ns
Kalibrierung der Verzögerungsschleife... 7479.29 BogoMIPS (lpj=37396480)
pid_max: standard: 32768 minimum: 301
Mount-Cache-Hash-TabelleneintrÀge: 512 (Ordnung: 0, 4096 Bytes)
Mountpoint-Cache-Hash-TabelleneintrÀge: 512 (Ordnung: 0, 4096 Bytes)
ĂberprĂŒfung, ob Host-PTYs die Ausgabe SIGIO unterstĂŒtzen...Ja
ĂberprĂŒfung, ob Host-PTYs SIGIO beim SchlieĂen unterstĂŒtzen...Nein, Workaround aktivieren
devtmpfs: initialisiert
random: get_random_bytes wurde von setup_net+0x48/0x1e0 mit crng_init=0 aufgerufen
Verwendung von 2.6 Host AIO
Uhrzeitquelle: jiffies: Maske: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
Futex-Hash-TabelleneintrÀge: 256 (Ordnung: 0, 6144 Bytes)
NET: Registrierte Protokollfamilie 16
Uhrzeitquelle: gewechselt zu Uhrzeitquelle timer
NET: Registrierte Protokollfamilie 2
tcp_listen_portaddr_hash Hash-TabelleneintrÀge: 256 (Ordnung: 0, 4096 Bytes)
TCP-Hash-TabelleneintrÀge: 1024 (Ordnung: 1, 8192 Bytes)
TCP-Bind-Hash-TabelleneintrÀge: 1024 (Ordnung: 1, 8192 Bytes)
TCP: Hash-Tabellen konfiguriert (etabliert 1024 bind 1024)
UDP-Hash-TabelleneintrÀge: 256 (Ordnung: 1, 8192 Bytes)
UDP-Lite-Hash-TabelleneintrÀge: 256 (Ordnung: 1, 8192 Bytes)
NET: Registrierte Protokollfamilie 1
Konsole [stderr0] deaktiviert
mconsole (Version 2) auf /home/cadey/.uml/tEwIjm/mconsole initialisiert
ĂberprĂŒfung der Host-MADV_REMOVE-UnterstĂŒtzung...OK
workingset: timestamp_bits=62 max_order=14 bucket_order=0
Blockschicht SCSI-Grafik (bsg) Treiberversion 0.4 geladen (major 254)
io-Planer noop registriert (Standard)
io-Planer bfq registriert
loop: Modul geladen
NET: Registrierte Protokollfamilie 17
Standardausgabe-Konsole Treiber initialisiert
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 1 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 2 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 3 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 4 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 5 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 6 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 7 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 8 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 9 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 10 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 11 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 12 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 13 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 14 : Konfiguration fehlgeschlagen
Verwendung eines Kanals, der auĂerhalb von UML konfiguriert ist
setup_one_line fehlgeschlagen fĂŒr GerĂ€t 15 : Konfiguration fehlgeschlagen
Konsole auf /dev/tty0 initialisiert
konsole [tty0] aktiviert
konsole [mc-1] aktiviert
Fehler beim Initialisieren des ubd-GerĂ€ts 0 : GröĂe der GerĂ€te-Datei konnte nicht bestimmt werden
VFS: Wurzel (hostfs-Dateisystem) auf GerÀt 0:11 gemountet.
devtmpfs: gemountet
Diese Architektur verfĂŒgt nicht ĂŒber einen Kernel-Speicherschutz.
FĂŒhren Sie /bin/sh als Init-Prozess aus
/bin/sh: kann tty nicht erreichen; Jobsteuerung deaktiviert
random: schneller Init abgeschlossen
/ # Die obigen Manipulationen geben uns ein minimales Gastbetriebssystem, ohne solche Dinge wie /proc oder benannten Hostnamen. Versuchen Sie zum Beispiel, die folgenden Befehle auszufĂŒhren:
- uname -av
- cat /proc/self/pid
- hostname
Um aus dem Gastbetriebssystem auszutreten, geben Sie ein exit oder drĂŒcken Sie Strg-D. Das wird die Shell mit einem nachfolgenden Kernel Panic beenden:
/ # exit
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000
fish: â./linux root=/dev/root rootflagâŠâ terminated by signal SIGABRT (Abort) Wir haben diesen Kernel Panic aufgrund der Tatsache erhalten, dass der Linux-Kernel denkt, dass der Initialisierungsprozess immer aktiv ist. Ohne ihn kann das System nicht mehr funktionieren und wird heruntergefahren. Da dies jedoch ein Prozess im Benutzermodus ist, sendet das erhaltene Ergebnis sich selbst an SIGABRT, was zum Austritt fĂŒhrt.
Einrichtung des Gastnetzes
Hier beginnt es, nicht nach Plan zu verlaufen. Das Netzwerk im User Mode Linux ist der Ort, an dem das gesamte Konzept des eingeschrĂ€nkten âBenutzermodusâ zu zerfallen beginnt. Denn ĂŒblicherweise ist das Netzwerk auf Systemebene privilegierten AusfĂŒhrungsmodi aus den uns allen bekannten GrĂŒnden eingeschrĂ€nkt.
Hinweis: Mehr ĂŒber verschiedene Optionen zur Arbeit mit Netzwerken in UML kann gelesen werden .
Reise zu slirp
Es gibt jedoch ein altes und nahezu nicht unterstĂŒtztes Werkzeug namens , mit dem User Mode Linux mit dem Netzwerk interagieren kann. Es funktioniert ungefĂ€hr wie ein TCP/IP-Stack auf Benutzerebene und benötigt keine Systemberechtigungen zum Starten. Dieses Werkzeug wurde 1995 veröffentlicht, und das letzte Update stammt aus 2006.Slirp ist sehr alt. WĂ€hrend der Zeit ohne UnterstĂŒtzung und Updates sind die Compiler so weit fortgeschritten, dass dieses Werkzeug nur als .
beschrieben werden kann. Also, lassen Sie uns Slirp aus den Ubuntu-Repositories installieren und versuchen, es zu starten:
sudo apt-get install slirp
/usr/bin/slirp
Slirp v1.0.17 (BETA)
Copyright (c) 1995,1996 Danny Gasparovski und andere.
Alle Rechte vorbehalten.
Dieses Programm ist urheberrechtlich geschĂŒtzt, freie Software.
Bitte lesen Sie die Datei COPYRIGHT, die mit dem Slirp
Paket geliefert wird, um die Nutzungsbedingungen zu erfahren.
IP-Adresse des Slirp-Hosts: 127.0.0.1
IP-Adresse Ihrer DNS(s): 1.1.1.1, 10.77.0.7
Ihre Adresse ist 10.0.2.15
(oder alles andere, was Sie möchten)
Geben Sie fĂŒnf Nullen (0) ein, um zu beenden.
[Automatische Erkennung SLIP/CSLIP, MTU 1500, MRU 1500, 115200 Baud]
SLiRP Bereit ...
fish: "/usr/bin/slirp" beendet durch Signal SIGSEGV (Adressgrenzenfehler)Oh, mein Gott. Lassen Sie uns einen Debugger fĂŒr Slirp installieren und sehen, ob wir herausfinden können, was hier vor sich geht:
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.
Lizenz GPLv3+: GNU GPL Version 3 oder neuer
Diese Software ist kostenlos: Sie können sie Àndern und weiterverbreiten.
Es gibt KEINE GARANTIE, soweit es das Gesetz zulÀsst. Tippen Sie "show copying"
und "show warranty" fĂŒr Details ein.
Dieses GDB wurde als "x86_64-linux-gnu" konfiguriert.
Tippen Sie "show configuration" fĂŒr Konfigurationsdetails ein.
FĂŒr Anleitungen zur Fehlermeldung siehe:
.
Finden Sie das GDB-Handbuch und andere Dokumentationsressourcen online unter:
.
FĂŒr Hilfe tippen Sie "help".
Tippen Sie "apropos word" um nach Befehlen zu suchen, die mit "word" zu tun haben...
Lese Symbole von /usr/bin/slirp...Lese Symbole von /usr/lib/debug/.build-id/c6/2e75b69581a1ad85f72ac32c0d7af913d4861f.debug...fertig.
fertig.
(gdb) run
Starte Programm: /usr/bin/slirp
Slirp v1.0.17 (BETA)
Copyright (c) 1995,1996 Danny Gasparovski und andere.
Alle Rechte vorbehalten.
Dieses Programm ist urheberrechtlich geschĂŒtzt, freie Software.
Bitte lesen Sie die Datei COPYRIGHT, die mit dem Slirp
Paket geliefert wurde, fĂŒr die Bedingungen und Konditionen des Urheberrechts.
IP-Adresse des Slirp-Hosts: 127.0.0.1
IP-Adresse Ihrer DNS(s): 1.1.1.1, 10.77.0.7
Ihre Adresse ist 10.0.2.15
(oder alles andere, was Sie wollen)
Geben Sie fĂŒnf Nullstellen (0) ein, um zu beenden.
[autodetect SLIP/CSLIP, MTU 1500, MRU 1500, 115200 baud]
SLiRP Bereit ...
Programm empfing Signal SIGSEGV, Segmentierungsfehler.
ip_slowtimo () in ip_input.c:457
457 ip_input.c: Datei oder Verzeichnis nicht gefunden.Ein Fehler tritt in . Lassen Sie uns den Stacktrace ansehen, vielleicht hilft er uns weiter:
(gdb) bt full
#0 ip_slowtimo () in ip_input.c:457
fp = 0x55784a40
#1 0x000055555556a57c in main_loop () in ./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) in ./main.c:95
Keine lokalen Variablen.Hier sehen wir, dass der Fehler wĂ€hrend des Starts der Hauptschleife auftritt, wenn Slirp versucht, die ZeitĂŒberschreitungen zu ĂŒberprĂŒfen. An diesem Punkt hĂ€tte ich aufgeben sollen, weiter zu debuggen. Aber lassen Sie uns sehen, ob Slirp, das aus den Quellen gebaut wurde, funktioniert. Ich habe das Archiv direkt von der Website heruntergeladen, , denn etwas von dort ĂŒber die Befehlszeile zu ziehen ist mĂŒhsam:
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 Hier sehen wir Warnungen ĂŒber undefinierte eingebaute Funktionen, d.h. es ist nicht möglich, die resultierende BinĂ€rdatei zu verlinken. Es scheint, als hĂ€tte gcc im Zeitraum zwischen 2006 und diesem Zeitpunkt aufgehört, Symbole zu erzeugen, die in eingebauten Funktionen in zwischenkompilierten Dateien verwendet werden. Lassen Sie uns versuchen, das SchlĂŒsselwort inline durch einen leeren Kommentar zu ersetzen und das Ergebnis zu betrachten:
vi slirp.h
:6
a
#define inline /**/
:wq
makeNein. Das funktioniert auch nicht. Ich kann die Symbole dieser Funktionen immer noch nicht finden.
An diesem Punkt gab ich auf und begann auf Github zu suchen . Meine Theorie basierte darauf, dass in irgendeinem Heroku-Build-Paket die benötigten BinĂ€rdateien enthalten sein wĂŒrden. SchlieĂlich fĂŒhrte mich meine Suche . Ich habe heruntergeladen und entpackt uml.tar.gz und fand Folgendes:
gesamt 6136
-rwxr-xr-x 1 cadey cadey 79744 10. Dez 2017 ifconfig*
-rwxr-xr-x 1 cadey cadey 373 13. Dez 2017 init*
-rwxr-xr-x 1 cadey cadey 149688 10. Dez 2017 insmod*
-rwxr-xr-x 1 cadey cadey 66600 10. Dez 2017 route*
-rwxr-xr-x 1 cadey cadey 181056 26. Jun 2015 slirp*
-rwxr-xr-x 1 cadey cadey 5786592 15. Dez 2017 uml*
-rwxr-xr-x 1 cadey cadey 211 13. Dez 2017 uml_run*Das ist die BinÀrdatei slirp! Funktioniert sie?
./slirp
Slirp v1.0.17 (BETA) FULL_BOLT
Copyright (c) 1995,1996 Danny Gasparovski und andere.
Alle Rechte vorbehalten.
Dieses Programm ist urheberrechtlich geschĂŒtzt, freeware.
Bitte lesen Sie die Datei COPYRIGHT, die mit dem Slirp
Paket geliefert wurde, um die Bedingungen und Bestimmungen des Urheberrechts zu erfahren.
IP-Adresse des Slirp-Hosts: 127.0.0.1
IP-Adressen Ihrer DNS(s): 1.1.1.1, 10.77.0.7
Ihre Adresse ist 10.0.2.15
(oder alles andere, was Sie wollen)
Geben Sie fĂŒnf Nullen (0) ein, um zu beenden.
[automatische Erkennung SLIP/CSLIP, MTU 1500, MRU 1500]
SLiRP Bereit ...
Es stĂŒrzt nicht ab â es sollte also funktionieren! Lassen Sie uns diese BinĂ€rdatei in ~ /bin/slirp:
cp slirp ~ /bin/slirpFĂŒr den Fall, dass der Paket-Ersteller es entfernt, habe ich .
Netzwerkkonfiguration
Jetzt lassen Sie uns das Netzwerk auf unserem Gastkernel einrichten. :
linux
root=/dev/root
rootfstype=hostfs
rootflags=$HOME/prefix/uml-demo
rw
mem=64M
eth0=slirp,,$HOME/bin/slirp
init=/bin/shJetzt aktivieren wir das Netzwerk:
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 Die ersten beiden Konfigurationsbefehle /proc und /sys sind notwendig fĂŒr die Funktion ifconfig, die das Netzwerk-Interface fĂŒr die Kommunikation mit Slirp einrichtet. Der Befehl Route richtet die Routingtabelle des Kernels ein, um den gesamten Verkehr durch den Slirp-Tunnel zu leiten. Lassen Sie uns dies mit einem DNS-Abfrage ĂŒberprĂŒfen:
nslookup google.com 8.8.8.8
Server: 8.8.8.8
Adresse 1: 8.8.8.8 dns.google
Name: google.com
Adresse 1: 172.217.12.206 lga25s63-in-f14.1e100.net
Adresse 2: 2607:f8b0:4006:81b::200e lga25s63-in-x0e.1e100.netEs funktioniert!
Anmerkung: Anscheinend wurde der ursprĂŒngliche Post auf einem Desktop mit einer kabelgebundenen Netzwerkkarte oder einer anderen Konfiguration, die keine zusĂ€tzlichen Treiber benötigt, verfasst. Bei einem Laptop mit WiFi 8265 von Intel tritt beim Aktivieren des Netzwerks ein Fehler auf.
/ # 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
/ #Offensichtlich kann der Kernel nicht mit dem Treiber der Netzwerkkarte kommunizieren. Der Versuch, die Firmware in den Kernel zu kompilieren, hat die Situation leider nicht verbessert. Zum Zeitpunkt der Veröffentlichung konnte in dieser speziellen Konfiguration bisher keine Lösung gefunden werden. In einfacheren Konfigurationen (zum Beispiel in Virtualbox) funktioniert das Interface jedoch korrekt.
Lassen Sie uns die Weiterleitung mit folgendem Shell-Skript automatisieren:
#!/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/shUnd machen wir es ausfĂŒhrbar:
chmod +x init.shUnd dann Àndern wir die Kernel-Befehlszeile:
linux
root=\/dev\/root
rootfstype=hostfs
rootflags=$HOME\/prefix\/uml-demo
rw
mem=64M
eth0=slirp,,$HOME\/bin\/slirp
init=\/init.sh
Und wiederholen wir:
SLiRP Bereit ...
Netzwerk eingerichtet
\/bin\/sh: kann tty nicht erreichen; Job-Kontrolle deaktiviert
nslookup google.com 8.8.8.8
Server: 8.8.8.8
Adresse 1: 8.8.8.8 dns.google
Name: google.com
Adresse 1: 172.217.12.206 lga25s63-in-f14.1e100.net
Adresse 2: 2607:f8b0:4004:800::200e iad30s09-in-x0e.1e100.netDas Netzwerk funktioniert stabil!
Docker-Datei
Um Ihnen das ĂberprĂŒfen zu erleichtern, habe ich , die die meisten beschriebenen Schritte automatisiert und Ihnen eine funktionierende Konfiguration bieten sollte. AuĂerdem habe ich eine , die alles enthĂ€lt, was im Beitrag beschrieben ist. Es ist jedoch wichtig zu verstehen, dass ich hier nur die minimale Konfiguration dargelegt habe.
Ich hoffe, dass dieser Beitrag Ihnen geholfen hat zu verstehen, wie man einen Gastkernel hochfĂ€hrt. Es ist ein ganz schöner Brocken geworden, aber der Beitrag war als umfassende Anleitung zur Erstellung, Installation und Konfiguration von User Mode in Linux fĂŒr moderne Betriebssystemversionen dieses Typs gedacht. Die nĂ€chsten Schritte sollten die Installation von Diensten und anderer Software innerhalb des Gastsystems umfassen. Da Docker-Images einfach gepackte tar-Archive sind, sollten Sie in der Lage sein, das Image ĂŒber docker export, zu extrahieren und den Installationspfad im Stammverzeichnis des Gastkernels festzulegen. Danach fĂŒhren Sie das Shell-Skript aus.
Ein besonderer Dank geht an Rkeene mit #lobsters auf Freenode. Ohne seine Hilfe beim Debuggen von Slirp wĂ€re ich nicht so weit gekommen. Ich habe keine Ahnung, wie sein Slackware-System korrekt mit slirp funktioniert, aber meine Systeme Ubuntu und Alpine haben slirp und die von Rkeene vorgeschlagene BinĂ€rdatei nicht akzeptiert. Aber ich bin froh, dass ich ĂŒberhaupt etwas zum Laufen gebracht habe.
Quelle: habr.com
