2 पॉइंट द्वारा GN⁺ 2024-07-28 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • Linux Kernel Module Programming Guide Linux v5.10 या उससे नए versions पर loadable kernel modules बनाने के लिए एक मुफ्त guide है, जो development environment से लेकर build, load, debugging और प्रमुख kernel interfaces तक को एक ही flow में कवर करती है
  • शुरुआती examples hello-*.c के जरिए module_init(), module_exit(), kbuild, insmod, rmmod, dmesg सिखाते हैं, और QEMU-based devtools host system को नुकसान पहुंचने का जोखिम कम करते हैं
  • Kernel modules kernel address space में चलते हैं, इसलिए गलत pointer, unload order, concurrency, या user memory copy errors kernel memory corruption या system instability का कारण बन सकते हैं
  • यह character devices, /proc, seq_file, threaded IRQ, input, PCI, USB, block, network, Device Model, Device Tree, static key तक विस्तार करती है और registration/unregistration order व lifetime management को बार-बार समझाती है
  • Kernel internal APIs version के अनुसार बदलते हैं, इसलिए LINUX_VERSION_CODE, KERNEL_VERSION, CONFIG_MODVERSIONS, SecureBoot signing, version magic जैसी conditions की जांच की जाती है, और examples में conditional compilation भी शामिल है

Guide की संरचना और basic flow

  • यह guide GitHub repository और PDF document उपलब्ध कराने वाला kernel module learning material है, जिसे Open Software License 3.0 की शर्तों के तहत copy, modify और distribute किया जा सकता है
  • मौजूदा guide Linux v5.10 को minimum supported baseline मानती है, और long-term support kernels में examples व instructions की compatibility बनाए रखना इसका लक्ष्य है
  • Learners को C language और normal process programs लिखने का अनुभव चाहिए; kernel modules dynamically load/unload होते हैं और reboot किए बिना kernel functionality बढ़ाते हैं
  • Basic development flow में kernel headers install करना, make से .ko build करना, modinfo check करना, insmod से load करना, dmesg या journalctl -k से logs देखना, और rmmod से unload करना शामिल है
  • devtools/ kernel source और BusyBox root filesystem build करता है, QEMU में boot करता है, examples/ को 9p virtfs से share करता है, और फिर guest में modules test करने देता है
  • Module initialization और cleanup के लिए module_init()·module_exit() का उपयोग पसंद किया जाता है; पुराने init_module()·cleanup_module() तरीके x86 IBT enabled kernel 6.15 के बाद कुछ conditions में build failures पैदा कर सकते हैं
  • Kernel modules printf() या libc का उपयोग नहीं करते; वे केवल kernel द्वारा exported symbols का उपयोग कर सकते हैं, और output terminal में नहीं बल्कि kernel log ring buffer में जाता है
  • User space और kernel space के बीच data movement के लिए put_user, get_user, copy_to_user, copy_from_user जैसे dedicated functions जरूरी हैं
  • Character device example register_chrdev, file_operations, dynamic major number, /dev node creation, exclusive open, put_user-based read, और unsupported write handling दिखाता है
  • /proc example proc_create, proc_ops, read/write callbacks, seq_file API को कवर करता है, और Linux v5.6 के बाद /proc handlers में file_operations की जगह proc_ops introduce होने वाले बदलाव को reflect करता है
  • Threaded IRQ request_threaded_irq() से top-half और bottom-half को अलग करता है; top-half interrupt context में केवल minimal work करता है और IRQ_WAKE_THREAD से thread-based bottom-half को जगाता है
  • आगे के chapters input, PCI, USB, block, network, Device Model, Device Tree जैसे real driver areas तक फैलते हैं, और हर subsystem के registration method तथा userspace ABI selection पर केंद्रित रहते हैं
  • Optimization और safety वाला हिस्सा likely·unlikely, static key, छोटे kernel stack, FPU use न करने, uninitialized padding leaks, और double-underscore internal API usage में सावधानी को कवर करता है

