跟踪分析Linux内核5.0系统86号调用处理过程
学号末位:186
原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/
实验背景
跟踪分析Linux内核5.0系统调用处理过程
选择系统调用号后两位与学号后两位相同的系统调用进行跟踪分析
分析系统调用、保护现场与恢复现场、系统调用号及参数传递过程
实验步骤
1.安装配置Linux5.0.1内核
- 官网下载Linux5.0.1内核,解压到/usr/linux-5.0.1目录下;
- 配置内核编译参数:
sudo make menuconfig;
- 编译内核
make -j8;
- 制作根文件系统;
mkdir ~/LinuxKernel
cd ~/LinuxKernel/
mkdir rootfs
git clone https://github.com/mengning/menu.git
cd menu/
gcc -o init linktable.c menu.c test.c -m32 -static -pthread
cd …/rootfs/
cp …/menu/init .
find . | cpio -o -Hnewc |gzip -9 > …/rootfs.img
- 启动MenuOS:
qemu-system-i386 -kernel bzImage -initrd rootfs.img;
- 跟踪调试内核启动
qemu-system-i386 -kernel bzImage -initrd rootfs.img -S -s -append nokaslr;
- 建立与qemu调试端口的attach
cd Desktop/linux-5.0.1
gdb
(gdb)file vmlinux
(gdb)target remote:1234
(gdb)break start_kernel
(gdb) c
- 开始跟踪系统调用。
2.跟踪系统调用
- 如图所示,学号尾数186对应的86号系统调用函数为uselib:
- 函数int uselib(const char *library),功能是选择要使用的二进制函数库:
系统调用uselib()用于加载要使用的共享库
通过调用进程。它有一个路径名。地址在哪里
在库本身中找到要加载的。库可以有任何
可识别的二进制格式。
- 在test.c中添加代码块
- 对uselib在gdb中进行断点运行
因为在断点执行中发生了堆栈的入栈出栈,多处函数的跳转与引用,此处仅列出部分调用。
- 相关代码
SYSCALL_DEFINE1(uselib, const char __user *, library)
{
struct linux_binfmt *fmt;
struct file *file;
struct filename *tmp = getname(library);
int error = PTR_ERR(tmp);
static const struct open_flags uselib_flags = {
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
.acc_mode = MAY_READ | MAY_EXEC,
.intent = LOOKUP_OPEN,
.lookup_flags = LOOKUP_FOLLOW,
};
if (IS_ERR(file))
goto out;
error = -EINVAL;
if (!S_ISREG(file_inode(file)->i_mode))
goto exit;
error = -EACCES;
if (path_noexec(&file->f_path))
goto exit;
fsnotify_open(file);
error = -ENOEXEC;
read_lock(&binfmt_lock);
list_for_each_entry(fmt, &formats, lh) {
if (!fmt->load_shlib)
continue;
if (!try_module_get(fmt->module))
continue;
read_unlock(&binfmt_lock);
error = fmt->load_shlib(file);
read_lock(&binfmt_lock);
put_binfmt(fmt);
if (error != -ENOEXEC)
break;
}
read_unlock(&binfmt_lock);
exit:
fput(file);
out:
return error;
}
- 实验总结
1.系统调用uselib()用于加载调用进程要使用的共享库。它有一个路径名。要加载的地址在库本身中找到。库可以具有任何可识别的二进制格式。
2.uselib()是特定用于Linux的,不在打算移植的程序中使用。早期libc启动代码使用uselib()加载共享库,在二进制文件的名称数组中找到名称。自libc 4.3.2以来,启动代码放弃尝试在这些名称前面加上“/usr/lib”、“/lib”和“”。在libc 4.3.4和更高版本中,这些名称在ld_library_path中的目录中查找,如果没有找到,则尝试使用前缀“/usr/lib”、“/lib”和“/”
3.系统调用通常通过函数进行调用,它们通常都需要定义一个或几个参数。系统调用通常会通过一个long类型的返回值来表示成功或者错误
致谢
本文完成于2019.3.19日,谢谢观看。