Contents

Ubuntu 24.04 手动升级 Linux 内核至 7.0 完整教程

Ubuntu 24.04 LTS 服务器手动升级主线内核至 7.0,修复 CVE-2026-31431 高危漏洞。从 6.8.0-111-generic 升级至 7.0.0-15-generic 的完整操作记录,涵盖下载、安装、验证全流程。

一、背景:为什么需要升级内核

1.1 漏洞概述

2026 年 4 月 29 日,安全厂商 Theori 公开披露了 Linux 内核高危漏洞 CVE-2026-31431(代号 Copy Fail):

属性详情
CVE 编号CVE-2026-31431
CVSS 评分9.8(严重)
漏洞类型本地权限提升(Local Privilege Escalation)
影响范围2017 年 8 月至 2026 年 3 月之间的所有 Linux 内核
不受影响的最低版本内核主线 7.0+、稳定版 6.18.22+、稳定版 6.19.12+

1.2 漏洞原理(简化说明)

漏洞存在于 Linux 内核加密子系统的 authencesn 模块中。攻击者通过以下方式利用:

  1. 创建 AF_ALG 套接字(内核提供的加密算法接口)
  2. 结合 splice() 系统调用(用于高效数据传输)
  3. 将目标文件的页缓存(Page Cache)引用暴露在可写的散列表中
  4. 实现对 setuid 程序(如 /usr/bin/su)页缓存的 4 字节越界写入
  5. 将普通用户提升为 root

关键特征

  • 利用代码仅 732 字节 Python 脚本
  • 无需竞争条件,成功率接近 100%
  • 仅修改内存中的页缓存不修改磁盘文件,因此 md5sum/sha256sum 校验无法检测是否已被攻击
  • 容器(Docker/Kubernetes)环境同样受影响,因为页缓存在宿主机与容器之间共享

1.3 影响评估

Ubuntu 24.04 LTS 默认内核 6.8.0-111 在受影响范围内。截至 2026 年 5 月,Ubuntu 官方仓库(除 26.04 LTS 外)尚未推送修复补丁,因此需要手动升级内核。

二、升级前准备

2.1 确认当前内核版本

uname -r
# 输出示例:6.8.0-111-generic(在受影响范围内)

2.2 确认 /boot 分区空间

内核安装需要约 200MB 空间(包含内核镜像、initramfs、模块等),建议 /boot 至少有 1GB 可用空间。

df -h /boot
# Filesystem      Size  Used Avail Use% Mounted on
# /dev/sda2       2.0G  101M  1.7G   6% /boot

2.3 清理旧内核(释放空间 + 减少干扰)

系统中可能积累了大量旧内核的残留配置文件(rc 状态),需要清理:

# 查看所有已安装的内核
dpkg --list | grep linux-image

# 查看残留配置文件(状态为 rc 的包)
dpkg --list | grep "^rc" | grep "linux"

# 一次性清除所有残留的旧内核配置
dpkg --list | grep "^rc" | grep "linux" | awk '{print $2}' | xargs sudo dpkg --purge 2>/dev/null

说明dpkg 中的包状态标记含义:

  • ii:已安装(正常)
  • rc:已卸载,但残留配置文件
  • iHR:安装异常(需要修复)

2.4 确认文件系统类型

本教程中的 run-parts 问题与 ZFS 无关,但确认一下可以避免后续踩坑:

df -Th / | tail -1
# /dev/mapper/ubuntu--vg-ubuntu--lv ext4   38G   14G   22G  40% /

如果输出显示 zfs,则安装 modules 包时不会出现 ZFS 依赖问题(因为 ZFS 已在系统中)。如果显示 ext4(绝大多数情况),modules 包会报 ZFS 依赖缺失,需要后续强制忽略。


三、查找可用的主线内核

3.1 为什么选择阿里云镜像

国内服务器通常无法直接访问 kernel.ubuntu.com(Ubuntu 官方主线内核仓库),但可以访问国内镜像站。阿里云镜像同步了 Ubuntu 官方仓库中的所有内核包。

3.2 搜索可用的 7.0 内核包

