Уступ ад перакладчыка: На фоне масавага ўваходу ў нашае жыццё рознага роду кантэйнераў можа быць даволі цікава і карысна даведацца, з якіх тэхналогій гэта ўсё пачыналася калісьці. Некаторыя з іх можна з карысцю ўжываць і дагэтуль, але не ўсё пра такія спосабы памятаюць (ці ведаюць, калі не заспелі падчас іх бурнага развіцця). Адной з такіх тэхналогій з'яўляецца User Mode Linux. Аўтар арыгінала ладна пакапалася, разбіраючыся, што са старых напрацовак яшчэ працуе, а што ўжо не вельмі, і сабрала нешта накшталт пакрокавай інструкцыі аб тым, як самому сабе завесці дамарослы UML у 2к19. І так, мы запрасілі на Хабр аўтара арыгінальнай пасады Cadey, Так што калі ёсць пытанні - задавайце на англійскай ў каментарах.
User Mode у Linux - гэта, фактычна, порт ядра Linux на само сябе. Гэты рэжым дазваляе запусціць паўнавартаснае ядро Linux у якасці карыстацкага працэсу і звычайна выкарыстоўваецца распрацоўшчыкамі для тэставання драйвераў. Але таксама гэты рэжым карысны і ў якасці прылады агульнай ізаляцыі, прынцып якой падобны на працу віртуальных машын. Дадзены рэжым забяспечваюць большую ізаляцыю, чым Docker, але меншую, чым паўнавартасная віртуальная машына накшталт KVM ці Virtual Box.
У цэлым, User Mode можа здацца дзіўным і складаным у выкарыстанні прыладай, але ў яго ўсё ж ёсць свае вобласці ўжывання. Бо гэта паўнавартаснае Linux-ядро, якое працуе ад непрывілеяванага карыстача. Гэтая асаблівасць дазваляе запускаць патэнцыйна ненадзейны код без якіх-небудзь пагроз для хост-машыны. А паколькі гэта паўнавартаснае ядро, яго працэсы ізаляваныя ад хост-машыны, гэта значыць працэсы, якія працуюць усярэдзіне User Mode, не будуць бачныя для хаста. Гэта не падобна на звыклы Docker-кантэйнер, у выпадку якога хост-машына заўсёды бачыць працэсы ўсярэдзіне сховішча. Паглядзіце на гэты кавалак pstree з аднаго з маіх сервераў:
І параўнайце гэта з pstree ядра Linux у User Mode:
linux─┬─5*[linux]
└─slirp
Пры працы з Docker-кантэйнерамі я магу бачыць з хаста імёны працэсаў, якія запушчаныя ў гасцёўні сістэме. З Linux User Mode гэта немагчыма. Што гэта значыць? Гэта значыць, што прылады маніторынгу, якія працуюць праз падсістэму аўдыту Linux (Linux's auditing subsystem) не бачаць працэсы, якія выконваюцца ў гасцявой сістэме. Але ў некаторых сітуацыях гэтая асаблівасць можа стаць палкай з двума канцамі.
Наогул увесь пост ніжэй - гэта набор даследаванняў і грубых спроб дамагчыся жаданага выніку. Для гэтага мне даводзілася выкарыстоўваць розныя старажытныя інструменты, чытаць зыходнікі ядра, займацца інтэнсіўнай адладкай кода, напісанага ў часы, калі я яшчэ хадзіла ў пачатковую школу, а таксама калупацца ў зборках Heroku з дапамогай спецыяльнага бінара ў пошуках патрэбных мне інструментаў. Уся гэтая праца прывяла да таго, што хлопцы ў маім IRC сталі называць мяне чараўніцай (magic). Я спадзяюся, што гэты пост паслужыць камусьці надзейнай дакументацыяй для таго, каб пракруціць усё тое ж самае, але ўжо з навейшымі ядрамі і версіямі АС.
Настройка
Настройка Linux User Mode выконваецца ў некалькі этапаў:
усталёўка залежнасцяў на хасце;
спампоўка ядра Linux;
настройка зборкі ядра;
зборка ядра;
інсталяцыя бінарніка;
настройка гасцявой файлавай сістэмы;
падбор параметраў запуску ядра;
настройка гасцявой сеткі;
запуск гасцявога ядра.
Я мяркую, што калі вы вырашыце самастойна гэта ўсё пракруціць, хутчэй за ўсё, будзеце рабіць усё апісанае ў якой-небудзь Ubuntu ці Debian-падобнай сістэме. Я спрабавала рэалізаваць усё вышэйапісанае ў маім каханым дыстрыбутыве – Alpine, але нічога не выйшла, па ўсёй бачнасці, па чынніку таго, што ядро Linux мае цвёрдую прывязку па glibc-isms для драйвераў у User Mode. Планую паведаміць пра гэта ў апстрым пасля таго, як канчаткова разбяруся ў праблеме.
Устаноўка залежнасцяў на хасце
Ubuntu патрабуе, прынамсі, наступныя пакеты для зборкі ядра Linux (пры ўмове чыстай усталёўкі):
Звярніце ўвагу, што запуск праграмы наладкі меню для ядра Linux запатрабуе ўсталёўкі libncurses-dev. Калі ласка, пераканайцеся, што ён усталяваны з дапамогай наступнай каманды (з правамі root ці з дапамогай sudo):
apt-get -y install libncurses-dev
Спампоўванне ядра
Вызначыце месца для загрузкі і наступнай зборкі ядра. Для гэтай аперацыі вам запатрабуецца вылучыць каля 1,3 Гб прасторы на цвёрдай кружэлцы, таму пераканайцеся, што яно ў вас ёсць.
Цяпер уваходзім у дырэкторыю, створаную пры распакаванні tarball:
cd linux-5.1.16
Настройка зборкі ядра
Сістэма зборкі ядра - гэта набор Make-файлаў с мноствам карыстацкіх інструментаў і скрыптоў для аўтаматызацыі працэсу. Для пачатку адкрыйце інтэрактыўную праграму наладкі:
make ARCH=um menuconfig
Яна часткова правядзе зборку і выведзе вам дыялогавае акно. Калі ўнізе акна высвеціцца '[Select]', вы зможаце заняцца наладай з дапамогай клавіш Прабел або Увод. Навігацыя па акне, як звычайна, стрэлкамі клавіятуры "уверх" і "ўніз", а вылучэнне элементаў - "налева" або "направа".
Паказальнік выгляду -> азначае, што вы знаходзіцеся ў падменю, уваход у якое ажыццяўляецца клавішай Увод. Выйсце з яго, відавочна, праз '[Exit]».
Уключыце наступныя параметры ў '[Select]' і пераканайцеся, што побач з імі ёсць сімвал '[*]':
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
Усё, з гэтага акна можна выходзіць, паслядоўна выбіраючы '[Exit]'. Толькі пераканайцеся, што ў канцы вам прапануе захаваць канфігурацыю і вылучыце '[Yes]».
Я рэкамендую вам пагуляцца з параметрамі зборкі ядра пасля прачытання гэтай пасады. Дзякуючы гэтым эксперыментамі вы зможаце шматлікае запазычыць у плане разумення працы нізкаўзроўневых механік ядра і ўплывы розных сцягоў на яго зборку.
Зборка ядра
Ядро Linux - гэта вялікая праграма, якая займаецца мноствам рэчаў. Нават пры такой мінімальнай канфігурацыі на старым абсталяванні яго зборка можа заняць дастаткова часу. Таму зьбірайце ядро з дапамогай наступнай каманды:
make ARCH=um -j$(nproc)
Навошта? Гэтая каманда скажа нашаму зборшчыку выкарыстоўваць усе даступныя ядры і патокі працэсара ў працэсе зборкі. Каманда $(nproc) у канцы Build падстаўляе выснову каманды nproc, якая з'яўляецца часткай coreutils у стандартнай зборцы Ubuntu.
Па сканчэнні некаторага часу наша ядро будзе сабрана ў выкананы файл ./linux.
Інсталяцыя бінарніка
Бо User Mode у Linux стварае звычайны бінарнік, вы можаце ўсталяваць яго, як і любую іншую ўтыліту. Вось як гэта рабіла я:
mkdir -p ~/bin
cp linux ~/bin/linux
Таксама варта пераканацца, што ~/bin знаходзіцца ў вашым $PATH:
export PATH=$PATH:$HOME/bin
Настройка гасцявой файлавай сістэмы
Стварыце дырэкторыю для гасцявой файлавай сістэмы:
mkdir -p $HOME/prefix/uml-demo
cd $HOME/prefix
Адкрыйце alpinelinux.org і ў раздзеле загрузак знайдзіце актуальную спасылку на запампоўку MINI ROOT FILESYSTEM. На момант напісання публікацыі гэта было:
Цяпер увайдзіце ў дырэкторыю гасцявой файлавай сістэмы і распакуйце архіў:
cd uml-demo
tar xf ../alpine-rootfs.tgz
Апісаныя дзеянні створаць маленькі шаблон файлавай сістэмы. З-за асаблівасцяў працы сістэмы ўсталёўваць пакеты праз дыспетчар apk Alpine будзе вельмі складана. Але дадзенай ФС будзе дастаткова для ацэнкі агульнай ідэі.
Таксама нам спатрэбіцца інструмент ціні для спынення спажывання памяці зомбі-працэсамі нашага гасцявога ядра.
wget -O tini https://github.com/krallin/tini/releases/download/v0.18.0/tini-static
chmod +x tini
Стварэнне каманднага радка ядра
У ядры Linux, як і ў большасці іншых праграм, ёсць аргументы каманднага радка, з якімі можна азнаёміцца, паказаўшы ключ --help.
Сам -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=<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.
Гэта палотнішча асвятляе асноўныя параметры запуску. Давайце запусцім ядро з мінімальным неабходным наборам опцый:
linux
root=/dev/root
rootfstype=hostfs
rootflags=$HOME/prefix/uml-demo
rw
mem=64M
init=/bin/sh
Радкі вышэй кажуць нашаму ядру наступнае:
Выкажам здагадку, што каранёвая файлавая сістэма з'яўляецца псеўда-прыладай /dev/root.
выберы hostfs у якасці драйвера каранёвай файлавай сістэмы.
Змантуй гасцёўню файлавую сістэму, якую мы стварылі ў root-прыладзе.
І так, у рэжыме чытання-запісы.
Выкарыстоўвай толькі 64 мегабайта аператыўнай памяці (вы можаце выкарыстоўваць значна менш, у залежнасці ад таго, што вы плануеце рабіць, але 64 МБ здаюцца аптымальным аб'ёмам).
Ядро аўтаматычна запускае /bin/sh як init-працэс.
Запусціце гэтую каманду, і вы павінны атрымаць нешта накшталт наступнага:
Яшчэ адна прасціна
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
/ #
Маніпуляцыі вышэй дадуць нам гасцёўню сістэму на мінімалках, без такіх рэчаў, як /proc ці прысвоены хостнейм. Для прыкладу, паспрабуйце выканаць наступныя каманды:
- uname -av
- cat /proc/self/pid
- hostname
Каб выйсці з гасцявой сістэмы, увядзіце exit ці націсніце control-d. Гэта прыстрэліць абалонку з наступным kernel panic:
/ # exit
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000
fish: “./linux root=/dev/root rootflag…” terminated by signal SIGABRT (Abort)
Мы атрымалі гэты kernel panic з прычыны таго, што ядро Linux лічыць, што працэс ініцыялізацыі заўсёды запушчаны. Без яго сістэма больш не можа функцыянаваць і завяршае працу. Але так як гэта працэс карыстацкага рэжыму, атрыманы вынік адпраўляе сам сябе ў SIGABRT, Што прыводзіць да выхаду.
Настройка гасцявой сеткі
А вось тут у нас усё пачынае ісці не па плане. Сетка ў User Mode Linux - гэта тое месца, дзе ўся канцэпцыя абмежаванага "карыстацкага рэжыму" пачынае развальвацца. Бо звычайна на сістэмным узроўні сетка абмежавана прывілеяванымі рэжымамі выканання па ўсіх нам зразумелых прычынах.
Заўв. зав.: больш аб розных варыянтах працы з сеткай у UML можна пачытаць тут.
Падарожжа ў slirp
Аднак жа існуе старажытная і практычна непадтрымоўваная прылада пад назовам Slirp, пры дапамозе якога User Mode Linux можа ўзаемадзейнічаць з сеткай. Ён працуе прыкладна як стэк TCP/IP на ўзроўні карыстача і не патрабуе якія-небудзь сістэмных дазволаў для запуску. Гэты інструмент быў выпушчаны ў 1995 годзе, а апошняе абнаўленне датуецца 2006 годам. Slirp вельмі стары. За час без падтрымкі і абнаўленняў кампілятары сышлі настолькі далёка, што зараз гэтая прылада можна ахарактарызаваць толькі як «code rot».
Такім чынам, давайце накацім Slirp з рэпазітараў Ubuntu і паспрабуем яго запусціць:
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)
Ох, бажачкі. Давайце ўсталюем адладчык для Slirp і паглядзім, ці зможам разабрацца, што тут адбываецца:
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.
Памылка б'ецца ў нас у гэтым радку. Давайце паглядзім на stacktrace, можа там нам што-небудзь дапаможа:
(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.
Тут мы бачым, што збой адбываецца падчас запуску асноўнага цыклу, калі slirp спрабуе праверыць тайм-аўты. Вось у гэты момант я мусіла адмовіцца ад спроб адладкі. Але давайце паглядзім, ці працуе Slirp, сабраны з сарцоў. Я паўторна загрузіла архіў напрамую з сайта Sourceforge, таму што цягнуць нешта адтуль праз камандны радок — боль:
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
Тут мы бачым алерты аб нявызначаных убудаваных функцыях, гэта значыць аб немагчымасці злінкаваць які атрымліваецца ў выніку бінарны файл. Падобна, у перыяд паміж 2006 годам і гэтым момантам gcc спыніў ствараць знакі, выкарыстоўваныя ў будаваных функцыях прамежкава скампіляваных файлаў. Давайце паспрабуем замяніць ключавое слова inline на пусты каментар і паглядзім на вынік:
vi slirp.h
:6
a
<enter>
#define inline /**/
<escape>
:wq
make
Не-а. Гэта таксама не працуе. Па-ранейшаму не ўдаецца знайсці сімвалы гэтых функцый.
На гэтым этапе я здалася і пачала шукаць на Github. пакеты зборкі Heroku. Мая тэорыя грунтавалася на тым, што ў якім-небудзь зборачным пакеце Heroku будуць утрымоўвацца неабходныя мне двайковыя файлы. У выніку пошукі прывялі мяне вось сюды. Я запампавала і распакавала uml.tar.gz і знайшла наступнае:
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*
Гэта бінарны файл slirp! А ён працуе?
./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 ...
Не падае - так што павінна спрацаваць! Давайце падсадзім гэты бінарнік у ~/bin/slirp:
cp slirp ~/bin/slirp
На выпадак, калі стваральнік пакета выдаліць яго, я зрабіла люстэрка.
Першыя дзве каманды наладкі /proc и /sys неабходны для працы ifconfig, якая устанаўлівае сеткавы інтэрфейс для сувязі з Slirp. Каманда route усталёўвае табліцу маршрутызацыі ядра для прымусовай адпраўкі ўсяго трафіку праз тунэль Slirp. Давайце праверым гэта з дапамогай DNS-запыту:
Заўв.пер.: Судзячы па ўсім, першапачатковы пост пісаўся на дэсктопе з правадной сеткавай картай, або нейкай іншай канфігурацыяй, не патрабавальнай дадатковых драйвераў. На наўтбуку з WiFi 8265 ад Intel жа пры ўзняцці сеткі ўзнікае памылка
/ # 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
/ #
Мабыць, ядро не можа звязацца з драйверам сецявухі. Спроба ўкампілаваць firmware у ядро сітуацыю, нажаль, не выправіла. На момант публікацыі менавіта ў такой канфігурацыі рашэння пакуль знайсці не ўдалося. На прасцейшых канфігах (напрыклад, у Virtualbox) інтэрфейс паднімаецца карэктна.
Давайце аўтаматызуем перанакіраванне з дапамогай наступнага shell-скрыпту:
linux
root=/dev/root
rootfstype=hostfs
rootflags=$HOME/prefix/uml-demo
rw
mem=64M
eth0=slirp,,$HOME/bin/slirp
init=/init.sh
І паўторым:
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
Сетка працуе стабільна!
Докер-файл
Каб вам было прасцей усё гэта праверыць, я сабрала Докер-файл, які аўтаматызуе большасць апісаных крокаў і павінен забяспечыць вам працоўную канфігурацыю. Яшчэ ў мяне ёсць гатовая канфігурацыя ядра, у якой ёсць усё, што апісана ў пасце. Але важна разумець, што тут я выклала толькі мінімальную настройку.
Я спадзяюся, што гэты пост дапамог вам зразумець, як падняць госцевае ядро. Атрымаўся нейкі монстар, але задумвалася публікацыя ў якасці ўсёабдымнага кіраўніцтва на тэму зборкі, усталёўкі і налады User Mode у Linux пад сучаснымі версіямі аперацыйных сістэм гэтага сямейства. Наступныя дзеянні павінны складацца з усталёўку сэрвісаў і іншага праграмнага забеспячэння ўжо ўсярэдзіне гасцявой сістэмы. Так як вобразы кантэйнераў Docker - гэта проста распіяраныя tar-архівы, вы павінны быць у стане атрымаць вобраз праз docker export, а затым вызначыць шлях яго ўстаноўкі ў корані файлавай сістэмы гасцявога ядра. Ну, а затым выканайце shell-скрыпт.
Асобны дзякуй Rkeene з #lobsters на Freenode. Без яго дапамогі ў адладцы Slirp я не зайшла б так далёка. Я паняцця не маю, як яго сістэма Slackware карэктна працуе са slirp, але мае сістэмы Ubuntu і Alpine не прынялі slirp і прапанаваны мне Rkeene бінарнік. Але мне дастаткова і таго, што ў мяне працуе хоць нешта.