【问题标题】:How to use syscall to change vDSO content如何使用系统调用更改 vDSO 内容
【发布时间】:2022-07-19 04:34:52
【问题描述】:

我正在尝试在x86 上实现一个syscall,它能够修改vDSO 的内容。鉴于vDSO 内容对于用户空间是只读的,我相信需要syscall。否则会导致分段错误。但是,我目前无法成功。

我的计划:

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 将读取在arch/x86/include/asm/vvar.h 中声明并在arch/x86/include/asm/vdso/vsyscall.h 中定义的_vdso_data。 然后它将变量__unused修改为用户输入的某个数字。

arch/x86/entry/vdso/vclock_gettime.c 中的 vDSO

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

预期结果

我想在syscall 之前看到0,在__vdso_query() 返回的syscall 之后看到10,因为如果一切按计划进行,syscall 将更改_vdso_data[0].__unused

当前结果

目前,无论syscall如何,内容始终为0

问题

如何正确访问_vdso_data

我尝试通过两种方式访问​​_vdso_data__arch_sync_vdso_data()extern

  1. 当我尝试使用在asm/vdso/vsyscall.h 中定义的__arch_get_k_vdso_data 函数来访问_vdso_data 时,我遇到了一些变量重新定义错误。如果我在kernel/sys.carch/x86/entry/vdso/vclock_gettime.c 中都包含vsyscall.h,似乎DEFINE_VVAR(struct vdso_data, _vdso_data); 将被调用两次并导致_vdso_data 的重新定义错误。我尝试在其周围放置#ifndef#def#endif 宏,但错误仍然存​​在。
  2. 我尝试的另一件事是仅将_vdso_data 声明为extern 变量,如syscall 实现中所示。如果我这样做,重新定义错误就消失了。代码编译和运行正常,没有错误或分段错误,但结果没有改变。

__arch_sync_vdso_data()函数

我在内核源代码中阅读了一些example usages,我发现人们最终使用__arch_sync_vdso_data函数编写了_vdso_data。但是,我认为这个函数在generic-asm 中实际上是空的,我能找到的唯一定义是在Arm 上。不确定这将如何在 x86 上工作,是否需要。

在网上很难找到 vdso 资源,我已经阅读了所有最近的帖子。非常感谢您的帮助和提前感谢。

【问题讨论】:

    标签: c linux linux-kernel system-calls vdso


    【解决方案1】:

    事实证明syscall 正在做正确的工作,问题是如何访问vDSO 数据。

    事实上,__arch_get_vdso_data 是访问 vDSO 数据的正确函数。它返回一个指针,可以进一步取消引用以访问 __arch_get_vdso_data()-&gt;__unused 等数据。

    另一方面,__arch_get_k_vdso_data 从不工作,我怀疑函数名中的_k_ 表示该函数只能在内核空间中使用。

    【讨论】:

      猜你喜欢
      • 2016-05-09
      • 2012-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 1970-01-01
      相关资源
      最近更新 更多