Модераторы: powerfox, ZeeLax
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как собрать модуль ядра? в Red Hat Linux 9.0 
V
    Опции темы
vzf
Дата 23.12.2006, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 203
Регистрация: 10.9.2005

Репутация: нет
Всего: 5



Надо написать модуль ядра Linux.

Беру пример из книги The Linux Kernel Module Programming Guide


Код

/*  
 *  hello-1.c - Простейший модуль ядра.
 */
#include <linux/module.h>  /*Необходим для любого модуля ядра */
#include <linux/kernel.h>  /*Здесь находится определение KERN_ALERT */

int init_module(void)
{
        printk("<1>Hello world 1.\n");

  /* 
   * Если вернуть ненулевое значение, то это
   * будет воспринято как признак ошибки,
   * возникшей в процессе работы init_module;
   * в результате модуль не будет загружен. 
   */
        return 0;
}

void cleanup_module(void)
{
        printk(KERN_ALERT "Goodbye world 1.\n");
}



В книге приводится Makefile  для ядра 2.6

Код

obj-m += hello-1.o


и команда для сборки
Код

make -C /usr/src/linux SUBDIRS=$PWD modules

 
Для ядра 2.6 это работает (пробовал в Mandrake 10)

Но в RedHat 9 возникли проблемы (ядро другое 2.4.20-8)

Во-первых он не подднрживает загружаемых модулей.

Следуя /usr/src/linux-2.4/README.txt

я пересобрал ядро

Код

make xconfig
make dep
make bzImage
make install


make install выполнилось с ошибкой, но теперь вроде бы стало можно загружать модули в ядро.

При запуске указанной выше команды сборки (make -C /usr/src/linux SUBDIRS=$PWD modules)
выводилась ошибка, что нет правила сборки цели modules.


Я нашел версию этой книги для более старых ядер там приводился такой пример:

код модуля:

Код


/* hello.c
 * Copyright (C) 1998 by Ori Pomerantz
 *
 * "Hello, world" - версия для модуля ядра.
 */

/* 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

/* Initialize the module */
int init_module()
{
  printk("Hello, world - this is the kernel speaking\n");
  /* If we return a non zero value, it means that
   * init_module failed and the kernel module
   * can't be loaded */
  return 0;
}

/* Cleanup - undid whatever init_module did */
void cleanup_module()
{
  printk("Short is the life of a kernel module\n");
}



код makefile:

Код

# Makefile для базисного ядерного модуля
CC=gcc
MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX

hello.o:        hello.c /usr/include/linux/version.h
                $(CC) $(MODCFLAGS) -c hello.c
                echo insmod hello.o to turn it on
                echo rmmod hello to turn if off
                echo
                echo X and kernel programming do not mix.
                echo Do the insmod and rmmod from outside X.


Теперь при сборки не находилась printk.
Тогда я явно указал подключаемые заголовочные файлы.

#include /usr/src/linux-2.4/include/linux/kernel.h
#include /usr/src/linux-2.4/include/linux/module.h

запустил makefile,
получил долгожданный файл hello.o
НО при выполнении insmod ./hello.o 
Выдается о шибка, что этот модуль собран под версию ядра 2.4.20, 
а используется 2.4.20-8

Кто-нибудь может сказать КАК ПРАВИЛЬНО собрать модуль ядра в Red Hat Linux 9.0 ? 



Это сообщение отредактировал(а) vzf - 23.12.2006, 21:17
--------------------
Java - Write Once, Test EveryWhere!
PM MAIL   Вверх
bilbobagginz
Дата 23.12.2006, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Naughtius Maximus
****


Профиль
Группа: Экс. модератор
Сообщений: 8813
Регистрация: 2.3.2004
Где: Israel

Репутация: 113
Всего: 317



Цитата

Кто-нибудь может сказать КАК ПРАВИЛЬНО собрать модуль ядра в Red Hat Linux 9.0 ? 


