Skip to content

Basic kernel-mode module and a user-mode application that interacts with it.

Notifications You must be signed in to change notification settings

ralienpp/hello-kernel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Overview

This is a basic kernel module that implements the following features:

  • entry point for loading and unloading the kernel module
  • debug statements that can be observed with dmesg
  • optionally transmitting a parameter, magic, when the module is loaded (otherwise a default value is used)
  • creation of a character device, /dev/oracle (mknod must be invoked manually for now)
  • implements the read API, which takes the current value of magic and copies it from the kernel to the user-space buffer
  • reacts to any ioctl sent to the module by incrementing magic

Instructions

This was tested on Debian 7 x64.

Prerequisites

This only needs to be done once, to prepare the compilation environment.

  • sudo apt-get install build-essentials
  • sudo apt-get install linux-headers-$(uname -r)

It is expected that you already have Python, it will be needed for the user-mode program to test ioctl handling.

Compilation

Get into the directory where you cloned the git repo and run make. The output will be stored in hellok.ko.

  1. git clone https://github.com/ralienpp/hello-kernel.git
  2. cd hello-kernel
  3. make

Basic test

You can make sure this loads and unloads correctly as follows:

  1. sudo insmod ./hellok.ko

  2. run lsmod and it should be in the list of loaded modules, e.g.

    Module                  Size  Used by
    hellok                 12452  0
    
  3. unload it with sudo rmmod hellok

  4. run dmesg to see what has just happened, the debug lines should be there:

    [73964.820487] hellok: module license 'unspecified' taints kernel.
    [73964.820492] Disabling lock debugging due to kernel taint
    [74342.727012] Loaded hellok
    [74469.278069] Unloaded hellok
    

Notes on parameters

  • You can pass a parameter at load time, e.g. sudo insmod ./hellok.ko magic=12. If not specified, a default value will be used.
  • The value can be examined after the module is loaded: cat /sys/module/hellok/parameters/magic
  • You can write to it (if permissions allow so), e.g. (as root) echo 45 > /sys/module/hellok/parameters/magic

Character-device operations

To check if the devices was created successfully, run cat /proc/devices and expect something like this:

Character devices:
100 Oracle

The number is the MAJOR defined in the code, and the name is the string we used to name the device.

Before you can interact with this device, run sudo mknod -m 666 /dev/oracle c 100 0 (create a character device, allowing everyone to do everything with it, 100 is MAJOR as defined in the code, and 0 is the minor [taken "as is" from a guide]).

User-mode tool

To demonstrate communication between kernel-space and user-space, you can run cat /dev/oracle and the value of magic will be shown on the screen as a string.

This happens by copying this value from a buffer in the kernel's address space, into a buffer in user-space, using copy_to_user.

Alternatively, run python testusermode.py, which will send an ioctl to /dev/oracle (the driver doesn't care what command is sent, they're all handled equally). You can observe the effect by reading from /dev/oracle, the read value should be incremeted after each ioctl call.

References

Questions

  1. why static? Other tutorials don't have that.
  2. what is the point of having major and minor versions?
  3. can mknod be invoked automatically?
  4. cat never stops, should I add an EOF at the end? (does stop when run as root, strange)
  5. #define ENOTTY 25 /* Not a typewriter */ why can't my character device handle this?
  6. what is a safe way to avoid MAJOR collisions?

Note to self

  • use %zu for size_t in debug statements

Reasoning

  • ioctl is used because I was aware of this concept earlier and expected it to be easier. After reading more about it while implementing it, I found it convenient that I can send a void payload, and use the presence of the message itself as a signal, which is sufficient for the purposes of this prototype. Otherwise, the benefit of the ioctl is that it provides the possibility to send arbitrary payloads, which may be handy in the future.
  • clearly, the communication done via /sys/module/hellok/parameters/magic is another form of interaction between kernel-space and user-space, which is not an ioctl and which appears to be a much simpler/cheaper method, because I got it "for free" (no need to write a handler for it).
  • when it comes to user-space, the "cheapest" way to prove it works is to read from /dev/oracle with any existing tool, thus there's no need to write any code at all.
  • however, I also wrote a Python program in order to check how the ioctl handler works. I used this language because it was much easier to write in, and I was thinking that if there were implementation issues it would be easier to debug them using the REPL. However, due to the simplicity of the current driver, there's not much room for something not to work.

About

Basic kernel-mode module and a user-mode application that interacts with it.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published