# Linux Kernel 5.5.1 Build ###### tags: `Linux` ## Development environment * Host * Ubuntu 18.04.1 x86_64 * Linux ubuntu 5.3.0-46-generic * Guest * Linux-5.5.1 * busybox-1.31.0 * QEMU emulator version 2.11.1 * Directory Hierarchy: ~/tmp |--linux-5.5.1 |--busybox-1.31.0 --- ## Prerequisites ```bash= $ sudo apt-get install qemu qemu-system -y $ sudo apt-get install libncurses5-dev build-essential -y $ sudo apt-get install flex bison -y $ sudo apt-get install bridge-utils -y ``` * `qemu` : 是一個免費的虛擬機軟體,QEMU的架構由純軟體實現,並在Guest與Host中間,來處理Guest的硬體請求,並由其轉譯給真正的硬體。 * `libncurses5-dev` : 是一個`ncurses`開發函式庫,可以允許程式設計師編寫獨立於終端的基於文字的使用者介面。 * `build-essential` : 提供必要的編譯環境。 * `flex` : 提供語意分析(編譯會用到)。 ## Linux kernel (x86_64) ### Linux kernel source code (v5.5.1) ```bash= $ wget https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.5.1.tar.gz $ tar -xvf linux-linux-5.5.1.tar.gz ``` ### Configuration > 在編譯你的kernel前,可以先選擇哪些功能你需要或者不需要,以下是兩種方法的範例。 ```bash= $ cd linux-5.5.1/ # method 1 $ make menuconfig # GUI # method 2 $ vim .config ``` * Method1 ```bash= KernelHacking --> [*]Compile the kernel with debug info [*]Compile the kernel with frame pointers [ ]Write protect kernel read-only data structures Processor type and features--> [ ]Paravirtualized guest support # This make debugging easier [ ] Randomize the address of the kernel image (KASLR) [ ] Compile also drivers which will not load [x] Optimize for size (-Os) ``` * Method2 > 選這個的目的是為了後面的網路功能,要先給他配一張網卡。 ```bash= CONFIG_PCI=y # by default CONFIG_E1000=y ``` ### Compile kernel ```bash= $ make -j8 ARCH=x86_64 ``` > 如果編譯成功在這個目錄下會有這個檔案`arch/x86_64/boot/bzImage` ## Root File system ### Busybox source code ```bash= $ wget https://busybox.net/downloads/busybox-1.31.0.tar.bz2 $ tar -xvf busybox-1.31.0.tar.bz2 ``` ### Compile Busybox ```bash= $ cd busybox-1.31.0/ $ make menuconfig Settings -> Build Options --> [*] Build Busybox as a static binary $ make -j8 install ``` > 當你編譯完成,會出現一個 **_install**。 ### Setting file system ```bash= $ cd _install $ mkdir proc sys dev etc etc/init.d $ vim etc/init.d/rcS # write a script #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys /sbin/mdev -s $ chmod +x etc/init.d/rcS ``` * `/proc` : 在`/proc`底下會有很多`process`的資訊,還有`memory`、`disk`等等資訊。 * `sys` : 在`/sys`底下則放一些`HW device`的驅動資訊 * `etc/init.d/rcS` : 這個`rcS`當做是`file system`剛啟動時的`init script` * `/sbin/mdev -s` : mdev(Busybox簡化版的udev),`udev`是linux的裝置管理器。它主要的功能是管理/dev目錄底下的裝置節點。(若無這個會發生**can't open /dev/tty2,3,4**的bug) ### Pack ```bash= $ find . | cpio -o --format=newc > ../rootfs.img ``` * `cpio` : 用於將files打包成一個package,這邊我們用來打包我們的檔案系統。(newc 是支援大於`65536 inode`的文件系統格式) ## Start up~ ```bash= $ cd linux-linux-5.5.1/ $ qemu-system-x86_64 -m 1024 -kernel arch/x86_64/boot/bzImage -initrd ../busybox-1.31.0/rootfs.img -append "root=/dev/ram rdinit=/sbin/init" ``` * `vmlinux` : 編譯出來的kernel,沒壓縮(debug時會用到) * `bzImage` : 由`vmlinux`用gzip壓縮後 * `initrd` : 又稱`initrd ramdisk`是一個臨時檔案系統,掛載在/dev/ram,它在啟動階段被Linux kernel呼叫,initrd主要用於當`root file system`被掛載之前,進行準備工作 * `append` : 附加kerenl啟動參數 * `root` : 用哪個目錄當作`root file system` * `rdinit` : kernel載入後,用`initrd`指定的路徑,創造第一個process * `nographic` : 不使用GUI介面,使用tty介面(terminal) * `-s -S` : 給gdb remote用,綁在port 1234 ![](https://i.imgur.com/pzhFzAc.jpg) ## Run a process on your kernel with QEMU * C code ```c= #include <stdio.h> int main() { printf("hello QEMU\n"); return 0; } ``` * Method1 > 使用`-static`編譯,原因是剛剛製作的`file system`不帶任何`library`所以直接用`靜態編譯`。 ```bash= $ gcc hello.c -o hello -static ``` * Method2 > 將他所需要的`library`複製過來即可。 ```bash= $ gcc hello.c -o hello $ ldd hello linux-vdso.so.1 (0x00007ffecb0ef000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff3d40d1000) # library /lib64/ld-linux-x86-64.so.2 (0x00007ff3d46c4000) # linker $ mkdir -p ./lib/x86_64-linux-gnu/ ./lib64 $ cp /lib/x86_64-linux-gnu/libc.so.6 ./lib/x86_64-linux-gnu/ $ cp /lib64/ld-linux-x86-64.so.2 ./lib64 ``` ## Network (bridge) * Add a bridge ```bash= $ sudo brctl addbr br0 $ sudo brctl addif br0 ens33 $ sudo ifconfig br0 up $ sudo ifconfig br0 <IP> ``` * Setting a qemu bridge helper ```bash= $ mkdir /etc/qemu $ vim /etc/qemu/bridge.conf allow br0 ``` * Enable IPv4 forwarding ```script= $ sudo -i # echo 1 > /proc/sys/net/ipv4/ip_forward ``` ## Start up with QEMU network parameters ```bash= $ sudo qemu-system-x86_64 -m 1024 -kernel arch/x86_64/boot/bzImage -initrd ../busybox-1.31.0/rootfs.img -append "root=/dev/ram rdinit=/sbin/init" -net nic -net bridge,br=br0 ``` ### Setting Network in QEMU * 檢查網卡是否存在 ![](https://i.imgur.com/EQcKWAB.jpg) * 給網卡一個IP ![](https://i.imgur.com/ZfQK0MQ.jpg) * Ping主機,檢查是否有通 ![](https://i.imgur.com/pgHDDaL.jpg) * 設定路由,並且檢查是否有通到WAN ![](https://i.imgur.com/HD9H9oN.jpg) ## Reference * http://pwn4.fun/2017/04/17/Linux%E5%86%85%E6%A0%B8%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%EF%BC%88%E4%B8%80%EF%BC%89%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/ * https://www.cnblogs.com/hac425/p/9416886.html * https://blog.csdn.net/ytusdc/article/details/77980915 * https://jacobpan3g.github.io/cn/2017/09/01/solve-kernel2.6.36-build-error-in-ubuntu16.04/ * https://zhuanlan.zhihu.com/p/105069730 * https://www.cnblogs.com/senix/archive/2013/02/21/2921221.html * https://zh.wikipedia.org/wiki/Initrd * https://github.com/OP-TEE/build/issues/103 * https://www.cnblogs.com/pengdonglin137/p/3328889.html * https://wiki.qemu.org/Documentation/Networking * [kernel debug](https://www.kernel.org/doc/html/latest/dev-tools/gdb-kernel-debugging.html)