【发布时间】: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