Почему при выполнении команды 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;
}

С уважением,
Оливер Ханаппи


person Oliver Hanappi    schedule 08.01.2011    source источник


Ответы (3)


Ваш copy_from_user звонок неправильный. Он возвращает не количество скопированных байтов, а количество байтов, которые не были скопированы. Что ты хочешь

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

(Вы можете пропустить назначение ret во фрагменте.)

person user562374    schedule 08.01.2011
comment
Обычная идиома: if (copy_from_user (...)) return -EFAULT; - person mpe; 09.01.2011

copy_from_user() возвращает количество байтов, которые нельзя не скопировать. Так что вам следует ожидать 0 успеха, а не sizeof(struct secvault_createoptions).

person Matthew Slattery    schedule 08.01.2011

Вы должны изменить оператор как,

  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 после успешного завершения.

Дополнительные сведения см. здесь.

person Pravin.2087    schedule 02.09.2014