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 я читаю запись my /proc и все работает нормально.

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

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

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

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

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

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