简体   繁体   English

如何使用系统调用更改 vDSO 内容

[英]How to use syscall to change vDSO content

I am trying to implement a syscall on x86 that is able to modify the content of vDSO .我正在尝试在x86上实现一个syscall ,该系统调用能够修改vDSO的内容。 Given vDSO content is read-only for userspace, I believe a syscall is needed.鉴于vDSO内容对于用户空间是只读的,我相信需要一个syscall Otherwise it will cause segmentation fault.否则会导致分段错误。 However, I can't do it successfully at this moment.但是,我目前无法成功。

My plan:我的计划:

syscall in kernel/sys.c 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;
}

The syscall will read the _vdso_data which is declared in arch/x86/include/asm/vvar.h and defined in arch/x86/include/asm/vdso/vsyscall.h . syscall将读取在arch/x86/include/asm/vvar.h _vdso_data声明并在arch/x86/include/asm/vdso/vsyscall.h Then it will modify the variable __unused into some number input by the user.然后它将变量__unused修改为用户输入的某个数字。

vDSO in arch/x86/entry/vdso/vclock_gettime.c 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;
}

I know it's a bad idea to define something unrelated to time in a timing fucntion, but this is what I'm testing right now.我知道在时序函数中定义与时间无关的东西是个坏主意,但这是我现在正在测试的。 The __vdso_query() function will read the data and return the value of the __unused variable. __vdso_query() function 将读取数据并返回__unused变量的值。

Testing plan测试计划

#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;
}

Expected results预期成绩

I want to see 0 before the syscall and 10 after the syscall returned by __vdso_query() since the syscall will change the _vdso_data[0].__unused if everything follows the plan.我想在系统调用之前看到0 ,在syscall __vdso_query()返回的系统syscall之后看到10 ,因为如果一切都按照计划进行, syscall将更改_vdso_data[0].__unused

Current results当前结果

For now, the content is always 0 regardless of the syscall .目前,无论syscall如何,内容始终为0

Questions问题

How to access _vdso_data properly如何正确访问_vdso_data

There are 2 ways I tried to access the _vdso_data : __arch_sync_vdso_data() and extern .我尝试通过两种方式访问_vdso_data__arch_sync_vdso_data()extern

  1. When I tried to use __arch_get_k_vdso_data function where defined in asm/vdso/vsyscall.h to access the _vdso_data , I encounter some variable redefinition errors.当我尝试使用在asm/vdso/vsyscall.h __arch_get_k_vdso_data定义的 __arch_get_k_vdso_data function 来访问_vdso_data时,我遇到了一些变量重新定义错误。 If I include vsyscall.h in both kernel/sys.c and arch/x86/entry/vdso/vclock_gettime.c , it seems DEFINE_VVAR(struct vdso_data, _vdso_data);如果我在kernel/sys.carch/x86/entry/vdso/vclock_gettime.c中都包含vsyscall.h ,似乎DEFINE_VVAR(struct vdso_data, _vdso_data); will be called twice and leads to redefinition error of _vdso_data .将被调用两次并导致_vdso_data的重新定义错误。 I tried to put #ifndef , #def , and #endif macros around it but the error still exists.我尝试在其周围放置#ifndef#def#endif宏,但错误仍然存在。
  2. Another thing I tried is only declaring the _vdso_data as extern variable shown in the syscall implementation.我尝试的另一件事是仅将_vdso_data声明为syscall实现中显示的extern变量。 The redefinition error is gone if I do this.如果我这样做,重新定义错误就消失了。 The code compiles and runs properly without error or segmentation fault, but the result doesn't change.代码编译并正常运行,没有错误或分段错误,但结果没有改变。

__arch_sync_vdso_data() function __arch_sync_vdso_data() function

I read some example usages in the kernel source code a little bit and I find people use __arch_sync_vdso_data function to write the _vdso_data in the end.我在 kernel 源代码中阅读了一些示例用法,我发现人们使用__arch_sync_vdso_data function 最后编写_vdso_data However, I think this function is actually empty in the generic-asm and the only definition I can find is on Arm .但是,我认为这个 function 在generic-asm中实际上是空的,我能找到的唯一定义是Arm Not really sure how this will work on x86 and is it needed.不确定这将如何在x86上工作,是否需要。

It's really hard to find vdso resources online and I've read all the recent posts.在网上很难找到 vdso 资源,我已经阅读了所有最近的帖子。 I would really appreciate the help and thanks in advance.我非常感谢您的帮助和提前感谢。

It turns out syscall is doing the right work and the problem is how to access the vDSO data.事实证明syscall正在做正确的工作,问题是如何访问vDSO数据。

In fact, __arch_get_vdso_data is the right function to access vDSO data.事实上, __arch_get_vdso_data是正确的 function 访问 vDSO 数据。 It returns a pointer which can be further dereferenced to access the data like __arch_get_vdso_data()->__unused .它返回一个指针,可以进一步取消引用以访问__arch_get_vdso_data()->__unused等数据。

On the other hand, __arch_get_k_vdso_data never works and I suspect the _k_ in the function name indicates that this function can be only used in kernel space.另一方面, __arch_get_k_vdso_data从不工作,我怀疑_k_名称中的 _k_ 表明这个 function 只能在 Z50484C19F1AFDAF38421ZA08 空间中使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM