Има ли начин модул на ядрото да намери адреси на секции на друг зареден модул?

В система x86 имам модул на ядрото на Linux („модул за наблюдение“), който се уведомява от ядрото всеки път, когато се зареди конкретен модул на ядрото („цел“). Почти всеки модул на ядрото може да бъде цел. Използвам това в инструментална система, върху която работя.

Когато модулът за наблюдение обработва такова известяване, може да е удобно по някаква причина, ако наблюдателят знае адресите на ELF секциите на заредения целеви модул. Някакви идеи как тази информация може да бъде получена в пространството на ядрото?

Разбира се, вероятно бих могъл да получа съдържанието на съответните файлове в /sys/module/<target_name>/sections/ в потребителското пространство веднага щом целта бъде заредена и след това по някакъв начин да предам тези данни на модула за наблюдение, но това е твърде тромаво. Бих искал да намеря начин да получа тази информация директно в пространството на ядрото.

Доколкото видях в изходните кодове на зареждащия модул, той не съхранява адресите на секциите в struct module, а просто създава sysfs файлове за секциите. Може би е възможно по някакъв начин да се намерят обектите на ядрото, съответстващи на тези файлове, и да се прочетат необходимите данни от тези обекти? Или вероятно да използвате друг подход?


person Eugene    schedule 21.10.2011    source източник
comment
Изглежда, че kobject, съдържащ се в struct module (mkobj.kobj поле), участва в представянето на модула в sysfs. Ще се задълбоча в това, когато имам време. Може да е възможно да стигнете до атрибутите, съдържащи имената и адресите на секциите, като използвате този kobject като начална точка.   -  person Eugene    schedule 23.10.2011


Отговори (2)


След като се зарових как информацията за секциите на модула попада в sysfs, не намерих начин да я извлека без да използвам дефинициите на структурата, вътрешни за ядрото. Използването на такива неща не е опция в моя проект, така че най-накрая внедрих друг подход, който, надявам се, е по-надежден.

Накратко идеята е следната. Моят модул на ядрото използва помощния API за потребителски режим, за да стартира процес в потребителското пространство (всъщност черупка, изпълняваща моя скрипт). Този процес получава името на "целевия" модул на ядрото като параметър и събира информацията за неговите секции от sysfs (/sys/module/<target_name>/sections/). От потребителското пространство тази информация може да бъде получена лесно. След това той предава събраните данни на моя модул на ядрото като низ чрез файл в debugfs. Модулът анализира низа и валидира неговото съдържание. Ако всичко е наред, имената и началните адреси на секциите на ELF ще бъдат налични.

Признавам, че трикът с помощника за потребителски режим е доста тромав, но върши работата.

Подготвих примерна реализация на подхода, описан по-горе - вижте "Секции " пример.

За подробности относно помощния API за потребителски режим вижте кода в <linux/kmod.c> и <linux/kmod.h> в източниците на ядрото, а именно дефиницията на call_usermodehelper(). Примерите, както и обяснението на типичната употреба на API са налични в тази статия.

Имайте предвид, че примерите от тази статия са малко неточни: функцията init на модула връща резултата от call_usermodehelper() там. Последният обаче връща 2-байтов код на състоянието (поне когато се извиква с UMH_WAIT_PROC), а не 0 или отрицателен код за грешка, който функцията init се очаква да върне. Това може да доведе до предупреждения по време на изпълнение. Какво всъщност връща call_usermodehelper() е обяснено тук.

person Eugene    schedule 06.11.2011

Файлът linux/kernel/module.c има някои нестатични функции (но без този EXPORT_SYMBOL отпред) като module_address_lookup(), но тези функции използват неща като preempt_disable() и _enable(). Предпочитам да не използвам тези функции и предлагам вместо това да използвате sysfs-интерфейс, въпреки че вашият драйвер вече е в режим на ядрото.

person Community    schedule 21.10.2011
comment
Благодаря за отговора. Да, знам за module_address_lookup() и други подобни. Те се използват в системата kallsyms за търсене на символи и други подобни. Но имам нужда от друго нещо, адресите на секции на модула (.text, .devinit.text, .exit.text и т.н.), а не символи. Мога да получа адресите на init и основните области на модула, но всяка от тях може да съдържа повече от един ELF раздел. - person Eugene; 23.10.2011
comment
Изглежда от изходния код на товарача, че до момента на издаване на известията за зареждане, информацията за секциите на току-що заредения модул е ​​налична само в sysfs. Ако не греша, всеки файл в sysfs е подкрепен от обект на ядрото. Ако имате идея как моят модул може да намери такива обекти, съответстващи на файловете в /sys/module/<target_name>, това би било страхотно. - person Eugene; 23.10.2011
comment
Не виждам начин да получа тази информация от ядрото, освен ако не промените kernel/module.c, за да експортирате символ или функция. Можете да опитате да изпратите корекция с разумно съобщение, защо го искате по този начин. - person ott--; 24.10.2011
comment
Да, самите неща, свързани с модула, не позволяват това. Вероятно съм намерил решение, но не е много надеждно. struct module съдържа kobject, съответстващ на необходимата директория в sysfs. Има експортирани функции за обхождане на такива директории. Когато се стигне до dentry за раздел, може да се извика методът show() на споменатия kobject, за да се получи съдържанието на необходимия атрибут като низ, който след това може да бъде анализиран с функции, подобни на strtoul. Това може да работи, но изисква дефиниции от fs/sysfs/sysfs.h, вътрешен заглавен файл. - person Eugene; 24.10.2011
comment
(продължение) Бих предпочел да стоя далеч от този вътрешен API. Може би бих могъл да се измъкна с call_usermodehelper неща, да създам процес на потребителско пространство по този начин, да го накарам да получи данните и да ги предаде обратно на ядрото. Помощният API за потребителски режим е доста стабилен и вече се използва за много задачи в ядрото. Вероятно ще проуча този подход. - person Eugene; 24.10.2011