Chybeta

Linux kernel development (1): 环境准备

linux kernel + busybox + qemu
Linux kernel development (1): 环境准备

寻坑之旅

linux kernel

打包上路

获取linux kernel源代码。因为书中根据的源代码是2.6,所以就只选择了这个版本。
可以从 这里获取 https://www.kernel.org/pub/linux/kernel/v2.6/ 比如:

1
chybeta@ubuntu:~$ wget https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.39.tar.bz2

解压,会详细的列出解压的文件,解压后的文件会保存在linux-2.6.39文件夹中:

1
chybeta@ubuntu:~$ tar xvjf linux-2.6.32.tar.bz2

或者使用git,(这个会下载很大的文件)

1
chybeta@ubuntu:~$ git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

然后根据需要的版本checkout出来。

进入解压出来的文件夹。接下去配置(config)内核。根据网上的方法,对于ubuntu系统,可以直接把/boot/ 里的.config文件拷贝到linux-2.6.32中。这里用用make menuconfig 来进行图形化配置内核并生成 .confgi文件:

1
chybeta@ubuntu:~/linux-2.6.39$ make menuconfig

不想进行个性化配置的话,可以使用默认生成的.config,我这里直接使用默认配置了:

1
chybeta@ubuntu:~/linux-2.6.39$ make defconfig

其他一些类似命令,这里仅列出:

  1. make oldconfig 使用已经存在的 ./.config的内容,将里面的原本值作为新config的设定值。新config中涉及的新特性则列出来让用户选择。
  2. make gconfig 用Gtx图形界面来配置。需要X window支持。
  3. make xconfig 用Qt图形界面来配置。需要X window支持。
  4. make config

配置完(我直接保持默认配置没进行改动)后,选择 Save an Alternate Configuration File,将配置保存到 .config 文件中。

接下里开始make

1
2
chybeta@ubuntu:~/linux-2.6.39$ make all
chybeta@ubuntu:~/linux-2.6.39$ make module

在make all中可能会遇到各种坑,遇到的话看这把。ps,好像make module可以不用。

最后编译完成:

生成的镜像存放在 arch/x86/boot/bzImage。

1
2
chybeta@ubuntu:~/linux-2.6.39$ file arch/x86/boot/bzImage
arch/x86/boot/bzImage: Linux kernel x86 boot executable bzImage, version 2.6.39 (chybeta@ubuntu) #1 SMP Sat Oct 21 00:50:51 CST 2017, RO-rootFS, root_dev 0x801, swap_dev 0x3, Normal VGA

正式填坑

这次是第一次,但绝不会是最后一次编译内核。所以这部份会长期保持更新。希望对各位有用。

有可能在make all的时候出现下面这些错误:

坑一


1
fatal error: linux/compiler-gcc5.h: No such file or directory

原因是 不支持gcc-5编译。可以到这里去下一份对应的compiler-gcc5.h。放到 include/linux/compiler-gcc5.h

坑二


1
2
Can't use 'defined(@array)' (Maybe you should just omit the defined()?) at kernel/timeconst.pl line 373.
/home/chybeta/linux-2.6.39/kernel/Makefile:141: recipe for target 'kernel/timeconst.h' failed

编辑 kernel/timeconst.pl ,第372行左右:

1
2
3
4
5
@val = @{$canned_values{$hz}};
if (!defined(@val)) {
@val = compute_values($hz);
}
output($hz, @val);

修改为:

1
2
3
4
5
@val = @{$canned_values{$hz}};
if (!@val) {
@val = compute_values($hz);
}
output($hz, @val);

坑三

1
2
3
4
5
6
7
8
9
10
drivers/gpu/drm/i915/i915_drv.o:i915_drv.c:(.text+0x406): first defined here
scripts/Makefile.build:405: recipe for target 'drivers/gpu/drm/i915/i915.o' failed
make[4]: *** [drivers/gpu/drm/i915/i915.o] Error 1
scripts/Makefile.build:419: recipe for target 'drivers/gpu/drm/i915' failed
make[3]: *** [drivers/gpu/drm/i915] Error 2
scripts/Makefile.build:419: recipe for target 'drivers/gpu/drm' failed
make[2]: *** [drivers/gpu/drm] Error 2
scripts/Makefile.build:419: recipe for target 'drivers/gpu' failed
make[1]: *** [drivers/gpu] Error 2
Makefile:919: recipe for target 'drivers' failed

google/stackoverflow上没找到解决方案。

我直接修改了由make defconfig生成的.config文件,其中第1781左右,是关于图形化(Graphics support)的部分,修改参数为如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#
# Graphics support
#
# CONFIG_AGP is not set
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=1
# CONFIG_VGA_SWITCHEROO is not set
# CONFIG_DRM is not set
# CONFIG_STUB_POULSBO is not set
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
# CONFIG_FB is not set
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_GENERIC=y
# CONFIG_BACKLIGHT_PROGEAR is not set
# CONFIG_BACKLIGHT_APPLE is not set
# CONFIG_BACKLIGHT_SAHARA is not set
# CONFIG_BACKLIGHT_ADP8860 is not set

busybox

busybox里面集成了多种常用linux命令。接下去需要用busybox来生成linux的根文件系统。

https://busybox.net/ 处下载源码,我下的版本是 BusyBox 1.27.2。

解压缩:

1
chybeta@ubuntu:~$ tar -xvjf busybox-1.27.2.tar.bz2

进入busybox文件夹,需要使用静态链接的方式来编译:

1
chybeta@ubuntu:~/busybox-1.27.2$ make menuconfig


先进入 Busybox Setting,之后选择Build Options中的 Build Busybox as a static library。

1
chybeta@ubuntu:~/busybox-1.27.2$ make install

安装成功。

install后,默认会在busybox的目录下生成一个 _install目录。接下来用这个目录来生成虚拟机挂载时需要的根文件目录。

这一步,创建一个目录用于保存rootfs.img

1
chybeta@ubuntu:~/busybox-1.27.2$ mkdir ../kernelrootfs

生成:

1
2
3
chybeta@ubuntu:~/busybox-1.27.2$ cd _install/
chybeta@ubuntu:~/busybox-1.27.2/_install$ find . | cpio -o --format=newc > ../../kernelrootfs/rootfs.img
5213 blocks

结果:

1
2
chybeta@ubuntu:~/kernelrootfs$ file rootfs.img
rootfs.img: ASCII cpio archive (SVR4 with no CRC)

Qemu

qemu是一个开源的虚拟机,它内部实现了一个gdb server,能方便和gdb对内核进行联合调试。安装qemu虚拟机:

1
chybeta@ubuntu:~$ sudo apt-get install qemu qemu-system

用qemu开启虚拟机:

1
chybeta@ubuntu:~$ qemu-system-x86_64 -kernel linux-2.6.39/arch/x86/boot/bzImage -initrd kernelrootfs/rootfs.img -append "root=/dev/ram rdinit=/bin/sh"

参数-kernel,用于指定内核的所在地,在前面部分已经保存在为 linux-2.6.39/arch/x86/boot/bzImage 。参数-initrd用于指定linux系统挂载用的根文件目录,由前面章节,已经保存在为 kernelrootfs/rootfs.img 。这两个参数,根据你前面的配置而定。

后记

还有一些其他的操作还没写出来,比如添加系统调用(syscall)之类的。以后用到再慢慢补充吧。

Refference

微信扫码加入知识星球【漏洞百出】
chybeta WeChat Pay

点击图片放大,扫码知识星球【漏洞百出】