如何在 Linux 中開始使用用戶模式

譯者介紹:在各種容器大量進入我們的生活的背景下,了解這些容器曾經是由哪些技術開始的,是非常有趣和有用的。 其中一些方法至今仍然有用,但並不是每個人都記得這些方法(或者知道它們在快速發展過程中是否未被捕獲)。 用戶模式 ​​Linux 就是其中一項技術。 原作者做了很多挖掘工作,弄清楚哪些舊的開發仍然有效,哪些無效,並整理出一些類似於如何在 2k19 中為自己提供自製 UML 的分步說明。 是的,我們邀請了原帖的作者到 Habr 卡迪,所以如果您有疑問,請在評論中用英語提問。

如何在 Linux 中開始使用用戶模式

Linux 中的用戶模式實際上是 Linux 內核對其自身的移植。 此模式允許您作為用戶進程運行完整的 Linux 內核,並且通常被開發人員用來測試驅動程序。 但這種模式作為通用隔離工具也很有用,其原理與虛擬機的操作類似。 此模式提供了比 Docker 更多的隔離,但不如 KVM 或 Virtual Box 等成熟的虛擬機。

總的來說,用戶模式似乎是一個奇怪且難以使用的工具,但它確實有其用途。 畢竟,這是一個以非特權用戶身份運行的成熟的 Linux 內核。 此功能允許潛在不受信任的代碼運行,而不會對主機造成任何威脅。 由於這是一個成熟的內核,因此它的進程與主機隔離,即 在用戶模式中運行的進程對主機不可見。 這與通常的 Docker 容器不同,在這種情況下,主機總是可以看到存儲庫內的進程。 從我的一台服務器上查看這段 pstree:

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

並將其與用戶模式下 Linux 內核的 pstree 進行比較:

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

使用 Docker 容器時,我可以從主機看到來賓中運行的進程的名稱。 這在 Linux 用戶模式下是不可能的。 這是什麼意思? 這意味著通過 Linux 審計子系統運行的監控工具 別看 來賓系統中運行的進程。 但在某些情況下,此功能可能成為一把雙刃劍。

總的來說,下面的整篇文章是為了達到預期結果而進行的研究和粗略嘗試的集合。 為此,我必須使用各種古老的工具,閱讀內核源代碼,對我還在小學時編寫的代碼進行深入調試,並使用特殊的二進製文件來修補 Heroku 構建,以搜索我需要的工具。 所有這些工作導致我的 IRC 上的人稱我為魔術師。 我希望這篇文章能夠作為可靠的文檔,供某人做同樣的事情,但使用更新的內核和操作系統版本。

調整

設置 Linux 用戶模式涉及幾個步驟:

  • 在主機上安裝依賴項;
  • 下載Linux內核;
  • 內核構建設置;
  • 內核彙編;
  • 二進制安裝;
  • 配置來賓文件系統;
  • 選擇內核啟動參數;
  • 設置訪客網絡;
  • 啟動來賓內核。

我認為如果您決定自己做,您很可能會執行某些 Ubuntu 或類似 Debian 的系統中描述的所有操作。 我嘗試在我最喜歡的發行版 Alpine 中實現上述所有內容,但沒有任何結果,顯然是因為 Linux 內核在用戶模式下對驅動程序有一個硬綁定的 glibc-isms。 我打算在最終了解問題後向上游報告此情況。

在主機上安裝依賴項

Ubuntu 至少需要以下軟件包來構建 Linux 內核(假設全新安裝):

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

您可以使用以下命令(以 root 身份或使用 sudo)安裝它們:

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

請注意,運行 Linux 內核的菜單自定義程序需要安裝 libncurses-dev。 請確保使用以下命令(以 root 身份或使用 sudo)安裝它:

apt-get -y install libncurses-dev

下載內核

決定在哪裡下載然後構建內核。 對於此操作,您將需要分配大約 1,3 GB 的硬盤空間,因此請確保您有它。

然後去 kernel.org 並獲取下載最新穩定內核版本的 URL。 在寫這篇文章時: https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

使用下載此文件 'wget':

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

並提取它 'tar':

tar xJf linux-5.1.16.tar.xz

現在我們進入解壓 tarball 時創建的目錄:

cd linux-5.1.16

內核構建設置

內核構建系統是一套 製作文件 с 許多 自定義工具和腳本來自動化該過程。 首先,打開交互式安裝程序:

make ARCH=um menuconfig

它將部分完成裝配並為您顯示一個對話框。 當燈光出現在窗口底部時[Select]',您可以使用空格鍵或 Enter 鍵配置設置。 像往常一樣使用鍵盤箭頭“向上”和“向下”在窗口中導航,並選擇“向左”或“向右”元素。

視圖指示符 -> 表示您位於子菜單中,可以使用 Enter 鍵訪問該子菜單。 擺脫困境的出路顯然是通過'[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)

