diff --git a/.gitignore b/.gitignore index 3755e51..4720a8b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ gitignore.* # Python trash. *.pyc __pycache__ +.venv # Accidents. /core diff --git a/38mbps-internet.html b/38mbps-internet.html index e66b631..6307e95 100644 --- a/38mbps-internet.html +++ b/38mbps-internet.html @@ -5,7 +5,7 @@ - + Linux Kernel Module Cheat + + + + + +
+
+
17.8.1.1. fops.c
+
+

This example illustrates the most basic system calls: open, read, write, close and lseek.

+
+ +
+

In it we create a debugfs special file that behaves like a regular file, except that it is stored in memory for as long as the kernel module is loaded, and it has a fixed lengh of 4 bytes. Any longer write attempt gets simply truncated up at the end:

+
+
+
+
./fops.sh
+echo $?
+
+
+
+

Outcome: the test passes:

+
+
+
+
0
+
+
+
+

Then give this a try:

+
+
+
+
sh -x ./fops.sh
+
+
+
+

We have put printks on each fop, so this allows you to see which system calls are being made for each command.

+
+ +
+ +
+
+ +
+ + + + + \ No newline at end of file diff --git a/fork-bomb.html b/fork-bomb.html index 596bc39..0454d1b 100644 --- a/fork-bomb.html +++ b/fork-bomb.html @@ -5,7 +5,7 @@ - + Linux Kernel Module Cheat + + + + + +
+
+
38.13.1.1. Linux worktree
+
+

If you are working with multiple Linux versions at once, it can be helpful to have their source code checked out all the time, in particular if you are going to be GDB step debugging.

+
+
+

We have some automation for that. Suppose that you are also interested in the kernel v6.14.4. Then you could do:

+
+
+
+
git -C submodules/linux worktree add ../../data/wt/linux/v6.14.4
+git -C data/wt/linux/v6.14.4 reset --hard v6.14.4
+
+
+
+

Then you can use a specific source for a specific Linux kernel build variants with:

+
+
+
+
./build-linux --linux-worktree v6.14.4 --linux-build-id v6.14.4
+./run --linux-build-id v6.14.4
+
+
+
+
    +
+
+
+ +
+ + + + + \ No newline at end of file diff --git a/list-of-gem5-cpu-types.html b/list-of-gem5-cpu-types.html index 58a9106..8c82e59 100644 --- a/list-of-gem5-cpu-types.html +++ b/list-of-gem5-cpu-types.html @@ -5,7 +5,7 @@ - + Linux Kernel Module Cheat + + + + + +
+
+
17.8.1.1.1. memfile.c
+
+

This example behaves the same as fops.c, except that the in-memory virtual file has unlimited size. In the kernel module we have therefore to so a bit of memory management and somehow increase the size of the buffer as needed.

+
+ +
+

TODO: this example builds but oopses with out of memory on our currently default kernel v5.9.2 when doing the big allocation at:

+
+
+
+
dd if=/dev/zero of="$f" bs=1k count=1M
+
+
+
+

It works however on kernel 6.8.12, we’re not sure why. We do have a potential krealloc vs kvrealloc on version check which is a very likely reason for the issue, but it has not been investigated.

+
+
+
    +
+
+
+ +
+ + + + + \ No newline at end of file diff --git a/memory-consistency.html b/memory-consistency.html index c7f78fd..cd7e72e 100644 --- a/memory-consistency.html +++ b/memory-consistency.html @@ -5,7 +5,7 @@ - + Linux Kernel Module Cheat + + + + + +
+
+

17.22.2. scull

+
+

This kernel module is a port of scull example from LDD3. It was tested on LKMC e1834763088b8a7532b5fae800039de880471f2d + 1 with Linux kernel 6.8.12.

+
+
+

"Scull" is an acronym for "Simple Character Utility for Loading Localities". This expansion is mostly meaningless however, but there you are.

+
+
+

Source code:

+
+ +
+

Create the devices and test them:

+
+
+
+
scull.sh
+
+
+
+

scull creates several character devices.

+
+
+

The most "basic" one is /dev/scull0, which acts a bit as an in-memory file, except that it has weird quantizations applied to it so that you can’t append as normal and it doesn’t really look like a regular file. What it actually is more like is an object pool.

+
+
+

The original scull interface is very weird and would erase all data on write-only O_WRONLY, but not on read/write O_RDWR, which doesn’t make much sense:

+
+
+
+
int scull_open(struct inode *inode, struct file *filp) {
+    if ( (filp->f_flags & O_ACCMODE) == O_WRONLY)
+        scull_trim(dev); /* ignore errors */
+
+
+
+

We have modified that to the much more reasonable:

+
+
+
+
	if ((filp->f_flags & O_TRUNC)) {
+
+
+
+

The old weird truncation condition makes the code hard to test as there is no way to write to two different blocks like it and keep them both in memory, unless you are able to find a CLI tool that supports O_RDWR or you write a C program to test things.

+
+
+

With our new inferface, we can differentiate clear all vs don’t clear all in the usual manner, e.g. this clears:

+
+
+
+
echo asdf > /dev/scull0
+
+
+
+

but this doesn’t:

+
+
+
+
echo asdf >> /dev/scull0
+
+
+
+

The examples from our test should make its weird behavior clearer e.g.:

+
+
+
+
# Append starts writing from the start of the 4k block, not like the usual semantic.
+printf asdf > "$f"
+printf qw >> "$f"
+[ "$(cat "$f")" = qwdf ]
+
+# Overwrite first clears everything, then writes to start of 4k block.
+printf asdf > /dev/${module}0
+printf qw > /dev/${module}0
+[ "$(cat "$f")" = qw ]
+
+# Read from the middle
+printf asdf > /dev/${module}0
+[ "$(dd if="$f" bs=1 count=2 skip=2 status=none)" = df ]
+
+# Write to the middle
+printf asdf > /dev/${module}0
+printf we | dd of="$f" bs=1 seek=1 conv=notrunc status=none
+[ "$(cat "$f")" = aqwf ]
+
+
+
+

It is also worth noting that the implementation of scull is meant to be "readable" but not optimal:

+
+
+
+
+

kmalloc is not the most efficient way to allocate large areas of memory (see Chapter 8), so the implementation chosen for scull is not a particularly smart one. The source code for a smart implementation would be more difficult to read, and the aim of this section is to show read and write, not memory management. That’s why the code just uses kmalloc and kfree without resorting to allocation of whole pages, although that approach would be more efficient.

+
+
+
+
+

Another shortcoming of the example is that it uses mutexes, where rwsem would be the clearly superior choice.

+
+
+

This module was derived from https://github.com/martinezjavier/ldd3/tree/30f801cd0157e8dfb41193f471dc00d8ca10239f/scull which had already ported it to much more recent kernel versions for us. Ideally we should just use that repo as a submodule, but we were lazy to setup the buildroot properly for now, and decided to dump it all into a single file to start with.

+
+
+
    +
+
+
+ +
+ + + + + \ No newline at end of file diff --git a/secondary-disk.html b/secondary-disk.html index 0081fe4..edeaebb 100644 --- a/secondary-disk.html +++ b/secondary-disk.html @@ -5,7 +5,7 @@ - + Linux Kernel Module Cheat