Use memory isolation for OOT drivers

Updated at:

Out-of-Tree (OOT) drivers vary in quality and can introduce memory safety bugs such as use-after-free errors and out-of-bounds access. Memory isolation for OOT drivers confines each driver to its own dedicated slab pool, so that corrupted memory cannot be allocated to other kernel modules. When a memory bug occurs, the blast radius is contained to the driver's isolated pool, which speeds up root-cause analysis and reduces business impact.

Limits

CategoryLimit
Supported OSAlibaba Cloud Linux 3, kernel version 5.10.134-17.al8 or later
Supported memory range8 bytes–8 KB of KMALLOC_NORMAL memory per allocation
Maximum isolated drivers16 OOT drivers

The following allocation functions support memory isolation:

  • kmalloc, kzalloc

  • kmalloc_node, kzalloc_node

  • kmalloc_array, kmalloc_array_node

  • kcalloc, kcalloc_node

Prerequisites

Before you begin, ensure that you have:

  • Root (sudo) access on the instance

  • Alibaba Cloud Linux 3 with kernel version 5.10.134-17.al8 or later (run uname -r to check)

  • The names of the OOT modules to isolate

Configure memory isolation for OOT drivers

Two methods are available. Choose based on whether the configuration must survive a restart.

MethodPersistent after restartRequires restart
Kernel command line (grubby)YesYes
sysfs echoNoNo

Method 1: Kernel command line (persistent)

This method writes the configuration to the boot parameters. It persists across restarts.

  1. Add the module.oot_list parameter to the kernel command line. Replace <OOT module 1>,<OOT module 2> with the actual module names, separated by commas.

    sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="module.oot_list=<OOT module 1>,<OOT module 2>"
  2. Restart the instance for the change to take effect.

    Warning

    Restarting stops the instance briefly and may interrupt running services. Back up critical data before restarting, and schedule the restart during off-peak hours.

    sudo reboot
  3. After the instance restarts, verify the configuration.

    dmesg | grep "oot-kmalloc"

    For each isolated module, a line similar to the following appears in the kernel log:

    Module <Module name> use oot-kmalloc-<index>.

    The <index> value identifies the separate slab allocated to that module. Record this value — you need it to configure cache limits and to enable KFENCE monitoring.

Method 2: sysfs echo (not persistent)

This method takes effect immediately without a restart. The configuration is lost when the instance restarts. To re-apply it after a restart, reload the OOT modules again.

  1. Write the module list to the oot_list parameter file. Replace <OOT module 1>,<OOT module 2> with the actual module names, separated by commas.

    sudo sh -c 'echo <OOT module 1>,<OOT module 2> > /sys/module/module/parameters/oot_list'
  2. Reload each OOT module for the isolation to take effect. Replace <OOT module> with the actual module name.

    rmmod <OOT module>.ko
    insmod <OOT module>.ko
  3. Verify the configuration.

    dmesg | grep "oot-kmalloc"

    For each isolated module, a line similar to the following appears in the kernel log:

    Module <Module name> use oot-kmalloc-<index>.

    Record the <index> value — you need it to configure cache limits and to enable KFENCE monitoring.

Manage memory overhead

Memory pages used by an OOT driver are treated as dirty memory. By default, these pages are cached for reuse by the same driver and are not returned to the buddy allocator, which can increase memory overhead. Use the following methods to inspect and control this behavior.

Set the cache limit via the kernel command line (persistent)

  1. Get the slab size. The slab size ranges from 8 B to 8 KB.

    sudo cat /proc/slabinfo
  2. Get the order value for the target slab. Replace <index> and <size> with the values from the previous step.

    cat /sys/kernel/slab/oot-kmalloc-<index>-<size>/order
  3. Set the cache limit. Replace <limit> with the maximum number of cache units. The unit is 2^order pages. For example, with <limit>=100 and order=2, the limit is 100 × 2² = 400 pages.

    sudo grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="module.oot_page_limit=<limit>"

Set the cache limit at runtime (not persistent)

  1. Get the slab size. The slab size ranges from 8 B to 8 KB.

    sudo cat /proc/slabinfo
  2. Get the order value for the target slab. Replace <index> and <size> with the values from the previous step.

    cat /sys/kernel/slab/oot-kmalloc-<index>-<size>/order
  3. Set the cache limit. Replace <limit> with the maximum number of cache units. The unit is 2^order pages.

    sudo sh -c 'echo <limit> > /sys/module/module/parameters/oot_page_limit'

View the current unit pages of a slab

  1. Get the slab size.

    sudo cat /proc/slabinfo
  2. Read the oot_page value for the target slab. Replace <index> and <size> with actual values.

    cat /sys/kernel/slab/oot-kmalloc-<index>-<size>/oot_page

Enable KFENCE to monitor a specific OOT slab

OOT drivers each use a dedicated slab. Kernel Electric-Fence (KFENCE) can monitor a specific slab to detect out-of-bounds reads and writes.

By default, KFENCE samples across all slabs randomly, which does not guarantee coverage of any particular OOT slab. The procedure below disables global KFENCE sampling and enables it only for the target slab, giving deterministic coverage of that driver's allocations.

For background on KFENCE, see Use KFENCE to detect kernel memory pollution.

# Disable KFENCE for all slabs
for file in /sys/kernel/slab/*
do
    sudo sh -c 'echo 0 > $file/kfence_enable'
done

# Disable KFENCE for order0 pages
sudo sh -c 'echo 0 > /sys/module/kfence/parameters/order0_page'

# Enable KFENCE for the target OOT slab
# Replace <index> and <size> with the values from your dmesg output
sudo sh -c 'echo 1 > /sys/kernel/slab/oot-kmalloc-<index>-<size>/kfence_enable'

FAQ

Why does the "no symbol version for __kmalloc/__kmalloc_node/kmalloc_caches" error appear?

This message appears the first time a memory-isolated OOT module is loaded, and only once. It is not an error — you can ignore it.

The message occurs because memory isolation redirects __kmalloc to a driver-specific symbol (oot___kmalloc) without modifying the module's compiled binary. When the kernel loads the module, it finds __kmalloc in the module's undefined symbol table but verifies the cyclic redundancy check (CRC) against oot___kmalloc. The name mismatch causes the CRC check to fail with this message. Because kernel APIs built on __kmalloc are stable, this mismatch has no functional impact.

What's next