curl -s http://mirrors.aliyun.com/ubuntu/pool/main/l/linux/ \
  | grep -oP 'href="\K[^"]*7\.0\.0[^"]*\.deb' \
  | grep -v "64k\|arm64\|dbg\|cloud" \
  | sort -u

命令解释

  • curl -s:静默模式获取网页内容
  • grep -oP 'href="\K[^"]*7\.0\.0[^"]*\.deb':提取所有包含 7.0.0 的 .deb 文件链接
  • grep -v "64k\|arm64\|dbg\|cloud":排除 64K 页内核、ARM 架构、调试包、云专用包
  • sort -u:排序去重

输出示例(截取关键部分):

linux-headers-7.0.0-15_7.0.0-15.15_all.deb
linux-headers-7.0.0-15-generic_7.0.0-15.15_amd64.deb
linux-image-unsigned-7.0.0-15-generic_7.0.0-15.15_amd64.deb
linux-modules-7.0.0-15-generic_7.0.0-15.15_amd64.deb

3.3 确认需要下载的 4 个核心包

包名用途大小(约)
linux-headers-7.0.0-15_7.0.0-15.15_all.deb内核头文件(通用,跨架构)15M
linux-headers-7.0.0-15-generic_7.0.0-15.15_amd64.deb内核头文件(amd64 架构)4M
linux-image-unsigned-7.0.0-15-generic_7.0.0-15.15_amd64.deb内核镜像(vmlinuz)17M
linux-modules-7.0.0-15-generic_7.0.0-15.15_amd64.deb内核模块(驱动、文件系统等)162M

四、下载内核包

# 创建临时目录
mkdir -p /tmp/kernel && cd /tmp/kernel

# 下载 4 个核心包
wget http://mirrors.aliyun.com/ubuntu/pool/main/l/linux/linux-headers-7.0.0-15_7.0.0-15.15_all.deb
wget http://mirrors.aliyun.com/ubuntu/pool/main/l/linux/linux-headers-7.0.0-15-generic_7.0.0-15.15_amd64.deb
wget http://mirrors.aliyun.com/ubuntu/pool/main/l/linux/linux-image-unsigned-7.0.0-15-generic_7.0.0-15.15_amd64.deb
wget http://mirrors.aliyun.com/ubuntu/pool/main/l/linux/linux-modules-7.0.0-15-generic_7.0.0-15.15_amd64.deb

# 确认下载完整
ls -lh /tmp/kernel/

五、安装内核包

5.1 安装 Headers 包(通常无问题)

cd /tmp/kernel

sudo dpkg -i linux-headers-7.0.0-15_7.0.0-15.15_all.deb
sudo dpkg -i linux-headers-7.0.0-15-generic_7.0.0-15.15_amd64.deb

说明:Headers 包包含内核编译所需的头文件,是编译第三方模块(如 NVIDIA 驱动)的必要依赖。这两个包通常不会有问题。

5.2 安装 Modules 包(ZFS 依赖问题 — 修复并重打包)

sudo dpkg -i linux-modules-7.0.0-15-generic_7.0.0-15.15_amd64.deb

可能遇到的报错

dpkg: dependency problems prevent configuration of linux-modules-7.0.0-15-generic:
 linux-modules-7.0.0-15-generic depends on linux-main-modules-zfs-7.0.0-15-generic; however:
  Package linux-main-modules-zfs-7.0.0-15-generic is not installed.

原因分析

Ubuntu 官方内核包默认依赖 ZFS 模块(linux-main-modules-zfs)。如果系统使用 ext4 文件系统(绝大多数情况),这个依赖是不必要的。同时,该 ZFS 包在主线内核仓库中可能根本不存在,导致 dpkg --force-depends 虽然能绕过 dpkg 层面的检查,但 apt 的依赖数据库仍会记录这个未满足的依赖,导致后续 apt update / apt upgrade 报错。

解决方案:移除依赖声明并重新打包 deb 包

不建议使用 dpkg --force-depends 强制跳过,因为这只能骗过 dpkg,无法骗过 apt,会为后续系统更新埋下隐患。

