【问题标题】:Successfully de-referenced userspace pointer in kernel space without using copy_from_user()在不使用 copy_from_user() 的情况下成功取消引用内核空间中的用户空间指针
【发布时间】:2017-04-25 00:36:34
【问题描述】:

我们公司代码库中的一个驱动程序存在多年的错误。 基本上我们通过ioctls 调用驱动程序。在用户空间和驱动程序空间之间传递的数据存储在struct 中,指向数据的指针被馈送到ioctl。驱动程序负责使用copy_from_user() 取消引用指针。但是这段代码多年来一直没有这样做,而只是取消引用用户空间指针。到目前为止(据我所知)它直到现在还没有引起任何问题。

我想知道这段代码怎么这么久都没有引起任何问题?在什么情况下直接从用户空间取消引用内核空间中的指针不会导致问题?

在用户空间中

struct InfoToDriver_t data;
data.cmd = DRV_SET_THE_CLOCK;
data.speed = 1000;

ioctl(driverFd, DEVICE_XX_DRIVER_MODIFY, &data);

在驱动程序中

device_xx_driver_ioctl_handler (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
    struct InfoToDriver_t *user_data;

    switch(cmd)
    {
        case DEVICE_XX_DRIVER_MODIFY:
            // what we've been doing for years, BAD
            // But somehow never caused a kernel oops until now
            user_data = (InfoToDriver_t *)arg;
            if (user_data->cmd == DRV_SET_THE_CLOCK)
            { .... }

            // what we're supposed to do
            copy_from_user(user_data, (void *)arg, sizeof(InfoToDriver_t));
            if (user_data->cmd == DRV_SET_THE_CLOCK)
            { ... }

【问题讨论】:

  • 我认为,如果你修改了结构对象,你会在内存上崩溃,如果你不修改用户数据的内容,你不会崩溃。
  • 您的用户空间数据所在的页面 (arg) 可能会被换出。在这种情况下会发生内核崩溃。
  • @AlexHoppus 谢谢。那么只要用户空间数据(arg)没有被换出,直接解引用指针就不会导致内核崩溃?
  • @Splaty 好问题,但我无法想象其他任何事情(但我相信应该有)。也许其他人会给你更复杂的例子。

标签: memory-management linux-kernel linux-device-driver


【解决方案1】:

一个可能的答案是,这取决于架构。如您所见,在健全的体系结构(例如 x86 或 x86-64)上,简单地取消引用 __user 指针就可以了。但是 Linux 假装支持所有可能的架构,有些架构简单的取消引用不起作用。否则 copy_to/from_user 将不存在。

copy_to/from_user 的另一个原因是用户模式端可能与内核端同时修改其内存(在另一个线程中)。您不能假设用户模式内存的内容在从内核访问时被冻结。恶意用户模式代码可以使用它来攻击内核。例如,您可以在执行工作之前探测指向输出数据的指针,但是当您将结果复制回用户模式时,该指针已经无效。哎呀。 copy_to_user API 确保(应该确保)内核在复制期间不会崩溃,而是会杀死有罪的应用程序。

更安全的方法是将整个用户模式数据结构复制到内核中(又名“捕获”),检查此副本的一致性。

底线...如果该驱动程序被证明在某些架构上运行良好,并且没有移植它的计划,则没有紧迫性对其进行更改。但是仔细检查内核代码的健壮性,如果需要捕获用户模式数据,或者从用户模式复制时可能会出现问题。

【讨论】:

    猜你喜欢
    • 2016-05-16
    • 1970-01-01
    • 2016-06-26
    • 1970-01-01
    • 1970-01-01
    • 2014-06-11
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    相关资源
    最近更新 更多