Build और load करते समय सबसे पहले आने वाली constraints

  • किसी एक kernel के लिए compile किया गया module दूसरे kernel में load नहीं हो सकता; version magic और CONFIG_MODVERSIONS match न होने पर Invalid module format या symbol version mismatch होता है
  • अधिकांश सामान्य Linux distribution kernels में modversioning enabled हो सकती है, इसलिए अगर examples सीधे काम न करें तो modversioning disabled kernel या QEMU environment पर विचार करना चाहिए
  • SecureBoot enabled systems में unsigned modules loading restricted हो सकती है, और यदि Lockdown: insmod: unsigned module loading is restricted दिखे तो SecureBoot disable करना या module signing process अपनाना जरूरी है

QEMU-based practice environment

  • devtools/setup.sh kernel tarball और BusyBox download/build करता है और initramfs package करता है
  • devtools/build-modules.sh QEMU kernel target modules build करता है, devtools/boot.sh guest shell देता है, और devtools/test-modules.sh हर module के लिए insmod·rmmod automated tests चलाता है
  • GDB debugging के लिए LKMPG_NO_PREBUILT=1 devtools/setup.sh से vmlinux build करने के बाद devtools/boot.sh --gdb और remote GDB connection का उपयोग किया जाता है

Kernel code लिखने के नियम

  • init function में registration/allocation fail हो सकते हैं, इसलिए acquired resources को goto-based error paths में reverse order में release करना चाहिए
  • Kernel में callback structure register करने पर user space init return से पहले भी callback call कर सकता है, इसलिए internal initialization पूरा करने के बाद सबसे आखिर में register करना और cleanup में सबसे पहले unregister करना—यानी register last, unregister first rule—महत्वपूर्ण है
  • process context, softirq/tasklet context, और hardirq context में sleep, user memory access, GFP_KERNEL, mutex use की availability अलग-अलग होती है; इस distinction को गलत समझना common kernel bugs का कारण बनता है

Devices और subsystem-specific cautions

  • Character devices driver को major number से identify करते हैं और driver के अंदर कई devices को minor number से अलग करते हैं; modern approach में register_chrdev() की तुलना में cdev interface recommended है
  • PCI driver fixed address assume नहीं करता, बल्कि PCI core द्वारा enumerated BAR resource को map करता है; Linux 5.10 के बाद के code में pcim_enable_device() और device-managed resource API teardown bugs कम करने में उपयोगी हैं
  • USB driver को hotplug और disconnect को normal events की तरह handle करना चाहिए, और design में यह मानकर चलना चाहिए कि URB completion और disconnect, timeout, suspend, userspace shutdown आपस में race कर सकते हैं
  • Block driver blk-mq, request, gendisk, queue limit, flush/FUA semantics के आधार पर काम करता है, और simple read/write callback नहीं बल्कि asynchronous request completion model में भाग लेता है
  • Network driver struct net_device, net_device_ops, sk_buff, NAPI, offload feature flag, link-state reporting से जुड़ा होता है; गलत offload declaration traffic corruption तक ले जा सकता है

Kernel version changes से निपटना

  • Examples Linux 6.4 में class_create() signature change, Linux v5.6 के proc_ops, Linux 6.11 में remove() return type change, और Linux 5.15~6.9 के बीच blk-mq helper changes को conditional compilation से handle करते हैं
  • Kernel internal interfaces system calls की तुलना में ज्यादा बार बदलते हैं, इसलिए multiple kernels support करने वाले modules के लिए LINUX_VERSION_CODE और KERNEL_VERSION comparisons से बचना मुश्किल है

Safety checkpoints

  • Kernel stack user space stack से काफी छोटा होता है और कई systems में 8 KiB या 16 KiB के आसपास हो सकता है, इसलिए बड़े arrays के लिए kmalloc()·kzalloc() का उपयोग करना चाहिए
  • copy_to_user() से user space में data भेजते समय padding सहित हर byte initialized होना चाहिए; ऐसा न होने पर kernel memory information leak हो सकता है
  • __kmalloc(), __list_add() जैसे double underscore से शुरू होने वाले APIs internal preconditions assume कर सकते हैं, इसलिए documentation जब तक न कहे, public wrapper को प्राथमिकता देनी चाहिए

छोड़ा गया scope

  • Input processing के दौरान कुछ original chunks length/cost limits के कारण छोड़े गए बताए गए हैं, इसलिए यह summary guide के सभी chapters, examples और code paths को पूरी तरह cover नहीं करती

