PAYATHON 2026

Ubuntu 的 GRUB 审计为何仍检测不到 AppArmor 参数?

数据小陈

结论

审计脚本把所有以 linux 开头的 GRUB 命令都当作 Ubuntu 内核条目检查。你贴出的失败输出指向 memtest86+x64.bin。这是 memtest 启动项,不是 Ubuntu Linux 内核启动项,通常不会带有 apparmor=1 和 security=apparmor。因此,即使修复已经把参数写入普通内核启动项,审计也可能因为 memtest 行缺少参数而失败。

此外,脚本用两次 grep -v 分别检查参数是否存在。这样检查的是“每一行是否包含该参数”,并不能确认目标内核启动项是否同时包含两个参数。

检查 GRUB 配置中的内核条目

下面的脚本逐行检查 GRUB 配置中的 linux、linuxefi 和 linux16 命令,跳过镜像路径包含 memtest 的条目,并要求其余条目都包含两个完整参数:

#!/usr/bin/env bash
set -o pipefail

cfg=/boot/grub/grub.cfg

if [[ ! -r "$cfg" ]]; then
  echo "无法读取 $cfg" >&2
  exit 2
fi

awk '
/^[[:space:]]*(linux|linuxefi|linux16)[[:space:]]/ {
  # 第二列是内核镜像路径;memtest 不是 Ubuntu Linux 内核条目。
  if ($2 ~ /(^|\/)memtest[^/]*$/) next

  checked++
  has_apparmor = 0
  has_security = 0

  for (i = 3; i <= NF; i++) {
    if ($i == "apparmor=1") has_apparmor = 1
    if ($i == "security=apparmor") has_security = 1
  }

  if (!has_apparmor || !has_security) {
    printf "缺少参数的内核条目:%s\n", $0
    failed = 1
  }
}
END {
  if (checked == 0) {
    print "未找到可检查的 Linux 内核条目" > "/dev/stderr"
    exit 2
  }
  if (failed) exit 1
  print "所有检查到的 Linux 内核条目均包含所需参数"
}
' "$cfg"

该检查按空白分隔 GRUB 命令参数,并逐字段进行完整匹配,不会把相似但不同的参数值误认为目标参数。如果没有找到待检查的内核条目,它也会返回错误,避免空结果被当作审计通过。

跳过 memtest 是根据你给出的输出,以及“检查 Linux 内核启动参数”这一目的作出的处理。如果你的合规规则要求检查所有 GRUB linux 命令,应按规则调整筛选条件,不要为了让检查通过而忽略实际要求检查的条目。

核对修复是否已写入配置

修复脚本会更新 /etc/default/grub 中的 GRUB_CMDLINE_LINUX,再通过 update-grub 生成 GRUB 配置。可以分别查看配置变量和生成后的内核命令:

grep '^GRUB_CMDLINE_LINUX=' /etc/default/grub
grep -E '^[[:space:]]*(linux|linuxefi|linux16)[[:space:]]' /boot/grub/grub.cfg

确认生成的配置中,目标内核条目确实包含这两个参数。修复脚本打印 CONFIGURED: Reboot required 时也提示了需要重启。重新生成配置后,当前运行中的内核还不一定使用了新参数。

检查当前运行内核

重启后,可以检查当前内核实际收到的参数:

tr ' ' '\n' </proc/cmdline | grep -Fx -e 'apparmor=1' -e 'security=apparmor'

这个命令查看的是当前启动会话,不能代替对所有 GRUB 启动项的配置审计。检查生成的配置可以确认启动项;检查 /proc/cmdline 可以确认当前运行内核。两项检查的结果和用途不同。

备注:内容仅供参考。