写点什么

内核调试环境搭建

  • 2023-05-30
    河南
  • 本文字数:10499 字

    阅读完需:约 34 分钟

目录


参考


利用qemu+gdb在ubuntu下搭建调试kernel的环境 - EwanHai - 博客园 (cnblogs.com)

经过测试好用的内核调试环境搭建过程

  • 1、使用 qemu 创建 Ubuntu 虚拟机

  • 2、使用 git 下载对应版本 获取源码

  • 3、源码编译 Ubuntu 内核 得到 deb 包

  • 4、qemu 虚拟机和主机互通 传输文件

  • 5、Ubuntu 更换内核 安装 deb 包

  • 6、关闭 kaslr

  • 7、调试技巧


在很多情况下,只使用 linux 内核加文件系统不能得到漏洞依赖的环境


VMware 虚拟机调试方便,但是在进行测试时虚拟机会崩溃关机。


用 make 方式编译安装 Ubuntu 内核可能会有一些内核选项没有开启,导致 Ubuntu 黑屏,用官方提供的方式编译成 deb 包是很稳定的。


用 apt 安装内核调试信息的方法,调试信息和源码很可能对应不上,自己编译安装是最稳妥的方式。

ubuntu 和 linux 版本

https://blog.csdn.net/Breeze_CAT/article/details/123787636


举例:linux 版本 5.15.5


  • 目前发布的主版本,增长很缓慢,通常后面的数字比较大了的时候该数字会增长。

  • 次版本号,表示稳定的版本号。

  • 修订版本号,代表改版本补丁次数,在下一个稳定版本发布之前出现补丁和修复会更新该版本号。非长期维护版本一般 20 多个。


很久之前内核通过版本号中的第二个数字即 B 的奇偶来表示稳定版和预发布版。但现在已经取消这个规则,现在预发布版用-rcX 来表示如 5.17-rc3,X 为数字,一般不超过 rc8


长期维护版本:5.15、5.10、5.4、4.19、4.14、4.9

查看 commit 所属的内核版本


kernel/git/torvalds/linux.git - Linux kernel source tree



查看 tree 中根目录下的 Makefile 文件可以看到对应的版本号

查看 Ubuntu 版本号等信息

cat /etc/issueUbuntu 20.04.2 LTS \n \llsb_release -a  命令No LSB modules are available.Distributor ID: UbuntuDescription:    Ubuntu 20.04.2 LTSRelease:        20.04   版本Codename:       focal   别名
查看Ubuntu信息➜ uname -aLinux tower-virtual-machine 5.15.0-71-generic #78~20.04.1-Ubuntu SMP Wed Apr 19 11:26:48 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux➜ uname -r5.15.0-71-generic 内核版本 5.15表示内核稳定版本号,一般ubuntu中最后小修订号都是0,因为ubuntu会自己合入补丁。 71表示由ubuntu进行的第35次修订(合入补丁)。 generic:通用版本,除此之外还可能有服务器版server或老式处理器的i386版等。
复制代码


Ubuntu 对应的别名



Ubuntu 使用的内核



经过测试,其他版本的内核是可以安装的(如 focal 系列的 Ubuntu 内核代码编译之后可以安装到 Ubuntu18 主机上)(没有经过更多测试)

下载与安装内核

下载内核

下载 ubuntu


https://mirrors.aliyun.com/oldubuntu-releases/releases/20.04.0/?spm=a2c6h.25603864.0.0.10467ff3XF6iMS 阿里云镜像


https://old-releases.ubuntu.com/releases/ Ubuntu 官方镜像


下载 Ubuntu 内核


https://kernel.ubuntu.com/~kernel-ppa/mainline/v5.15.10/ 较粗的 deb 包


下载 linux 内核源码


https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/ 版本比较粗


kernel/git/torvalds/linux.git - Linux kernel source tree Linux 源码


Kernel/Dev/KernelGitGuide - Ubuntu Wiki Ubuntu 内核源码


找到对应的源码:


git tag | grep 4.10.0-19
git checkout ubuntu-4.10.0-19........
复制代码

ubuntu 更换内核

  • 下载对应 image 和 modules

  • sudo dpkg -i *.deb

  • 重启


或使用 apt 更换内核


sudo apt search 'linux-image-5.4.0-81-generic'sudo apt install 'linux-image-5.4.0-81-generic'更新并重启sudo update-initramfs -u -k allsudo update-grubreboot安装新版本内核头文件,用于开发编译sudo apt install linux-headers-$(uname -r)
复制代码