1 टिप्पणियां

 
GN⁺ 2024-07-28
Hacker News की रायें
  • QEMU kernel hacking का अनुभव लेने का अच्छा तरीका है
    अच्छा होगा अगर कोई LDD(Linux Device Drivers) और Linux kernel की किताबों को अपडेट कर दे; ऐसी technical books से मुनाफा कमाना मुश्किल होता है, इसलिए Linux Foundation इसे sponsor करे तो भी अच्छा लगेगा

    • driver लिखने और QEMU में custom device बनाकर जोड़ने की प्रक्रिया पर थोड़ा लिखा हुआ एक लेख है: [0] https://blog.davidv.dev/posts/learning-pcie/, [1] https://blog.davidv.dev/posts/pcie-driver-dma/
    • virtme-ng https://github.com/arighi/virtme-ng इस्तेमाल करने पर QEMU में development वाला kernel boot करना वाकई आसान हो जाता है
    • console भी न होने वाली early-stage kernel debugging में QEMU का खूब उपयोग होता है
      इसी हफ्ते v6.8 में यह issue QEMU + GDB से reproduce किया कि arm64 kernel command-line parameter 146 characters से ज्यादा होने पर kernel तुरंत चुपचाप रुक जाता है; फिर Debian 12 Bookworm amd64 host पर arm64 kernel build emulate करके problem code को line-by-line follow करते हुए root cause ढूंढा
      flow यह है: build dependencies और cross-compile tools तैयार environment में arm64 kernel image और GDB के लिए script build करें, host पर gdb, जरूरत हो तो gdb-multiarch, और qemu-system-arm install करें, फिर qemu-system-aarch64 को -S -gdb tcp::1234 के साथ stopped state में launch करें और दूसरे terminal से gdb-multiarch ./vmlinux के जरिए attach करें
      इसके बाद GDB में target remote :1234, break __parse_cmdline, continue चलाने पर memory, variables, stack inspect करने और single-step execution जैसी सामान्य GDB सुविधाएं इस्तेमाल की जा सकती हैं
      kernel GDB debugging और lx-* scripts के लिए https://www.kernel.org/doc/html/latest/dev-tools/gdb-kernel-... देखें
      GDB को lx-* Python scripts इस्तेमाल कराने के लिए आम तौर पर echo "add-auto-load-safe-path ${SRC_DIR}/scripts/gdb/vmlinux-gdb.py" > ~/.gdbinit जैसी path अनुमति भी जरूरी होती है
    • अभी kernel में शामिल WireGuard test suite QEMU के साथ kernel module develop करने और automated tests तक आजमाने का अच्छा example है
    • Greg KH ने काफी साफ कहा है कि LDD 4th edition नहीं आएगा
  • संबंधित HN threads: https://news.ycombinator.com/item?id=35782630, https://news.ycombinator.com/item?id=28283030

  • The Linux Memory Manager भी देखने लायक है: https://linuxmemory.org/chapters
    लेखक ने जुलाई की शुरुआत में जो last update भेजा था, उसके मुताबिक first draft पूरा हो गया था और अब publisher के साथ editing phase में प्रवेश कर गया है

    • table of contents अच्छा दिखता है, लेकिन production support करने के लिए कोई pre-order नहीं है, यह अफसोस की बात है
  • कुछ examples सीधे चलाकर देखना मुश्किल लगते हैं
    जैसे “Detecting button presses” मानता है कि आप RPi के लिए module build कर सकते हैं, लेकिन यह अपने-आप में cross-compilation जैसे काम मांगता है, इसलिए आसान नहीं हो सकता

    • थोड़ा झंझट भरा सही, पर लगता है कि बस Raspberry Pi पर compiler चला दें तो हो जाना चाहिए
  • detailed और hands-on है, और तुरंत kernel module build कराकर दिखाने वाला tutorial होने के कारण बेहतरीन है

  • साथ में देखने लायक resource: https://0xax.gitbooks.io/linux-insides/content/index.html

  • filesystem या memory management जैसी Linux kernel programming overall कहां से देखनी चाहिए, यह जानना चाहता हूं
    बहुत पहले Robert Love की “Linux Kernel Development” थी, लेकिन लगता है अब वह update नहीं होती

  • इसे पहली बार पढ़े हुए करीब 22 साल हो गए :)