# Building a Simple Linux Kernel Object Cache with the SLAB Allocator: From Module Signing to Cleanup


# Building a Simple Linux Kernel Object Cache Using SLAB Allocator

Linux kernel development is very different from user-space programming.

In user space, developers typically use:

```c
malloc();
free();
```

Inside the kernel, memory allocation is handled using specialized allocators such as:

```c
kmalloc();
kfree();
```

and for frequently created kernel objects:

```c
kmem_cache_alloc();
kmem_cache_free();
```

In this article we build and load a simple kernel module that implements a tiny caching layer using the Linux SLAB allocator and then walk through module signing, loading, debugging, and cleanup.

Source Repository:

[GitHub Repository](https://github.com/aj333git/linux_kernel_kobjex2?utm_source=chatgpt.com)

---

# Why Object Caches Exist

Many kernel subsystems repeatedly allocate and destroy the same type of object.

Examples include:

- Inodes
- Dentries
- Socket buffers
- Process-related structures

Allocating these structures from a dedicated cache is usually faster than repeatedly requesting generic memory blocks.

The SLAB allocator provides:

- Object reuse
- Better cache locality
- Reduced fragmentation
- Optional constructors
- Faster allocation for hot objects

---

# High-Level Architecture

Our module creates a cache of objects and maintains them in a linked list.

## Architecture Diagram

```text
                 +------------------+
                 |  SLAB CACHE      |
                 | kmem_cache       |
                 +--------+---------+
                          |
          +---------------+--------------+
          |                              |
          v                              v

     cache_obj                     cache_obj
    +---------+                   +---------+
    | id = 1  |----next---------> | id = 2  |
    | alpha   |                   | beta    |
    +---------+                   +---------+

          Linked List of Objects
```

---

# The Cache Object

Each object stored inside the cache contains:

```c
struct cache_obj {
        int id;
        char name[32];
        unsigned long created;
        struct list_head list;
};
```

Each object stores:

| Field | Purpose |
|---------|---------|
| id | Unique identifier |
| name | Human readable label |
| created | Creation timestamp |
| list | Kernel linked-list node |

---

# Why Not Use kmalloc()

A beginner may wonder:

```c
obj = kmalloc(sizeof(*obj), GFP_KERNEL);
```

Why create a cache at all?

Because the allocator only sees:

```text
Allocate 64 bytes
Allocate 64 bytes
Allocate 64 bytes
```

It does not know these are identical objects.

SLAB caches know exactly what object type is being allocated.

```text
Give me cache_obj
Give me cache_obj
Give me cache_obj
```

This enables object reuse.

---

# kmalloc() vs kmem_cache_alloc()

| Feature | kmalloc() | kmem_cache_alloc() |
|----------|-----------|--------------------|
| Generic allocator | Yes | No |
| Object aware | No | Yes |
| Reuse objects | Limited | Yes |
| Constructor support | No | Yes |
| Best for buffers | Yes | No |
| Best for kernel objects | No | Yes |

---

# Memory Allocation Flow

## kmalloc()

```text
Request
   |
   v
Allocate N Bytes
   |
   v
Return Pointer
```

## kmem_cache_alloc()

```text
Request Object
      |
      v

+------------------+
|     SLAB CACHE   |
|                  |
| free object      |
| free object      |
| free object      |
+---------+--------+
          |
          v

Return Prepared Object
```

---

# Creating a Cache

A cache is created during module initialization.

Example:

```c
cachep = kmem_cache_create(
            "cache_obj",
            sizeof(struct cache_obj),
            0,
            0,
            NULL);
```

Parameters:

```text
Name         : cache_obj
Object Size  : sizeof(cache_obj)
Alignment    : default
Flags        : none
Constructor  : NULL
```

After creation the cache can hand out objects very quickly.

---

# Allocating Objects

Objects are allocated from the cache.

```c
obj = kmem_cache_alloc(cachep, GFP_KERNEL);

if (!obj)
        return -ENOMEM;
```

The NULL check is mandatory.

Without it:

```c
obj->id = 1;
```

could become:

```c
NULL->id = 1;
```

leading to:

```text
BUG: kernel NULL pointer dereference
```

---

# Understanding -ENOMEM

```c
if (!obj)
        return -ENOMEM;
```

Meaning:

```text
Memory allocation failed.

Stop execution and notify caller that
the system is out of memory.
```

Common kernel error codes:

```c
-ENOMEM   // Out of memory
-EINVAL   // Invalid argument
-EFAULT   // Invalid address
-EBUSY    // Resource busy
```

---

# Linking Objects Together

The kernel provides a generic linked-list implementation.

Example:

```text
alpha --> beta --> gamma
```

Visualization:

```text
+-------+      +-------+      +-------+
| alpha | ---> | beta  | ---> | gamma |
+-------+      +-------+      +-------+
```

This avoids writing custom linked-list code.

---

# Building the Module

Compile:

```bash
make
```

Expected output:

```text
CC [M] simple_cache.o
LD [M] simple_cache.ko
```

The generated file:

```text
simple_cache.ko
```

is a loadable kernel module.

---

# Why Module Signing Matters

Modern Linux distributions often enable Secure Boot.

Unsigned modules may fail to load.

Flow:

```text
Kernel Module
      |
      v
 Module Signature
      |
      v
 Secure Boot Validation
      |
      v
 Load or Reject
```

---

# Signing the Kernel Module

Sign the module using the kernel's signing utility.

```bash
sudo /usr/src/linux-headers-$(uname -r)/scripts/sign-file \
sha256 \
~/kernel_keys/MOK.key \
~/kernel_keys/MOK.crt \
simple_cache.ko
```

Explanation:

| Component | Purpose |
|------------|----------|
| sign-file | Kernel signing utility |
| sha256 | Digest algorithm |
| MOK.key | Private key |
| MOK.crt | Public certificate |
| simple_cache.ko | Module being signed |

---

# Loading the Module

Insert the module:

```bash
sudo insmod simple_cache.ko
```

Initialization sequence:

```text
Module Load
      |
      v
Create SLAB Cache
      |
      v
Allocate Objects
      |
      v
Insert Into Linked List
      |
      v
Print Kernel Logs
```

---

# Monitoring Kernel Messages

Open a live kernel log viewer.

```bash
dmesg -w
```

Expected output:

```text
CACHE: created 1 alpha
CACHE: created 2 beta
```

Architecture:

```text
Kernel Module
      |
      v
 printk()
      |
      v
 Kernel Ring Buffer
      |
      v
    dmesg
```

---

# Cleaning Up

Remove the module.

```bash
sudo rmmod simple_cache
```

Cleanup sequence:

```text
Delete Objects
      |
      v
Free Objects
      |
      v
Destroy Cache
      |
      v
Module Exit
```

---

# Correct Memory Pairing

Always pair allocation and free APIs correctly.

Correct:

```c
ptr = kmalloc(size, GFP_KERNEL);
kfree(ptr);
```

Correct:

```c
obj = kmem_cache_alloc(cachep, GFP_KERNEL);
kmem_cache_free(cachep, obj);
```

Incorrect:

```c
obj = kmem_cache_alloc(cachep, GFP_KERNEL);
kfree(obj);
```

Incorrect:

```c
ptr = kmalloc(size, GFP_KERNEL);
kmem_cache_free(cachep, ptr);
```

Mixing allocators can corrupt kernel memory.

---

# Real Kernel Components Using SLAB

Many core Linux subsystems depend heavily on slab caches.

Examples:

```text
inode cache
dentry cache
socket buffers
VFS metadata
network objects
task structures
```

Our module is a miniature version of the same concept.

---

# Complete Execution Flow

```text
make
 |
 v

simple_cache.ko
 |
 v

sign-file
 |
 v

Signed Module
 |
 v

insmod
 |
 v

Create SLAB Cache
 |
 v

Allocate Objects
 |
 v

Store in Linked List
 |
 v

Observe via dmesg
 |
 v

rmmod
 |
 v

Free Objects
 |
 v

Destroy Cache
```

---

# Key Takeaways

- `kmalloc()` is a generic kernel allocator.
- `kmem_cache_alloc()` is optimized for repeatedly used object types.
- SLAB caches improve performance and memory locality.
- Always check allocation failures.
- Pair allocation and deallocation APIs correctly.
- Module signing is required on many Secure Boot systems.
- `dmesg -w` is invaluable when debugging kernel modules.
- Proper cleanup is mandatory inside kernel code.

---

# References

Linux Kernel Documentation

- Memory Management
- SLAB Allocator
- Loadable Kernel Modules

Repository:

https://github.com/aj333git/linux_kernel_kobjex2



* * *

**Footer**

Source code and experiments are available in the repository: https://github.com/aj333git/linux\_kernel\_kobjex2

Based on the kernel object cache concepts and notes provided in your source material.
