Это очень сомнительно. На самом деле, это совершенно опасно. Я дам автору здесь преимущество сомнения, поскольку они просто пытаются показать, как работают copy_from_user
и copy_to_user
, но они действительно должны были привести пример, который не был так опасен.
Особенно , поскольку в книге много лирического рассказа о том, как вы должны быть особенно осторожными:
Системные вызовы должны тщательно проверять все их параметры, чтобы убедиться, что они действительны и
legal.The системный вызов выполняется в пространстве ядра, и если пользователь может передать неверный ввод в
ядро без ограничений, безопасность и стабильность системы могут пострадать.
, а затем предоставляет пользователю возможность полностью уничтожить ядро: -)
Текст из имеющейся у меня копии гласит:
Давайте рассмотрим пример системного вызова, который использует copy_from_user()
и copy_to_user()
. Этот системный вызов silly_copy()
совершенно бесполезен; он копирует данные из своего первого параметра во второй. Это неоптимально в том смысле, что он включает в себя промежуточное и постороннее копирование в пространство ядра без какой-либо выгоды. Но это помогает проиллюстрировать это.
/*
* silly_copy - pointless syscall that copies the len bytes from
* ‘src’ to ‘dst’ using the kernel as an intermediary in the copy.
* Intended as an example of copying to and from the kernel.
*/
SYSCALL_DEFINE3(silly_copy,
unsigned long *, src,
unsigned long *, dst,
unsigned long len)
{
unsigned long buf;
/* copy src, which is in the user’s address space, into buf */
if (copy_from_user(&buf, src, len))
return -EFAULT;
/* copy buf into dst, which is in the user’s address space */
if (copy_to_user(dst, &buf, len))
return -EFAULT;
/* return amount of data copied */
return len;
}
Кроме катастрофического сбоя не проверки параметров, я почти уверен, что последний параметр SYSCALL_DEFINE3
пропускает запятую (хотя это будет просто опечатка).
Гораздо лучший пример, без выделения произвольной памяти, будет выглядеть следующим образом:
SYSCALL_DEFINE3(silly_copy,
unsigned long *, src,
unsigned long *, dst,
unsigned long, len)
{
unsigned long buf[64]; /* Buffer for chunks */
unsigned long lenleft = len; /* Remaining size */
unsigned long chunklen = sizeof(buf); /* Initial chunk length */
/* Loop handling chunk sizes */
while (lenleft > 0) {
/* Change chunk length on last chunk */
if (lenleft < chunklen) chunklen = lenleft;
/* copy src(user) to buf(kernel) then dst(user) */
if (copy_from_user(buf, src, chunklen)) return -EFAULT;
if (copy_to_user(dst, buf, chunklen)) return -EFAULT;
/* Adjust pointers and remaining size */
src += chunklen; dst += chunklen; lenleft -= chunklen;
}
/* return amount of data copied */
return len;
}
Любому, кто пытается реализовать этот системный вызов, рекомендуется избегать этого конкретного примера в книге, хотя я полагаю, что, как минимум, это даст вам хороший опыт отладки ядра: -)