# --- 步骤 A:解包 deb 并查看依赖 ---
mkdir -p /tmp/fix-dep && cd /tmp/fix-dep
ar x /tmp/kernel/linux-modules-7.0.0-15-generic_7.0.0-15.15_amd64.deb
mkdir ctrl && cd ctrl
tar xf ../control.tar

# 查看当前依赖声明
grep -i "^Depends" control
# 输出示例:
# Depends: linux-image-7.0.0-15-generic (= 7.0.0-15.15), linux-main-modules-zfs-7.0.0-15-generic (>= 7.0.0-15.15), wireless-regdb

# --- 步骤 B:编辑 control 文件,移除 ZFS 依赖 ---
sed -i 's/, linux-main-modules-zfs-7.0.0-15-generic[^,)]*//g' control
sed -i 's/linux-main-modules-zfs-7.0.0-15-generic[^,)]*,\s*//g' control
sed -i 's/linux-main-modules-zfs-7.0.0-15-generic[^)]*//g' control

# 确认修改结果(ZFS 依赖已消失)
grep -i "^Depends" control
# 输出示例:
# Depends: wireless-regdb

# --- 步骤 C:重新打包 ---
cd /tmp/fix-dep
tar cf control.tar --owner=0 --group=0 -C ctrl .
ar rcs linux-modules-fixed.deb debian-binary control.tar data.tar

# --- 步骤 D:清除旧包状态并安装修复后的包 ---
sudo dpkg --purge --force-all --force-scripts linux-modules-7.0.0-15-generic
sudo dpkg -i linux-modules-fixed.deb

优势:与 --force-depends 不同,此方法从根源上移除了不存在的依赖声明,apt 和 dpkg 层面都不会再报错,后续系统更新不会受影响。

重要提醒:与修复 image 包时一样,ar x 解包 deb 后会在当前目录生成 data.tar。如果在同一个目录中解包多个 deb 包,后解包的会覆盖前面的 data.tar。务必在不同目录中解包不同的 deb 包。

5.3 安装 Image 包(run-parts 报错 — 关键异常点)

sudo dpkg -i linux-image-unsigned-7.0.0-15-generic_7.0.0-15.15_amd64.deb

报错输出

Preparing to unpack .../linux-image-unsigned-7.0.0-15-generic_7.0.0-15.15_amd64.deb ...
run-parts: missing operand
Try `run-parts --help' for more information.
dpkg: error processing archive ... (--install):
 new linux-image-unsigned-7.0.0-15-generic package pre-installation script subprocess returned error exit status 1
run-parts: missing operand
Try `run-parts --help' for more information.
dpkg: error while cleaning up:
 new linux-image-unsigned-7.0.0-15-generic package post-removal script subprocess returned error exit status 1
Errors were encountered while processing:
 ...linux-image-unsigned-7.0.0-15-generic_7.0.0-15.15_amd64.deb

原因分析

run-parts 是 Debian/Ubuntu 系统中用于按顺序执行指定目录下所有脚本的工具。主线内核 deb 包中的 preinst(安装前)和 postrm(卸载后)脚本在调用 run-parts 时未正确传递目录参数,导致报错。这个问题在直接从主线仓库下载的 deb 包上较为常见,因为这些包的脚本主要针对标准发布版本的目录结构编写。

解决方案:三步走

由于 dpkg 安装脚本失败,需要:

  1. 手动提取内核文件到系统目录
  2. 重建修复后的 deb 包(替换有问题的安装脚本)
  3. 让 dpkg 正确注册包状态

步骤 A:手动提取内核镜像到 /boot

由于 dpkg 无法正常安装,我们需要手动将内核镜像文件提取到正确位置:

# 创建临时目录用于解包
mkdir -p /tmp/image && cd /tmp/image

# 从 deb 包中解包(ar 是 Debian 归档工具)
ar x /tmp/kernel/linux-image-unsigned-7.0.0-15-generic_7.0.0-15.15_amd64.deb

# 查看 data.tar 中的文件列表
tar -tf data.tar
# 输出:
# ./
# ./boot/
# ./boot/vmlinuz-7.0.0-15-generic    ← 这就是内核镜像
# ./usr/...