為了什麼? 該命令將告訴我們的構建器在構建過程中使用所有可用的 CPU 核心和線程。 團隊 $(nproc) 在 Build 的末尾插入命令的輸出 nproc,這是一部分 coreutils 在標準 Ubuntu 構建中。

一段時間後,我們的內核將被編譯成可執行文件 ./linux.

安裝二進製文件

由於 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。 在撰寫本文時,情況是:

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

使用 wget 下載此 tarball:

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

現在進入來賓文件系統的目錄並提取存檔:

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

所描述的操作將創建一個小型文件系統模板。 由於系統的工作方式,通過 Alpine apk 管理器安裝軟件包將非常困難。 但這個FS足以評估總體思路。

我們還需要一個工具 TINI 停止內存消耗 殭屍進程 我們的來賓內核。

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

創建內核命令行

Linux 內核與大多數其他程序一樣,具有可以通過指定鍵來訪問的命令行參數 --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.
  • 選擇 主機文件系統 作為根文件系統驅動程序。
  • 掛載我們在根設備上創建的來賓文件系統。
  • 是的,在讀寫模式下。
  • 僅使用 64 MB RAM(根據您的計劃,您可以使用更少的 RAM,但 64 MB 似乎是最佳數量)。
  • 內核自動啟動 /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。 這將觸發 shell,然後出現內核恐慌:

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

我們得到這個內核恐慌是因為 Linux 內核認為初始化進程總是在運行。 沒有它,系統將無法再運行並關閉。 但由於這是一個用戶模式進程,因此結果將自身發送到 SIGABRT,這會產生一個輸出。

設置訪客網絡

這就是事情開始出錯的地方。 用戶模式中的網絡 Linux 是有限“用戶模式”的整個概念開始崩潰的地方。 畢竟通常在系統層面,網絡是有限的 特權 執行模式出於我們所有人都可以理解的原因。

筆記per.:您可以閱讀有關在 UML 中使用網絡的不同選項的更多信息 這裡.

滑翔之旅

然而,有一種古老且幾乎不受支持的工具,稱為 斯利普,用戶模式 ​​Linux 可以通過它與網絡交互。 它的工作方式與用戶級 TCP/IP 堆棧非常相似,並且不需要任何系統權限即可運行。 這個工具是 1995年發布,並且最新更新日期為 2006年。 斯利普已經很老了。 在沒有支持和更新的時期,編譯器已經發展到現在這個工具只能被描述為 代碼腐爛.

因此,讓我們從 Ubuntu 存儲庫下載 Slirp 並嘗試運行它:

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.

錯誤在我們心中跳動 這條線。 讓我們看一下堆棧跟踪,也許有些東西可以幫助我們:

(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

如果包的創建者將其刪除,我 做了一面鏡子.

網絡配置

現在讓我們在來賓內核上設置網絡。 更新啟動選項:

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  eth0=slirp,,$HOME/bin/slirp 
  init=/bin/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

前兩條配置命令 /proc и /sys 工作所必需的 ifconfig,它設置一個網絡接口來與 Slirp 通信。 團隊 route 設置內核路由表以強制所有流量通過 Slirp 隧道發送。 讓我們通過 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

它的作品!

注:顯然,原始帖子是在帶有有線網卡或其他不需要額外驅動程序的配置的台式機上編寫的。 在配備 Intel WiFi 8265 的筆記本電腦上,提升網絡時出現錯誤

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

顯然,內核無法與網卡驅動程序通信。 不幸的是,嘗試將固件編譯到內核中並沒有解決這個問題。 在發佈時,尚未找到此特定配置的解決方案。 在更簡單的配置上(例如,在 Virtualbox 中),接口可以正確啟動。

讓我們使用以下 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

並將其標記為可執行:

chmod +x init.sh

然後讓我們對內核命令行進行更改:

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

網絡穩定!

泊塢窗文件

為了方便大家查看,我收集了 Dockerfile,它會自動執行所描述的大部分步驟,並且應該為您提供一個工作配置。 我也有 準備好內核配置,其中包含帖子中描述的所有內容。 但重要的是要明白,我在這裡只概述了最低設置。

我希望這篇文章能夠幫助您了解如何構建來賓內核。 事實證明它是某種怪物,但該出版物的目的是成為有關在該系列操作系統的現代版本下在 Linux 中組裝、安裝和配置用戶模式主題的綜合指南。 後續步驟應包括安裝客戶系統中已有的服務和其他軟件。 由於 Docker 容器映像只是升級的 tarball,因此您應該能夠通過以下方式提取映像 docker export,然後確定在來賓內核文件系統的根目錄中安裝它的路徑。 好吧,然後運行shell腳本。

特別感謝 Freenode 上 #lobsters 的 Rkeene。 如果沒有他調試 Slirp 的幫助,我不可能走到這一步。 我不知道他的 Slackware 系統如何與 slirp 一起正常工作,但我的 Ubuntu 和 Alpine 系統不接受 slirp 以及 Rkeene 向我建議的二進製文件。 但對我來說,至少有一些對我有用的東西就足夠了。

來源: www.habr.com

添加評論