Paano simulan ang paggamit ng User Mode sa Linux

Panimula mula sa tagasalin: Laban sa backdrop ng malawakang pagpasok sa ating buhay ng iba't ibang uri ng mga lalagyan, maaari itong maging kawili-wili at kapaki-pakinabang upang malaman kung anong mga teknolohiya ang lahat ng ito ay nagsimula nang minsan. Ang ilan sa kanila ay maaaring magamit nang kapaki-pakinabang hanggang sa araw na ito, ngunit hindi lahat ay naaalala ang gayong mga pamamaraan (o alam kung hindi sila nahuli sa kanilang mabilis na pag-unlad). Ang isang naturang teknolohiya ay ang User Mode Linux. Ang may-akda ng orihinal ay gumawa ng maraming paghuhukay, inaalam kung alin sa mga lumang pag-unlad ang gumagana pa rin at alin ang hindi, at pinagsama-sama ang isang bagay tulad ng sunud-sunod na pagtuturo sa kung paano makakuha ng iyong sarili ng isang homebrew na UML sa 2k19. At oo, inimbitahan namin ang may-akda ng orihinal na post kay Habr Cadey, kaya kung mayroon kang anumang mga katanungan - magtanong sa Ingles sa mga komento.

Paano simulan ang paggamit ng User Mode sa Linux

Ang User Mode sa Linux ay, sa katunayan, isang port ng Linux kernel sa sarili nito. Binibigyang-daan ka ng mode na ito na magpatakbo ng isang buong Linux kernel bilang proseso ng user at karaniwang ginagamit ng mga developer upang subukan ang mga driver. Ngunit ang mode na ito ay kapaki-pakinabang din bilang isang pangkalahatang tool sa paghihiwalay, ang prinsipyo nito ay katulad ng pagpapatakbo ng mga virtual machine. Ang mode na ito ay nagbibigay ng higit na paghihiwalay kaysa sa Docker, ngunit mas mababa sa isang ganap na virtual machine tulad ng KVM o Virtual Box.

Sa pangkalahatan, maaaring mukhang kakaiba at mahirap gamitin ang User Mode, ngunit mayroon pa rin itong mga gamit. Pagkatapos ng lahat, ito ay isang ganap na Linux kernel na tumatakbo mula sa isang unprivileged user. Ang tampok na ito ay nagbibigay-daan sa potensyal na hindi pinagkakatiwalaang code na tumakbo nang walang anumang banta sa host machine. At dahil ito ay isang ganap na kernel, ang mga proseso nito ay nakahiwalay sa host machine, iyon ay ang mga prosesong tumatakbo sa loob ng User Mode ay hindi makikita ng host. Hindi ito tulad ng karaniwang lalagyan ng Docker, kung saan palaging nakikita ng host machine ang mga proseso sa loob ng repositoryo. Tingnan ang piraso ng pstree na ito mula sa isa sa aking mga server:

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

At ihambing ito sa pstree ng Linux kernel sa User Mode:

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

Kapag nagtatrabaho sa mga lalagyan ng Docker, nakikita ko mula sa host ang mga pangalan ng mga prosesong tumatakbo sa bisita. Sa Linux User Mode, hindi ito posible. Ano ang ibig sabihin nito? Nangangahulugan ito na ang mga tool sa pagsubaybay na tumatakbo sa subsystem ng pag-audit ng Linux Huwag Tignan mga prosesong tumatakbo sa guest system. Ngunit sa ilang mga sitwasyon, ang tampok na ito ay maaaring maging isang tabak na may dalawang talim.

