Linux qemu环境搭建

开始学习与Linux kernel相关的东西,第一步就是环境搭建,记录一些错误和解决方法。

参考

参考以下两篇博客:
https://www.anquanke.com/post/id/85837
http://p4nda.top/2018/04/04/kernel-pwn-start/

环境

1
2
3
系统镜像:ubuntu-14.04-desktop-i386
内核源码:linux-2.6.32.1
busybox:busybox-1.28.2

内核编译

1
2
3
4
5
6
7
sudo apt-get install libncurses5-dev
sudo apt-get install qemu qemu-system
cd linux-2.6.32.1
make menuconfig
make
make all
make modules

错误1

1
2
3
4
5
6
/home/ubuntu/kernel/linux-2.6.32.1/arch/x86/include/asm/ptrace.h:146:13: note: previous declaration of ‘syscall_trace_leave’ was here
extern void syscall_trace_leave(struct pt_regs *);
^
make[2]: *** [arch/x86/kernel/ptrace.o] Error 1
make[1]: *** [arch/x86/kernel] Error 2
make: *** [arch/x86] Error 2

这里的错误是说ptrace.c中syscall_trace_leave函数的定义与ptrace.h中的声明不同:

1
2
3
4
5
6
7
linux-2.6.32.1/arch/x86/include/asm/ptrace.h
extern long syscall_trace_enter(struct pt_regs *);
extern void syscall_trace_leave(struct pt_regs *);

linux-2.6.32.1/arch/x86/kernel/ptrace.c
asmregparm long syscall_trace_enter(struct pt_regs *regs);
asmregparm void syscall_trace_leave(struct pt_regs *regs);

将ptrace.h中的声明修改为和ptrace.c定义相同即可,另外添加一个头文件:

1
2
3
4
linux-2.6.32.1/arch/x86/include/asm/ptrace.h
#include <linux/linkage.h> //line 133
extern asmregparm long syscall_trace_enter(struct pt_regs *);
extern asmregparm void syscall_trace_leave(struct pt_regs *);

解决方案参考:https://bestwing.me/Complie-linux-kernel-and-running-it-using-qemu.html

错误2

1
2
3
4
5
gcc: error: elf_i386: No such file or directory
gcc: error: unrecognized command line option ‘-m’
make[2]: *** [arch/x86/vdso/vdso32-int80.so.dbg] Error 1
make[1]: *** [arch/x86/vdso] Error 2
make: *** [arch/x86] Error 2

解决方案:

1
2
3
4
5
6
7
8
9
linux-2.6.32.1/arch/x86/vdso/Makefile
VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \ //line 28
-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1 //line 73

//修改为
VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
-Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1

解决方案参考:https://www.anquanke.com/post/id/85837

错误3

1
2
3
4
5
6
7
8
drivers/net/igbvf/igbvf.h: At top level:
drivers/net/igbvf/igbvf.h:128:15: error: duplicate member ‘page’
struct page *page;
^
make[3]: *** [drivers/net/igbvf/ethtool.o] Error 1
make[2]: *** [drivers/net/igbvf] Error 2
make[1]: *** [drivers/net] Error 2
make: *** [drivers] Error 2

修改命名冲突:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
linux-2.6.32.1/drivers/net/igbvf/igbvf.h
struct igbvf_buffer { //line 111
dma_addr_t dma;
struct sk_buff *skb;
union {
/* Tx */
struct {
unsigned long time_stamp;
u16 length;
u16 next_to_watch;
};
/* Rx */
struct {
struct page *_page; //修改
u64 page_dma;
unsigned int page_offset;
};
};
struct page *page;
};

解决方案参考:https://www.anquanke.com/post/id/85837

之后执行以下命令过程中,就没有出现错误了。

1
2
make all
make modules

busybox

主要是busybox的编译和配置

busybox编译

1
2
3
make menuconfig
make
make install

为了避免一些错误,在make menuconfig阶段将一些配置选项修改:
将Linux System Utilities —>中的mkfs_ext2和mkfs_vfat的[*]include改为[ ]exclude,如下图。
1
将Linux System Utilities —>中的Support mounting NFS file systems on Linux < 2.6.23 (NEW)的[*]include改为[ ]exclude:
2
将Networking Utilities —>中的inetd (18 kb) (NEW)的[*]include改为[ ]exclude:
3
将Settings->Build Options->Build static binary(no shared libs)的[ ]exclude改为[*]include:
6

busybox配置

记录一下配置busybox的命令,首先添加inittab命令。

1
2
3
4
cd _install
mkdir -pv {bin,sbin,etc,proc,sys,usr/{bin,sbin}}
cd etc
gedit inittab

inittab的内容如下:

1
2
3
4
5
6
7
#!/bin/sh
::sysinit:/etc/init.d/rcS
::askfirst:/bin/ash
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
::restart:/sbin/init

添加rcS文件:

1
2
3
4
cd _install/etc/
mkdir init.d
cd init.d
gedit rcS

rcS文件的内容如下:

1
2
3
4
5
6
7
#!/bin/sh
#!/bin/sh
mount -t proc none /proc
mount -t sys none /sys
/bin/mount -n -t sysfs none /sys
/bin/mount -t ramfs none /dev
/sbin/mdev -

为rcS文件添加可执行权限:

1
chmod +x rcS

然后在_install目录下配置dev目录:

1
2
3
4
mkdir dev
sudo mknod dev/ttyAMA0 c 204 64
sudo mknod dev/null c 1 3
sudo mknod dev/console c 5 1

生成rootfs:

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

启动qemu:

1
2
3
4
32位启动:
qemu-system-i386 -kernel linux-2.6.32.1/arch/i386/boot/bzImage -initrd busybox-1.28.2/rootfs.img -append "root=/dev/ram rdinit=/sbin/init"
64位启动:
qemu-system-x86_64 -kernel linux-2.6.32.1/arch/x86/boot/bzImage -initrd busybox-1.28.2/rootfs.img -append "root=/dev/ram rdinit=/sbin/init"

问题1

但是在运行后出现了一个问题,qemu终端显示”can’t open /dev/tty: No such file or directory”,一直以为是busybox配置的问题,后来配置了几遍之后仍然是这个问题,后来查到了解决方案,在配置dev目录时需要再添加一句命令:

1
sudo mknod /dev/tty1 c 4 1

解决方案参考:https://www.linuxquestions.org/questions/linux-software-2/dev-tty-no-such-file-or-directory-889996/

问题2

再次启动qemu后,出现以下问题:
4
查找资料,找到解决方法,编辑_install/etc/目录下的inittab文件:

1
2
将::askfirst:/bin/ash
修改为::askfirst:-/bin/ash

再次启动qemu,成功启动:
5

关闭canary

后面再做题的时候需要关闭canary,因此需要将内核重新编译,修改内核的配置文件.config,将下列语句注释掉:

1
2
#./linux-2.6.32.1/.config
#CONFIG_CC_STACKPROTECTOR=y

重新编译:

1
2
3
4
make
make
make all
make modules