开机按 esc 选择选高级,找到对应版本内核启动


如果进不去需要修改引导启动信息:


  • 修改文件/etc/default/grub

  • 注释掉 GRUB_TIMEOUT_STYLE=hidden

  • 修改 GRUB_TIMEOUT=0 为 GRUB_TIMEOUT=10

  • 执行 sudo update-grub 启用修改

  • reboot 重启时会进入引导界面等待选择内核

手动下载并切换到指定源码

https://bbs.kanxue.com/thread-249192.htm


https://wiki.ubuntu.com/Kernel/Dev/KernelGitGuide选择对应的 Ubuntu 系列


查看主机的 Ubuntu 系列(这里需要下载被调试主机的源码)


➜  CVE-2021-3493 git:(main) ✗ cat /etc/apt/sources.listdeb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
复制代码


如 Ubuntu20 可以下载


git clone https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/focal
git tag | grep 4.10.0-19git checkout ubuntu-4.10.0-19........
复制代码


gdb 中指定源代码路径,或把 source 文件直接拷贝到 gdb 检测源码的目录(如/build/linux-kcrkKx/linux-5.4.0)


set substitute-path PATH1 PATH2,PATH1是vmlinux中的路径信息,PATH2是source code存放的真实路径。
复制代码

用 apt 下载源码

apt source linux-image-unsigned-5.11.0-44-generic # 版本号根据需求更改,可以用apt search搜索
复制代码


ubuntu 内核 git:https://kernel.ubuntu.com/git/ubuntu/

使用 git 下载对应版本

可以查看分支名https://kernel.ubuntu.com/git/ubuntu/ubuntu-focal.git/refs/tags


git clone git://kernel.ubuntu.com/ubuntu/ubuntu-focal.git -b Ubuntu-hwe-5.13-5.13.0-35.40_20.04.1 --depth 1
复制代码

编译并安装 linux 内核(使用 linux-5.15.10 版本)

make ARCH=x86_64 x86_64_defconfig make ARCH=x86_64 menuconfig配置 Kernel-hacking -> Compile-time checks and compiler optionsCompile the kernel with debug info —> Provide GDB scripts for kernel debugging关闭 Reduce debugging information

make -j8
复制代码


sudo make modules_install   安装模块sudo make install      安装sudo update-initramfs -c -k 5.3.10 启用(数字为版本号)sudo update-grub   更新grubreboot
复制代码


也可以使用 docker 编译https://registry.hub.docker.com/r/chenaotian/kernelcompile(编译 5.x)


docker run -ti --rm -h kc --name kc -v D:/share:/work chenaotian/kernelcompile:latest /bin/bashdocker exec -it kc /bin/bash
复制代码

得到 Ubuntu 内核需要的编译选项

常用的内核编译选项

# 设置调试符号CONFIG_DEBUG_INFO=y# fuse 开启,一些漏洞利用会用到CONFIG_FUSE_FS=y# VIPC 开启,可以使用msg系列CONFIG_SYSVIPC=yCONFIG_SYSVIPC_SYSCTL=yCONFIG_SYSVIPC_COMPAT=yCONFIG_CHECKPOINT_RESTORE=y # 设置这个才能正确调用msg 里的copy 系列函数
复制代码

查看已有操作系统的编译选项

cat /usr/src/linux-headers-`uname -r`/.config cat /boot/config-`uname -r`
复制代码

源码编译 Ubuntu 内核

Kernel/BuildYourOwnKernel - Ubuntu Wiki


安装依赖


sudo apt-get build-dep linuxsudo apt-get install libncurses-dev gawk flex bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf llvm
复制代码


编译


LANG=C fakeroot debian/rules cleanLANG=C fakeroot debian/rules binary-headers binary-generic binary-perarch  快速编译# if you need linux-tools or lowlatency kernel, run instead: 会多出来更多东西LANG=C fakeroot debian/rules binary  
复制代码

得到有调试信息的源码编译结果

sudo apt-get install pkg-config-dbgsymLANG=C fakeroot debian/rules cleanLANG=C fakeroot debian/rules binary-headers binary-generic binary-perarch skipdbg=false
复制代码

查看编译结果

System.map 文件可以查看一些关键函数有没有


cat System.map |grep function_name
复制代码


查看字符串


strings vmlinux |grep function_name
复制代码

qemu 的安装和使用

