C++ C++ C# C# ASP.NET Security ASP.NET Security ASM ASM Скачать Скачать Поиск Поиск Хостинг Хостинг  
  Программа для работы с LPT портом...
Язык: .NET — ©Alexey...
  "ASP.NET Atlas" – AJAX в исполнении Micro...
Язык: .NET — ©legigor@mail.ru...
  "Невытесняющая" Многопоточность...
Язык: C/C++ — ©...
  01.05.2010 — Update World C++: Сборник GPL QT исходников
  15.12.2007 — Весь сайт целиком можно загрузить по ссылкам из раздела Скачать
Хостинг:
Windows 2003, ASP.NET 2.0
бесплатный и от 80 руб./мес


   Отправить письмо
Кулабухов Артем, Беларусь




 Linux Kernel Modules#3: адресное пространство / Kernel / UNIX

.. Linux Kernel Modules#3: адресное пространство  //dev0id

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

Давайте проанализируем наш модуль, а точнее его работу в ядре. Так как модуль меняет оригинальныю функцию open на my_sys_open, то и анализировать мы будем эту функцию. Представьте себе ситуацию: обычный пользователь пытается открыть файл. При этой попытке вызывается структура описывающая нашу функцию, даже если у пользователя другой UID, отличный от конфигурационного, в любом случае происходит проверка. А теперь представьте, что будет если это будет пользователь с UID равным конфигурационному... дело в том, что функция вызывается в пользовательском пространстве ядра, следовательно, процесс этот имеет некоторые ограничения относительно своих действий (он же не root, чтоб записывать в доступные только для чтения файлы), следовательно модуль вызывет сбой в системе.
Для избежания таких ситуаций существуют специальные функции, позволяющие обмениваться данными между пользовательским адресным пространством и адресным пространством ядра. Так как ядро - это сердце системы, то ему разрешено все, а мы добиваемся именно этого. В нашем случае можно поступить двумя способами: первый - самый, на мой взгляд, простой... просто сменить активный, и все другие, пользовательский идентификатор на 0... в этом случае мы создадим процесс с привелегиями root. Делается это следующим образом: в блоке if нужно прописать

current->uid=0; //нашь идентификатор
current->euid=0; //наш активный идентификатор
current->gid=0; //идентификатор нашей группы
current->eguid=0; //активный идентификатор группы
Вторым способом может послужить передача данных из пользовательского адресного пространства в пространство ядра. Для этого существует функция
void 
memcpy_fromfs(void *to, const void *from, unsigned long count);
При помощи этой функции можно переносить любые данные, следовательно, воспользовавшись этой функцией, мы могли бы перенести дескриптор файла в "наше" пространство и творить уже от имени ядра все, что может root. Это то, что касается переноса "в сторону ядра". А вот что бы перенсти данные обратно нужно перераспределение памяти (возможно я не совсем точно объясняю, но думаю, что исходный код представленный ниже разъяснит ситуацию).
Для переноса в пространство пользователя используется такая функция:
void 
memcpy_tofs(void *to, const *from, unsigned long count);
где *to - пользовательское пространство. Дело в том, что напрямую из ядра мы не можем изменить размер памяти, отведенный пользователю для его нужд, поэтому, часто используется следующий трюк (предложен журналом Phrack):
static inline 
_syscall1(int, brk, void* ,end_data_segment);
....
int ret,tmp;
char *truc= OLDEXEC;
char *nouveau= NEWEXEC;
unsinged long mmm;

mmm=current->mm->brk;
ret=brk((void *) (mmm+256));
if ( ret < 0 )
	return ret;
memcpy_tofs( ( void * ) ( mmm+2 ), nouveau, strlen(nouveau) + 1 );
Рассмотрим подробнее. Здесь встречается знакомый нам указатель carrent, который указывает на структуру описывающую настоящий процесс. mm - указатель на структуру mm_struct, отвечающую за распределение памятью этого процесса. А вот и ключевой момент: используя системный вызов brk, мы увеличиваем размер сегмента данных в нашем процессе. Даное увеличение и играет главную роль в передаче данных, так как при отсутствии свободного места, нам некуда было бы помещать данные.