【问题标题】:return a kernel handle from an IOCTL call - security issue?从 IOCTL 调用返回内核句柄 - 安全问题?
【发布时间】:2012-05-25 15:32:21
【问题描述】:

我有一个设备驱动程序,它允许用户空间应用程序使用 ioctl 机制执行各种操作。作为初始 ioctl 调用的一部分返回的是一个句柄,该句柄应该对应用程序在其他 ioctl 调用中提供的用户空间应用程序是不透明的。

在驱动程序内部,句柄是内核空间中某些控制/上下文块的地址。如果可以信任应用程序忠实地传回返回的句柄,那么一切都很好。担心的是如果应用程序是恶意的并传回一些任意句柄,然后驱动程序将其转换为适当的指针类型并取消引用它。

我正在考虑的一个健全性检查是与 PAGE_OFFSET 进行比较,如果小于则拒绝(以确保地址至少指向内核内存)。如果我认为在内核空间中不合法的页面错误怎么办?一个简单的方案可能是检查句柄是否先前已返回到用户空间,但搜索的开销可能很高(因为可能有很多这样的句柄)。

是否有一种强大而有效的方法来验证句柄?任何帮助表示赞赏。

谢谢。

【问题讨论】:

    标签: linux-kernel linux-device-driver


    【解决方案1】:

    永远不要接受来自不受信任程序的指针。
    这对您的代码和其他代码(例如,使用您窥视进程不得访问的内存)造成的攻击没有止境。

    有很多方法可以验证它,但它们很复杂或很昂贵。例如:
    1. 将所有手柄放在一个阵列中。验证指针是否在数组内,并且正确对齐。但是你可以使用数组索引作为句柄。
    2. 扫描您的句柄数据库并将指针与用户提供的指针进行比较。在数据库中找到之前不要取消引用句柄。但同样,使用一些 ID 进行查找,而不是指针,可以简化它。

    您可能需要验证更多内容:
    1. 正如 Alex 所评论的,如果有几种可能的句柄类型,请验证您是否获得了正确的类型(即阻止 h = get_handle_typeA(); use_handle_typeB(h))。
    2. 确保每个进程只使用它创建的句柄。所以一个进程将无法猜测句柄值并希望捕捉到一个有效的值。

    【讨论】:

    • 此外,如果有不同类型的“句柄”(例如,对于 A 类型的对象和 B 类型的对象),它们也需要进行类型检查(即,您确实得到了A 型句柄,您期望 A 型句柄的位置)。如果某些句柄或其他输入参数是相关的,则不仅需要验证它们在作为单独实体时是否有意义,而且在呈现的组合中它们一起有意义。此外,返回指针会削弱地址随机化方案,并可以简化成功的漏洞利用创建。我会使用索引,而不是指针。
    【解决方案2】:

    为什么你还需要一个把手?打开的文件一个句柄,你可以在里面存放你自己的私有数据,例如:

    static long your_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
    {
          struct your_struct *p = f->private_data;
          ...
    

    【讨论】:

    • 我仍然需要一些方法将“arg”映射到整个“struct your_struct”中的特定私有数据(因为有许多私有子数据实例)。我使用每个句柄类型的 RB 树数据库来验证“arg”句柄。
    • 所以你的意思是应用可以多次调用初始ioctl并获得几个不同的句柄?如果是这样,那么是的,您需要某种方法来获取 arg 并确定它在 your_struct 中的哪个句柄。到那时,您最好只更改 API,以便每个打开的文件有一个句柄,如果应用程序需要多个句柄,它会多次打开您的设备。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 1970-01-01
    相关资源
    最近更新 更多