لینکس kernel module یہ کوڈ کا ایک چھوٹا ٹکڑا ہے جسے پورے دانا کو دوبارہ بنائے بغیر چلتے ہوئے دانا میں لوڈ کیا جا سکتا ہے۔
یہ کافی آسان لگتا ہے، لیکن یہاں تک کہ کم سے کم ماڈیولز مشین جیسی آبجیکٹ فائلوں، میٹا ڈیٹا، برآمد شدہ اور غیر حل شدہ علامتوں اور حتمی فائلوں کی حیرت انگیز مقدار پیدا کرتے ہیں۔ .ko یہ ایک باقاعدہ ایگزیکیوٹیبل فائل سے بالکل مختلف ہے۔
یہاں مکمل طور پر کام کرنے والا لینکس کرنل ماڈیول ہے: یہ صرف 22 لائنوں پر مشتمل ہے، جن میں سے 7 ایمبیڈنگز اور میٹا ڈیٹا ہیں۔
#include
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chris Roy");
MODULE_DESCRIPTION("A minimal loadable kernel module");
MODULE_VERSION("0.1");
static int __init hello_init(void)
{
pr_info("hello: loaded, module at %pSn", hello_init);
return 0;
}
static void __exit hello_exit(void)
{
pr_info("hello: unloadedn");
}
module_init(hello_init);
module_exit(hello_exit);
جس کمپیوٹر پر میں یہ لکھ رہا ہوں اسے مرتب کرنے سے تقریباً 106,000 بائٹس کی فائل تیار ہوتی ہے۔ اگر آپ ڈیبگ کی معلومات کو ہٹاتے ہیں، تو وہی ماڈیول 4,864 بائٹس کا ہوگا۔ جو کچھ بلڈ فراہم کرتا ہے اس کا 95٪ کوڈ نہیں ہے۔
آپ کی کل رقم میرے مقابلے میں مختلف ہے اور یہ متوقع رقم نہیں ہے۔ ان میں سے کچھ صارف کے بنائے ہوئے مقامات ہیں۔ چونکہ ڈیبگ انفارمیشن اس ڈائرکٹری کو ریکارڈ کرتی ہے جس سے صارف نے مرتب کیا ہے، گہرے نیسٹڈ پاتھ کی قیمت چھوٹے راستوں کے برعکس سینکڑوں بائٹس لگ سکتی ہے۔ کمپائلر ورژن اور کرنل کنفیگریشنز زیادہ جدید ہو جاتی ہیں۔ تناسب برقرار ہے۔ بائٹس کی صحیح تعداد صرف اس مشین کے ذریعہ تیار کی جاتی ہے۔
زیادہ تر کرنل ماڈیول ٹیوٹوریلز اوپر کی فہرست دکھاتے ہیں، تاکہ یہ خلا شروع کرنے کے لیے ایک اچھی جگہ ہو۔ makeاور رک جاؤ۔
یہ اس بات کی پیروی کرتا ہے کہ تعمیر نے اصل میں کیا پیدا کیا، ماڈیول نے کچھ بھی مفید لکھنے سے پہلے کس چیز پر انحصار کیا، اور 2014 میں جو ٹیوٹوریل مجھے ملا وہ اب کیوں مرتب نہیں ہوتا ہے۔
انڈیکس
آپ کو کیا ضرورت ہے
اس کے ساتھ چلنے کے لیے، آپ کو کوڈ لوڈ کرنے کے لیے ایک لینکس مشین، چلانے والے کرنل کے ہیڈرز، اور ایک کمپائلر کی ضرورت ہوگی۔
Debian یا Ubuntu کے لیے:
sudo apt install build-essential linux-headers-$(uname -r)
فیڈورا میں، مساوی ہے: kernel-devel اور kernel-headersاور آرک میں linux-headers دانا سے ملنے والا پیکیج۔
اس بات کو یقینی بنائیں کہ ہیڈرز وہاں پہنچیں جہاں آپ کی تعمیر کی توقع ہے۔
ls -d /lib/modules/$(uname -r)/build
وہ راستہ ہیڈر پیکج کا ایک ہم آہنگی ہے، اور راستے کا غائب ہونا سب سے عام وجوہات میں سے ایک ہے جس کی وجہ سے ماڈیول کی تعمیر ایک خرابی کے ساتھ ناکام ہو جاتی ہے جس میں ہیڈر کے بارے میں کچھ بھی نہیں بتایا گیا ہے۔
ماڈیول کو دو وجوہات کی بناء پر بننے کے بعد بھی لوڈ نہیں کیا جا سکتا۔ سیکیور بوٹ غیر دستخط شدہ ماڈیولز کو مسترد کرتا ہے اور کرنل لاکنگ انہیں خفیہ موڈ میں لوڈ ہونے سے روکتا ہے۔ درج ذیل میں سے سبھی کو چیک کریں:
mokutil --sb-state
cat /sys/kernel/security/lockdown
یہاں مشین پر سیکیور بوٹ غیر فعال ہے اور لاک اپ کی اطلاع ہے۔ [none] integrity confidentialityقوسین ایکٹو موڈ کی نشاندہی کرتے ہیں۔ اگر سیکیور بوٹ کو فعال کے طور پر درج کیا گیا ہے، تو آپ کو فرم ویئر میں سیکیور بوٹ کو غیر فعال کرنا ہوگا یا ماڈیول لوڈ کرنے سے پہلے ماڈیول پر دستخط کرنا ہوں گے۔
میں کرنل 5.15.0-190-generic اور gcc 11.4 کے ساتھ Ubuntu 22.04 استعمال کر رہا ہوں۔ آپ کا ورژن مختلف ہو سکتا ہے اور مضمون کہتا ہے کہ یہ کہاں اہمیت رکھتا ہے۔
سب سے چھوٹا ماڈیول جو کام کرتا ہے۔
اس دستاویز کے شروع میں درج ذیل کوڈ کو محفوظ کریں: hello.c. اسے دوبارہ حوالہ کے لیے یہاں درج کیا گیا ہے۔
#include
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chris Roy");
MODULE_DESCRIPTION("A minimal loadable kernel module");
MODULE_VERSION("0.1");
static int __init hello_init(void)
{
pr_info("hello: loaded, module at %pSn", hello_init);
return 0;
}
static void __exit hello_exit(void)
{
pr_info("hello: unloadedn");
}
module_init(hello_init);
module_exit(hello_exit);
وہاں کی چار چیزیں اصل کام کر رہی ہیں۔
module_init اور module_exit ان فنکشنز کو رجسٹر کرتا ہے جنہیں کرنل کال کرتا ہے جب ماڈیول لوڈ اور ان لوڈ ہوتے ہیں۔ وہ نہیں کرتے main. ایک ماڈیول میں ایک بھی انٹری پوائنٹ نہیں ہوتا ہے جہاں سے یہ چلتا ہے اور واپس آتا ہے۔ اس میں ایک ہک ہے جو دو مخصوص واقعات پر چلتا ہے، اور اس کے درمیان کچھ نہیں ہوتا جب تک کہ دوسرا واقعہ نہ بلایا جائے۔
__init اور __exit سیکشن مارکر۔ __init آپ بوٹ لاگ میں "غیر استعمال شدہ کرنل میموری کو جاری کریں” دیکھیں گے کیونکہ یہ کرنل کو بتاتا ہے کہ یہ کوڈ ایک بار چلے گا اور بعد میں میموری کو آزاد کر دے گا۔ __exit تعمیر کو مطلع کرتا ہے کہ اس فنکشن کی ضرورت صرف اس صورت میں ہے جب ماڈیول کو بالکل بھی اتارا جا سکے۔
MODULE_LICENSE("GPL") یہ کوئی دستاویز نہیں ہے۔ کرنل لوڈ کے وقت اس کی جانچ کرتا ہے، اور ماڈیول جو کہ غیر GPL لائسنس کا اعلان کرتے ہیں نشان زد علامتوں تک رسائی سے انکار کر دیا جاتا ہے۔ EXPORT_SYMBOL_GPLیہ سب سے دلچسپ چیز ہے۔ اگر آپ میکرو کو مکمل طور پر چھوڑ دیتے ہیں، تو دانا خود کو آلودہ کر دے گا اور شکایات درج کر لے گا۔
pr_info کی جدید ہجے ہے۔ printk(KERN_INFO ...). یہ ٹرمینل کے بجائے کرنل رِنگ بفر کو لکھتا ہے، لہذا یہ پہلی بار تقریباً ہر ایک کے لیے کام کرے گا۔
کہ MODULE_AUTHOR, MODULE_DESCRIPTIONاور MODULE_VERSION میکرو میٹا ڈیٹا ہیں، اعمال نہیں، اور بالآخر modinfo پڑھیں۔ اگر آپ اسے اسی طرح چھوڑ دیتے ہیں تو اس سے کوئی پریشانی نہیں ہوگی، لیکن حالیہ دانا آپ کو تعمیر کرتے وقت کوتاہی کے بارے میں خبردار کرے گا۔ MODULE_DESCRIPTIONشروع سے تینوں لکھنے کے لیے یہی وجہ کافی ہے۔
میک فائل نظر آنے سے زیادہ اجنبی ہے۔
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
یہ میک فائل کی طرح لگتا ہے، لیکن اس میں سے زیادہ تر میک فائل نہیں ہے۔ obj-m += hello.o یہ میک متغیر نہیں ہے جسے آپ نے ایجاد کیا ہے۔ یہ ایک اعلامیہ ہے جسے kbuild کے ذریعے پڑھا جاتا ہے، جو کرنل کا اپنا بلڈ سسٹم ہے۔
کہ make -C لائن ڈائرکٹریز کو کرنل ہیڈر میں تبدیل کرتی ہے اور وہاں کرنل کا بلڈ سسٹم چلاتی ہے، گزرتے ہوئے: M=$(PWD) "ماڈیول کا ذریعہ یہاں ہے۔” میک فائل ایک پتلا ریپر ہے جو کام کو ایک ایسے بلڈ سسٹم تک پہنچاتا ہے جسے آپ نے نہیں لکھا اور اسے آسانی سے تبدیل نہیں کیا جا سکتا۔
ان بالواسطہ وجوہات کی وجہ سے ماڈیول کی تعمیر ان طریقوں سے ناکام ہو جاتی ہے جو کوڈ سے غیر متعلق معلوم ہوتے ہیں۔ یہ کرنل ہیڈر کے خلاف اس طرح مرتب نہیں کرتا ہے جس طرح یہ libc ہیڈر کے خلاف مرتب کرتا ہے۔ میں جھنڈوں اور قواعد کا استعمال کرتے ہوئے فائل سے کرنل بلڈ چلا رہا ہوں۔
تعمیر نے اصل میں کیا کیا
چلائیں make اسے نہ چھوڑیں اور آؤٹ پٹ پڑھیں۔
make -C /lib/modules/5.15.0-190-generic/build M=/home/chris/lkm modules
make[1]: Entering directory '/usr/src/linux-headers-5.15.0-190-generic'
CC [M] /home/chris/lkm/hello.o
MODPOST /home/chris/lkm/Module.symvers
CC [M] /home/chris/lkm/hello.mod.o
LD [M] /home/chris/lkm/hello.ko
BTF [M] /home/chris/lkm/hello.ko
Skipping BTF generation for /home/chris/lkm/hello.ko due to unavailability of vmlinux
پانچ مراحل میں سے صرف پہلا مرحلہ متوقع تالیف ہے۔
CC [M] hello.o ماخذ مرتب کریں۔ عام
MODPOST یہ جاننے کے قابل ایک قدم ہے۔ یہ حوالہ شدہ لیکن غیر متعینہ علامتوں کے لئے آبجیکٹ فائلوں کو تلاش کرتا ہے، برآمد شدہ دانا کے سمبل ٹیبل کے خلاف ہر علامت کو چیک کرتا ہے، اور اگر یہ دانا کی طرف سے فراہم نہیں کی گئی کوئی چیز استعمال کرتا ہے تو تعمیر کو ناکام بنا دیتا ہے۔ بھی بنائیں hello.mod.cیہ ایک چھوٹی سی گلو فائل ہے جس میں ماڈیول کا میٹا ڈیٹا ہوتا ہے۔
CC [M] hello.mod.o مرتب کریں اور گلو بنائیں LD [M] ہم آخر میں اسے اعتراض کے ساتھ جوڑتے ہیں۔ .ko.
BTF [M] ٹریکنگ ٹول کے ذریعے استعمال ہونے والی قسم کی معلومات منسلک کریں۔ چونکہ BTF بنانے کے لیے ایک غیر کمپریسڈ فائل کی ضرورت ہوتی ہے، اس لیے ہم نے اسے یہاں چھوڑ دیا ہے۔ vmlinux امیجز اور اوبنٹو اسے بطور ڈیفالٹ فراہم نہیں کرتے ہیں۔ تعمیر انتباہ اور جاری ہے. یہ درست ہے۔ BTF مفید ہے، لیکن ضروری نہیں ہے۔
.ko فائل کے اندر کیا ہے۔
کوئی راستہ نہیں .ko یہ ایک سادہ ELF آبجیکٹ ہے جس میں کرنل کے مخصوص حصے شامل کیے گئے ہیں۔ میٹا ڈیٹا پر ایک نظر ڈالیں۔
modinfo ./hello.ko
version: 0.1
description: A minimal loadable kernel module
author: Chris Roy
license: GPL
srcversion: 39D86510C9FF65D797EAF90
depends:
retpoline: Y
name: hello
vermagic: 5.15.0-190-generic SMP mod_unload modversions
یہ سب ایک ELF سیکشن میں ہے اور null-separated strings کے طور پر محفوظ ہے۔ آپ فائل سے براہ راست پڑھ سکتے ہیں۔
objcopy -O binary --only-section=.modinfo hello.ko /dev/stdout | tr ' ' 'n'
آئیے ابتدائی نمبروں پر واپس جائیں۔ ایک ماڈیول ڈسک پر تقریباً 106,000 بائٹس کا ہوتا ہے۔
ls -l hello.ko
cp hello.ko /tmp/ && strip --strip-debug /tmp/hello.ko && ls -l /tmp/hello.ko
105984 hello.ko
4864 /tmp/hello.ko
اصل ماڈیول 5KB سے کم ہے۔ باقی سب کچھ DWARF ڈیبگ انفارمیشن ہے جسے بلڈ نے برقرار رکھا ہے، لہذا اس طرح کے ٹولز موجود ہیں: crash اور gdb اگر آپ گھبراتے ہیں تو آپ کوڈ کو سمجھ سکتے ہیں۔ ماڈیول لوڈ کرتے وقت، دانا ڈیبگ سیکشن کو لوڈ نہیں کرتا ہے، اس لیے میموری کی قیمت بڑی کے بجائے ایک چھوٹی تعداد ہے۔
آپ کی ہیلو ورلڈ پہلے ہی تین چیزوں پر منحصر ہے:
یہ وہ حصہ ہے جو کاش کسی نے مجھے پہلے دکھایا ہوتا۔ دانا سے پوچھیں کہ آبجیکٹ کو کیا ضرورت ہے۔
nm -u hello.ko
U __fentry__
U _printk
U __x86_return_thunk
U اس کا مطلب ہے غیر متعینہ۔ یہ وہ علامتیں ہیں جن کا ماڈیول حوالہ دیتا ہے اور وہ علامتیں جو دانا کو لوڈ کے وقت فراہم کرنا ضروری ہے۔
_printk آپ وضاحت کر سکتے ہیں، کیونکہ pr_info اس پر پھیلتا ہے۔
__fentry__ کیونکہ کرنل فنکشن ٹریسنگ سپورٹ کے ساتھ بنایا گیا ہے، یہ ایک کال ہے جسے کمپائلر ہر فنکشن کے اوپر رکھتا ہے۔ ہر فنکشن جو آپ ماڈیول میں لکھتے ہیں وہ ہک حاصل کرتا ہے، چاہے اس کی درخواست کی گئی ہو یا نہیں۔ ftrace آپ بعد میں کسی بھی چیز کو دوبارہ مرتب کیے بغیر اپنے کوڈ کو آلہ بنا سکتے ہیں۔
__x86_return_thunk سپیکٹر تخفیف. مرتب کرنے والے نے معمول کی واپسی کی ہدایات کو تھنک کال سے بدل دیا، جو قیاس آرائی پر عمل درآمد کے راستے سے بچتا ہے جس پر کمزوری انحصار کرتی ہے۔ تخفیف اس سسٹم کے تمام کرنل کوڈ پر لاگو ہوتی ہے، قطع نظر اس کے کہ یہ ماڈیول ہے یا نہیں، اس لیے یہ ان ماڈیولز میں ظاہر ہوتا ہے جو ایک لائن پرنٹ کرتے ہیں۔
ہیلو ورلڈ کی تین علامتوں میں سے دو مشینوں پر لگائے گئے انفراسٹرکچر ہیں۔ کرنل کوڈ لکھنا کیسا ہے اس کی یہ ایک منصفانہ تصویر ہے۔
MODPOST نے یقینی بنایا کہ لنک کامیاب ہونے سے پہلے تینوں موجود تھے۔ اگر آپ نے کسی ایسے فنکشن کو کال کیا تھا جسے کرنل نے برآمد نہیں کیا تھا، تو یہ ماڈیول تیار کرنے کے بجائے "غیر متعینہ علامت” غلطی کے ساتھ ناکام ہوجاتا جو لوڈ پر ناکام ہوجاتا۔
vermagicاور کیوں ماڈیول لوڈ کرنے سے انکار کرتا ہے۔
اس لائن کو دوبارہ دیکھو modinfo:
vermagic: 5.15.0-190-generic SMP mod_unload modversions
کسی بھی چیز کو لوڈ کرنے سے پہلے، دانا اس سٹرنگ کا اپنے سٹرنگ سے موازنہ کرتا ہے اور کسی بھی طرح کی مماثلت کو مسترد کرتا ہے۔ یہ ریلیز کا احاطہ کرتا ہے، چاہے دانا SMP ہے، آیا ماڈیول ان لوڈنگ کو مرتب کیا گیا ہے، اور آیا علامت ورژن آن کیا گیا ہے۔
یہی وجہ ہے کہ ایک سسٹم پر بنائے گئے ماڈیول عام طور پر دوسرے پر لوڈ نہیں ہوتے ہیں، اور کیوں کرنل کو اپ گریڈ کرنے کا مطلب ماڈیول کو دوبارہ بنانا ہے۔
لینکس کرنل کے اندر ABI کے استحکام کی کوئی ضمانت نہیں ہے۔ ریلیز کے درمیان اندرونی ڈھانچہ تبدیل ہوتا ہے، اور اگر ایک لے آؤٹ کے لیے مرتب کردہ ماڈیول دوسرے لے آؤٹ کے خلاف چلتا ہے، تو یہ میموری کو مکمل طور پر ناکام ہونے کے بجائے خراب کر دے گا۔ لوڈ کرنے سے انکار ایک ایسی چیز ہے جس کے بارے میں دانا محتاط ہے۔
یہی وجہ ہے کہ DKMS موجود ہے۔ اگر آپ کے پاس VirtualBox، ZFS، یا NVIDIA ڈرائیورز انسٹال ہیں، تو آپ کے ماڈیولز پہلے ہی اس طرح سے دوبارہ بنائے جا رہے ہیں۔ یہاں مشین پر:
modinfo vboxdrv | head -3
filename: /lib/modules/5.15.0-190-generic/updates/dkms/vboxdrv.ko
version: 6.1.50_Ubuntu r161033 (0x00320000)
license: GPL
براہ کرم اس کا حوالہ دیں۔ updates/dkms/ اس سڑک پر۔ ڈی کے ایم ایس سورس کو برقرار رکھتا ہے اور ہر بار جب نیا دانا انسٹال ہوتا ہے تو ماڈیول دوبارہ بناتا ہے۔ یہ ناگزیر طور پر برماجیک معائنہ کی وجہ سے دیکھ بھال کے اخراجات کا نتیجہ ہے۔
بوجھ پر پیرامیٹرز پاس کرنا
آپ شاذ و نادر ہی ایسا ماڈیول چاہتے ہیں جو ہمیشہ ایک ہی کام کرتا ہو۔ module_param متغیرات کو بے نقاب کریں تاکہ لوڈ کے وقت ان کی قدریں سیٹ کی جاسکیں۔ اس کو بطور محفوظ کریں۔ param.c پہلو بہ پہلو hello.c:
#include
#include
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A module that takes parameters");
static char *who = "world";
static int times = 1;
module_param(who, charp, 0444);
MODULE_PARM_DESC(who, "who to greet");
module_param(times, int, 0644);
MODULE_PARM_DESC(times, "how many times to greet");
static int __init param_init(void)
{
int i;
for (i = 0; i < times; i++)
pr_info("param: hello, %sn", who);
return 0;
}
static void __exit param_exit(void)
{
pr_info("param: unloadedn");
}
module_init(param_init);
module_exit(param_exit);
فہرست درآمد کرنے کے لیے اسے اپنی میک فائل میں شامل کریں:
obj-m += hello.o param.o
تین دلائل ایک متغیر، اس کی قسم، اور فائل پر اجازتیں ہیں جو اس متغیر کی نمائندگی کرتی ہیں۔ /sys/module/. موڈ 0444 یہ پڑھنے کے قابل ہے اور لوڈ ہونے کے بعد اس میں ترمیم کی جاتی ہے۔ 0644 یہ مفید ہے کیونکہ روٹ اس فائل کو لکھ سکتا ہے اور ماڈیول کے چلنے کے دوران اس کی اقدار کو تبدیل کرسکتا ہے۔ یہ تنازعہ پیدا ہونے کا ایک طریقہ بھی ہے اگر کوئی ماڈیول کسی متغیر کو بدلنے کی توقع کیے بغیر پڑھتا ہے۔
charp char ایک پوائنٹر ہے اور دیگر عام اقسام ہیں: int, bool, long اور charp صف کے ذریعے module_param_array. اگر آپ کوئی ایسی قسم پاس کرتے ہیں جو آپ کے متغیر سے مماثل نہیں ہے تو، بعد میں غلط برتاؤ کرنے کی بجائے تعمیر ناکام ہو جائے گی۔
MODULE_PARM_DESC تفصیل کو ماڈیول میٹا ڈیٹا میں ڈالیں۔ یہاں modinfo اسے تلاش کریں:
name: param
parm: who:who to greet (charp)
parm: times:how many times to greet (int)
لوڈ ٹائم پر، اسے اس طرح سیٹ کریں: name=value جوڑا:
sudo insmod ./param.ko who=kernel times=3
کوئی بھی ماڈیول لوڈ کرنے سے پہلے اس کے قبول کردہ پیرامیٹرز کو پڑھ سکتا ہے۔ یہ پریشان کن ہونے کی بنیادی وجہ ہے۔ MODULE_PARM_DESC کوئی بھی
لوڈ اور آؤٹ پٹ مقامات
sudo insmod ./hello.ko
sudo dmesg | tail -2
lsmod | grep hello
sudo rmmod hello
کہ pr_info آؤٹ پٹ کرنل رنگ بفر میں جاتا ہے، تو dmesg اگر ٹرمینل کے بجائے dmesg یہ بے بنیاد رد ہے۔ kernel.dmesg_restrictاور sudo journalctl -k | tail اسی پیغام کو جریدے کے ذریعے پڑھا جاتا ہے۔
کہ %pS فارمیٹ سٹرنگ میں، کرنل پوائنٹرز کو خام پتوں کی بجائے علامتی ناموں اور آفسیٹ کے بطور پرنٹ کریں۔ یہ ہیکسا ڈیسیمل کے بجائے لاگ لائن سے پڑھنے کے قابل کچھ حاصل کرنے کا ایک طریقہ ہے۔
lsmod پڑھیں /proc/modules یہ تین کالم دکھاتا ہے: ماڈیول کا نام، میموری کا سائز، اور ماڈیول پر مبنی نام کے ساتھ استعمال کی گنتی۔ غیر صفر استعمال کی گنتی والے ماڈیولز کو اتارا نہیں جا سکتا۔ یہ سب سے عام وجہ ہے۔ rmmod میں انکار کرتا ہوں۔
کسی بھی چیز کو لوڈ کرنے سے پہلے، ایک انتباہ ہے۔ صارف کی جگہ میں ایک بگ پروگرام کے کریش ہونے کا سبب بنتا ہے۔ تاہم، یہاں موجود کیڑے آپ کے سسٹم کے کریش ہونے یا آپ کے فائل سسٹم کے خراب ہونے کا سبب بن سکتے ہیں۔ ابتدائی طور پر، آپ اسے ورچوئل مشین پر کئی بار کریں گے۔ اسنیپ شاٹ کی قیمت خراب ڈسک کی قیمت سے بہت کم ہے۔
4 تعمیراتی غلطیاں اور ان کا کیا مطلب ہے۔
یہ چار لوگ زیادہ تر وقت ضائع کرتے ہیں، اور ہر ایک کچھ مخصوص کہتا ہے جب آپ جان لیں کہ کیا پڑھنا ہے۔
No rule to make target 'modules'. Stop. کرنل ہیڈر غائب ہے یا علامتی لنک اس میں موجود ہے: /lib/modules/$(uname -r)/build کہیں بھی کوئی پوائنٹ نہیں ہے۔ ہیڈر پیکجز انسٹال کریں جو چلانے والے کرنل سے بالکل مماثل ہوں۔ اگر آپ نے اپ ڈیٹ کے بعد سے ریبوٹ نہیں کیا ہے، تو تازہ ترین دانا اکثر انسٹال نہیں ہوگا۔
ERROR: modpost: "some_function" [hello.ko] undefined! آپ نے ایک علامت کا حوالہ دیا جو دانا کے ذریعہ برآمد نہیں کیا جاتا ہے۔ یہاں یہ ہے کہ یہ اصل تعمیر میں کیسا لگتا ہے:
ERROR: modpost: "this_symbol_does_not_exist" [bad.ko] undefined!
make[2]: *** [scripts/Makefile.modpost:133: Module.symvers] Error 1
دوبارہ کوشش کرنے سے کوئی فائدہ نہیں ہوگا۔ فنکشن دانا کے اندر ہے اور اسے برآمد نہیں کیا جاتا ہے، یا اس کے ساتھ برآمد کیا جاتا ہے: EXPORT_SYMBOL_GPL اور آپ کا ماڈیول غیر GPL لائسنس کا اعلان کرتا ہے۔ اسے چیک کریں grep the_symbol /proc/kallsymsدارالحکومت یہاں T دوسرے کالم میں کا مطلب ہے کہ یہ عالمی متن کی علامت ہے۔
insmod: ERROR: could not insert module: Invalid module format: تعمیر کامیاب رہی، لیکن ورمجک چلنے والے دانا سے مماثل نہیں ہے۔ موازنہ modinfo ./hello.ko | grep vermagic کے خلاف uname -r. درست ہیڈر کے خلاف دوبارہ تعمیر کرنے سے مسئلہ حل ہو جائے گا۔
insmod: ERROR: could not insert module: Operation not permitted: عام طور پر، سیکیور بوٹ یا تو غیر دستخط شدہ ماڈیولز کو مسترد کر دیتا ہے یا انہیں خفیہ موڈ میں لاک کر دیتا ہے۔ چیک کریں mokutil --sb-state اور cat /sys/kernel/security/lockdown یہ فرض کرنے سے پہلے کہ آپ کا کوڈ ناقص ہے۔
ایک اور چیز، بعد میں ڈیبگ کرنے کے بجائے ابھی سیکھنا آسان ہے۔ درخت سے باہر کے ماڈیول کو لوڈ کرنے سے دانا میں داغدار جھنڈا لگ جائے گا، جسے لاگ ان کیا جائے گا اور بعد میں ہونے والی غلطیوں یا گھبراہٹ پر رپورٹ کیا جائے گا۔
cat /proc/sys/kernel/tainted
قدر ایک بٹ ماسک ہے۔ یہاں مشین 4096 پڑھتی ہے جو کہ بٹ 12 ہے۔ TAINT_OOT_MODULEاس کا مطلب یہ ہے کہ کسی وقت درخت سے باہر کا ماڈیول لوڈ کیا گیا تھا۔
بٹ 13 پڑوسی بٹ ہے جس کے بارے میں لوگ الجھن میں پڑ جاتے ہیں۔ TAINT_UNSIGNED_MODULEسیکیور بوٹ کی یہی پرواہ ہے۔
مکمل فہرست یہاں ہے: include/linux/panic.h کرنل ماخذ سے۔ کرنل ڈویلپرز آپ سے بگ کو صاف دانا پر دوبارہ پیش کرنے کو کہیں گے اس سے پہلے کہ وہ اسے دیکھیں، اور یہ وہ فائل ہے جو آپ کو بتائے گی کہ آیا انہوں نے بگ کو دوبارہ پیش کیا ہے یا نہیں۔
مجھے جو ٹیوٹوریل ملا ہے وہ مرتب کیوں نہیں ہوتا ہے۔
ویب پر زیادہ تر ماڈیول ٹیوٹوریلز چند تبدیلیوں سے آگے ہیں، اور یہی اہم ہے۔
printk(KERN_INFO "...") اگرچہ یہ اب بھی کام کرتا ہے۔ pr_info موجودہ ہجے ہے اور لاگ لیول رکھتا ہے۔
init_module اور cleanup_module کیونکہ سادہ فنکشن کے نام پرانے کنونشن تھے۔ استعمال کریں module_init اور module_exit اس کے بجائے آپ کا اپنا نام استعمال کرنا فائل کو بغیر کسی تنازعہ کے دونوں کی وضاحت کرنے کی اجازت دیتا ہے۔
MODULE_LICENSE اصل میں، یہ ایک بار اختیاری تھا. یہ اب صرف GPL کے برآمد کردہ علامتوں تک رسائی کو روکتا ہے، لہذا یہ بوجھ برداشت کر سکتا ہے۔
کہ M= دلائل ہجے کے طور پر استعمال ہوتے تھے۔ SUBDIRS=. اس ہجے کو ہٹا دیا گیا ہے اور اس کا استعمال کرنے والے ٹیوٹوریلز ایک غیر بیان کردہ غلطی کے ساتھ ناکام ہو جاتے ہیں۔ SUBDIRS کہیں
ہیڈر پاتھ کو منتقل کر دیا گیا ہے۔ کسی بھی چیز کا ذکر /usr/src/linux یہ کرنل کے مخصوص ہیڈر پیکجوں میں تقسیم ہونے سے پہلے تھا، اور یہ کافی پرانا ہے کہ باقی کو بھی چیک کرنے کی ضرورت ہے۔ چھوٹی علامات: شامل کئی سالوں سے دونوں کو شامل کرنے والے سبق صرف پرانے کی کاپیاں ہیں، چاہے دونوں کو شامل کرنا بے ضرر ہو۔
اگر ٹیوٹوریل آپ کے دانا کے بارے میں انتباہ کے بغیر بناتا ہے، تو یہ کافی حالیہ ہے۔ دوسری صورت میں، ہدف شدہ کرنل ورژن عام طور پر پہلی غلطی میں پرنٹ کیا جاتا ہے.
نتیجہ
اب آپ کرنل ماڈیول بنا سکتے ہیں، بلڈ کے ذریعے تیار کردہ مواد کو پڑھ سکتے ہیں، اور ان تمام علامتوں کا حساب لگا سکتے ہیں جن پر یہ منحصر ہے۔
زیادہ مفید طور پر، آپ دیکھ سکتے ہیں کہ یہ ایک خاص طریقے سے کیوں ناکام ہو رہا ہے۔ لاپتہ /lib/modules/$(uname -r)/build یہ ہیڈر کا مسئلہ ہے۔ نقصان دہ عدم مطابقتیں تعمیر نو ہیں۔ MODPOST میں ایک غیر متعینہ علامت کا مطلب ہے کہ دانا آپ کی درخواست کردہ چیز کو خارج نہیں کرے گا، اور دوبارہ کوششوں کی کوئی مقدار اسے تبدیل نہیں کر سکے گی۔
آپ یہاں سے چند سمت جا سکتے ہیں۔ رجسٹر کریں /proc میں داخل ہونا proc_create یہ سب سے چھوٹی مفید چیز ہے جو ایک ماڈیول کر سکتا ہے۔
دانا خود پڑھنا Module.symvers نیچے /usr/src/linux-headers-$(uname -r)/ MODPOST ٹیبل کو چیک کرنے کے لیے، آپ کو اس سسٹم سے 26,420 برآمد شدہ علامتیں نظر آئیں گی اور ہر ایک کو ڈسپلے کریں گے۔ EXPORT_SYMBOL یا EXPORT_SYMBOL_GPL.
یا اپنے ماڈیول فنکشن کا سراغ لگائیں جو کام کرتا ہے کیونکہ: __fentry__ یہ ایک ہک ہے جو پہلی تعمیر کے بعد سے ہی ہے۔ موجود نہیں ہے ftrace یہ عمل کرنے کا حکم ہے۔ ذیل میں انٹرفیس ہے۔ /sys/kernel/tracingلہذا، یہ ایک فائل پر لکھ کر کارفرما ہے۔
sudo sh -c 'echo hello_init > /sys/kernel/tracing/set_ftrace_filter'
sudo sh -c 'echo function > /sys/kernel/tracing/current_tracer'
sudo cat /sys/kernel/tracing/trace
پرانے سسٹمز پر، راستہ یہ ہوگا: /sys/kernel/debug/tracing اس کے بجائے۔ اگر آپ براہ راست فائل میں نہیں لکھنا چاہتے ہیں۔ trace-cmd ایک ہی انٹرفیس کو لپیٹتا ہے۔
ایپیلاگ
مندرجہ بالا سبھی مانتے ہیں کہ آپ یہ کر سکتے ہیں، اور یہی مجھے دلچسپ لگتا ہے۔ بھری ہوئی ماڈیولز انہی اجازتوں کے ساتھ چلتی ہیں جو خود کرنل کی ہوتی ہیں۔ یہ کسی بھی میموری کو پڑھ سکتا ہے، کسی بھی فنکشن کو پیچ کر سکتا ہے، اور کسی بھی پالیسی کو نظر انداز کر سکتا ہے جو اس کے خیال میں سسٹم نافذ کر رہا ہے۔ کیونکہ جب یہ چلتا ہے تو اس پر کچھ نہیں ہوتا جسے رد کیا جا سکے۔
یہ ماڈیول لوڈنگ کو ایک آپریشن بناتا ہے جس میں اجازت ماڈل شامل نہیں ہو سکتا۔ یہی وجہ ہے کہ دانا اجازتوں کے بجائے دستخطوں اور تالے والے ماڈیولز کی حفاظت کرتا ہے۔
میں نے ایک خصوصیت کے قابل ڈیسک ٹاپ OS پر کام کرتے ہوئے اس منزل کو مارا جہاں ایک پروگرام کا مینی فیسٹ وہی ہے جو یہ کرسکتا ہے اور ڈیبین ماحولیاتی نظام کو ابھی بھی اس کے نیچے کام کرنا ہے۔ ایک ماڈیول وہ ہوتا ہے جہاں ماڈل کی نمائندگی نہیں کی جاتی ہے، لہذا ماڈل کو قبول کرنے سے پہلے دانا کی جانچ پڑتال کے بارے میں بالکل ٹھیک کام کرنا کوئی تفصیل نہیں ہے اور یہ ڈیزائن کی رکاوٹ بن جاتا ہے۔
میں نظام اور اس کے اسرار کے بارے میں thechris.in پر لکھتا ہوں۔