# 提取到系统根目录
sudo tar -xf data.tar -C /

# 确认内核镜像到位
ls -lh /boot/vmlinuz-7.0.0-15-generic
# -rw------- 1 root root 17M ... /boot/vmlinuz-7.0.0-15-generic

重要提醒ar x 解包 deb 后会在当前目录生成 data.tar。如果在同一个目录中解包多个 deb 包,后解包的会覆盖前面的 data.tar。务必在不同目录中解包不同的 deb 包。

步骤 B:重建修复后的 deb 包

为了让 dpkg 正确注册包状态(避免 dpkg --audit 报错和阻塞 apt install),需要修复 deb 包中有问题的安装脚本,然后重新安装。

# 1. 重新下载 image 包(确保干净的源文件)
wget -q http://mirrors.aliyun.com/ubuntu/pool/main/l/linux/linux-image-unsigned-7.0.0-15-generic_7.0.0-15.15_amd64.deb \
  -O /tmp/linux-image.deb

# 2. 创建重建工作目录
mkdir -p /tmp/rebuild && cd /tmp/rebuild

# 3. 解包 deb(ar 会解出 debian-binary、control.tar、data.tar)
ar x /tmp/linux-image.deb

# 4. 解包 control.tar(包含元数据和安装脚本)
mkdir ctrl && cd ctrl && tar xf ../control.tar

# 5. 查看控制目录中的脚本文件
ls -la
# 会看到:preinst、postinst、postrm 等脚本

# 6. 用安全的空脚本替换所有有问题的安装脚本
# preinst(安装前脚本)
cat > preinst << 'EOF'
#!/bin/sh
exit 0
EOF
chmod +x preinst

# postinst(安装后脚本)
cat > postinst << 'EOF'
#!/bin/sh
exit 0
EOF
chmod +x postinst

# postrm(卸载后脚本)
cat > postrm << 'EOF'
#!/bin/sh
exit 0
EOF
chmod +x postrm

# 7. 确认三个脚本都已替换
ls -la preinst postinst postrm

# 8. 重新打包 control.tar(回到 rebuild 目录)
cd /tmp/rebuild
tar cf control.tar --owner=0 --group=0 -C ctrl .

# 9. 重新构建 deb 包(ar rcs 会覆盖原文件)
ar rcs /tmp/linux-image-fixed.deb debian-binary control.tar data.tar

脚本替换说明

  • preinst:安装前执行,用于检查和准备。原始脚本调用 run-parts 报错。
  • postinst:安装后执行,用于配置和触发。原始脚本调用 run-parts 报错。
  • postrm:卸载后执行,用于清理。原始脚本调用 run-parts 报错。
  • 将它们替换为空脚本(直接 exit 0)不会影响内核的正常运行,因为这些脚本主要用于触发 initramfs 更新和 GRUB 更新,我们将手动执行这些操作。

步骤 C:清除旧包状态并安装修复后的包

# 清除之前失败安装留下的损坏包状态
# --force-all:忽略所有强制检查
# --force-scripts:跳过所有安装/卸载脚本的执行
sudo dpkg --purge --force-all --force-scripts linux-image-unsigned-7.0.0-15-generic

# 安装修复后的 deb 包
sudo dpkg -i /tmp/linux-image-fixed.deb

为什么需要 --force-scripts: 即使原始的 preinst 脚本有问题,dpkg 在卸载(purge)时仍会尝试执行它。--force-scripts 跳过脚本执行,避免再次触发 run-parts 错误。


六、生成 initramfs 和更新 GRUB

6.1 生成 initramfs

sudo update-initramfs -c -k 7.0.0-15-generic
# update-initramfs: Generating /boot/initrd.img-7.0.0-15-generic

什么是 initramfs: initramfs(Initial RAM Filesystem)是一个临时的根文件系统,在 Linux 启动早期加载到内存中。它包含了挂载真正根文件系统所需的驱动和工具(如 LVM、RAID、文件系统驱动等)。没有 initramfs,内核可能无法找到和挂载根分区。

