第 2
篇 钉了两条等级驱动路径。本篇进入五轴的 libscap
/ 协商轴:原始 syscall
上下文如何越过内核边界,进入用户态统一事件流。读者常见误区是把「DaemonSet
Ready」当成「已有 scap 事件」,或把 0.43 驱动配 0.44
用户态的静默/启动失败当成规则写错。真正要钉死的是:libscap
的职责边界;打开会话与 ring;API Version 与 Schema Version
各自约束什么;scap-open
只到原始捕获边界;双引擎在接口层如何分叉。
本篇在系列中的位置
篇目 核心内容 第 2 篇 · 双引擎对照 modern_ebpf ∥ kmod 第 3 篇 · libscap 会话、ring、API/Schema、scap-open 边界 第 4 篇 · libsinsp 状态富化与用户态进程树 系列目录 全部篇目
版本锚定:Falco 0.44.1;驱动
10.2.0+driver。机制叙述对齐官方 Kernel Events Architecture、falcosecurity/libs 的 libscap,以及 0.44.0 Changelog 对 API/Schema major bump 的说明。无环境则不粘贴伪造falco --version/scap-opendump。 0.43 驱动与 0.44 用户态不兼容。
一、libscap 的职责
falcosecurity/libs 把栈分成三层:
| 层 | 仓库位置(概念) | 职责 |
|---|---|---|
| drivers | driver/(modern_bpf 与 kmod) |
在内核侧采集与 syscall 相关的事件 |
| libscap | userspace 中 System CAPture |
与驱动通信、读 ring、打开/关闭捕获会话、scap 文件读写、部分 OS 状态收集 |
| libsinsp | System INSPection | 机器状态富化、过滤与规则引擎、输出 |
Kernel Events Architecture 的定义更短:libscap 是 Falco libraries 里从 syscall 侧收集数据、并与内核交互的组件;它实现「用驱动收集内核事件」所需的全部功能。对值班排障而言,轴 2 的问题不是「规则 YAML 缩进」,而是:
- 驱动是否已按预期引擎加载;
- libscap 是否成功打开会话;
- API/Schema 是否协商通过;
- ring 上是否持续有原始事件流出。
plugin 框架也落在 libs 里,可扩展非 syscall
源;本篇主线仍是 syscall 驱动 → libscap
→(下一篇)libsinsp。engine.kind=nodriver
/ replay
等形态只作边界提示:没有内核驱动时,本轴的「协商失败」叙事不适用,应改查
plugin 或 scap 回放路径。
把 libscap 说成「Falco 里读 eBPF 的那一层」会丢掉 kmod:它是对驱动的统一捕获门面。五轴里把它单独成轴,正是因为升级事故、错引擎、环未打开都会在这里收敛成「没有原始事件」——这一表象与规则未命中共享「无告警」,却要求完全不同的证据包。
flowchart LR
drv["modern_ebpf or kmod"] --> open["libscap open session"]
open --> nego["API and Schema negotiate"]
nego --> ring["ring or maps read path"]
ring --> evt["scap event stream"]
evt --> sinsp["libsinsp enrich"]
图:协商成功之前没有稳定的用户态事件流。节点为英文;失败应停在 open/nego,而不是规则引擎。
二、打开会话与 ring
Architecture 文档强调:为兼容大量内核版本,穿越内核/用户态边界的低层通信机制随驱动类型与版本变化,但都实现同一套事件收集接口。打开会话时的分工是:
- kmod:驱动须事先以内核对象形式安装;libscap 连接已存在的模块与设备/通信端点。
- modern_ebpf:探针可由 libscap 直接安装(嵌入 binary 的 CO-RE 路径,见第 2 篇)。
会话建立后,事件以 scap 事件格式从内核流出。文档给出的公共头部语义如下(结构名与字段以 libs / Architecture 文档为准):
struct ppm_evt_hdr {
uint64_t ts; /* nanoseconds from epoch */
uint64_t tid; /* thread id that generated the event */
uint32_t len; /* event length including header */
uint16_t type; /* event type */
uint32_t nparams;/* number of parameters */
};载荷是「各参数长度数组 + 参数内容」;参数类型用数值标识映射到 Syscall Events 参考。libscap 的 API 保证:一旦驱动加载并初始化完成,上层看到的是一致编码的事件流,而不是两套完全不同的用户态对象模型。
ring / 共享缓冲是会话的热路径:内核写入、用户态消费;跟不上就会 drop(第 5 篇)。打开会话失败时,规则引擎与输出 sink 都还没有可判定的输入——表象常是「完全无 syscall 事件」,容易被误写成「默认规则集坏了」。
配置侧与会话相关的旋钮(buf_size_preset、drop_failed_exit、modern
专有的 cpus_for_each_buffer
等)改变的是缓冲几何与内核侧丢弃策略,不改变「必须先协商成功」这一门闩。
打开会话还可以从失败模式反推:若进程能启动却长期读不到事件,优先核对「会话是否真的进入 running 捕获」与「Driver 行是否为预期引擎」,而不是先改规则优先级。Architecture 文档把跨边界通信写成随驱动与内核版本变化——这意味着同一套用户态在换内核大版本后,即便 Schema 名义兼容,通信路径(ioctl 参数、map 布局、ring 映射)仍可能要求匹配的驱动构建。0.44 用 major bump 把「假装兼容」的空间收得很窄:错配更常表现为明确失败,而不是半残的字段流。
三、API Version 与 Schema Version
Architecture
文档把协商钉成启动硬步骤:连接内核对端时,libscap
必须协商驱动识别的 API
Version 与 Schema
Version。二者都用 semver
子集表达,具体常量与兼容函数在 libs 仓库(例如
scap_is_api_compatible /
check_api_compatibility 一类路径:对
major/minor/patch 做语义化检查;驱动提供
get_api_version /
get_schema_version 时才执行)。
| 版本 | 约束对象 | 文档语义 |
|---|---|---|
| API Version | 内核 ↔︎ 用户态通信机制 | 随驱动而异;kmod 侧常见 ioctl + ring;modern_ebpf 侧用 maps 等,并随内核版本变化。驱动可与 Falco 分开部署,故启动时必须验证正在连接的驱动是否兼容。 |
| Schema Version | 驱动支持的事件类型集合与参数布局 | Syscall Events 文档列出各版本字段;列表一变,Schema Version 随之更新。 |
falco --version 在真实节点上用于核对 Libs /
Driver API / Schema / Default driver 等行。Architecture
文档曾用 0.35.1 示例展示字段布局;本系列不粘贴伪造的
0.44.1 输出。语义上,值班应把「API/Schema 行是否与
10.2.0+driver 及当前用户态期望一致」当作轴 2
的第一抓手。
0.44 相对 0.43 的 major bump
0.44.0 Changelog 写明:驱动 API 与 schema 经历
major bump;随 Falco 0.43.0 发布的 kmod 与
modern_ebpf 不兼容 0.44.0 用户态。驱动线从
9.1.0+driver 升到
10.2.0+driver。删除 legacy
eBPF 与 bump
同期发生,进一步缩小「旧探针凑合连上」的空间。
| 错配组合 | 预期机制后果(官方口径) | 易被误判成 |
|---|---|---|
| 0.44 用户态 + 0.43 驱动 | 协商失败 / 无法使用该驱动 | 「规则写错」「chart 没挂 rules」 |
| 0.43 用户态 + 0.44 驱动 | 同样不在支持矩阵内 | 「升级成功但无告警」 |
配置残留 engine.ebpf |
0.44 启动因已删键失败 | 「镜像坏了」 |
成对升级检查单见 第 12 篇。本篇结论只需一句:无原始事件时,先查协商,再查规则。
API 与 Schema
拆开还有一层运维含义:通信机制未变但事件类型集合变了(Schema
bump),规则可能开始引用新 syscall
字段,或旧字段布局失效;通信机制变了但 Schema 名义相近(API
bump),则表现为连不上或读环失败。0.44 对两者同时 major
bump,因此「只换 chart、不换 driver」与「只换
.ko、不换用户态」都会踩同一类事故,只是日志落点不同。libs
把兼容检查收进
libscap(而非散落在各引擎私有路径)的意图,是让所有仍支持版本协商的引擎走同一套
semver 门闩——引擎若未实现
get_*_version,检查可为 no-op,但 kmod /
modern_ebpf 在 0.44 线上属于必须核对的一侧。
四、scap-open
边界(只写语义,不贴伪造 dump)
libs 仓库提供
scap-open:给贡献者与专家用户从多种驱动
dump 原始事件 的工具。Architecture
文档把它放在「检查内核数据收集」一节——边界是:
| 在边界内 | 在边界外 |
|---|---|
| 验证驱动是否产出 scap 编码事件 | 规则条件求值、优先级、异常 |
观察原始 type / 参数布局 |
libsinsp 路径富化、进程树字段 |
| 对比引擎切换后原始流是否仍打开 | stdout/file/http 等 sink 与 plugin 元数据 |
因此:scap-open 能证明的是 轴
1–2(驱动 +
libscap),不能证明「规则应该告警」。本仓库实验台账无
Falco 节点时,不粘贴伪造 dump;有环境时再按
libs 仓库说明构建与运行,并注明删减。
把 scap-open 有输出、Falco
无告警,翻译成排障语言:事件已进入用户态捕获层 → 下一锤打
libsinsp 富化 或
规则引擎(第 4、6 篇),而不是重装
driver。
scap-open
也不能替代版本协商检查:它证明「当前这套驱动+打开参数能出事件」,不自动证明生产
DaemonSet 用的是同一 API/Schema 组合。生产排障仍以 Falco
进程自身的协商结果为准;工具只是把轴 2
从黑盒里拆出来的实验室探针。有环境时贴输出须注明版本与删减,本仓库当前不编造样本。
五、与双引擎的接口差
两条引擎在进入 libscap 之后共享「scap 事件流」抽象,但在如何装上、如何通信、哪些旋钮生效上分列:
| 接口点 | modern_ebpf | kmod |
|---|---|---|
| 安装 | libscap 可直接注入嵌入探针 | 必须预先有 .ko |
| 通信 | maps 等;随内核版本变化;BPF ring buffer | 常见 ioctl + ring |
| 协商 | 同样检查 API/Schema | 同样检查 API/Schema |
| 缓冲几何 | buf_size_preset +
cpus_for_each_buffer |
buf_size_preset;无 modern 专有 CPU
映射 |
| 0.44 状态回填 | BPF iterators(可关,见第 5 篇) | 不以 modern iterators 路径对称假设 |
| 权限失败落点 | capability / BPF 加载 | 模块签名、设备节点、特权安装 |
排障口诀与第 1 篇一致:双引擎在轴 1–2 分列证据包。协商失败时,先读实际引擎,再读 API/Schema,不要用另一引擎的安装手册解释本引擎的日志。
一个可操作的检查顺序是:确认 engine.kind /
Helm driver.kind 意图 → 确认实际 Driver 行 →
确认 API/Schema 与 10.2.0+driver 对齐 → 再谈
ring 几何与规则。跳过前三步直接改
buf_size_preset,只会在「根本没有会话」时浪费时间。反过来,协商已成功却仍无业务告警,应把火力转到第
4–6 篇,而不是反复重装驱动。
谱系与开放问题
经典 BPF / 扩展 BPF(过滤与可编程边界)
→ 可加载驱动把 syscall 上下文送出内核(scap 谱系)
→ libscap:统一事件接口 + 分驱动通信 + 版本协商
→ 0.44:API/Schema major bump;legacy 探针删除放大「错配即失败」
争论:分开部署驱动带来运维灵活性(kmod
预装、异构内核),也带来版本协商税;全部嵌入
modern_ebpf 减少 .ko 流水线,却把失败前移到 BPF
特性与能力集。本系列不宣布单一赢家,只要求错配可归因到轴
2。
开放问题:导出采样(若启用)与真实事件完备性如何在指标上对齐;双引擎在相同 Schema 下字段完备性是否可做自动差分(留给 05、14、16)。
本篇不写什么
- 伪造
falco --version/scap-open输出。 - 把 live
/docs/的后版本 API 写成 0.44.1。 - libsinsp 富化与规则求值细节(第 4、6 篇)。
- 完整 Syscall Events 字段百科。
参考资料
规范 / 官方文档 / 源码(A)
- Falco Kernel Events
Architecture(libscap;API/Schema;kmod vs modern
安装;scap 头部;
scap-open) - Falco Kernel Events(双驱动总览)
- Falco 0.44.0 Changelog(API/Schema
major bump;drivers
10.2.0+driver;与 0.43 不兼容) - falcosecurity/libs:libscap;
driver/;API 兼容检查(如scap_is_api_compatible/check_api_compatibility) - falco.yaml @
0.44.1:
engine.*缓冲相关项
站内对照
- 第 2 篇 · 双引擎对照
- 第 1 篇 · 五轴
- PLAN.md §九篇 03
学术谱系(A)
- McCanne & Jacobson, The BSD Packet Filter, USENIX Winter 1993
- Garfinkel, Traps and Pitfalls…, NDSS 2003
上一篇:双引擎对照
读完这篇,下一步读什么
优先读同系列或同问题的下一篇,把单篇消费变成主题集群。
【Falco】运行时检测全景:缺口、五轴坐标系与 16 篇路线
相对 Tetragon 排除树、可观测对照与 linux/ebpf-security 快速启用清单,钉清 Falco 0.44.1 检测内核缺口;定义 Driver、libscap、libsinsp、规则引擎、输出与丢事件五条轴,并强调 modern_ebpf 与 kmod 分列证据包。
【Falco】运维与升级:0.43→0.44 成对换驱动
按 0.44.0/0.44.1 Release Notes 钉破坏面:legacy eBPF、gVisor、gRPC output 已删;API/Schema 大 bump 要求用户态与 10.2.0+driver 成对升级;附升级否证表与 live 文档 vs tag 门禁。
【Falco】排障坐标系:五轴否证与双引擎证据包
按 Falco 五轴映射无事件、协商失败、富化空洞、规则未命中与输出/丢事件;强调先点名轴、modern_ebpf 与 kmod 分列证据包;并说明不可与 Tetragon 五轴混因果。
Falco / 运行时检测:从双引擎驱动到规则引擎
补齐站内 Tetragon 排除树与产品对照之上的 Falco 检测内核:modern_ebpf 与 kmod 双引擎、libscap/libsinsp、规则引擎与输出,并以排障与相对 Tetragon/auditd/seccomp 的选型收束。