安装 qemu

sudo apt-get install qemu qemu-system  
复制代码

使用

常用的启动脚本


#! /bin/sh
cd ./rootfsfind . | cpio -o --format=newc > ../rootfs.img cd ../
qemu-system-x86_64 \-m 512M \-kernel ./bzImage \-initrd ./rootfs.img \-nographic \-append "console=ttyS0 root=/dev/sda rw nokaslr quiet" \-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \-cpu kvm64,+smep,+smap \-gdb tcp::10086
复制代码

创建文件系统

文件系统的操作

解包和打包


cpio -idmv < ../rootfs.img #解包cpiofind . | cpio -o --format=newc > ../rootfs.img #打包cpio
复制代码


有可能在外层更进行了一次 gzip 压缩,使用 binwalk 可以可以解包


binwalk -Me ./rootfs.img
复制代码


如果一定需要动态链接的 exp,偷懒方法就是,ldd 查看 exp 需要的动态库,然后将 ld-linux-x86-64.so.2 和其他依赖的 so 全部拷贝到文件系统中,qemu 启动后,用 LD_LIBRARY_PATH 来运行


将其依赖的 so 全部拷贝到一个文件夹内然后放入 rootfs 中制作成 initrd.img,然后启动 qemu,按照如下方法运行


cp ...so ./rootfs/exp #将so 拷贝到制作initrd.img的目录中cd ./rootfsfind . | cpio -o --format=newc > ../rootfs.img #制作initrd.imgcd .././boot.sh #启动qemu# qemu 启动后cd /expdirexport LD_LIBRARY_PATH=`pwd`./ld-linux-x86-64.so.2 ./exploit
复制代码

编译文件系统

使用 busybox 构建文件系统比较复杂,用 buildroot 相对简单


git clone git://git.buildroot.net/buildrootcd buildrootmake menuconfig
复制代码


  • 在跳出的 UI 界面依次选择


Target options


Target Architecture (x86_64)


x86_64上按空格键,以选择该选项


  • 再返回与Target options同一级的界面


选择Filesystem images


ext2/3/4 root filesystem按 Y,并进入ext2/3/4 variant (ext4)选择ext4


make -j4
复制代码

用 busybox 创建文件系统

wget https://busybox.net/downloads/busybox-1.35.0.tar.bz2tar -jxvf busybox-1.35.0.tar.bz2
cd busybox-1.35.0make defconfigmake menuconfig
复制代码


选择 settings 中选择静态链接



make -j4sudo make install
复制代码


make install 会把文件拷贝到当前目录下的 _install 目录


拷贝文件,创建 init