Sa pangkalahatan, ang buong post sa ibaba ay isang koleksyon ng pananaliksik at magaspang na pagtatangka upang makamit ang ninanais na resulta. Upang gawin ito, kailangan kong gumamit ng iba't ibang mga sinaunang tool, basahin ang mga mapagkukunan ng kernel, gumawa ng masinsinang pag-debug ng code na isinulat noong mga araw noong ako ay nasa elementarya pa, at mag-tinker din sa Heroku build gamit ang isang espesyal na binary upang mahanap ang mga tool na kailangan ko. . Ang lahat ng gawaing ito ay humantong sa mga tao sa aking IRC na tawagin akong magic. Umaasa ako na ang post na ito ay nagsisilbing maaasahang dokumentasyon para sa isang tao na subukan ang parehong bagay sa mas bagong mga kernel at mga bersyon ng OS.

pag-aayos

Ang pag-set up ng Linux User Mode ay nagsasangkot ng ilang hakbang:

  • pag-install ng mga dependency sa host;
  • pag-download ng Linux kernel;
  • pagsasaayos ng pagbuo ng kernel;
  • pagpupulong ng kernel;
  • pag-install ng binary;
  • pag-set up ng guest file system;
  • pagpili ng mga parameter ng paglulunsad ng kernel;
  • pag-set up ng isang guest network;
  • pagsisimula ng guest kernel.

Ipinapalagay ko na kung magpasya kang gawin ito sa iyong sarili, malamang na gagawin mo ang lahat ng inilarawan sa ilang sistemang tulad ng Ubuntu o Debian. Sinubukan kong ipatupad ang lahat ng nasa itaas sa aking paboritong pamamahagi - Alpine, ngunit walang nangyari dito, tila dahil sa katotohanan na ang Linux kernel ay may hard-binding glibc-isms para sa mga driver sa User Mode. Plano kong iulat ito sa upstream pagkatapos kong maunawaan ang problema.

Pag-install ng mga dependency sa host

Ang Ubuntu ay nangangailangan ng hindi bababa sa mga sumusunod na pakete upang bumuo ng Linux kernel (ipagpalagay na malinis ang pag-install):

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

Maaari mong i-install ang mga ito gamit ang sumusunod na command (bilang ugat o may sudo):

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

Tandaan na ang pagpapatakbo ng Linux kernel menu setup program ay mangangailangan ng pag-install ng libncurses-dev. Pakitiyak na naka-install ito gamit ang sumusunod na command (bilang ugat o may sudo):

apt-get -y install libncurses-dev

Pag-download ng kernel

Magpasya kung saan magda-download at pagkatapos ay buuin ang kernel. Para sa operasyong ito, kakailanganin mong maglaan ng humigit-kumulang 1,3 GB ng espasyo sa hard disk, kaya siguraduhing mayroon ka nito.

Pagkatapos ay pumunta sa kernel.org at kunin ang URL para i-download ang pinakabagong stable kernel. Sa oras ng pagsulat ito ay: https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

I-download ang file na ito gamit ang 'wget':

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

At i-extract ito gamit ang 'tar':

tar xJf linux-5.1.16.tar.xz

Ngayon ay ipinasok namin ang direktoryo na nilikha kapag binubuksan ang tarball:

cd linux-5.1.16

Pag-setup ng kernel build

Ang kernel build system ay isang set Gumawa ng mga file с marami mga custom na tool at script para i-automate ang proseso. Una, buksan ang interactive na setup program:

make ARCH=um menuconfig

Ito ay bahagyang bubuo at magpapakita ng isang dialog box para sa iyo. Kailan '[Select]', maaari mong i-configure ang mga setting gamit ang Spacebar o Enter key. Mag-navigate sa window, gaya ng dati, gamit ang mga arrow sa keyboard na "pataas" at "pababa", at piliin ang mga elemento - "kaliwa" o "kanan".

Ang view pointer —> ay nangangahulugan na ikaw ay nasa isang submenu, na na-access sa pamamagitan ng pagpindot sa Enter key. Ang daan palabas dito ay malinaw na sa pamamagitan ng '[Exit]'.

Isama ang mga sumusunod na opsyon sa '[Select]' at siguraduhing mayroon silang '[*]' sa tabi nila:

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

