funwithlinux guide

How to Patch a Kernel: A Step-by-Step Guide

The Linux kernel is the core of the operating system, managing hardware resources, process scheduling, and system security. Over time, developers release patches to fix bugs, address security vulnerabilities, add new features, or improve hardware compatibility. Patching the kernel allows you to update your system without upgrading the entire kernel version, which is especially useful for maintaining stability in production environments or adding custom functionality. This guide will walk you through the process of patching a Linux kernel, from understanding what a patch is to testing the modified kernel. Whether you’re a system administrator, developer, or enthusiast, you’ll learn the tools, workflows, and best practices to safely apply kernel patches.

Table of Contents

  1. Prerequisites
  2. Understanding Kernel Patches
  3. Step-by-Step Guide to Patching the Kernel
  4. Testing the Patched Kernel
  5. Troubleshooting Common Issues
  6. Conclusion
  7. References

Prerequisites

Before starting, ensure you have the following:

  • A Linux System: This guide assumes a Debian/Ubuntu-based distribution, but the steps are adaptable to others (e.g., Fedora, Arch).
  • Root/Sudo Access: Kernel patching requires administrative privileges.
  • Hardware Resources: At least 10GB of free disk space, 4GB+ RAM, and a multi-core CPU (compiling the kernel is CPU-intensive).
  • Essential Tools: Install build dependencies with:
    sudo apt update && sudo apt install -y build-essential libncurses-dev bison flex libssl-dev libelf-dev git  
  • Backup: Always back up critical data (e.g., /boot, /lib/modules) before modifying the kernel.

Understanding Kernel Patches

A kernel patch is a text file containing differences between the original kernel source code and the modified version. It is generated using tools like diff and applied with patch or Git. Patches come in various types:

  • Security Patches: Fix vulnerabilities (e.g., CVEs like Spectre/Meltdown).
  • Bugfix Patches: Resolve stability or functionality issues.
  • Feature Patches: Add new hardware support or system calls.
  • Custom Patches: User-generated modifications (e.g., for embedded systems).

Patches are typically distributed as .patch files and must be compatible with your kernel version. Always verify the patch’s target version (e.g., linux-5.15.0) matches your source tree.

Step-by-Step Guide to Patching the Kernel

Step 1: Identify Your Current Kernel Version

First, check your running kernel version to ensure compatibility with the patch:

uname -r  

Example output: 5.15.0-78-generic

Note the version (e.g., 5.15.0)—you’ll need this to fetch the correct source code.

Step 2: Obtain the Kernel Source Code

You need the unmodified source code corresponding to your kernel version. Use one of these methods:

Option 1: From Distribution Repositories

Debian/Ubuntu users can fetch the source via apt:

sudo apt source linux-image-$(uname -r)  

This downloads the source to a directory like linux-5.15.0 in your current folder.

Option 2: From Kernel.org (Git)

For upstream kernels, clone the official Git repository and check out your version:

git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/  
cd linux  
git checkout v5.15.0  # Replace with your kernel version  

Step 3: Download the Patch File

Obtain the patch from a trusted source:

  • Kernel.org: Security patches are in the stable tree.
  • Distribution Portals: Ubuntu’s Launchpad, Fedora’s Koji.
  • Mailing Lists: Linux Kernel Mailing List (LKML) or project-specific lists (e.g., linux-wireless).

Save the patch as my-patch.patch in the kernel source directory.

Step 4: Prepare the Source Tree

Navigate to the kernel source directory:

cd linux-5.15.0  # Replace with your source folder  

If using Git, ensure the tree is clean (no uncommitted changes):

git status  # Should show "nothing to commit"  

Step 5: Apply the Patch

Use the patch command to apply the patch. The -p1 flag strips the leading directory from file paths in the patch (adjust -p if needed):

patch -p1 < ../my-patch.patch  # Path to your .patch file  

Key Options:

  • --dry-run: Test the patch without applying it:
    patch -p1 --dry-run < ../my-patch.patch  
  • -R: Reverse a previously applied patch (if needed).

Handling Conflicts:

If you see Hunk #1 FAILED at 123, the patch conflicts with your source. Resolve conflicts manually:

  1. Open the conflicting file (e.g., drivers/net/ethernet/intel/e1000e/netdev.c).
  2. Look for markers like <<<<<<< HEAD (original code) and >>>>>>> PATCH (patch code).
  3. Edit the file to merge changes, then run patch -p1 --continue to finish.

If using Git, use git apply for better conflict handling:

git apply --3way ../my-patch.patch  # Uses Git’s 3-way merge for conflicts  

Step 6: Configure the Kernel

The kernel requires a configuration file (.config) to define enabled features. Reuse your current kernel’s config to avoid breaking existing functionality:

zcat /proc/config.gz > .config  # Copies running config to .config  

Update the config to include new options from the patch:

make oldconfig  

Answer prompts with Enter (default) or y/n to enable/disable new features.

For a graphical interface, use make menuconfig (ncurses) or make xconfig (Qt).

Step 7: Build the Kernel and Modules

Compile the kernel and its modules. Use -j$(nproc) to parallelize the build (faster on multi-core CPUs):

make -j$(nproc)  # Compiles the kernel image  
make -j$(nproc) modules  # Compiles kernel modules  

Note: This takes 30–60 minutes (or longer) depending on your hardware.

Step 8: Install the Patched Kernel

Install modules and the kernel image to system directories:

sudo make modules_install  # Installs modules to /lib/modules/5.15.0-patched/  
sudo make install  # Installs kernel image, initramfs, and System.map to /boot/  

This creates:

  • /boot/vmlinuz-5.15.0-patched (kernel image)
  • /boot/initrd.img-5.15.0-patched (initial RAM disk)
  • /lib/modules/5.15.0-patched/ (modules)

Step 9: Update the Bootloader

Update your bootloader (usually GRUB) to include the new kernel:

sudo update-grub  

GRUB will detect the new kernel and add it to the boot menu. For systems using systemd-boot (e.g., Arch), copy the kernel and initramfs to /boot and update loader/entries/*.conf.

Testing the Patched Kernel

  1. Reboot: Select the new kernel from the GRUB menu during boot.
  2. Verify Version: Confirm the patched kernel is running:
    uname -r  # Should show 5.15.0-patched  
  3. Test Functionality: Validate the patch (e.g., check for fixed bugs with dmesg, test new hardware).

Troubleshooting Common Issues

1. Build Errors

  • Missing Dependencies: Install missing packages (e.g., libssl-dev for crypto support).
  • Old Config: Regenerate .config with make olddefconfig to reset to defaults.

2. Boot Failures

  • Stuck at GRUB: Reboot and select the old kernel from the GRUB menu.
  • Initramfs Issues: Rebuild the initramfs:
    sudo update-initramfs -u -k 5.15.0-patched  
  • Module Mismatch: Ensure modules are installed to /lib/modules/$(uname -r).

3. Reverting a Patch

To undo changes:

  1. Reboot into the old kernel.
  2. Delete the patched kernel files:
    sudo rm -rf /boot/*5.15.0-patched* /lib/modules/5.15.0-patched  
  3. Update GRUB: sudo update-grub.

Conclusion

Patching the Linux kernel is a powerful skill for system administrators and developers, enabling customization, security hardening, and hardware support. By following this guide, you can safely apply patches, build a custom kernel, and test it in your environment. Always prioritize backups and testing in non-production systems first!

References