Copy_to_user vs memcpy

Мне всегда говорили (в книгах и учебниках), что при копировании данных из пространства ядра в пространство пользователя мы должны использовать copy_to_user(), а использование memcpy() вызовет проблемы в системе. Недавно по ошибке я использовал memcpy(), и он отлично справился с любыми проблемами. Почему мы должны использовать copy_to_user вместо memcpy()

Мой тестовый код (модуль ядра) выглядит примерно так:

static ssize_t test_read(struct file *file, char __user * buf,
             size_t len, loff_t * offset)
{
    char ani[100];

    if (!*offset) {
        memset(ani, 'A', 100);
        if (memcpy(buf, ani, 100))
            return -EFAULT;
        *offset = 100;
        return *offset;
    }

    return 0;
}

struct file_operations test_fops = {
    .owner = THIS_MODULE,
    .read = test_read,
};

static int __init my_module_init(void)
{
    struct proc_dir_entry *entry;

    printk("We are testing now!!\n");
    entry = create_proc_entry("test", S_IFREG | S_IRUGO, NULL);
    if (!entry)
        printk("Failed to creats proc entry test\n");

    entry->proc_fops = &test_fops;
    return 0;
}
module_init(my_module_init);

Из приложения user-space я читаю запись /proc, и все работает нормально.

Посмотрите на исходный код copy_to_user(), который также является простым memcpy(), где мы просто пытаемся проверить, действительно ли указатель действителен или нет с access_ok и выполняет memcpy.

Итак, мое понимание в настоящее время состоит в том, что , если мы уверены в том, что мы передаем указатель, memcpy() всегда можно использовать вместо copy_to_user.

Пожалуйста, исправьте меня, если мое понимание неверно, а также любой пример, в котором работает copy_to_user, а memcpy() будет очень полезен. Спасибо.

Ответ 1

Есть несколько причин для этого.

Во-первых, безопасность. Поскольку ядро ​​может писать на любой адрес, который он хочет, если вы используете только адрес пользователя и используете memcpy, злоумышленник может писать на другие страницы процесса, что является большой проблемой безопасности. copy_to_user проверяет, что целевая страница доступна для записи текущим процессом.

Есть также некоторые соображения архитектуры. Например, на x86 целевые страницы должны быть закреплены в памяти. На некоторых архитектурах вам могут понадобиться специальные инструкции. И так далее. Цель ядра Linux - быть очень портативной, требует такой абстракции.