Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Criando seu primeiro módulo, Linux Kernel Camp #2

Criando seu primeiro módulo, Linux Kernel Camp #2

O grupo Linux Kernel Camp tem o objetivo de estudar o kernel do linux, o maior projeto de código aberto do mundo, realizando experimentos, incentivando os participantes a contribuir com o projeto e compartilhando o aprendizado com todos seus integrantes.

HackerSpace Blumenau

June 25, 2019
Tweet

More Decks by HackerSpace Blumenau

Other Decks in Technology

Transcript

  1. Agenda • Device Driver in Linux – What is –

    Types – Hello world! – Tracing
  2. What is • A software program that operates a hardware

    device • Knows the hardware intimately
  3. Types - Character • Stream oriented – Transfers characters •

    Audio devices • Video capture • Serial communications • Keyboard/mouse
  4. Types - Character • ‘c’ character in /dev files •

    ls -l /dev crw------- 1 root root 10, 223 Jun 21 08:26 uinput crw-rw-rw- 1 root root 1, 9 Jun 21 08:26 urandom
  5. Types - Block • Block oriented – Transfers fixed-size blocks,

    seekable • HDD/SSD • USB Sticks • CD-ROM
  6. Types - Block • ‘b’ character in /dev files •

    ls -l /dev • brw-rw---- 1 root disk 8, 0 Jun 21 08:26 sda • brw-rw---- 1 root disk 8, 1 Jun 21 08:26 sda1 • brw-rw---- 1 root disk 8, 2 Jun 21 08:26 sda2 • brw-rw---- 1 root disk 8, 3 Jun 24 00:42 sda3 • brw-rw---- 1 root disk 8, 16 Jun 21 08:26 sdb • brw-rw---- 1 root disk 8, 17 Jun 21 08:26 sdb1 • brw-rw---- 1 root disk 8, 18 Jun 21 08:26 sdb2
  7. Types - Network • Different from char and block –

    Don’t have a device file in /dev – Uses packet transmission, no read/write functions – Receives packets from outside asynchronously. There is no “request” as in block layer
  8. Hello World! cat hello.c #include <linux/module.h> static int __init hello_init(void)

    { pr_info("Module hello init\n"); return 0; } static void __exit hello_exit(void) { pr_info("Module hello exit\n"); } module_init(hello_init); module_exit(hello_exit);
  9. Hello World! • We can use virtme to virtualize the

    current system, in order to avoid a Kernel Panic while testing the driver: – virtme-run --installed-kernel • All tests can be done inside the instantiated VM • To exit the VM: – Ctrl-A + x
  10. Hello World! make -C /lib/modules/$(uname -r) M=$(pwd) modules • Files

    created: hello.c hello.ko hello.mod.c hello.mod.o hello.o Makefile modules.order Module.symvers • hello.ko: kernel object == module == device driver • To load the module: – insmod hello.ko
  11. Hello World! • dmesg – show kernel messages [ 1039.274297]

    hello: loading out-of-tree module taints kernel. [ 1039.274304] hello: module license 'unspecified' taints kernel. [ 1039.274306] Disabling lock debugging due to kernel taint [ 1039.274409] hello: module verification failed: signature and/or required key missing - tainting kernel [ 1039.274951] Module hello init
  12. Hello World! • lsmod – list kernel modules loaded lsmod

    | grep hello Module Size Used by hello 16384 0
  13. Hello World! • To remove a module: – rmmod hello

    • dmesg – [ 1292.741789] Module hello exit
  14. Hello World! • Implementation of a char device driver using

    misc interface – Easy to implement – Can show how real world is like – Creates a device file in /dev automatically – Work done with less code
  15. Hello World! #include <linux/fs.h> #include <linux/module.h> #include <linux/miscdevice.h> #define MODNAME

    "char_hello" static char *msg = "This is a message from Hello char driver!"; static bool debug; module_param(debug, bool, false); MODULE_PARM_DESC(debug, "Enable char_hello debugging"); static ssize_t char_read(struct file *filp, char __user *buffer, size_t len, loff_t *ppos) { if (debug) pr_info("len: %ld, ppos: %lld", len, *ppos); return simple_read_from_buffer(buffer, len, ppos, msg, strlen(msg)); } static struct file_operations hello_fops = { .read = char_read, }; static struct miscdevice hello_misc = { .minor = MISC_DYNAMIC_MINOR, .name = MODNAME, .fops = &hello_fops, }; module_misc_device(hello_misc);
  16. Hello World! • insmod char_hello.ko • Using bash to read

    the first 3 characters read -n3 out </dev/char_hello [ 97.309243] opened! echo $out Thi
  17. Hello World! • Using a custom program to test the

    driver, reading two characters per read – Shows how char drivers maintain the last read position
  18. Hello World! #include <err.h> #include <stdio.h> #include <fcntl.h> #include <unistd.h>

    static void read_fd(int fd) { int i = 0; char buf[50] = {0}; while (read(fd, buf + i, 2) > 0) { printf("buf: %s\n", buf); i += 2; } } int main(void) { int i = 2, fd; while (i--) { fd = open("/dev/char_hello", O_RDONLY); if (fd == -1) err(fd, "failed to open"); read_fd(fd); close(fd); } return 0; }
  19. Hello World! • ./test – buf: Th – buf: This

    – buf: This i – buf: This is – buf: This is a – buf: This is a me – ...
  20. Hello World! • How it works: – MAJOR:MINOR: ls -l

    /dev/char_hello crw------- 1 root root 10, 55 Jun 20 23:24 /dev/ char_hello – Major 10, Minor 55 • Used to find the correct driver to issue the operations (read in our test driver)
  21. Hello World! • How it works: – Major number 10

    is related to MISC modules – Minor is used by the driver only, it is the identifier of the “instance” driver
  22. Hello World! • How it works: – Userspace open /dev/char_hello

    • Kernel calls open method of char_hello driver – Using the fd returned by open, all read calls will call the read() method of char_hello
  23. Hello World! • How it works: – Strace is capable

    of showing how the program interacts with the kernel
  24. Hello World! • strace ./test execve("./test", ["./test"], 0x7ffc7e20e0c0 /* 10

    vars */) = 0 ... openat(AT_FDCWD, "/dev/char_hello", O_RDONLY) = 3 read(3, "Th", 2) = 2 fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x4, 0x40), ...}) = 0 ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0 brk(NULL) = 0x1ba7000 brk(0x1bc8000) = 0x1bc8000 write(1, "buf: Th\n", 8buf: Th ) = 8 read(3, "is", 2) = 2 write(1, "buf: This\n", 10buf: This ) = 10 read(3, " i", 2) = 2 write(1, "buf: This i\n", 12buf: This i ) = 12 read(3, "s ", 2) = 2 write(1, "buf: This is \n", 14buf: This is ) = 14 ...
  25. Summary • Device drivers are code compiled that is “attached”

    to the kernel. • Network device drivers are different from char and block ones. • Virtme is a good tool to test device drivers without crashing your system • strace can trace all interactions from a userspace with the kernel.
  26. Summary • Character device drivers are “simple” – it’s just

    a stream of bytes • Block device drivers are request based – Always working in blocks • It’s easy to interact with device drivers from userspace