-c 参数表示创建新的 initramfs(而非更新已有的)。 -k 参数指定为哪个内核版本生成。

6.2 更新 GRUB 引导配置

sudo update-grub

输出中应包含:

Found linux image: /boot/vmlinuz-7.0.0-15-generic
Found initrd image: /boot/initrd.img-7.0.0-15-generic
Found linux image: /boot/vmlinuz-6.8.0-111-generic
Found initrd image: /boot/initrd.img-6.8.0-111-generic

GRUB(GRand Unified Bootloader) 是 Linux 系统的引导加载程序。update-grub 会扫描 /boot 目录中的所有内核镜像,自动生成引导菜单配置。新安装的 7.0 内核会自动出现在菜单中。

6.3 确认 GRUB 默认启动项

grep "menuentry" /boot/grub/grub.cfg | grep "linux"

GRUB 菜单结构示例:

0 → Ubuntu(默认,指向菜单第一项)
  └── Advanced options for Ubuntu
        ├── 0 → Ubuntu, with Linux 7.0.0-15-generic
        ├── 1 → Ubuntu, with Linux 7.0.0-15-generic (recovery mode)
        ├── 2 → Ubuntu, with Linux 6.8.0-111-generic
        └── 3 → Ubuntu, with Linux 6.8.0-111-generic (recovery mode)

确保 GRUB_DEFAULT=0(默认启动第一项,即 7.0 内核):

# 检查当前 GRUB 默认值
grep GRUB_DEFAULT /etc/default/grub

# 如果不是 0,修改为 0
sudo sed -i 's/^GRUB_DEFAULT=.*/GRUB_DEFAULT=0/' /etc/default/grub
sudo update-grub

七、重启并验证

sudo reboot

重启后执行以下验证命令:

# 1. 确认内核版本
uname -r
# 期望输出:7.0.0-15-generic

# 2. 确认 algif_aead 模块未加载
lsmod | grep algif_aead
# 无输出 = 正常

# 3. 确认系统文件系统正常
df -Th /
# Filesystem                        Type  Size  Used Avail Use% Mounted on
# /dev/mapper/ubuntu--vg-ubuntu--lv ext4   38G   14G   22G  39% /

# 4. 确认 Ubuntu 版本
lsb_release -a
# Description:    Ubuntu 24.04.4 LTS

# 5. 确认 dpkg 包状态无损坏
dpkg --audit 2>&1
# 无输出 = 正常

# 6. 确认 apt 工作正常
sudo apt update

八、善后操作

8.1 设置 algif_aead 模块禁用(双重保险)

虽然 7.0 内核不受 CVE-2026-31431 影响,但禁用 algif_aead 模块作为额外防护层是良好的安全实践:

echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf

原理/etc/modprobe.d/ 目录下的 .conf 文件用于配置内核模块的加载行为。install <模块名> /bin/false 告诉 modprobe 在尝试加载该模块时执行 /bin/false(一个立即返回失败的程序),从而阻止模块加载。

影响范围:禁用 algif_aead 不会影响 dm-crypt/LUKS(磁盘加密)、IPsec、SSH 或 OpenSSL 的默认构建等标准加密服务。

8.2 清理临时文件

rm -rf /tmp/kernel /tmp/image /tmp/rebuild /tmp/linux-image.deb /tmp/linux-image-fixed.deb

8.3 确认 GRUB 保留回退内核

# 确认 6.8 内核仍在 GRUB 中
grep "6.8.0-111" /boot/grub/grub.cfg

保留 6.8.0-111 作为回退内核,万一 7.0 出现兼容性问题,可以在 GRUB 菜单中选择旧内核启动。

8.4 (可选)隐藏 GRUB 菜单

如果不需要在启动时看到 GRUB 菜单(正常启动直接进入系统):

sudo sed -i 's/GRUB_TIMEOUT_STYLE=menu/GRUB_TIMEOUT_STYLE=hidden/' /etc/default/grub
sudo sed -i 's/GRUB_TIMEOUT=5/GRUB_TIMEOUT=0/' /etc/default/grub
sudo update-grub