mkdir ramdiskcd ramdiskcp -r ../busy-1.25.0/_install/* .
cd ramdiskln -s bin/busybox init
复制代码


设置启动程序,init 程序首先会访问 etc/inittab 文件,以获取开机要启动的程序列表,因此我们得编写一个 inittab


cd etcvim inittab  
::sysinit:/etc/init.d/rcS ::askfirst:-/bin/sh ::restart:/sbin/init ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r ::shutdown:/sbin/swapoff -a
chmod +x etc/inittab
复制代码


系统初始化寻找 etc/init.d/rcS,需要创建,内容添加


#!/bin/sh
mount procmount -o remount,rw /mount -a clear echo "My Tiny Linux Start :D ......"
复制代码


并加权限


chmod +x  rcS
复制代码


rcS 中,mount -a 是自动挂载 /etc/fstab 中的内容,因此我们需要一个 fstab 文件,以设置需要挂载的系统, 创建文件并添加内容


proc            /proc        proc    defaults          0       0sysfs           /sys         sysfs   defaults          0       0devtmpfs        /dev         devtmpfs  defaults        0       0
复制代码


最后把文件压缩成镜像


cd ramdiskfind . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.img
cpio --null或-0接受新增列控制字符,通常配合find指令的"-print0"参数使用。-o或--create  执行copy-out模式,建立备份档。-v或--verbose  详细显示指令的执行过程。newc 新型 (SVR4) 跨平台格式, 支持大于 65536 i节点的文件系统,一般 制作 ramdisk 就用 这个 格式-9 表示压缩率
复制代码

用别人创建的 initrd(文件系统)

用文件系统启动内核

启动内核

使用 buildroot 编译的镜像


qemu-system-x86_64 -kernel bzImage -boot c -m 1024 -hda rootfs.ext2 -append "root=/dev/sda rw console=ttyS0, 115200 acpi=off nokaslr" -serial stdio -display none -s -S
复制代码


使用 busybox 构建的镜像启动命令


# 在A Terminal中运行以下命令qemu-system-x86_64 -kernel bzImage -boot c -m 1024 -initrd initramfs.img -append "root=/dev/sda rw console=ttyS0, 115200 acpi=off nokaslr" -serial stdio -display none -s -S
复制代码


如果需要调试内核的 kvm 模块,则向上述命令添加 -enable-kvm

启动调试

gdb vmlinuxtarget remote localhost:1234
复制代码

文件共享

把自己的文件放入文件系统


  • 如果使用 busybox 创建文件系统,直接把文件拷贝到对应目录,执行命令把文件打包成镜像


find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.img
复制代码


  • 如果使用 buildroot 构建镜像,添加自定义文件到文件系统 System configuration 菜单下选择 Custom scripts to run before creating filesystem images 写入命令,把文件拷贝到对应目录 output/target 目录下 ,在测试的时候报错命令出错。

  • 编译过之后,直接用手动拷贝文件到 output/target 然后再执行一次 make -j4 得到的镜像内部有需要的文件

调试技巧

关于符号信息的坑

vmlinux 文件可能不包含一些符号,如图



原因是 ovlerlay 文件系统被编译成了内核模块文件,需要手动添加


gef➤  add-symbol-file ./fs/overlayfs/overlay.ko  0xffffffffc04ee000
复制代码


查看内核模块加载地址(内核模块被加载了之后才能看到,可能需要先执行一次相关的命令或执行相关的 poc)


cat /proc/modules
复制代码

关于源代码

用 docker 编译的内核会从 docker 中的路径寻找二进制源码,在调试时会出现找不到源码的情况


gef➤  list46      in /work/ubuntu-focal/arch/x86/include/asm/irqflags.h
复制代码


用 set 命令重定位源码目录即可


set substitute-path /work/ubuntu-focal /home/tower/aiwencode/vul/CVE-2023-0386/ubuntu-focal
复制代码

安装 vmlinux 调试信息

Ubuntu 内核默认不包含调试信息


安装内核调试信息


https://developer.aliyun.com/article/899339


获取 Ubuntu 内核调试信息


https://bbs.kanxue.com/thread-249192.htm


cat /boot/config-uname -r| grep -i "GDB"查看当前内核是否支持KGDB增加符号对应的源文件codename=$(lsb_release -c | awk '{print $2}')sudo tee /etc/apt/sources.list.d/ddebs.list << EOFdeb http://ddebs.ubuntu.com/ ${codename} main restricted universe multiversedeb http://ddebs.ubuntu.com/ ${codename}-security main restricted universe multiversedeb http://ddebs.ubuntu.com/ ${codename}-updates main restricted universe multiversedeb http://ddebs.ubuntu.com/ ${codename}-proposed main restricted universe multiverseEOF# 添加访问符号服务器的秘钥文件wget -O - http://ddebs.ubuntu.com/dbgsym-release-key.asc | sudo apt-key add -# 更新源文件sudo apt-get update
或sudo apt-get install aptitude
复制代码


获取被调试内核信息,并安装对应内核符号


被调试主机:unamr -r
调试主机:sudo apt-get install linux-image-<被调试主机执行uname -r结果>-dbgsym
复制代码


在调试主机上进行调试


gdb -s /usr/lib/debug/boot/vmlinux-5.15.0-71-generic   直接加载之前下载的包含符号信息的vmlinuxset architecture i386:x86-64:intel
target remote localhost:8864
复制代码

调试 qemu 的 Ubuntu 虚拟机

创建 qemu 虚拟机

创建虚拟磁盘


qemu-img create -f qcow2 qemu_disk.img 10G查看磁盘信息qemu-img info qemu_disk.img
复制代码


可以创建的格式如下



Supported formats: blkdebug blklogwrites blkreplay blkverify bochs cloop compress copy-on-read dmg file host_cdrom host_device luks nbd null-aio null-co nvme parallels qcowqcow2 qed quorum raw replication sheepdog throttle vdi vhdx vmdk vpc vvfat
复制代码


启动虚拟机


qemu-system-x86_64 -m 4G -smp 4  -boot d  -hda ubuntu20.qcow2 -cdrom ubuntu-18.04.5-desktop-amd64.iso
boot order 的选项如下,代表系统的启动顺序,每种方式都有一个对应的字母缩写-boot [order=drives][,once=drives][,menu=on|off]  'drives': floppy (a), hard disk (c), CD-ROM (d), network (n)
复制代码


安装好之后再次启动


qemu-system-x86_64 -m 8G -smp 4  -hda ubuntu20.qcow2 
复制代码


https://www.cnblogs.com/sun-ye/p/15750205.html

qemu 虚拟机和主机互通

https://www.cnblogs.com/haiyonghao/p/14440163.html


网桥模式


用 ip addr 命令查看自己的网络中可以使用的网卡名


2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP group default qlen 1000    link/ether 00:0c:29:9e:f6:c2 brd ff:ff:ff:ff:ff:ff    altname enp3s0
复制代码


主机创建网桥,把主机网卡添加到网桥上(网络会断开重启),启用 stp ,


apt-get install bridge-utils  安装依赖brctl addbr br0    创建brctl addif br0 ens160绑定brctl stp br0 onifconfig ens160 0dhclient br0route   查看创建网桥的信息(br0的信息),对应填到qemu虚拟机里
复制代码


启动 qemu 虚拟机,在启动命令后加


-net nic -net tap,ifname=tap1
复制代码


修改 qemu 虚拟机内的网络配置编辑/etc/netplan/ *-cloud-init.yaml 文件


ip 设置为和 br0 同一网段,gateway 设置为 route 查到的(我这里是 0.0.0.0),dns 8.8.8.8


配置网络 https://blog.csdn.net/allway2/article/details/121949816 (Ubuntu18 以上)

关闭 kaslr(添加内核启动选项)(否则断点断不下来)

断点断不下来原因为地址不对,如果不关闭 kaslr,需要查看/proc/kallsys 中对应的符号地址下断点


sudo vim /etc/default/grub
添加GRUB_CMDLINE_LINUX_DEFAULT="quiet splash nokaslr" 添加内核启动选项
复制代码


更新,重启


sudo update-grubreboot
复制代码

调试 vmware 虚拟机

启用调试

在文件 xxx.vmx 中最后添加(在 gdb 执行 c 之后虚拟机崩溃问题没有解决)


debugStub.listen.guest64="TRUE"
debugStub.port.guest64 = "8864"
复制代码


用 gdb 连接 127.0.0.1:8864


用其他主机进行调试可以加一个端口转发


netsh interface portproxy add v4tov4 listenaddress=192.168.1.68 listenport=8864 connectaddress=127.0.0.1 connectport=8864使用ipv4 to ipv4模式将源地址是127.0.0.1的8864端口代理到192.168.1.68(本机当前ip)8864端口上,源地址处也可以改为可以内网互通的服务器的内网地址。
netsh interface portproxy show all关闭转发,这种方式转发可能会失败(不报错)需要删除之后重新设置netsh interface portproxy delete v4tov4 listenaddress=192.168.1.68 listenport=8864
复制代码


安装 vmwaretools


sudo apt upgradesudo apt install open-vm-tools-desktop -ysudo reboot
复制代码

问题

下断点 continue 之后崩溃退出



没有找到解决方案

vmware 双机调试(用串口)

https://blog.csdn.net/Breeze_CAT/article/details/123787636


https://bbs.kanxue.com/thread-249192.htm


http://blog.nsfocus.net/gdb-kgdb-debug-application/

编译内核模块

Makefile 替换 babydriver 为文件名,KERNELDIR 为内核源码的目录


#!/bin/bash
obj-m += babydriver.o
#CROSS_COMPILE ?= /opt/linaro/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- # Compiler path settings
KERNELDIR :=/home/tower/aiwencode/sourcecode/linux-5.15/ # Kernel code directory
PWD ?= $(shell pwd)
all: make -C $(KERNELDIR) M=$(PWD) modules # Compile the instructions of the kernel module
clean: rm -rf *.ko *.mod.c *.o modules.* Module.symvers # delete all generated files

复制代码


源码举例


/** arttnba3_module.ko* developed by arttnba3*/#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/device.h>#include <linux/slab.h>#include <linux/uaccess.h>
#define DEVICE_NAME "babydev"#define CLASS_NAME "a3module"
static int major_num;static struct class * module_class = NULL;static struct device * module_device = NULL;static spinlock_t spin;
static int __init kernel_module_init(void);static void __exit kernel_module_exit(void);static int a3_module_open(struct inode *, struct file *);static ssize_t a3_module_read(struct file *, char __user *, size_t, loff_t *);static ssize_t a3_module_write(struct file *, const char __user *, size_t, loff_t *);static int a3_module_release(struct inode *, struct file *);static long a3_module_ioctl(struct file *, unsigned int cmd, long unsigned int param);
static struct file_operations a3_module_fo = { .owner = THIS_MODULE, .unlocked_ioctl = a3_module_ioctl, .open = a3_module_open, .read = a3_module_read, .write = a3_module_write, .release = a3_module_release,};
static struct{ void *device_buf; size_t device_buf_len;}babydev_struct;
module_init(kernel_module_init);module_exit(kernel_module_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("arttnba3");
static int __init kernel_module_init(void){ spin_lock_init(&spin); printk(KERN_INFO "[arttnba3_TestModule:] Module loaded. Start to register device...\n"); major_num = register_chrdev(0, DEVICE_NAME, &a3_module_fo); if(major_num < 0) { printk(KERN_INFO "[arttnba3_TestModule:] Failed to register a major number.\n"); return major_num; } printk(KERN_INFO "[arttnba3_TestModule:] Register complete, major number: %d\n", major_num);
module_class = class_create(THIS_MODULE, CLASS_NAME); if(IS_ERR(module_class)) { unregister_chrdev(major_num, DEVICE_NAME); printk(KERN_INFO "[arttnba3_TestModule:] Failed to register class device!\n"); return PTR_ERR(module_class); } printk(KERN_INFO "[arttnba3_TestModule:] Class device register complete.\n");
module_device = device_create(module_class, NULL, MKDEV(major_num, 0), NULL, DEVICE_NAME); if(IS_ERR(module_device)) { class_destroy(module_class); unregister_chrdev(major_num, DEVICE_NAME); printk(KERN_INFO "[arttnba3_TestModule:] Failed to create the device!\n"); return PTR_ERR(module_device); } printk(KERN_INFO "[arttnba3_TestModule:] Module register complete.\n"); return 0;}
static void __exit kernel_module_exit(void){ printk(KERN_INFO "[arttnba3_TestModule:] Start to clean up the module.\n"); device_destroy(module_class, MKDEV(major_num, 0)); class_destroy(module_class); unregister_chrdev(major_num, DEVICE_NAME); printk(KERN_INFO "[arttnba3_TestModule:] Module clean up complete. See you next time.\n");}
static long a3_module_ioctl(struct file * __file, unsigned int cmd, long unsigned int param){ if (cmd == 65537) { kfree(babydev_struct.device_buf); babydev_struct.device_buf = kmalloc(param, GFP_ATOMIC); babydev_struct.device_buf_len = param; printk(KERN_INFO "alloc done\n"); return 0; } else { printk(KERN_INFO "default arg is %ld\n", param); return -22; }}
static int a3_module_open(struct inode * __inode, struct file * __file){ babydev_struct.device_buf = kmalloc(0x40, GFP_ATOMIC); babydev_struct.device_buf_len = 0x40; printk(KERN_INFO "device open\n"); return 0;}
static int a3_module_release(struct inode * __inode, struct file * __file){ kfree(babydev_struct.device_buf); printk(KERN_INFO "device release\n"); return 0;}
static ssize_t a3_module_read(struct file * __file, char __user * user_buf, size_t size, loff_t * __loff){ size_t result;
if (!babydev_struct.device_buf) return -1LL; result = -2LL;
if (babydev_struct.device_buf_len > size) { copy_to_user(user_buf, babydev_struct.device_buf, size); result = size; } return result;}
static ssize_t a3_module_write(struct file * __file, const char __user * user_buf, size_t size, loff_t * __loff){ size_t result;
if (!babydev_struct.device_buf ) return -1LL; result = -2LL; if ( babydev_struct.device_buf_len > size) { copy_from_user(babydev_struct.device_buf, user_buf, size); result = size; } return result;}
复制代码

其他

查看内核支持的选项


grep CONFIG_PID_NS /boot/config-$(uname -r)
复制代码


查看内核崩溃日志


/proc/last_kmsg/sys/fs/pstore/console-ramoops
复制代码


发布于: 59 分钟前阅读数: 3
用户头像

全球高精准IP地址实时定位技术领航者 2020-02-15 加入

一个终生致力于网络空间地图测绘技术创新应用的开拓者

评论

发布
暂无评论
内核调试环境搭建_网络安全_郑州埃文科技_InfoQ写作社区