【问题标题】:Kernel mode access to user space variable [closed]内核模式访问用户空间变量
【发布时间】:2012-10-10 12:01:49
【问题描述】:

我正在编写一个内核函数 foo,它以结构指针作为参数

void foo(struct struct1 *param)
{

    if(param!=NULL)
    {
        if(param->param1!=NULL)
        {
            if(param->param1->bool_value)
                Some code
        }
    }
    some code
}

此函数在进程上下文中运行。 我在上述函数的这一行发生了崩溃。 if(param->param1->bool_value)。 这次崩溃是一次崩溃,并且再也没有发生过。

BADVA 地址指向用户空间地址。这个地址是param1->bool_value的地址吗?如果是这样,内核模式代码是否可以在不使用 copy_from_user 的情况下访问该地址进行读取?

【问题讨论】:

  • 它闻起来像一个坏指针。
  • 这两个结构的定义/初始化是什么?
  • 别管一些代码,。它只是崩溃前执行的条件检查。结构参数1 { bool bool_value; //首先在 param1 中声明更多布尔值}; struct param 在其定义中包含 param1 结构
  • 我很确定内核崩溃日志说明了一切。可以贴吗?
  • 引用您的编辑:引用内存的指针(不指向 NULL)不一定指向有效的(在调用进程的上下文中为“有效”)内存地址。

标签: c linux memory-management linux-kernel


【解决方案1】:

param->param1 可能未初始化或已被覆盖。

当您初始化struct1 时,您是否总是将其成员设置为NULL?如果您不这样做,您的问题可能与使用未初始化的数据有关,并且处理起来相对简单。如果您总是初始化为 NULL,则其他一些代码可能已经覆盖了该成员;这将更难诊断。

【讨论】:

  • 是的。该结构在初始化时被清零。另一种情况有哪些诊断方法?
  • 如果你可以运行gdb,你可以尝试在param->param1的地址改变时设置一个watchpoint。如果您无法运行调试器,则可能不得不在整个代码中进行分散检查,以逐渐缩小问题范围。
  • 只发生过一次,它有一大段代码来进行分散检查。 :(你能给我举一个“覆盖成员”的例子吗——你回答的第二种情况。?
  • 任何设置/复制/移动内存的代码如果写入的内存多于目标分配的内存,都可能出现故障。
  • Nominal Animal 检查线程安全的建议也很好。如果您的代码是多线程的,您确定在您的 foo 函数运行时另一个线程没有修改您的 struct1 实例吗?
【解决方案2】:

您是否确保(使用锁)在测试和访问之间不会从您的下方修改结构?也许你可以使用

void foo(struct somestruct *const param)
{
    if (param) {
        struct otherstruct *const param1 = param->param1;

        if (param1 && param1->bool_value) {
            /* Do stuff */
        }
    }
}

请注意,C 为 && 指定了短路逻辑,因此如果在最里面的测试中 param1 为 NULL,param1不会被取消引用。

这种访问模式(没有最外层的if (param))在Linux内核中很常见。唯一需要注意的是,丢弃param1 仍然必须受到某种锁的保护,这样它就不会在其他 CPU 仍在访问它时(通过缓存指针)被释放。

【讨论】:

  • 谢谢。在这种情况下,param1 不为空,因此 param1->bool_value 也不为空。这一点,我从寄存器转储中确定。
  • @Sibi:是否有可能另一个 CPU 修改了param1(在param 结构内)?如果是这样,那么param1 可能已在更新中被访问;即部分旧值和部分新值。不过,它可能必须跨越缓存线边界才能发生这种情况。
  • 我的是单处理器环境。
  • @Sibi:如果内核是可抢占的,那么您的内核代码可能会被内核认为更重要的任何事情中断。 param1 地址的第二位设置了吗? (即address % 4 == 2)如果是这样,那么我认为您修改param1 的代码可能在指针更改的中途被抢占。如果它真的只是一次性的,它可能只是一个高能粒子恰到好处地翻转一样简单的事情。这是极其罕见的情况,但确实会发生。哦,我希望没有闭源驱动程序(受污染的内核)?
  • 内核崩溃说它被污染了。从你的问题来看,地址的第二位有什么关系。我们关心的地址是00008683。啊。 .U 是对的,我猜这个地址属于用户区域。内核态操作是不允许访问用户地址的吧?
猜你喜欢
  • 2019-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-30
  • 2018-05-22
  • 2015-07-08
  • 2018-04-23
  • 1970-01-01
相关资源
最近更新 更多