为什么在ioctl命令中从用户空间复制结构会失败?

时间:2011-01-08 16:14:10

标签: c linux-kernel kernel kernel-module ioctl

我正在开发设备驱动程序,需要使用IOCTL。不幸的是我无法从用户空间复制结构。这是代码(简化,错误处理已删除):

结构

struct secvault_createoptions {
    int secvaultId;
    long dataSize;
    char key[SECVAULT_KEYSIZE];
};

应用

void createSecvault(int secvaultId)
{
    struct secvault_createoptions creationOptions;
    /* fill with data */
    sendIoctlCommand(SECVAULT_IOCTL_CREATE, &creationOptions);
}

void sendIoctlCommand(int command, void *arg)
{
    FILE *stream;
    int fd, err;

    stream = fopen(SECVAULT_DEV_CONTROL, "r");
    fd = fileno(stream);
    ioctl(fd, command, arg);
    fclose(stream);
}

内核模块

int control_device_ioctl(struct inode *node, struct file *filp, unsigned int cmd, unsigned long arg)
{
    struct secvault_createoptions creationOptions;
    int returnCode;

    switch (cmd)
    {
        case SECVAULT_IOCTL_CREATE:
            if (copy_from_user(&creationOptions, (void*)arg, sizeof(struct secvault_createoptions)) != sizeof(struct secvault_createoptions))
            {
                /* Always this branch gets executed */
                printk(KERN_ALERT "Copying secure vault creation options from user space failed.\n");
                returnCode = -EFAULT;
                break;
            }
            printk(KERN_ALERT "2 IOCTL create request on control device received: secvaultId = %d, dataSize = %ld.\n",
                creationOptions.secvaultId, creationOptions.dataSize);

            returnCode = createDataDevice(&creationOptions);
            break;
    }
    return returnCode;
}

最诚挚的问候,
Oliver Hanappi

3 个答案:

答案 0 :(得分:4)

您的copy_from_user电话错误。它不返回复制的字节数,而是返回未复制的字节数。你想要的是

if (copy_from_user(...) != 0)
        return -EFAULT;

(您可以跳过代码段中的ret分配。)

答案 1 :(得分:3)

copy_from_user()返回复制的字节数。因此,您应该期望0取得成功,而不是sizeof(struct secvault_createoptions)

答案 2 :(得分:0)

您应该将语句修改为

  if (copy_from_user(&creationOptions, (void*)arg, sizeof(struct secvault_createoptions)) != 0)
            {
                /* Always this branch gets executed */
                printk(KERN_ALERT "Copying secure vault creation options from user space failed.\n");
                returnCode = -EFAULT;
                break;
            }

因为copy_from_user在成功完成后总是返回0。

请参阅to this了解详情。