Linux kernel 从IOCTL调用返回内核句柄-安全问题?

Linux kernel 从IOCTL调用返回内核句柄-安全问题?,linux-kernel,linux-device-driver,Linux Kernel,Linux Device Driver,我有一个设备驱动程序,允许用户空间应用程序使用ioctl机制执行各种操作。作为初始ioctl调用的一部分返回的是一个句柄,该句柄对于应用程序在其他ioctl调用中提供的用户空间应用程序来说应该是不透明的 在驱动程序内部,句柄是内核空间中某些控件/上下文块的地址。如果可以信任应用程序忠实地传递返回的句柄,那么一切都很好。问题是,如果应用程序是恶意的,并传回一些aribitrary句柄,然后驱动程序将其强制转换为适当的指针类型并取消引用它,该怎么办 我考虑的一个健全性检查是与PAGE_OFFSET进

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

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

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

是否有一种可靠而有效的方法来验证句柄?感谢您的帮助


谢谢。

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

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

您可能需要验证更多内容:
1.正如Alex所评论的,如果有几种可能的句柄类型,请验证您是否获得了正确的类型(即阻止
h=get\u handle\u typeA();使用\u handle\u typeB(h)
)。

2.确保每个进程只使用它创建的句柄。因此,进程将无法猜测句柄值并希望捕获有效值。

为什么您甚至需要句柄?打开的文件是一个句柄,您可以将自己的私有数据隐藏在其中,例如:

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

更重要的是,如果有不同类型的“句柄”(例如,对于类型A的对象和类型B的对象),它们也需要进行类型检查(即,您确实获得了类型A句柄,而您期望的是类型A句柄)。如果某些句柄或其他输入参数是相关的,则需要验证它们不仅在作为单独的实体时有意义,而且在呈现的组合中它们在一起也有意义。此外,返回指针会削弱地址随机化方案,并可以简化成功利用漏洞的创建。我会使用索引,而不是指针。我仍然需要某种方法将“arg”映射到整个“struct your_struct”中的特定私有数据(因为有许多私有子数据实例)。我使用RB树数据库来验证每个句柄类型的“arg”句柄。你是说应用程序可以多次调用初始ioctl并获得几个不同的句柄?如果是这样的话,那么您需要一些方法来获取arg并确定它在您的结构中是哪个句柄。在这一点上,虽然你最好只是改变API,使每个打开的文件有一个句柄,如果应用程序需要多个句柄,它会多次打开你的设备。