Code Monkey home page Code Monkey logo

lkm-sandbox's Introduction

Linux Kernel Module (LKM) Sandbox

Build Status

Modules / Building / Make / Testing / PoC / Rehearsal / Notes / Disclaimer / License / Books / Links

The Linux Kernel Module (LKM) Sandbox is a collection of different modules to learn, discover and experiment with the development of Linux Kernel Modules. The purpose of this repository is also to practice development within the Linux Kernel and study miscellaneous concepts before moving on to submit the very first patch to the kernel.

Most of the modules illustrate one concept and show how to use the Kernel API. A few of the modules combine more than one concept to present how concepts are working together. For example the module lkm_device is accessing a character device and storing its major number in /proc. Or the module lkm_mem is exposing memory/swap information by files in /proc as well.

I hope it can be valuable for other developers which try to approach the Linux Kernel.

No. Module Source Description
1 LKM DebugFS lkm_debugfs.c Module showing how to use the debugging filesystem debugfs
2 LKM Device lkm_device.c Module showing how to operate with character devices and storing device information in /proc
3 LKM Device Numbers lkm_device_numbers.c Illustrating statically and dynamically allocated device numbers
3 LKM Memory lkm_mem.c Module exposing memory and swap information to /proc
4 LKM Memory-based Device lkm_mev.c Driver for a memory-based character device, based to some degree on scull, developed in the book Linux Device Drivers, Chapter 3
5 LKM Parameters lkm_parameters.c Module for passing parameters from user- to kernelspace
6 LKM Pretty Printk lkm_pp.c Module for testing integration of pretty-printk
7 LKM Proc lkm_proc.c Module accessing /proc filesystem using sequential I/O
8 LKM Process lkm_process.c Accessing and printing current process information
9 LKM Sandbox lkm_sandbox.c Sandbox module for different experiments
10 LKM Skeleton lkm_skeleton.c Skeleton module for faster scaffolding of new modules

When cloning for the first time, please clone also submodules with --recurse-submodules to get pretty-printk as well.

git clone --recurse-submodules [email protected]:tpiekarski/lkm-sandbox.git
make clean && make

Screenshots of make

To run all available tests, including basic loading/unloading and all additional concept tests..

make test

Testing by loading, unloading and outputting Kernel Ring Buffer (sudo will ask for root permissions).

make test-module name=<module-name>

Additional tests for the sandbox device including loading module, gathering major device number from /proc, creating device and comparing the final message either run the Makefile target with make test-device or run the following commands.

For creating character device the major number is needed and can be obtained by catting the file /proc/lkm_device_major. This major number is written to the Kernel Ring Buffer as well. It is possible to provide this major number using the module parameter param_major_num and load this module like sudo insmod lkm_device.ko param_major_num=241 (At this moment this static allocation seems not to work reliable. The registration of the sandbox device fails sometimes. It was tried with a major of -16 when registration fails and the operation is not permitted like that - the reason is unknown.)

sudo insmod lkm_device.ko
dmesg | grep "Registered sandbox device"
sudo mknod /dev/lkm_device c $(cat /proc/lkm_device_major) 0
test -c /dev/lkm_device && cat /dev/lkm_device || echo "Device /dev/lkm_device" not found."
sudo rmmod lkm_device

Additional tests for sandbox access to /proc including loading module, testing if file inside /proc exists and outputting that file. Either run the Makefile target test-proc with make test-proc or the following few commands:

sudo insmod lkm_proc.ko
test -f /proc/lkm_proc && cat /proc/lkm_proc || echo "File /proc/lkm_proc not found."
sudo rmmod lkm_proc

