Applying Security Patches to the Raspberry Pi 5 Kernel
Applying Security Patches to the Raspberry Pi 5 Kernel
The Linux kernel receives hundreds of commits daily, many addressing security vulnerabilities. When running a Raspberry Pi 5 with a custom or older kernel, you may need to apply security patches before the Raspberry Pi Foundation releases an official update.
This guide covers the complete workflow: tracking CVEs, locating upstream fixes, backporting patches to the Pi kernel tree, and verifying the fix.
Understanding the Patch Ecosystem
The Kernel Release Model
Linux follows a structured release model that affects how patches flow:
Mainline (Linus) → 6.8, 6.9, 6.10 ...
↓
Stable (Greg K-H) → 6.6.15, 6.6.16, 6.6.17 ...
↓
LTS (Long Term) → 6.1.x, 6.6.x (maintained 2-6 years)
↓
Vendor Trees → Raspberry Pi, Android, Distros
Mainline receives new features and fixes first. Stable kernels get critical fixes backported, tagged with Cc: stable@vger.kernel.org. LTS kernels receive extended maintenance. Vendor trees (like the Pi kernel) cherry-pick from stable/mainline.
The Raspberry Pi Foundation tracks the 6.6.y LTS branch, but there's always a lag between upstream fixes and Pi kernel updates—sometimes days, sometimes weeks for less critical issues.
Why Manual Patching Matters
Consider this timeline for a hypothetical CVE:
- Day 0: Vulnerability disclosed, fix merged to mainline
- Day 1-3: Fix backported to stable kernels (6.6.x, 6.1.x)
- Day 7-14: Raspberry Pi Foundation merges to rpi-6.6.y
- Day 14-30: Your distro (Raspberry Pi OS) releases updated package
If you're running a production Pi 5 exposed to untrusted networks, waiting 2-4 weeks for an official update isn't acceptable. Manual patching closes this window.
Tracking Security Vulnerabilities
Kernel CVE Database
The Linux kernel maintains its own CVE database with detailed analysis:
# Clone the kernel CVE database
git clone https://git.kernel.org/pub/scm/linux/security/vulns.git linux-cve-db
cd linux-cve-db
# List recent CVEs
ls -lt cve/published/ | head -20
# Search for specific subsystem CVEs
grep -r "net/bluetooth" cve/published/
Each CVE entry contains:
- Affected kernel versions
- Fix commit hash
- Severity assessment
- Affected subsystems
Monitoring Channels
Set up monitoring for security announcements:
Mailing Lists:
linux-kernel@vger.kernel.org- All kernel developmentlinux-cve-announce@vger.kernel.org- CVE announcements onlyoss-security@lists.openwall.com- Cross-project security
RSS Feeds:
# Kernel stable releases (includes security fixes)
https://www.kernel.org/feeds/kdist.xml
# NVD CVE feed for Linux kernel
https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-recent.json.gz
Automated Monitoring Script:
#!/bin/bash
# check-kernel-cves.sh - Monitor for new kernel CVEs
CVE_DB="$HOME/linux-cve-db"
LAST_CHECK="$HOME/.last-cve-check"
cd "$CVE_DB" && git pull -q
if [ -f "$LAST_CHECK" ]; then
NEW_CVES=$(find cve/published -newer "$LAST_CHECK" -name "CVE-*.json")
if [ -n "$NEW_CVES" ]; then
echo "New kernel CVEs since last check:"
for cve in $NEW_CVES; do
jq -r '"\(.cveId): \(.containers.cna.title)"' "$cve"
done
fi
fi
touch "$LAST_CHECK"
Identifying Relevant CVEs
Not every kernel CVE affects your Pi 5. Filter by:
Architecture: ARM64-specific vulnerabilities
grep -l "arm64\|aarch64" cve/published/CVE-2024-*.json
Enabled Subsystems: Check your kernel config
# On the Pi, extract running config
zcat /proc/config.gz > running.config
# Check if vulnerable subsystem is enabled
grep CONFIG_BLUETOOTH running.config
# CONFIG_BLUETOOTH=m → Affected
# CONFIG_BLUETOOTH is not set → Not affected
Attack Surface: Consider your exposure
- Network-facing services → Prioritize net/ipv4, net/ipv6, bluetooth
- USB peripherals → Prioritize drivers/usb
- Local users only → Lower priority for local privilege escalation
Locating Upstream Fixes
Finding the Fix Commit
Once you identify a CVE, locate the fixing commit:
Method 1: CVE Database
# The CVE JSON contains the fix commit
jq -r '.containers.cna.references[] | select(.tags[]? == "patch") | .url' \
cve/published/CVE-2024-XXXX.json
Method 2: Stable Kernel Changelog
# Search stable kernel commits
cd ~/rpi-linux
git log --oneline --grep="CVE-2024-XXXX" origin/linux-6.6.y
Method 3: Commit Message Search Security fixes often reference the CVE or describe the vulnerability:
git log --oneline --all --grep="use-after-free" --grep="net/bluetooth" --all-match
Method 4: LKML Archives Search the mailing list archives at https://lore.kernel.org/lkml/ for the CVE ID or vulnerability description.
Anatomy of a Security Fix
Let's examine a real security fix structure:
commit abc123def456...
Author: Security Researcher <researcher@example.com>
Date: Mon Jan 15 10:30:00 2024 +0000
net: fix use-after-free in sk_buff handling
When processing fragmented packets, the sk_buff can be freed
while still referenced by the fragment queue. This leads to
a use-after-free that can be triggered by a malicious packet.
Fix by taking an additional reference before queueing.
Reported-by: Security Team <security@example.com>
Fixes: def789abc123 ("net: add fragment queue support")
Cc: stable@vger.kernel.org
Signed-off-by: Security Researcher <researcher@example.com>
Signed-off-by: Network Maintainer <maintainer@kernel.org>
Key elements:
- Fixes: tag points to the commit that introduced the bug
- Cc: stable indicates the fix should be backported
- Signed-off-by chain shows review process
Extracting the Patch
# Get the patch for a specific commit
git format-patch -1 abc123def456 --stdout > fix-cve-2024-xxxx.patch
# Or export a range of related commits
git format-patch abc123^..def456 -o patches/
Examine the patch before applying:
# View patch statistics
diffstat fix-cve-2024-xxxx.patch
# Check which files are modified
grep "^diff --git" fix-cve-2024-xxxx.patch
Backporting to the Raspberry Pi Kernel
Setting Up the Workspace
# Clone Pi kernel if not already done
git clone --depth=1 --branch rpi-6.6.y \
https://github.com/raspberrypi/linux.git rpi-linux
cd rpi-linux
# Add mainline as a remote for fetching fixes
git remote add mainline https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git remote add stable https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
# Fetch stable branch metadata (not full history)
git fetch stable linux-6.6.y --depth=100
Clean Cherry-Pick (Ideal Case)
When the patch applies cleanly:
# Create a branch for your security fixes
git checkout -b security-patches-$(date +%Y%m%d)
# Cherry-pick the fix commit from stable
git cherry-pick -x abc123def456
# The -x flag adds "cherry picked from commit..." to the message
If successful, the patch is now in your tree. Skip to the verification section.
Handling Conflicts
Real-world backporting often involves conflicts due to code drift between mainline and the Pi tree.
git cherry-pick -x abc123def456
# CONFLICT (content): Merge conflict in net/core/skbuff.c
# error: could not apply abc123...
Resolving Conflicts:
# View the conflict
git diff
# Open conflicted file
nano net/core/skbuff.c
You'll see conflict markers:
<<<<<<< HEAD
// Pi kernel version of the code
skb = alloc_skb(size, GFP_KERNEL);
if (!skb)
return -ENOMEM;
=======
// Mainline version with the fix
skb = alloc_skb(size, GFP_KERNEL);
if (!skb)
return -ENOMEM;
skb_get(skb); // <- This is the security fix
>>>>>>> abc123... net: fix use-after-free
Resolution Strategy:
-
Understand the fix: What does
skb_get(skb)do? It increments the reference count. -
Understand the context: Why does the Pi kernel differ? Maybe function signatures changed, or the Pi has additional error handling.
-
Apply the fix logic, not literal code: The fix adds a reference count increment. Apply that concept to the Pi kernel's code structure.
// Resolved: Pi kernel code with the fix applied
skb = alloc_skb(size, GFP_KERNEL);
if (!skb)
return -ENOMEM;
skb_get(skb); // Security fix: prevent use-after-free
# Mark resolved
git add net/core/skbuff.c
# Continue cherry-pick
git cherry-pick --continue
Multi-Commit Fixes
Some vulnerabilities require multiple commits. Apply them in order:
# List the fix series
git log --oneline abc123^..def789
# Apply the series
git cherry-pick -x abc123^..def789
# Or apply individually for complex conflicts
for commit in abc123 bcd234 cde345 def456; do
git cherry-pick -x $commit || {
echo "Conflict in $commit - resolve and run: git cherry-pick --continue"
break
}
done
Using Quilt for Patch Management
For managing multiple patches over time, quilt provides better tracking:
# Install quilt
sudo apt install quilt
# Initialize quilt in kernel tree
cd rpi-linux
mkdir -p patches
echo "patches" > .pc/.quilt_patches
# Import a patch
quilt import ../fix-cve-2024-xxxx.patch
quilt push
# If conflicts, edit and refresh
quilt push -f
# ... resolve conflicts ...
quilt refresh
# List applied patches
quilt series
Building and Testing the Patched Kernel
Compile with the Fix
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
# Use your existing config
make bcm2712_defconfig
# Build
make -j$(nproc) Image.gz modules dtbs
Verify the Fix is Included
# Check the patch is in the git log
git log --oneline -5
# Should show your cherry-picked commit
# Verify the fixed code is in the binary (if symbols available)
# Recompile with CONFIG_KALLSYMS=y
grep "skb_get" System.map
Testing the Fix
Static Analysis:
# Run sparse (semantic parser)
make C=2 net/core/skbuff.o
# Run coccinelle checks if available
make coccicheck MODE=report M=net/core/
Runtime Testing:
Deploy to a test Pi 5 first:
# Copy to test Pi
scp arch/arm64/boot/Image.gz pi@test-pi:/tmp/
ssh pi@test-pi "sudo cp /tmp/Image.gz /boot/firmware/kernel8.img && sudo reboot"
Trigger the Vulnerability (Safely):
For network vulnerabilities, use a fuzzer or PoC in a controlled environment:
# Example: Test with network stress
sudo apt install netperf
netperf -H test-pi -t TCP_STREAM -l 60
# Monitor for kernel warnings
ssh pi@test-pi "dmesg -w" &
Verify the Fix:
# Check for KASAN reports (if enabled)
ssh pi@test-pi "dmesg | grep -i kasan"
# Check for general warnings
ssh pi@test-pi "dmesg | grep -iE 'warning|bug|error|oops'"
Documenting Your Patches
Maintain a record of applied security patches:
# Create a patches directory in your tree
mkdir -p Documentation/security-patches
# Document each patch
cat > Documentation/security-patches/CVE-2024-XXXX.md << 'EOF'
# CVE-2024-XXXX: Use-after-free in network stack
## Summary
- **CVE ID**: CVE-2024-XXXX
- **Severity**: High (CVSS 7.8)
- **Affected**: net/core/skbuff.c
- **Fix Commit**: abc123def456 (mainline)
- **Applied**: 2024-01-20
- **Tested**: Yes (netperf stress test)
## Description
A use-after-free vulnerability in sk_buff handling allows
remote attackers to cause denial of service or potentially
execute arbitrary code via crafted network packets.
## Verification
- Kernel builds successfully
- No KASAN reports under stress testing
- Network performance unchanged
EOF
Automating Security Updates
Patch Tracking Script
#!/bin/bash
# track-security-fixes.sh
PI_KERNEL="$HOME/rpi-linux"
STABLE_BRANCH="linux-6.6.y"
cd "$PI_KERNEL"
# Fetch latest stable
git fetch stable $STABLE_BRANCH
# Find security-relevant commits not in Pi tree
git log --oneline stable/$STABLE_BRANCH ^HEAD --grep="Cc: stable" | \
while read hash msg; do
# Check if already applied
if ! git log --oneline HEAD | grep -q "${msg:0:60}"; then
echo "Missing: $hash $msg"
fi
done
CI Integration
Add to your CI pipeline (GitHub Actions example):
name: Security Patch Check
on:
schedule:
- cron: '0 6 * * *' # Daily at 6 AM
jobs:
check-patches:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for missing security fixes
run: |
git remote add stable https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
git fetch stable linux-6.6.y --depth=50
MISSING=$(git log --oneline stable/linux-6.6.y ^HEAD --grep="CVE-" | wc -l)
if [ "$MISSING" -gt 0 ]; then
echo "::warning::$MISSING security commits missing from this tree"
git log --oneline stable/linux-6.6.y ^HEAD --grep="CVE-"
fi
Best Practices
Do's
- Always test on non-production hardware first - A bad patch can brick your Pi
- Keep your patch branch separate - Don't pollute the upstream tracking branch
- Document everything - Future you will thank present you
- Subscribe to security lists - Early warning is critical
- Verify the fix source - Only apply patches from kernel.org or trusted maintainers
Don'ts
- Don't blindly apply patches - Understand what they fix and why
- Don't skip testing - Even "obvious" fixes can have unexpected interactions
- Don't ignore conflicts - A misresolved conflict can introduce new vulnerabilities
- Don't forget to update - One patch doesn't make you secure forever
Conclusion
Applying upstream security patches to your Raspberry Pi 5 kernel is a critical skill for maintaining a secure system. The process requires:
- Monitoring CVE announcements and stable kernel releases
- Identifying which vulnerabilities affect your configuration
- Locating and extracting fix commits from mainline/stable
- Carefully backporting patches, resolving conflicts when necessary
- Thorough testing before production deployment
Combined with custom kernel building, you can maintain a Pi 5 that's both optimized for your workload and protected against known vulnerabilities—without waiting for upstream distribution updates.
Stay vigilant, patch promptly, and always verify your fixes.