我正在尝试实现一个syscall
能够x86
修改vDSO
. 鉴于vDSO
内容对于用户空间是只读的,我相信 asyscall
是需要的。否则会导致分段错误。但是,我目前无法成功。
我的计划:
系统调用kernel/sys.c
extern struct vdso_data _vdso_data[CS_BASES] __attribute__((visibility("hidden")));
SYSCALL_DEFINE1(foo, int, num) {
struct vdso_data *vdata = _vdso_data;
vdata[0].__unused = num;
return 0;
}
将syscall
读取在_vdso_data
中声明arch/x86/include/asm/vvar.h
和定义的内容arch/x86/include/asm/vdso/vsyscall.h
。然后它将变量修改为__unused
用户输入的一些数字。
vDSO 在arch/x86/entry/vdso/vclock_gettime.c
#include <asm/vdso/vsyscall.h>
notrace int __vdso_query()
{
struct vdso_data *vdata = __arch_get_k_vdso_data();
return vdata[0].__unused;
}
我知道在时序函数中定义与时间无关的东西是个坏主意,但这是我现在正在测试的。该__vdso_query()
函数将读取数据并返回__unused
变量的值。
测试计划
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
#define SYS_foo 548
extern int __vdso_query();
int main(int argc, char **argv)
{
int before = __vdso_query();
printf("Before syscall: %d\n", before);
int num = 10;
long res = syscall(SYS_foo, num);
int after = __vdso_query();
printf("After syscall: %d\n", after);
return res;
}
预期成绩
我想在返回0
之前syscall
和10
之后查看,因为如果一切都按照计划进行,将会改变。syscall
__vdso_query()
syscall
_vdso_data[0].__unused
当前结果
目前,内容始终0
与syscall
.
问题
如何_vdso_data
正确访问
我尝试通过两种方式访问_vdso_data
:__arch_sync_vdso_data()
和extern
.
- 当我尝试使用
__arch_get_k_vdso_data
函数 where defined inasm/vdso/vsyscall.h
来访问时_vdso_data
,我遇到了一些变量重新定义错误。如果我同时包含vsyscall.h
andkernel/sys.c
,arch/x86/entry/vdso/vclock_gettime.c
它似乎DEFINE_VVAR(struct vdso_data, _vdso_data);
会被调用两次并导致_vdso_data
. 我试图在它周围放置#ifndef
、#def
和#endif
宏,但错误仍然存在。 - 我尝试的另一件事是仅声明实现中显示的
_vdso_data
asextern
变量syscall
。如果我这样做,重新定义错误就消失了。代码编译并正常运行,没有错误或分段错误,但结果没有改变。
__arch_sync_vdso_data()
功能
我在内核源代码中阅读了一些示例用法__arch_sync_vdso_data
,我发现人们最终使用函数来编写_vdso_data
。但是,我认为这个函数实际上是空的generic-asm
,我能找到的唯一定义是 on Arm
。不确定这将如何工作x86
以及是否需要。
在网上很难找到 vdso 资源,我已经阅读了所有最近的帖子。我非常感谢您的帮助和提前感谢。