内核准备

打开调试

make menuconfig 开启如下选项: Kernel hacking -> Compile-time checks and compiler options -> Compile the kernel with debug info Kernel hacking -> Generic Kernel Debugging Instruments -> KGDB: kernel debugger

qemu-system-x86_64 关闭 Kernel ALSR 以便于调试内核: -append "nokaslr"

调试内核时,为了加载 vmlinux 符号表,必须额外指定 -append “nokaslr"以关闭 kernel ASLR。这样符号表才能正确的对应至内存中的指定位置,否则将无法给目标函数下断点,
还可以通过内核选项关闭aslr: Processor type and features ---> [ ] Randomize the address of the kernel image (KASLR)

内核中的对齐宏:__ALIGN_KERNEL

1
2
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))

其本质就是对齐的地位补0,以8字节对齐为例: int size = 8; <----> 1000(bin) 计算a以size为倍数的下界数: 就让这个数(要计算的这个数)表示成二进制时,最后三位为0就可以达到这个目标。只要下面这个数与a进行"与运算"就可以了: 11111111 11111111 11111111 11111000 而上面这个数实际下就是 ~(size - 1),可以将该数称为size的对齐掩码size_mask.

#define alignment_up(a, size) ((a+size-1) & (~ (size-1))) 注: 上界数的计算方法,如果要求出比a大的是不是需要加上8就可以了?可是如果a本身就是8的倍数,这样加8不就错了吗,所以在a基础上加上(size - 1), 然后与size的对齐掩码进行与运算.

所以0x123 八字节对齐为:

1
2
3
4
5
6
7
8
9
0001 0010 0011(bin)
+
0111
= 
0001 0010 1010
&
1000
=
0001 0010 1000(0x128)

debug 启动参数:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
export IMAGE=~/mywork/linux-5.4.230/rootfs/ubuntu-rootfs-build
export KERNEL=~/mywork/linux-5.11.14
           
qemu-system-x86_64 -cpu host \
    -m 2G -smp 2 \ 
    -kernel $KERNEL/arch/x86/boot/bzImage \
    -append "console=ttyS0 root=/dev/sda rw earlyprintk=serial net.ifnames=0 nokaslr" \
    -drive file=$IMAGE/rootfs.img,format=raw \
    -net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \
    -net nic,model=e1000 \
    -virtfs local,path=~/mywork,mount_tag=tag001,security_model=mapped-xattr \
    -enable-kvm \
    -nographic \
    -gdb tcp::12345 \
    -S \                                                  
    -pidfile vm.pid 2>&1 | tee vm.log

-S :表示启动后就挂起,等待 gdb 连接;
-gdb tcp::12345 也可以改成-s 表示:-gdb tcp::1234

此时启动gdb:

1
2
3
4
gdb
gef➤  file vmlinux
gef➤  target remote localhost:12345
gef➤  gef-remote localhost 12345

一个简单的启动脚本:

1
2
3
4
5
6
gdb \
    -ex "add-auto-load-safe-path ~/mywork/linux-5.11.14/" \
    -ex "file ~/mywork/linux-5.11.14/vmlinux" \
    -ex "target remote localhost:1234" \
    -ex "b cmdline_proc_show" \
    -ex "c"

效果图: kernel-gdb