Iyon lang, maaari kang lumabas sa window na ito sa pamamagitan ng sunud-sunod na pagpili sa '[Exit]'. Siguraduhin lamang na sasabihan ka na i-save ang configuration sa dulo at piliin ang '[Yes]'.

Inirerekomenda ko na maglaro ka sa mga pagpipilian sa pagbuo ng kernel pagkatapos basahin ang post na ito. Sa pamamagitan ng mga eksperimentong ito, marami kang matututuhan sa mga tuntunin ng pag-unawa sa gawain ng mababang antas ng kernel mechanics at ang epekto ng iba't ibang flag sa pagpupulong nito.

Pagbuo ng kernel

Ang Linux kernel ay isang malaking programa na gumagawa ng maraming bagay. Kahit na may kaunting pagsasaayos sa lumang hardware, maaaring tumagal ito ng mahabang panahon upang mabuo. Kaya bumuo ng kernel gamit ang sumusunod na command:

make ARCH=um -j$(nproc)

Para saan? Sasabihin ng command na ito sa aming builder na gamitin ang lahat ng available na CPU core at thread sa proseso ng build. Koponan $(nproc) sa dulo ng Build ay pinapalitan ang output ng command nproc, na bahagi ng coreutils sa isang karaniwang build ng Ubuntu.

Pagkaraan ng ilang oras, ang aming kernel ay isasama sa isang maipapatupad na file ./linux.

Pag-install ng binary

Dahil ang User Mode sa Linux ay lumilikha ng isang regular na binary, maaari mo itong i-install tulad ng anumang iba pang utility. Narito kung paano ko ito ginawa:

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

Ito rin ay nagkakahalaga ng pagtiyak na iyon ~/bin ay nasa iyong $PATH:

export PATH=$PATH:$HOME/bin

Pagse-set up ng guest file system

Lumikha ng isang direktoryo para sa guest file system:

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

Buksan ang alpinelinux.org at sa seksyon ng pag-download hanapin ang aktwal na link sa pag-download MINI ROOT FILESYSTEM. Sa oras ng pagsulat ito ay:

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

I-download ang tarball na ito gamit ang wget:

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

Ngayon ipasok ang direktoryo ng guest file system at kunin ang archive:

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

Ang mga hakbang na inilarawan ay lilikha ng isang maliit na template ng file system. Dahil sa likas na katangian ng system, napakahirap mag-install ng mga package sa pamamagitan ng Alpine apk manager. Ngunit ang FS na ito ay sapat na upang suriin ang pangkalahatang ideya.

Kailangan din namin ng tool tini upang pigilan ang pagkonsumo ng memorya mga proseso ng zombie ang aming guest kernel.

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

Paglikha ng isang kernel command line

Ang Linux kernel, tulad ng karamihan sa iba pang mga programa, ay may mga command-line na argumento na maaaring ma-access sa pamamagitan ng pagtukoy sa susi --help.

Mismo—tulong

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.

Itinatampok ng panel na ito ang pangunahing mga parameter ng paglulunsad. Patakbuhin natin ang kernel na may pinakamababang kinakailangang hanay ng mga opsyon:

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

Ang mga linya sa itaas ay nagsasabi sa aming kernel ng mga sumusunod:

  • Ipagpalagay na ang root filesystem ay isang pseudo device /dev/root.
  • Pumili ka hostfs bilang isang root filesystem driver.
  • I-mount ang guest filesystem na ginawa namin sa root device.
  • At oo, nasa read-write mode.
  • Gumamit lamang ng 64 MB ng RAM (maaari kang gumamit ng mas kaunti depende sa kung ano ang plano mong gawin, ngunit ang 64 MB ay tila ang pinakamainam na halaga).
  • Awtomatikong magsisimula ang kernel /bin/sh bilang init-proseso.

Patakbuhin ang utos na ito at dapat kang makakuha ng isang bagay tulad ng sumusunod:

Isang sheet pa

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

