My-library.info
Все категории

Ори Померанц - Энциклопедия разработчика модулей ядра Linux

На электронном книжном портале my-library.info можно читать бесплатно книги онлайн без регистрации, в том числе Ори Померанц - Энциклопедия разработчика модулей ядра Linux. Жанр: Программирование издательство неизвестно, год 2004. В онлайн доступе вы получите полную версию книги с кратким содержанием для ознакомления, сможете читать аннотацию к книге (предисловие), увидеть рецензии тех, кто произведение уже прочитал и их экспертное мнение о прочитанном.
Кроме того, в библиотеке онлайн my-library.info вы найдете много новинок, которые заслуживают вашего внимания.

Название:
Энциклопедия разработчика модулей ядра Linux
Издательство:
неизвестно
ISBN:
нет данных
Год:
неизвестен
Дата добавления:
17 сентябрь 2019
Количество просмотров:
273
Читать онлайн
Ори Померанц - Энциклопедия разработчика модулей ядра Linux

Ори Померанц - Энциклопедия разработчика модулей ядра Linux краткое содержание

Ори Померанц - Энциклопедия разработчика модулей ядра Linux - описание и краткое содержание, автор Ори Померанц, читайте бесплатно онлайн на сайте электронной библиотеки My-Library.Info
Linux Kernel Module Programming Guide свободная книга; Вы можете воспроизводить и/или изменять ее в соответствии с версией 2 (или, в вашем случае, любой более поздней версией) GNU General Public License, опубликованной Free Software Foundation. Версия 2 поставляется с этим документом в Приложении E.Эта книга распространяется в надежде, что будет полезна, но без какой-либо гарантии; даже без подразумеваемой гарантии высокого спроса или пригодности какой-либо для специфической цели.Автор поощряет широкое распространение этой книги для персонального или коммерческого использования, если вышеупомянутое примечание относительно авторского права остается неповрежденным, и распространитель твердо придерживается условий GNU General Public License (см. Приложение E). Вы можете копировать и распространять эту книгу бесплатно или для получения прибыли. Никакое явное разрешение не требуется от автора для воспроизводства этой книги в любой среде, физической или электронной.Обратите внимание, производные работы и переводы этого документа должны быть помещены согласно GNU General Public License, и первоначальное примечание относительно авторского права должно остаться неповрежденным. Если Вы пожертвовали новый материал этой книге, Вы должны сделать исходный текст доступным для ваших изменений. Пожалуйста делайте изменения и модификации, доступные непосредственно поддерживающему данный проект Ori Pomerantz. Он объединит модификации и обеспечит непротиворечивость изменений для всего Linux сообщества.Если Вы планируете издавать и распространять эту книгу коммерчески, пожертвования, лицензионные платежи, и/или напечатанные копии будут высоко оценены автором и Linux Documentation Project (LDP). Содействие таким образом показывает вашу поддержку свободного программного обеспечения и Linux Documentation Project. Если Вы имеете вопросы или комментарии, пожалуйста войдите в контакт с автором по адресу, приведенному выше.

Энциклопедия разработчика модулей ядра Linux читать онлайн бесплатно

Энциклопедия разработчика модулей ядра Linux - читать книгу онлайн бесплатно, автор Ори Померанц

/* In 2.2.3 /usr/include/linux/version.h includes a

* macro for this, but 2.0.35 doesn't - so I add it

* here if necessary. */

#ifndef KERNEL_VERSION

#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))

#endif


/* Emmanuel Papirakis:

*

* Parameter names are now (2.2) handled in a macro.

* The kernel doesn't resolve the symbol names

* like it seems to have once did.

*

* To pass parameters to a module, you have to use a macro

* defined in include/linux/modules.h (line 176).

* The macro takes two parameters. The parameter's name and

* it's type. The type is a letter in double quotes.

* For example, "i" should be an integer and "s" should

* be a string. */

char *str1, *str2;