For additional tests for passing parameters to module lkm_parameters run the Makefile target test-parameter with make test-parameters. This will load/unload the module and compare the parameters number and message passed when loading the module with the values read in the /sys filesystem (/sys/module/lkm_parameters/parameters/*). Or run the following commands.

sudo insmod lkm_parameters.ko number=33 message=\"Some message...\"
cat /sys/module/lkm_parameters/parameters/number
cat /sys/module/lkm_parameters/parameters/message
sudo rmmod lkm_parameters

While triaging, debugging and working with bugs and issues it can come in handy to experiment with some code and write a PoC to prove some statements or to answer a question. In the following are a collection of such PoC which follow up on a lead to prove statements, ideas and questions I recently came across.

File Description Motivation
comparing-iopl-ioperm.c Comparing I/O Permissions granted by iopl and ioperm Bug 205317 - iopl(2) - privilege level is set per-process or per-thread?
permissions-revisited.c How are I/O Permissions granted when using clone, fork, execve or pthread? Bug 205317 - iopl(2) - privilege level is set per-process or per-thread?

For a better understanding of concepts in the kernelspace it is necessary to review and rehearse fundamental basics of C and the standard library. Next to being able to improve understanding it is possible to compare approaches. Most of those basics are low-level, starting with file I/O and can be looked through as a companion source. It is never bad to rehearse things, but sometimes a little embarrassing to admit having to rehearse such things :)

File Concept
clone.c Cloning processes with clone()
execve.c Executing another process with execve()
fork.c Creating child process with fork()
io_ports.c Low-level port-mapped I/O operations
read.c Reading of files in vanilla C
simple_circular_buffer.c Simple and straight forward circular buffer
write.c Writing/Appending to files in vanilla C

To build those files just run make clean && make in ./rehearsals/ and all executables will be placed in the build directory.

"A Linux kernel module is a piece of compiled binary code that is inserted directly into the Linux kernel, running at ring 0, the lowest and least protected ring of execution in the x86–64 processor."

"Traditional application development paradigms can be largely discarded. Other than loading and unloading of your module, you’ll be writing code that responds to system events rather than operates in a sequential pattern."

"With kernel development, you’re writing APIs, not applications themselves."

This repository will ask you for root permission, because certain operations like loading/unloading modules and accessing files in the Linux/GNU System depends on root privileges. The Makefile will state beforehand for what these permissions will be used.

You can review all this operations by searching this repository for sudo and be sure that this won't be misused in any way. I am aware of that this can be a security issue, but I am trying to make this process as much transparent as possible. But be also aware that these modules are coming without any warranty. Kernel panics and data loss can happen, please use them preferably inside a Virtual Machine.

Use of sudo

In the following is a table with all locations where sudo is used (except the README.md).

grep -n -r "sudo" *
File:Line Use of sudo
Makefile:118 $(call test_file_exists,$(number_file),"-r", "sudo")
Makefile:119 $(eval number_file_content = sudo cat $(number_file))
Makefile:122 $(eval message_file_content = `sudo cat $(message_file)
Makefile:123 $(call test_file_exists,$(message_file),"-r", "sudo")
Makefile:126 @sudo rmmod $(module_filename)
Makefile:140 @sudo mknod $(device_filename) c cat $(proc_filename) 0
Makefile:143 @sudo rm $(device_filename)
Makefile:144 @sudo rmmod $(module_filename)
Makefile:162 @sudo rmmod $(module_filename)
Makefile:175 @sudo mknod $(device_file) c $(major) 0
Makefile:176 @echo "Testing" | sudo tee $(device_file)
Makefile:178 @sudo rm -fv $(device_file)
Makefile:179 @sudo rmmod $(module)
Makefile:190 @sudo insmod $(module).ko number=$(number) message="$(message)"
Makefile:193 @sudo rmmod $(module)
Makefile:207 @sudo rmmod ${module}
Makefile:219 @sudo insmod $(module).ko
Makefile:222 @sudo rmmod $(module)
tests.mk:31 @lsmod | awk '{print $$1}' | grep -qE "^$(1)$$" && (sudo rmmod $(1) &amp;&amp; sudo insmod $(1).ko) || sudo insmod $(1).ko
tests.mk:75 @sudo dmesg --clear
tests.mk:78 @sudo rmmod $(1)

LKM Sandbox is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.

LKM Sandbox is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with LKM Sandbox. If not, see https://www.gnu.org/licenses/.

lkm-sandbox's People

Contributors

tpiekarski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

lkm-sandbox's Issues

Create a random quote device

Create a random quote device

Like MOTD (Message of the day) a device like /dev/quote should randomized output one quote.

$ cat /dev/quote
Lorem ipsum dolor hic amet...

Concepts

  • Basic I/O with a character device (rehearsal)
  • Handling arrays of characters within C (rehearsal)
  • Randomize data the kernel way (new)
  • Access to external files from the kernel (new)
  • Exchange between kernel- and userspace (rehearsal)
  • Testing randomness (rehearsal)

Create a Makefile target to test lkm_device

Create a target for testing lkm_device with following steps:

  • Load module
  • Identify device major
  • Create device file in /device using previously identified major
  • Read a few messages from /device
  • Delete device file
  • Unload module

Create an auxiliary script to keep the sudo listing updated

Create an auxiliary script to keep the sudo listing updated

With solving #33 there have been introduced a listing of all file locations where sudo is used. This list has to be kept updated (preferably with a git hook which is running prior to every commit).

Create a memory-based character device

Create a memory-based character device

To deepen knowledge about file input/output at kernel level create a module offering a memory-based character device.

Concepts

  • Device major/minor numbers and allocation
  • Introduction to structures like file and inode
  • Registration of devices

Reference

  • Linux Device Drivers, Chapter 3 about character devices. The module lkm_mev will be based to some varying degree upon scull

Integrate pretty-printk

Integrate pretty-printk and use it to printk information to the Kernel Ring Buffer in a test module.

  • Integration via a git submodule (packaging is not worth the hassle, no other packages would be used in Linux Kernel Development anyway)
  • pdump won't be used at the moment (Makefile and build-process have to be changed)

Add security-related disclaimer for use of sudo

Add security-related disclaimer for use of sudo

Dropping by, cloning repository at github and then running make which asks you for credentials to become root is, well... can be scary.

In the Makefile it is already the message Root permissions are needed for loading/unloading module with insmod/rmmod and creating device with mknod, but is this enough? Add also an explanation into README.md which should state the reason and mention possible data loss and crashes due to the nature of this sandbox repository learning Linux Kernel Development.

Best would be to integrate something like kvm or qemu into the test targets to avoid having the itch becoming root.

Integrate Testing Pipelines like AppVeyor or Travis

Integrate Testing Pipelines

Check if and how it could be possible to integrate AppVeyor or Travis CI and consider rewriting test targets accordingly.

The test piple should be able to compile all modules and run all present test targets in the Makefile. Next steps could be to take a look at kunit - unit testing kernel stuff 😄

Add function name to the prefix for all printks

Add function name to the prefix for all printks

All calls to printk should be additionally contain the function name by using pre-processor macro.

The final prefix should look like module_foo/function_bar:. It'll improve hopefully tracking things and knowing when what is happening in the kernel.

Also the snippets for Visual Studio Code should be updated as well.

Split memory information in /proc/meminfo in a new sandbox module

Splitting Memory Information

Split current /proc/meminfo into separate files into /proc/mem/* and /proc/swap/* with the following schema. This memory information should be a module with optional arguments for how to display those values (i.e. bytes, kilobytes, megabytes). Add probably an auxiliary program to convert this values like done in /fs/proc/meminfo.c.

/proc/mem

  • total
  • free
  • available
  • buffers
  • cached

/proc/swap

  • total
  • free
  • cached

Links

Access and output of current process information

Character device for output of current process information

Get hold of current process information like PID and name and expose those as a character device /dev/process with a constant stream of process data.

Possible output:
<pid>: <comm> (<parent:comm>)\n

Concepts

  • Creating and using character devices (rehearsal)
  • Accessing current process information
  • Working with struct task_struct

References and Links

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.