Ядро Linux в комментариях

Exec_modprobe


exec_modprobe запускает программу, которая присоединяет модуль к ядру. Имя модуля определяется как void *, а не char *, поскольку порождаемые kernel_thread функции требуют одного параметра void *.

Установка списка параметров и среды для modprobe. modprobe_path (строка ), который определяет расположение программы modprobe, изменяется через возможность sysctl ядра, описываемую в (см. строку ). Это означает, что администратор может динамически задавать программу, которая будет выполняться вместо /sbin/modprobe, например, если modprobe находится в другом каталоге.

Избавление от задержанных сигналов и их дескрипторов, что связано с вопросами безопасности (как описано в коде). Наиболее важной частью здесь является обращение к flush_signal_handlers (строка ), которая заменяет все определенные пользователем дескрипторы сигналов на дескрипторы, определенные в ядре по умолчанию. На любые сигналы, которые могут поступить после этого момента, будет обеспечиваться стандартная реакция, которая заключается либо в игнорировании сигнала, либо в уничтожении процесса; в данном случае минимизируется риск нарушения системы безопасности. Ввиду того, что эта функция разветвляется из процесса, который ее активизирует (как описывалось ранее), не будет никакой разницы, если в этом месте оригинальный процесс изменит свои установленные дескрипторы сигналов.

Закрытие всех файлов, которые могли быть открыты вызываемым процессом. Самое важное — это то, что программа modprobe не будет наследовать у вызываемого процесса ни стандартного ввода, ни стандартного вывода, ни стандартного потока ошибок, что потенциально может оказаться прорехой в системе защиты. (Проблема может быть решена в программе, которая придет на замену modprobe.)

Программа modprobe запускается как привелигированный процесс, со всеми вытекающими из этого последствиями. Следует отметить, что этот привелигированный процесс, как и во множестве других мест в ядре, получает идентификатор пользователя всегда равный 0. Пользовательские идентификаторы, а также разрешительная система рассматриваются в .


Попытка запуска программы modprobe. В случае неудачного завершения этой попытки ядро выдает сообщение об ошибке (при помощи printk) и возвращает код ошибки. Это одно из тех мест, где может возникнуть переполнение буфера printk — поскольку длина module_name не задается, все, что можно сказать, глядя на вызов, так это то, что длина может составлять миллионы символов. Дабы иметь уверенность в невозможности переполнения буфера, стоит пройтись по всем вызовам printk (в данном случае по вызовам request_module) и убедиться, что все они работают с достаточно короткими именами модулей, т.е. проблем с printk возникать не должно.

Если execve выполняется удачно, возврата из нее не происходит, а это значит, что данная точка не достигается. Однако, компилятору это неизвестно, потому присутствующий оператор return служит только для gcc.

Более глубокое исследование системы модулей ядра выходит далеко за пределы этой главы и частично рассматривается в главах  и . Дополнительно исследуются два файла — include/linux/module.h (начинается со строки ) и kernel/module.c (начинается со строки ). В частности обратите внимание на struct module (строка ), а также на функции sys_create_module (строка ), sys_init_module (строка ), sys_delete_module (строка ) и sys_query_module (строка ). Эти функции реализуют системные вызовы, которые использует modprobe, плюс связанные программы insmod, lsmod и rmmod для установки, поиска и удаления модулей.

Может вызвать удивление тот факт, что ядро активизирует программу, которая просто делает вызовы того же ядра. Однако при этом выполняется дополнительная работа. С одной стороны, программа modprobe выполняет поиск на диске необходимых файлов модуля, которые должны быть загружены. Кроме того, и это более важно, привелигированный пользователь (root) получает больший контроль над системой модулей ядра, поскольку такой пользователь может запускать modprobe и связанные с нею программы. Следовательно, привелигированный пользователь имеет возможность вручную загружать, запрашивать и удалять модули, либо это может делать само ядро в автоматическом режиме.


Содержание раздела