Ang mga manipulasyon sa itaas ay magbibigay sa atin sistema ng panauhin sa pinakamababa, nang walang mga bagay tulad ng /proc o nakatalagang hostname. Halimbawa, subukan ang mga sumusunod na command:

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

Upang mag-log out sa bisita, i-type exit o pindutin ang control-d. Papatayin nito ang shell na sinusundan ng isang kernel panic:

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

Nakuha namin ang kernel panic na ito dahil sa tingin ng Linux kernel ay palaging tumatakbo ang proseso ng pagsisimula. Kung wala ito, hindi na maaaring gumana ang system at magsasara. Ngunit dahil ito ay isang proseso ng user-mode, ang nagreresultang output ay nagpapadala mismo sa SIGABRT, na nagreresulta sa isang output.

Setup ng guest network

Ngunit dito nagsisimula ang mga bagay na mali para sa amin. Networking sa User Mode Linux ay kung saan ang buong konsepto ng limitadong "user mode" ay nagsisimulang masira. Pagkatapos ng lahat, ang network ay karaniwang limitado sa antas ng system may pribilehiyo execution mode para sa ating lahat na mauunawaang dahilan.

Tandaan. per .: maaari kang magbasa nang higit pa tungkol sa iba't ibang mga opsyon para sa pagtatrabaho sa isang network sa UML dito.

Paglalakbay sa Slirp

Gayunpaman, mayroong isang sinaunang at halos hindi suportadong tool na tinatawag Slirp, kung saan ang User Mode Linux ay maaaring makipag-ugnayan sa network. Gumagana ito tulad ng isang stack ng TCP/IP sa antas ng user at hindi nangangailangan ng anumang mga pahintulot ng system upang tumakbo. Ang tool na ito ay inilabas noong 1995, at ang pinakabagong update ay napetsahan 2006 year. Napakaluma na ng Slirp. Sa panahong walang suporta at mga update, ang mga compiler ay napakalayo na ngayon na ang tool na ito ay maaari lamang ilarawan bilang code rot.

Kaya't i-download natin ang Slirp mula sa mga repositoryo ng Ubuntu at subukang patakbuhin ito:

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

Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.

IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)

Type five zeroes (0) to exit.

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

SLiRP Ready ...
fish: “/usr/bin/slirp” terminated by signal SIGSEGV (Address boundary error)

Oh mga diyos. I-install natin ang debugger ng Slirp at tingnan kung malalaman natin kung ano ang nangyayari dito:

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.

Ang pagkakamali ay tumatalo sa atin linyang ito. Tingnan natin ang stacktrace, baka may makatulong sa atin doon:

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

Dito makikita natin na nangyayari ang pag-crash sa panahon ng pagsisimula ng pangunahing loop kapag sinubukan ng slirp na tingnan ang mga timeout. Sa puntong ito, kinailangan kong sumuko sa pagsubok na mag-debug. Ngunit tingnan natin kung gumagana ang Slirp na binuo mula sa mga uri. Muli kong na-download ang archive nang direkta mula sa site Sourceforge, dahil ang pag-drag ng isang bagay mula doon sa pamamagitan ng command line ay isang sakit:

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

Dito nakikita namin ang mga alerto tungkol sa hindi natukoy na mga built-in na function, iyon ay, tungkol sa kawalan ng kakayahang i-link ang nagresultang binary file. Lumalabas na sa pagitan ng 2006 at sa puntong ito, huminto ang gcc sa paggawa ng mga simbolo na ginagamit sa mga built-in na function ng intermediate compiled file. Subukan nating palitan ang keyword inline sa isang walang laman na komento at tingnan ang resulta:

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

Hindi. Hindi rin ito gumagana. Hindi pa rin makahanap ng mga simbolo para sa mga function na ito.

Sa puntong ito, sumuko ako at nagsimulang tumingin sa Github Heroku build packages. Ang aking teorya ay ang ilang Heroku build package ay naglalaman ng mga binary na kailangan ko. Sa huli, pinangunahan ako ng paghahanap dito. Nag-download ako at nag-unpack uml.tar.gz at natagpuan ang sumusunod:

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*

