Разработка ядра Linux | страница 83



>/*

>* Системный вызов silly copy — крайне бесполезная функция,

>* которая копирует len байтов из области памяти,

>* на которую указывает параметр src, в область памяти,

>* на которую указывает параметр dst, с использованием ядра

>* безо всякой на то причины. Но это хороший пример!

>*/

>asmlinkage long sys_silly_copy(unsigned long *src,

> unsigned long *dst, unsigned long len) {

> unsigned long buf;

> /* возвращаем ошибку, если размер машинного слова в ядре

>    не совпадает с размером данных, переданных пользователем */

> if (len != sizeof(buf))

>  return -EINVAL;

> /* копируем из src, который является адресом в пространстве

>    пользователя, в buf */

> if (copy_from_user(&buf, src, len))

>  return -EFAULT;

> /* копируем из buf в dst, который тоже является адресом

>    в пространстве пользователя */

> if (copy_to_user(dst, &buf, len))

>  return -EFAULT;

> /* возвращаем количество скопированных данных */

> return len;

>}

Следует заметить, что обе функции, >copy_from_user() и >copy_to_user(), могут блокироваться. Это возникает, например, если страница памяти, содержащая данные пользователя, не находится в физической памяти, а в данный момент вытеснена на диск. В таком случае процесс будет находиться в приостановленном состоянии до тек пор, пока обработчик прерываний из-за отсутствия страниц (page fault handler) не возвратит страницу памяти в оперативную память из файла подкачки на диске.

Последняя проверка — это проверка на соответствие правам доступа. В старых версиях ядра Linux стандартом было использование функции >suser() для системных вызовов, которые требуют прав пользователя root. Эта функция просто проверяла, запущен ли процесс от пользователя root. Сейчас эту функцию убрали и заменили более мелко структурированным набором системных "возможностей использования" (capabilities). В новых системах предоставляется возможность проверять специфические права доступа к специфическим ресурсам. Функция >capable() с допустимым значением флага, определяющего тип прав, возвращает ненулевое значение, если пользователь обладает указанным правом, и нуль— в противном случае. Например, вызов >capable (>CAP_SYS_NICE) проверяет, имеет ли вызывающий процесс возможность модифицировать значение параметра nice других процессов. По умолчанию суперпользователь владеет всеми правами, а пользователь, не являющийся пользователем root, не имеет никаких дополнительных прав. Следующий пример системного вызова, который демонстрирует использование возможностей использования, тоже является практически бесполезным.