#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

MODULE_PARM(str1, "s");

MODULE_PARM(str2, "s");

#endif


/* Initialize the module - show the parameters */

int init_module() {

 if (str1 == NULL || str2 == NULL) {

  printk("Next time, do insmod param str1=<something>");

  printk("str2=<something>n");

 } else printk("Strings:%s and %sn", str1, str2);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

 printk("If you try to insmod this module twice,");

 printk("(without rmmod'ingn");

 printk("it first), you might get the wrong");

 printk("error message:n");

 printk("'symbol for parameters str1 not found'.n");

#endif

 return 0;

}


/* Cleanup */

void cleanup_module() { }

Системные вызовы

Пока что все программы, которые мы сделали должны были использовать хорошо определенные механизмы ядра, чтобы регистрировать /proc файлы и драйверы устройства. Это прекрасно, если Вы хотите делать что-то уже предусмотренное программистами ядра, например писать драйвер устройства. Но что, если Вы хотите сделать что-то необычное, изменить поведение системы некоторым способом?

Это как раз то место, где программирование ядра становится опасным. При написании примера ниже, я уничтожил системный вызов open. Это подразумевало, что я не могу открывать любые файлы, я не могу выполнять любые программы, и я не могу закрыть систему командой shutdown. Я должен выключить питание, чтобы ее остановить. К счастью, никакие файлы не были уничтожены. Чтобы гарантировать, что Вы также не будете терять файлы, пожалуйста выполните sync прежде чем Вы отдадите команды insmod и rmmod.

Забудьте про /proc файлы и файлы устройств. Они только малые детали. Реальный процесс связи с ядром, используемый всеми процессами, это системные вызовы. Когда процесс запрашивает обслуживание из ядра (типа открытия файла, запуска нового процесса или запроса большего количества памяти), используется этот механизм. Если Вы хотите изменить поведение ядра интересными способами, это как раз подходящее место. Между прочим, если Вы хотите видеть какие системные вызовы использованы программой, выполните: strace <command> <arguments>.

