计算机操作系统实验动态模块篡改系统调用为什么返回值不正确
在完成操作系统实验动态模块与字符设备时,我已经成功的将 78 号系统调用修改为自定义函数,更改后的自定义函数如下:
asmlinkage int hello(int a,int b) //new function
{
printk("No 78 syscall has changed to hello");
return a+b;
}
模块加载结果如下:
[ 3604.213062] Module loading...
[ 3604.228647] sys_call_addr: 00000000bca137c4
[ 3604.228941] old_sys_call_func: ffff0000083735e0
[ 3604.229251] syscall 78 replaced successfully with hello function
[ 3604.231748] No 78 syscall has changed to hello
[ 3604.232071] a: 537460416, b: 14352384
但是在用户程序中调用时,返回的结果却不对
modify_new_syscall.c
#include<stdio.h>
#include<sys/time.h>
#include<unistd.h>
int main()
{
int ret=syscall(78,10,20); //after modify syscall 78
printf("%d\n",ret);
return 0;
}
[root@kp-test01 modify_syscall]# ./modify_new_syscall
570293952
[root@kp-test01 modify_syscall]# ./modify_new_syscall
572391104
如上,会返回一个很大的数,不知道为什么会这样 🤤,想知道这种会不会影响验收
mod
#2 · 猜测是初始化问题
rotartsinimdA 感谢😊我再试试
解决了。在尝试的过程中发现,传入的参数中,a 实际上是地址,使用*a 可以从日志中看见是正确的值,但是 b 我就不知道了,即使当作地址来解析还是不正确。
最终的解决方案是读取寄存器 x0,和 x1 的值,这两个寄存器中的值是正确的。
// 新的系统调用函数
asmlinkage int hello(/* int *a, int *b */void) {
int a = (int)current_pt_regs()->regs[0]; // 从寄存器 x0 获取参数 a
int b = (int)current_pt_regs()->regs[1]; // 从寄存器 x1 获取参数 b
printk("No 78 syscall has changed to hello\n");
printk("a: %d, b: %d\n", a, b);
return a + b; // 返回 a 和 b 的和
}
总之就是由于地址空间的问题这里只应该从寄存器里拿,关于*a 能取到正确的值的话如果不是偶然现象可能是因为 a 被“拷贝”到了内核栈用于加速 syscall(?),这是一个 linux 使用的系统调用加速手段,但这里我也不太确定
Zerick 好的,感谢
同学你好,请问你是怎么修改地址的呢,运行环境是什么?详细信息我私发你了
同学请问你初期有没有遇到一挂载就重启的问题,是怎么解决的 😢
我就是这样。。。感觉我修改的 syscalltable 的地址也是对的
关闭对应位置的写保护。此外,使用的符号地址我是通过函数动态获取的,最后打印到日志发现动态查找的地址和在文件中找到的地址也并不一样,这部分可能也会影响
yuaay 感谢已解决