Ito ang slirp binary! Nagtatrabaho ba siya?

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

Hindi nag-crash - kaya dapat itong gumana! Itanim natin ang binary na ito ~/bin/slirp:

cp slirp ~/bin/slirp

Kung sakaling alisin ito ng gumawa ng package, I gumawa ng salamin.

Ang pagsasaayos ng network

Ngayon, i-configure natin ang network sa ating guest core. I-update ang mga opsyon sa paglulunsad:

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

Ngayon paganahin natin ang network:

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

Ang unang dalawang utos ng pagsasaayos /proc и /sys kailangan para sa trabaho ifconfig, na nagtatakda ng interface ng network upang makipag-ugnayan sa Slirp. Koponan route itinatakda ang kernel routing table upang pilitin ang lahat ng trapiko na ipadala sa pamamagitan ng Slirp tunnel. Suriin natin ito gamit ang isang DNS query:

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

Gumagana ito!

Tandaan bawat .: Malamang, ang orihinal na post ay isinulat sa isang desktop na may wired network card, o ilang iba pang configuration na hindi nangangailangan ng karagdagang mga driver. Sa isang laptop na may WiFi 8265 mula sa Intel, ang isang error ay nangyayari kapag itinaas ang network

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

Tila, ang kernel ay hindi maaaring makipag-usap sa driver ng network card. Ang isang pagtatangka na i-compile ang firmware sa kernel, sa kasamaang-palad, ay hindi naayos ang sitwasyon. Sa oras ng paglalathala, hindi posible na makahanap ng solusyon sa pagsasaayos na ito. Sa mas simpleng mga config (halimbawa, sa Virtualbox), ang interface ay tumataas nang tama.

I-automate natin ang pag-redirect gamit ang sumusunod na shell script:

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

At markahan itong maipapatupad:

chmod +x init.sh

At pagkatapos ay gagawa kami ng mga pagbabago sa kernel command line:

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

At ulitin natin:

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

Stable na ang network!

docker file

Upang gawing mas madali para sa iyo na suriin ang lahat ng ito, nakolekta ko dockerfile, na nag-automate sa karamihan ng mga hakbang na inilarawan at dapat magbigay sa iyo ng gumaganang configuration. meron din akong paunang na-configure na kernel, na naglalaman ng lahat ng inilarawan sa post. Ngunit mahalagang maunawaan na dito ko binalangkas lamang ang mga minimum na setting.

Umaasa ako na ang post na ito ay nakatulong sa iyo na maunawaan kung paano magtaas ng guest kernel. Ito ay naging isang uri ng halimaw, ngunit ang publikasyon ay naisip bilang isang komprehensibong gabay sa pagbuo, pag-install at pag-configure ng User Mode sa Linux sa ilalim ng mga modernong bersyon ng mga operating system ng pamilyang ito. Dapat kasama sa mga susunod na hakbang ang pag-install ng mga serbisyo at iba pang software na nasa loob na ng guest system. Dahil ang mga imahe ng lalagyan ng Docker ay mga pampubliko lamang na tarball, dapat mong ma-extract ang larawan sa pamamagitan ng docker export, at pagkatapos ay tukuyin ang landas ng pag-install nito sa ugat ng file system ng guest kernel. Well, pagkatapos ay isagawa ang script ng shell.

Espesyal na pasasalamat kay Rkeene mula sa #lobsters sa Freenode. Kung wala ang tulong niya sa pag-debug ng Slirp, hindi ako aabot ng ganito. Wala akong ideya kung paano gumagana nang tama ang kanyang Slackware system sa slirp, ngunit ang aking Ubuntu at Alpine system ay hindi tumanggap ng slirp at ang binary na Rkeene ay iminungkahi sa akin. Pero sapat na para sa akin na kahit papaano ay may gumagana para sa akin.

Pinagmulan: www.habr.com

Magdagdag ng komento