为后续的linux内存技术作铺垫 问题的来源在哪呢?在于做
Inline hook
时候用到了一个函数kallsyms_lookup_name
,这个函数会返回一个内核符号地址,我想有没有方法能够直接通过函数地址来调用函数呢?。 当时写了这样的代码:
int (*proc_pid_readdirnew)(struct file *, struct dir_context *);
proc_pid_readdirnew = kallsyms_lookup_name("proc_pid_readdir");
printk("%p",*proc_pid_readdirnew);
输出的结果是这样的
但是呢,通过/proc/kallsyms
直接获取到的地址是怎样的呢?
int (*proc_pid_readdirnew)(struct file *, struct dir_context *);
proc_pid_readdirnew =0x000000009e26b34f;
printk("%p",*proc_pid_readdirnew);
这样的结果就是内核Oops
了,但是依然输出了地址
可以看到此刻输出的地址是00000000f837ac5b
,而不是我们填写的000000009e26b34f
,接着再做一个实验,把地址修改成ffffffffb14f5260
又Oops
了,那么问题就来了,为什么呢?抱着这个问题开始了Linux内存问题的学习。
首先先解决的问题是%p
的输出地址怎样才能和/proc/kallsyms
一样,这就得先看下kallsyms
的输出
内核编译需要开启
CONFIG_KALLSYMS=y
从内核源码可以看出,kallsyms
输出的是十六进制的符号地址,同时也能够输出人类可读的符号名称等。因此最前面实验的代码改成这样
int (*proc_pid_readdirnew)(struct file *, struct dir_context *);
proc_pid_readdirnew = kallsyms_lookup_name("proc_pid_readdir");
printk("[1]%p\n",*proc_pid_readdirnew);
printk("[2]%lx",*proc_pid_readdirnew);
结果就很明显了,能够顺利输出我们想要的结果
两个问题:
- 为什么要用
lx
形式来输出(这个不重要,暂时先不管了) 符号地址
的产生以及作用
先前有学习过提取内核函数地址的方法,主要介绍下/proc/kallsyms
的方法,这是一个动态文件,在内核启动过程中创建并实时更新,其中记录了当前系统的情况,包含了内核符号的地址,但是同样的这是属于内核提供的功能,主要是为了方便开发者调试内核,kallsyms
抽取了内核用到的所有的函数地址
和非栈数据变量地址
生成数据块,也就相当于内核中再存了一个System.map
为了启用此功能,需要内核编译时支持
CONFIG_KALLSYMS
,这个代表所有的内核函数地址
,CONFIG_KALLSYMS_ALL
则包含了所有的非栈数据变量地址
那其实调用也是非常简单了,因为已经得到地址的关系,只需要把函数地址
强转成函数指针
我们就可以自由调用相应的内核函数了。
图灵机概念
- 有一个向两端无限延伸的带子,可以在上面记录内容
- 有一个可以在带子上擦除/写入的读写头,可以在带子上任意移动
- 有一个控制器,控制读写头的移动和擦除/写入操作
而图灵机
对应于现代计算机的体系结构:
- 带子对应于一个内存(内存大小取决于硬件,因此这就决定了计算机的处理能力是有上限的)
- 读写头在输入带上任意移动读写对应了内存的随机存取(Random Access Memory)
- 控制器对应了中央处理器(CPU,Central Process Unit)
内存寻址
就是在内存上找到正确的位置以便进行存取。在图灵机
中,读写头可以按照要求立即在输入带
上找到正确的位置,但是在实际的计算机结构中,这却是需要竭力解决并提高效率的问题,即如何有效的进行内存寻址
。
- 从用户空间内存分离出内核内存
这个的核心观念就在于内核必须永远不能执行用户空间的内存。内核也必须永远不能在没有显式预期的情况下访问用户空间内存
。但是这并不是问题的关键,因为真正的问题在于KASLR
,也就是俗称的内核地址空间布局随机化
- 内存寻址
- Linux内存管理1---内存寻址
- Linux用户空间与内核地址空间
- Linux内存管理--内存地址空间分布
- Linux slab 分配器剖析
- 探索 Linux 内存模型
- 物理内存布局
- 进程页表页和内核页表
- 程序内存地址==>虚拟内存==>物理内存
- 对抗栈帧地址随机化/ASLR的两种思路和一些技巧
- Linux内核对内存的使用方法
- 【转】Linux内存管理(最透彻的一篇)
- 初探——内存读写内核达到提权
- 内核模块直接通过kallsyms获得的地址调用export 函数
- 编译问题文档
- inux内核之内存管理图解
- Linux 内核自防护项目 KSPP
- 内核符号表详解——如何在module中利用内核符号
- linux内核符号表kallsyms
- 内核模块编程遇到的一些问题