Вообще, процесс не способен обратиться к ядру. Он не может обращаться к памяти ядра и не может вызывать функции ядра. Аппаратные средства CPU предписывают такое положение дел (недаром это называется `protected mode' (защищенный режим)). Системные вызовы исключение из этого общего правила. Процесс заполняет регистры соответствующими значениями и затем вызывает специальную команду, которая переходит к предварительно определенному месту в ядре (конечно, оно читается процессами пользователя, но не перезаписывается ими). Под Intel CPUs, это выполнено посредством прерывания 0x80. Аппаратные средства знают, что, как только Вы переходите к этому месту, Вы больше не работаете в ограниченном режиме пользователя. Вместо этого Вы работаете как ядро операционной системы, и следовательно вам позволено делать все, что Вы хотите сделать.

Место в ядре, к которому процесс может переходить, названо system_call. Процедура, которая там находится, проверяет номер системного вызова, который сообщает ядру чего именно хочет процесс. Затем, она просматривает таблицу системных вызовов (sys_call_table), чтобы найти адрес функции ядра, которую надо вызвать. Затем вызывается нужная функция, и после того, как она возвращает значение, делается несколько проверок системы. Затем результат возвращается обратно процессу (или другому процессу, если процесс завершился). Если Вы хотите посмотреть код, который все это делает, он находится в исходном файле arch/<architecture> /kernel/entry.S, после строки ENTRY(system_call).

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

Исходный текст, приводимый здесь, является примером такого модуля. Мы хотим «шпионить» за некоторым пользователем, и посылать через printk сообщение всякий раз, когда данный пользователь открывает файл. Мы заменяем системный вызов, открытия файла нашей собственной функцией, названной our_sys_open. Эта функция проверяет uid (user id) текущего процесса, и если он равен uid, за которым мы шпионим, вызывает printk, чтобы отобразить имя файла, который будет открыт. Затем вызывает оригинал функции open с теми же самыми параметрами, фактически открывает файл.

Функция init_module меняет соответствующее место в sys_call_table и сохраняет первоначальный указатель в переменной. Функция cleanup_module использует эту переменную, чтобы восстановить все назад к норме. Этот подход опасен, из-за возможности существования двух модулей, меняющих один и тот же системный вызов. Вообразите, что мы имеем два модуля, А и B. Системный вызов open модуля А назовем A_open и такой же вызов модуля B назовем B_open. Теперь, когда вставленный в ядро системный вызов заменен на A_open, который вызовет оригинал sys_open, когда сделает все, что ему нужно. Затем, B будет вставлен в ядро, и заменит системный вызов на B_open, который вызовет то, что как он думает, является первоначальным системным вызовом, а на самом деле является A_open.

Теперь, если B удален первым, все будет хорошо: это просто восстановит системный вызов на A_open, который вызывает оригинал. Однако, если удален А, и затем удален B, система разрушится. Удаление А восстановит системный вызов к оригиналу, sys_open, вырезая B из цикла. Затем, когда B удален, он восстановит системный вызов к тому, что он считает оригиналом, На самом деле вызов будет направлен на A_open, который больше не в памяти. На первый взгляд кажется, что мы могли бы решать эту специфическую проблему, проверяя, если системный вызов равен нашей функции open и если так, не менять значение этого вызова (так, чтобы B не изменил системный вызов, когда удаляется), но это вызовет еще худшую проблему. Когда А удаляется, он видит, что системный вызов был изменен на B_open так, чтобы он больше не указывал на A_open, так что он не будет восстанавливать указатель на sys_open прежде, чем будет удалено из памяти. К сожалению, B_open будет все еще пробовать вызывать A_open, который больше не в памяти, так что даже без удаления B система все равно рухнет.

Я вижу два способа предотвратить эту проблему. Первое: восстановить обращение к первоначальному значению sys_open. К сожалению, sys_open не является частью таблицы ядра системы в /proc/ksyms, так что мы не можем обращаться к нему. Другое решение состоит в том, чтобы использовать счетчик ссылки, чтобы предотвратить выгрузку модуля. Это хорошо для обычных модулей, но плохо для «образовательных» модулей.

syscall.c

/* syscall.c

*

* System call "stealing" sample

*/

/* Copyright (C) 1998-99 by Ori Pomerantz */


/* The necessary header files */

/* Standard in kernel modules */

#include <linux/kernel.h> /* We're doing kernel work */

#include <linux/module.h> /* Specifically, a module */


/* Deal with CONFIG_MODVERSIONS */

#if CONFIG_MODVERSIONS==1

#define MODVERSIONS

#include <linux/modversions.h>

#endif


#include <sys/syscall.h> /* The list of system calls */

/* For the current (process) structure, we need

* this to know who the current user is. */

#include <linux/sched.h>


/* In 2.2.3 /usr/include/linux/version.h includes a

* macro for this, but 2.0.35 doesn't - so I add it

* here if necessary. */

#ifndef KERNEL_VERSION

#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))

#endif


#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

#include <asm/uaccess.h>

#endif


/* The system call table (a table of functions). We

* just define this as external, and the kernel will

* fill it up for us when we are insmod'ed */

extern void *sys_call_table[];


/* UID we want to spy on - will be filled from the command line */

int uid;


#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)

MODULE_PARM(uid, "i");

#endif


/* A pointer to the original system call. The reason


Ори Померанц читать все книги автора по порядку

Ори Померанц - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки My-Library.Info.


Энциклопедия разработчика модулей ядра Linux отзывы

Отзывы читателей о книге Энциклопедия разработчика модулей ядра Linux, автор: Ори Померанц. Читайте комментарии и мнения людей о произведении.

Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*
Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту librarybook.ru@gmail.com или заполнить форму обратной связи.