提示:如果想保留 GRUB 菜单以便在出问题时手动选择内核,可以跳过此步骤。


九、回退方案

9.1 重启时手动选择旧内核

重启时在 GRUB 菜单中:

  1. 选择 Advanced options for Ubuntu
  2. 选择 Ubuntu, with Linux 6.8.0-111-generic

9.2 临时显示 GRUB 菜单

如果 GRUB 菜单被隐藏了,重启时按住 Shift 或 Esc 可以强制显示。

或者永久显示:

sudo sed -i 's/GRUB_TIMEOUT_STYLE=hidden/GRUB_TIMEOUT_STYLE=menu/' /etc/default/grub
sudo sed -i 's/GRUB_TIMEOUT=0/GRUB_TIMEOUT=5/' /etc/default/grub
sudo update-grub
sudo reboot

9.3 完全卸载 7.0 内核(回到 6.8)

# 确保当前不在 7.0 内核上运行(需要先用 6.8 内核启动)

# 卸载 7.0 相关包
sudo dpkg --purge --force-all --force-scripts linux-image-unsigned-7.0.0-15-generic
sudo dpkg --purge linux-modules-7.0.0-15-generic
sudo dpkg --purge linux-headers-7.0.0-15-generic linux-headers-7.0.0-15

# 清理 /boot 中的 7.0 文件
sudo rm -f /boot/vmlinuz-7.0.0-15-generic /boot/initrd.img-7.0.0-15-generic
sudo rm -rf /lib/modules/7.0.0-15-generic

# 更新 GRUB
sudo update-grub

# 重启
sudo reboot

十、后续内核升级

7.0 内核不在 Ubuntu 官方包管理中,后续需要手动升级时,重复以下流程:

# 1. 查找新版本
curl -s http://mirrors.aliyun.com/ubuntu/pool/main/l/linux/ \
  | grep -oP 'href="\K[^"]*7\.[0-9]+\.[0-9]+[^"]*\.deb' \
  | grep -v "64k\|arm64\|dbg\|cloud" \
  | sort -u

# 2. 下载新版本的 4 个包(以新版本号替换)

# 3. 安装 headers(通常无问题)
sudo dpkg -i linux-headers-*.deb

# 4. 安装 modules(忽略 ZFS 依赖)
sudo dpkg --force-depends -i linux-modules-*.deb

# 5. 手动提取 image 到 /boot
mkdir -p /tmp/newimage && cd /tmp/newimage
ar x /path/to/linux-image-unsigned-xxx.deb
sudo tar -xf data.tar -C /

# 6. 生成 initramfs
sudo update-initramfs -c -k <新版本号>-generic

# 7. 更新 GRUB
sudo update-grub

# 8. 重启
sudo reboot

十一、关键异常点总结

异常原因解决方案
modules 包报 ZFS 依赖缺失Ubuntu 内核包默认依赖 ZFS 模块,ext4 系统不需要sudo dpkg --force-depends -i
image 包报 run-parts: missing operand主线内核 deb 包的安装脚本与系统 run-parts 不兼容手动提取内核文件 + 修复 deb 包安装脚本
apt --fix-broken install 报找不到 archivedpkg 中注册了包但文件不完整sudo dpkg --purge --force-all --force-scripts 清除后重装
卸载当前运行内核报 Aborting removaldpkg 不允许卸载当前正在运行的内核先重启切换到其他内核,再卸载
dpkg --audit 报包状态损坏安装脚本失败导致包注册不完整重建修复后的 deb 包并重新安装

十二、参考资源

  • CVE-2026-31431 官方公告:https://ubuntu.com/security/CVE-2026-31431
  • Ubuntu 主线内核仓库:https://kernel.ubuntu.com/mainline/
  • 阿里云 Ubuntu 镜像:http://mirrors.aliyun.com/ubuntu/
  • Linux 内核官方:https://www.kernel.org/

最后更新:2026 年 5 月 3 日

测试环境:Ubuntu 24.04.4 LTS (noble) / amd64 / ext4 on LVM

本文章已被查看 0