Энциклопедия разработчика модулей ядра Linux - [14]
Функция 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
>*
>* System call "stealing" sample
>*/
>/* Copyright (C) 1998-99 by Ori Pomerantz */
>/* The necessary header files */
>/* Standard in kernel modules */
>#include
>#include
>/* Deal with CONFIG_MODVERSIONS */
>#if CONFIG_MODVERSIONS==1
>#define MODVERSIONS
>#include
>#endif
>#include
>/* For the current (process) structure, we need
>* this to know who the current user is. */
>#include
>/* 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
>#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
>* we keep this, rather than call the original function
>* (sys_open), is because somebody else might have
>* replaced the system call before us. Note that this
>* is not 100% safe, because if another module
>* replaced sys_open before us, then when we're inserted
>* we'll call the function in that module - and it
>* might be removed before we are.
>*
>* Another reason for this is that we can't get sys_open.
>* It's a static variable, so it is not exported. */
>asmlinkage int (*original_call)(const char *, int, int);
>/* For some reason, in 2.2.3 current->uid gave me
>* zero, not the real user ID. I tried to find what went
>* wrong, but I couldn't do it in a short time, and
>* I'm lazy - so I'll just use the system call to get the
>* uid, the way a process would.
>*
>* For some reason, after I recompiled the kernel this
>* problem went away.
>*/
>asmlinkage int (*getuid_call)();
>/* The function we'll replace sys_open (the function
>* called when you call the open system call) with. To
>* find the exact prototype, with the number and type
>* of arguments, we find the original function first
>* (it's at fs/open.c).
>*
>* In theory, this means that we're tied to the
>* current version of the kernel. In practice, the
>* system calls almost never change (it would wreck havoc
>* and require programs to be recompiled, since the system
>* calls are the interface between the kernel and the processes). */
>asmlinkage int our_sys_open(const char *filename, int flags, int mode) {
> int i = 0;
> char ch;
> /* Check if this is the user we're spying on */
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Сейчас во многих школах, институтах и других учебных заведениях можно встретить компьютеры старого парка, уже отслужившие свое как морально, так и физически. На таких компьютерах можно изучать разве что Dos, что далеко от реалий сегодняшнего дня. К тому же у большинства, как правило, жесткий диск уже в нерабочем состоянии. Но и выбросить жалко, а новых никто не дает. Различные спонсоры, меценаты, бывает, подарят компьютер (один) и радуются, как дети. Спасибо, конечно, большое, но проблемы, как вы понимаете, этот компьютер в общем не решает, даже наоборот, усугубляет, работать на старых уже как-то не хочется, теперь просто есть с чем сравнивать.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.