исходя из факта, что на машине, на к-рой тебе предстоит запускать модуль тебе нужно быть с повышенными правами ( т.е. root )
1. проверь, что у тебя есть заголовки ядра ТВОЕЙ версии. при наличии быстрого канала легче всего это достигается скачиванием всех исходников ядра, и установки его в систему. при разработке у тебя должно бежать именно это ядро.
2. ядро должно поддерживать загружаемые модули ( эта опция может быть вылкючена на некоторых рабочих системах )
3. версия ядра и заголовков, а также подверсия компилятора, который собирал ядро и твой модуль должны совпадать ( поэтому есть смысл использовать свою версию ядра, при старом ядре, и современном компиляторе.
4. стоит читать СООТВЕТСТВУЮЩУЮ документацию, т.е. для 2.4 ядра, читать документы о ядре 2.4 с  версии 2.4 в ядре МНОГО ЧЕГО изменилось.

вот тут есть вся документация, по-английски: www.tldp.org
( точнее: http://www.tldp.org/LDP/lkmpg/2.4/html/index.html )
после ознакомления, поищи ( если надо ) по-русски.

ядро лучше всего скачивать с www.kernel.org

при нормальной настройке всех пакетов, ссылка /usr/src/linux должна указывать на бегущую и правильную версию ядра ( или заголовков ). Поэтому, если ты пытаешься собрать модуль,  а заголовков make не находит, надо настраивать систему.




--------------------
Я ещё не демон. Я только учусь.
PM WWW   Вверх
vzf
Дата 24.12.2006, 03:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 203
Регистрация: 10.9.2005

Репутация: нет
Всего: 5



Спасибо за дельный совет про оригинальную версию книгу. Хоть и во второй книге, которая у меня была, написано, что она для ядер 2.0...2.4, но наверное про 2.4 переводчик погорячлся.

Итак, пример из оригинальной книги собрался и работает (единственное, что пришлось поменять это
строчку CC = gcc-3.0 в Makefile'е на CC=gcc).

Но при попытке собрать модуль, перехватывающий системные вызовы появилась другая проблема:

ядро 2.4.20-8 не экспортирует больше таблицу системных вызовов, поэтому при выполнении
insmod появляется ошибка unresolved symbol sys_call_table.

Кто нибудь знает как сделать так, чтобы ядро экспортировало таблицу системных вызовов?

В книге для ядер 2.6 приводится патч на ядро. Но для для 2.4 он не подходит.

В оригинальной версии книги про эту проблему ничего не сказано (видимо примеры выполнялись на самых ранних версиях ядра 2.4).

Вот код модуля:

Код


/*  syscall.c 
 * 
 *  System call "stealing" sample.
 */


/* Copyright (C) 2001 by Peter Jay Salzman */


/* 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 
 * 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 */
  if (uid == getuid_call()) {  
   /* getuid_call is the getuid system call, 
    * which gives the uid of the user who
    * ran the process which called the system
    * call we got */

    /* Report the file, if relevant */
    printk("Opened file by %d: ", uid); 
    do {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
      get_user(ch, filename+i);
#else
      ch = get_user(filename+i);
#endif
      i++;
      printk("%c", ch);
    } while (ch != 0);
    printk("\n");
  }

  /* Call the original sys_open - otherwise, we lose 
   * the ability to open files */
  return original_call(filename, flags, mode);
}



/* Initialize the module - replace the system call */
int init_module()
{
  /* Warning - too late for it now, but maybe for 
   * next time... */
  printk("I'm dangerous. I hope you did a ");
  printk("sync before you insmod'ed me.\n");
  printk("My counterpart, cleanup_module(), is even"); 
  printk("more dangerous. If\n");
  printk("you value your file system, it will ");
  printk("be \"sync; rmmod\" \n");
  printk("when you remove this module.\n");

  /* Keep a pointer to the original function in 
   * original_call, and then replace the system call 
   * in the system call table with our_sys_open */
  original_call = sys_call_table[__NR_open];
  sys_call_table[__NR_open] = our_sys_open;

  /* To get the address of the function for system 
   * call foo, go to sys_call_table[__NR_foo]. */

  printk("Spying on UID:%d\n", uid);

  /* Get the system call for getuid */
  getuid_call = sys_call_table[__NR_getuid];

  return 0;
}


/* Cleanup - unregister the appropriate file from /proc */
void cleanup_module()
{
  /* Return the system call back to normal */
  if (sys_call_table[__NR_open] != our_sys_open) {
    printk("Somebody else also played with the ");
    printk("open system call\n");
    printk("The system may be left in ");
    printk("an unstable state.\n");
  }

  sys_call_table[__NR_open] = original_call;
}  


Код makefile:

Код

TARGET  := syscall
WARN    := -W -Wall -Wstrict-prototypes -Wmissing-prototypes
INCLUDE := -isystem /lib/modules/`uname -r`/build/include
CFLAGS  := -O2 -DMODULE -D__KERNEL__ ${WARN} ${INCLUDE}
CC      := gcc

${TARGET}.o: ${TARGET}.c

.PHONY: clean

clean:
    rm -rf ${TARGET}.o


--------------------
Java - Write Once, Test EveryWhere!
PM MAIL   Вверх
MAKCim
Дата 24.12.2006, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 21
Всего: 207



Цитата

ядро 2.4.20-8 не экспортирует больше таблицу системных вызовов, поэтому при выполнении

2.6* не экспортирует, с 2.4* должно быть ОК
Цитата

перехватывающий системные вызовы

Код

/* handler.S */

INTERRUPT    =    0x80

.data
.align 4
address:
    /* тут хранится оригинальный адрес обработчика system_call */
    .long -1
.text
.align 4
.globl __sys_address
__sys_handler:
    pushal /* сохраняем все регистры */
    pushl    %eax  /* сохраняем номер системного вызова в стеке для функции __system_call */
    call __system_call /* собственно ее вызов */
    addl    $4, %esp /* выталкиваем из стека сохраненный параметр */
    popal /* очищаем стек */
    jmpl    *address /* переход на оригинальный обработчик */
__sys_address:
    sidt    -6(%esp)    /* получаем значение регистра IDTR */
    movl    -4(%esp), %ebx  /* в ebx помещаем линейный адрес начала таблицы IDT */
    movl    $INTERRUPT, %eax /* в eax помещаем номер прерывания (индекс в IDT) */
    leal    (%ebx, %eax, 8), %ebx   /* находим дескриптор в IDT, который соответствует INTERRUPT */
    movw    (%ebx), %ax /* эта и следующие 3 строки - сохранение в eax адреса оригинального обработчика */
    rol    $16, %eax
    movw    6(%ebx), %ax
    rol    $16, %eax
    movl    %eax, address 
    movl    $__sys_handler, %eax     /* сохраняем адрес нового обработчика */
    cli   /* запрещаем прерывания */
    movw    %ax, (%ebx) /* эта и следующие 2 строки - сохранение в дескрипторе нового обработчика */
    rol    $16, %eax
    movw    %ax, 6(%ebx)
    sti /* разрешение прерываний */
    ret

Код

/* system_call.c */
....
extern void __sys_address();
void __system_call(u32 eax) {
    /* анализ eax и вызов обработчика (своего) на системный вызов с номером eax  */
}

int init_module() {
    __sys_address();
    return 0;
}
...

прежде чем тестировать это творчество, будь готов, что система может рухнуть  smile 
но принцип должен быть виден (как можно в обход ядра это дело перехватить)

Добавлено @ 11:25 
vzf,
а вообще зачем тебе перехват вызовов? Чисто побаловаться?

Это сообщение отредактировал(а) MAKCim - 24.12.2006, 11:21


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
vzf
Дата 24.12.2006, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 203
Регистрация: 10.9.2005

Репутация: нет
Всего: 5



Цитата

а вообще зачем тебе перехват вызовов? Чисто побаловаться?


Если бы... Задание такое дали в универе.

Кстати я добился, чтобы таблица системных вызовов была доступной. Дописал в ksyms.c строчку

EXPORT_SYMBOL(sys_call_table); и пересобрал ядро.

Но ядро пересобралось с ошибками и поэтому когда его загружаю не запускается X-сервер. А когда делаю insmod он уже не находит printk (пишет unresolved symbol printk). Но это не так критично, я просто закоментил все printk. Загрузил модуль, проверил - работает.

Сейчас попробую твой вариант.
--------------------
Java - Write Once, Test EveryWhere!
PM MAIL   Вверх
MAKCim
Дата 24.12.2006, 16:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 21
Всего: 207



Цитата

Если бы... Задание такое дали в универе.

Классный у вас универ, ядро изучаете smile 
Цитата

Сейчас попробую твой вариант. 

только осторожно, я его сам не проверял  smile 


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
vzf
Дата 26.12.2006, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 203
Регистрация: 10.9.2005

Репутация: нет
Всего: 5



Понял почему ядро не собиралось нормально. Надо было сначала перед make xconfig сделать make mrproper.

Сейчас пересобрал собрал ядро. Все работает. Всем огромное спасибо.

P.S. В целях осторожности, боясь уронить ОС, я все же не стал пробовать твой пример (хотя думаю, что он должен работать правильно)

P.S. 
Цитата

Классный у вас универ, ядро изучаете


Да только интересно, что такое задание не по предмету ОС, который уже у нас был, а по предмету
"безопасность и СПО мобильных устройств". Хотя принцип написания модулей ядра ОС и перехватывания системных вызовов наверное схож для всех ос, будь то Linux, uCLinux, Windows XP или Windows CE.
--------------------
Java - Write Once, Test EveryWhere!
PM MAIL   Вверх
MAKCim
Дата 26.12.2006, 17:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 21
Всего: 207



Цитата

Хотя принцип написания модулей ядра ОС и перехватывания системных вызовов наверное схож для всех ос, будь то Linux, uCLinux, Windows XP или Windows CE.

сомневаюсь, что он будет схож

Добавлено @ 17:24 
Цитата

В целях осторожности, боясь уронить ОС, я все же не стал пробовать твой пример

В принципе, максимум, что будет - полное зависание системы, от которой спасает только reset, а так ничего страшного  smile 


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Linux/UNIX: Oбщие вопросы"
nickless
Imple
nerezus

В тему здесь вопросы общие - не привязанные к определенному ПО или дистрибутиву BSD/Linux/UNIX.
Например вопросы о выборе ОС для определенных задач (но если Вы просто хотите узнать "Какой дистрибутив лучше", то для этого есть Клуб юнуксоидов).
Общие вопросы по shell-программированию тоже лучше задавать здесь.


  • Вопросы мобильной разработки тут
  • Вы должны соблюдать правила форума.
  • Помните: какой вопрос, такой и ответ. Прежде чем задать вопрос прочитайте вот эту статью на форуме CIT.
  • Оскорблять запрещается.
  • Религиозные войны в Религиозных войнах.
  • Общение "просто так" в Клубе юнуксоидов. В отличие от многих других разделов, здесь разрешается сдержанно оффтопить и юморить в тему.

За интересные статьи, находки, решения, программы и просто реальную помощь будут ставиться + в репу).


В данный момент этот раздел модерируют nerezus, nickless, powerfox, pythonwin, Imple и ZeeLax. Если вы хотите помочь нам, пишите в ПМ и мы обсудим.


Спасибо. И use UNIX or die; С уважением, nerezus, nickless, powerfox, pythonwin, Imple, ZeeLax.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | *NIX системы: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0865 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.