3. Linux 内核安全机制:Namespace、Cgroup、Capabilities、Seccomp、LSM 与 eBPF 的关系

在构建多租户 eBPF 隔离方案时,理解 Linux 内核现有的安全机制是基础。这些机制并非孤立存在,而是与 eBPF 形成互补或协同的关系。本章将逐一剖析六大核心机制,并揭示它们如何与 eBPF 交互,共同构成租户隔离的底层防线。

3.1 六大内核安全机制概览

下表从隔离维度、控制粒度、动态性三个关键属性对比了各机制,帮助建立全局认知:

机制 隔离维度 控制粒度 动态性 与 eBPF 关系
Namespace 全局资源视图 进程组 创建时静态 eBPF 可感知 ns 归属,辅助审计
Cgroup 资源使用上限 进程组 运行时调整 eBPF 可附加 cgroup 钩子,实现精细化记账与限流
Capabilities 特权操作 单个线程 运行时调整 eBPF 可检查 cap 位,辅助决策
Seccomp 系统调用 单个进程 加载后静态 eBPF 可作为 seccomp 过滤器(BPF_PROG_TYPE_SECCOMP)
LSM 安全策略 内核对象 策略可加载 eBPF 通过 LSM 钩子扩展安全策略(BPF_PROG_TYPE_LSM)
eBPF 可编程内核行为 事件级 运行时热加载 自身即安全机制,同时增强其他机制

3.2 Namespace:资源视图隔离

Namespace 为进程组提供独立的全局资源视图。每个租户的容器拥有独立的 PID、网络、挂载、UTS、IPC、User 和 Cgroup 命名空间。eBPF 程序可以通过 bpf_get_current_pid_tgid() 和辅助函数获取当前进程所属的 namespace ID,从而在审计日志中标记租户身份。

关键点: eBPF 无法直接修改 namespace 归属,但可以在 tracepoint 或 kprobe 中读取 namespace 信息,实现租户维度的监控与统计。

3.3 Cgroup:资源上限控制

Cgroup(v2)将进程组织成层级树,并对 CPU、内存、IO、网络等资源进行上限控制。eBPF 提供了 BPF_PROG_TYPE_CGROUP_SKB、BPF_PROG_TYPE_CGROUP_SOCK 等程序类型,可以直接附加到 cgroup 路径上,实现租户级别的网络流量过滤、带宽限制和连接跟踪。

// 示例:cgroup skb 程序框架
SEC("cgroup_skb/ingress")
int cgroup_ingress(struct __sk_buff *skb) {
    // 读取 skb 元数据,执行租户策略
    return 1; // 允许通过
}

3.4 Capabilities:细粒度特权拆分

传统 root/non-root 二元模型过于粗放。Capabilities 将 root 特权拆分为 40+ 个独立单元(如 CAP_NET_ADMIN、CAP_SYS_ADMIN)。eBPF 程序在加载时需要进行 capability 检查(CAP_BPF、CAP_PERFMON、CAP_NET_ADMIN 等)。在运行时,eBPF 可以通过 bpf_get_current_cgroup_id() 结合辅助函数查询进程的 capability 位,实现基于特权的访问控制。

实践建议: 在租户隔离场景中,应尽量剥离 CAP_SYS_ADMIN,改用 CAP_BPF + CAP_PERFMON 的组合,降低提权风险。

3.5 Seccomp:系统调用过滤

Seccomp(Secure Computing Mode)限制进程可使用的系统调用。eBPF 是 seccomp 过滤器的底层实现技术——BPF_PROG_TYPE_SECCOMP 程序直接作为 seccomp 的过滤逻辑。这意味着 eBPF 不仅是被隔离的对象,也是实现隔离的工具。

// seccomp BPF 过滤器示例(伪代码)
struct sock_filter filter[] = {
    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_write, 0, 1),
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
};

3.6 LSM:内核安全策略框架

Linux Security Module(LSM)在内核关键路径上插入钩子,供 SELinux、AppArmor 等安全模块实施访问控制。eBPF 在 5.7 内核引入了 BPF_PROG_TYPE_LSM,允许用户编写 eBPF 程序直接附加到 LSM 钩子上,实现可编程的安全策略,而无需加载内核模块或修改 LSM 模块。

安全注意: LSM eBPF 程序拥有极高的权限,可以拦截文件访问、任务创建等关键操作。必须确保只有可信的租户或管理面才能加载此类程序。

3.7 六机制协同关系图

下图展示了六种机制在 Linux 内核中的分层关系,以及 eBPF 如何作为粘合剂与增强层与其他机制交互:

Linux 内核安全机制与 eBPF 协同关系 用户空间(容器 / 租户进程) 系统调用层(Seccomp BPF 过滤器) 内核核心层 Namespace Cgroup Capabilities LSM 钩子 eBPF 虚拟机(程序类型:LSM / CGROUP / SECCOMP / TRACING) 可编程安全策略 · 运行时热加载 · 租户感知审计 硬件层(CPU / 内存 / 网络设备) eBPF 位于内核核心层与硬件层之间,通过多种程序类型与上层安全机制交互

3.8 协同工作流程:eBPF 如何增强传统机制

以一个典型的多租户场景为例,展示各机制如何协同:

  1. Namespace 隔离: 每个租户容器拥有独立的网络和 PID 命名空间,确保资源视图隔离。
  2. Cgroup 限制: 控制租户的 CPU 和内存上限,防止资源争抢。
  3. Capabilities 裁剪: 容器仅保留 CAP_NET_BIND_SERVICE 等必要权限,移除 CAP_SYS_ADMIN。
  4. Seccomp 过滤: 限制容器只能调用白名单内的系统调用,减少攻击面。
  5. eBPF LSM 增强: 附加 LSM eBPF 程序,拦截特定文件路径的访问,实现租户粒度的自定义安全策略。
  6. eBPF Cgroup 监控: 通过 cgroup skb 程序统计每个租户的网络流量,触发告警或限流。
核心结论: eBPF 不是替代 Namespace、Cgroup 等传统机制,而是在它们之上提供可编程的增强层。传统机制提供静态、粗粒度的隔离,eBPF 提供动态、细粒度的策略执行与观测能力。两者结合,才能构建完整的租户隔离蓝图。