---
# System prepended metadata

title: Linux Kernel 4.4.1 Build

---

# Linux Kernel 4.4.1 Build

我的環境是:
* Ubuntu 16.04 x64
* qemu
* linux-4.4.1
* busybox-1.31.0
* gcc 5.4.0
* gdb 8.3

目錄:

    mykernel
        |--linux-4.4.1
        |--busybox-1.31.0

---

## qemu

    $ sudo apt-get install qemu qemu-system


## Linux kernel 編譯

    $ wget https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.4.1.tar.gz
    or https://cdn.kernel.org/pub/linux/kernel/v4.x/
    $ tar zxvf linux-linux-4.4.1.tar.gz
    $ cd linux-linux-4.4.1/
    $ sudo apt-get install libncurses5-dev build-essential 
    $ make menuconfig
    $ make -j8 ARCH=x86_64 all

### make menuconfig

編譯前配置參數
    
    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
    
    [ ] Randomize the address of the kernel image (KASLR)
    [ ] Compile also drivers which will not load
    [x] Optimize for size (-Os)
    
    網路配置需要
    $ vim .config
    CONFIG_PCI=y
    CONFIG_E1000=y

### makefile 修改 (gcc > 5)

    KBUILD_CFLAGS += -fno-pie
    
![](https://i.imgur.com/muYfcNP.jpg)

    
## busybox

    $ wget https://busybox.net/downloads/busybox-1.31.0.tar.bz2 
    $ tar -jxvf busybox-1.31.0.tar.bz2
    $ cd busybox-1.31.0
    $ make menuconfig  
    $ make install

### make menuconfig

編譯前配置參數

    Busybox Settings -> Build Options -->
        [*] Build Busybox as a static binary
    
    Networking Utilities -->
        [ ] inetd 
        

### file system

在編譯好後,busybox目錄下有個**_install**

    $ cd _install
    $ mkdir proc sys dev etc etc/init.d
    $ vim etc/init.d/rcS
        
        #!/bin/sh
        mount -t proc proc /proc
        mount -t sysfs proc /sys
        /sbin/mdev -s
        
    $ chmod +x etc/init.d/rcS

`proc` : 用於掛載`/proc`
`sys` : 用於掛載`/sys`
`etc/init.d` : 放busybox的啟動腳本
`dev` : 用於mdev創設備節點
::::info
/proc,/sys : 這個目錄下通常放的是process的訊息，所以得掛載進來
::::

此時是在**_install**下

    $ find . | cpio -o --format=newc > ../rootfs.img


### gdb 
    
    $ wget https://mirror.bjtu.edu.cn/gnu/gdb/gdb-8.3.tar.xz
    $ tar -xvf gdb-8.3.tar.xz
    $ cd gdb-8.3
    $ vim gdb/remote.c

```code=
/* Further sanity checks, with knowledge of the architecture.  */
/*
if (buf_len > 2 * rsa->sizeof_g_packet)
    error (_("Remote 'g' packet reply is too long (expected %ld bytes, got %d "
        "bytes): %s"),
    rsa->sizeof_g_packet, buf_len / 2,
    rs->buf.data ());
*/

if (buf_len > 2 * rsa->sizeof_g_packet) {
    rsa->sizeof_g_packet = buf_len;
    for (i = 0; i < gdbarch_num_regs (gdbarch); i++){
        if (rsa->regs[i].pnum == -1)
            continue;
        if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
            rsa->regs[i].in_g_packet = 0;
        else
            rsa->regs[i].in_g_packet = 1;
    }
}
```
    $ ./configure
    $ make -j8
    在gdb目錄下會有新編譯的gdb


## Run

在**linux-4.4.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"
    
    debug啟動
    $ 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 console=ttyS0" --nographic -s -S
    (gdb) target remote localhost:1234
    

![大功告成](https://i.imgur.com/3RWKR4k.jpg)

## Network(tuntap)

     $ sudo apt-get install bridge-utils -y
     $ sudo brctl addbr br0         # 增加一個bridge
     $ sudo brctl addif br0 ens33   # 將host的物理端口綁上去
     $ sudo ifconfig br0 up
     $ sudo ifconfig br0 <IP>       # 給這個bridge一個IP讓guest可以跟host溝通

> 需要修改這個文件
 
    $ sudo vim /etc/qemu-ifup

```cpp=
$ sudo vim /etc/qemu-ifup

20    switch=$(ip route ls | \
21        awk '/^default / {
22           for(i=0;i<NF;i++) { if ($i == "dev") { print $(i+1); next; } }
23          }'
24         )
改成
      switch = br0
```
    $ sudo vim /etc/qemu/bridge.conf
    allow=br0

> qemu網路參數
 
    -net nic,macaddr=52:54:00:12:34:23 -net tap,ifname=tap1,script=/etc/qemu-ifup,downscript=no

![](https://i.imgur.com/sSqfgms.jpg)



## QEMU argc

`vmlinux` : 編譯出來的kernel,沒壓縮
`bzImage` : 由`vmlinux`用gzip壓縮後
`initrd` : 又稱`initrd ramdisk`是一個臨時檔案系統,掛載在/dev/ram,它在啟動階段被Linux核心呼叫,initrd主要用於當「root」檔案系統被掛載之前,進行準備工作
`append` : 附加kerenl啟動參數
`root` : 用哪個目錄當作root file system
`rdinit` : kernel載入後,用`initrd`指定的路徑,創造第一個process
`nographic` : 不創造視窗
`-s -S` : 給gdb remote用,綁在port 1234


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













