type
status
date
slug
summary
tags
category
icon
password
rwProcMem33的尝试修复
错误情况
rwProcMem33编译出模块之后,无法进行正常的内存读取/写入。内核版本Linux 5.10.189

1.找到错误信息
在编译前从源码中打开debug模式的宏,让我们可以用dmesg看到内核的日志。于是发现开始就出现了这样几个错误:



作者写了几个函数,用来自动找到mmap_lock,map_count和cmdline的偏移量,但是三个都失败了。mmap_lock位于mmap_struct结构体中。扩大查找范围至整个结构体,无果。

2.修复mmap_lock和map_count
查看linux源码,可知mm_stuct的结构。对比作者所写demo,传给驱动的数值是/proc/self/maps文件的行数,驱动收到后然后以mmap_lock为基础,查找前40和后40字节的信息,是否能读出int值与map_count相等。如果相等,则取这个相等位置往后挪动两个int的位置,这里作为绝对偏移。

那么这个偏移有什么作用呢?如下是使用方式
把这个位置转换成
struct rw_semaphore *
指针。但这个指针的类型,就是mm结构体里面的mmap_lock的类型。map_count是int,所以往后挪动了一个int,spinlock_t大小和编译相关,但一般是32位,也可以算是int。所以又挪回来了。
那就直接让accurate offset等于mmap_lock对于mm结构体地址的偏移就完事了
让这个语句中g_mmap_lock_offset_proc_maps=0.
非常简单。注释掉上述自动找offset函数中的for循环,设置标识位为1,偏移为0即可。
对于map_count,采用相同做法即可。在init_map_count_offset函数中,注释掉for循环,并添加以下两行。
3.cmdline_offset修复
如果以上两个修复好了,会发现cmdline offset已经好用了。
这是因为上面两个修复完成,就已经可以读取和写入内存了。而找cmdline offset的时候用到了读取。

但同时也会发现,找到的offset是0。但他实现的是读物理内存直到读出来和应用传入的命令字符串相同,就判断找到了。不知道是否有用,是否是会变得,所以不改这里。
4.其他相关自动偏移(无需修补)
已经看到这里了,还剩一个自动偏移cred,一起看了吧。
先看实现代码
通过读取
/proc/self/status
中的进程名称,并将其与任务结构中的可能偏移位置进行比较,以real_cred为基础,找前100,后300字节的内容,直到相等。运行这段代码发现自动找到偏移量为8.这是正确的,因为根据linux内核源码,cred确实在real_cred后8个字节处

在Linux内核中,
real_cred
和 cred
是任务结构(task structure)中的两个成员,分别表示任务的真实凭据和有效凭据。理解它们的区别对理解任务的权限管理非常重要。下面详细解释这两个字段的区别及其用途:real_cred
(Objective and real subjective task credentials)real_cred
表示任务的真实凭据。这些凭据描述了任务实际的身份信息,不会因为临时的权限提升而改变。- 通常用于需要确保操作是以任务的真实身份进行的场景,例如,在设置新的权限时,系统会检查
real_cred
。 - 任务的真实用户ID(real user ID, ruid)、真实组ID(real group ID, rgid)等信息存储在
real_cred
中。
cred
(Effective (overridable) subjective task credentials)cred
表示任务的有效凭据。这些凭据是当前任务在执行期间实际使用的凭据,可能会因为临时权限提升(如通过setuid
或setgid
系统调用)而改变。- 用于大部分权限检查,例如文件访问权限,系统调用权限等。在这些情况下,系统会检查
cred
中的信息。 - 任务的有效用户ID(effective user ID, euid)、有效组ID(effective group ID, egid)等信息存储在
cred
中。
举个例子
假设有一个进程,它的真实用户ID(ruid)是1000,但为了执行某些特权操作,它的有效用户ID(euid)被提升到0(即root用户)。
real_cred
将始终保持ruid为1000,因为这是进程的真实身份。
cred
会显示euid为0,因为这是进程当前的有效身份,用于权限检查。
所以我们可以利用setgid的方式改变程序的Gid,并用驱动读取,对比输出结果。
程序输出
至此,大部分功能已经能正常运行了。还剩一个getpid没改,后续再说。
添加如下代码,进行gid的修改以便验证(因为我们要在root下运行测试工具,但是root下运行该程序uid和gid都是0不能直观的看到结果):
编译一下testKo,注释掉物理内存相关的部分(实在是慢的令人发指,但能用)输出如下
- Author:Lynnette177
- URL:https://next.lynnette.uk/article/patch_proc_mem_33
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts