首页 文章 精选 留言 我的

精选列表

搜索[muse],共187篇文章
优秀的个人博客,低调大师

Muse Sentinel 逆向工程(3):问题复盘

# 复盘:双容器治理改造全程 样例工程前后干了四件事: - ① 把系统改造成双容器治理拓扑; - ② 优化配置项; - ③ 理清楚架构边界想清楚; - ④ 污点功能静默失效的排查。 ## 0. 总览 |阶段|主题|结果| | --- | --- | --- | |1|双容器治理改造|冻结对象从"进程"改为"容器",治理拓扑定型| |2|配置优化|删掉 8 个配置键,冻结语义| |3|架构梳理|首连报错、冻结半径、污点粒度等边界问题归档| |4|排障|污点链静默失效(主因)+ fork 挂载被内核拒(次因)| ## 1. 双容器治理改造 ### 1.1 初衷 sentinel 本身也跑在容器里,并且去治理 demo-agent 这个容器。这样把 cgroup freezer 冻结的对象可以指定为容器"。加了硬约束: **挂载治理目标走命令行**(sentinel-cli),不进配置文件。 ### 1.2 定型拓扑 ||sentinel-mgmt|sentinel-agent| | --- | --- | --- | |角色|daemon + CLI + 工具链|被治理的 demo-agent| |权限|privileged + pid: host + cgroupns: host|无特权| |关键点|能看到宿主 PID 和全局 cgroup 树|connect 钩子只挂它的 cgroup| 冻结语义为"**冻结整个 agent 容器**"——同容器的无辜 进程会一起暂停,这是**有意为之**。 ### 1.3 运行时挂载 ``` Windows: docker inspect -f '{{.State.Pid}}' sentinel-agent → 宿主 PID sentinel 内:attach-agent.sh (脚本读 /proc//cgroup 找到容器 cgroup 路径 → sentinel-cli cgroup ) ``` 一次动作完成两件事:connect 钩子挂上该 cgroup + freezer 锁定冻结目标。 **注意:挂载状态存在 daemon 内存里,daemon 重启后必须重新挂载**—— 这是"map 不 pin"取舍的一部分(见 3.5)。 ## 2. 配置优化 原则:**能靠固定语义解决的,不给用户旋钮**。逐个决策过程: |键|去向|理由| | --- | --- | --- | |cgroup_path / cgroup_name|删|挂载是运行时动作(CLI),不是静态配置| |freeze_on_review / thaw_on_approve / thaw_on_deny|删|这三个开关只有一种正确组合,固化成行为| |auto_deny_on_timeout|删|超时不是裁决,不该产生裁决动作| |pin_path|删(连同整个 pin 机制)|map 生命周期跟进程走,少一个 bpffs 运行前提| |cleanup_interval|删(改为代码内常量 30s)|避免为每个临时条目建 timer;常量旁写足注释| 固化后的**四种结局**(无任何开关可改): |结局|动作| | --- | --- | |人工批准|临时放行(TTL)+ 解冻| |人工拒绝|永久拉黑 + 解冻| |审批超时|只解冻,不进黑名单,重连重新审批| |没有审批通道|视同拒绝:拉黑 + 解冻| ## 3. 架构梳理 ### 3.1 首次连接必报 EPERM,是架构必然 cgroup/connect 钩子**没有能力"挂起"一个系统调用等审批**——它只能 当场放行或当场拒绝。所以被拦进程的第一次连接必然失败(报权限错误), **重试就是重新触发审批的机制**;审批通过后临时放行生效,重试即成功。 ### 3.2 冻结的爆炸半径 - 整个 agent 容器一起冻; - 已建立的 TCP 连接**停滞而非断开**(冻结期间内核照常代答 ACK),解冻后自动恢复; - 容器里的用户态定时器也被冻结——**审批超时不会因为冻结而白白烧掉**。 ### 3.3 判定粒度 vs 执行粒度 污点判定按**进程**(读过敏感文件的进程才升级),拦截/冻结按**容器**。 一个进程读敏感文件 → 它自己连任何目标都要审批 → 触发审批时整个容器陪冻。两层粒度各司其职。 ### 3.4 污点路径匹配的已知弱点 匹配的是 openat 传入的**原始字符串**(容器内视角),前缀匹配 + 边界检查(`/root/.ssh` 不会匹配 `/root/.sshx`)。已知绕过面:相对路径、symlink 指向敏感文件(字符串不同就不命中)、跨容器同路径歧义。 要根治需路径规范化(bpf_d_path 方向),暂未做,已记录。 ### 3.5 map 不 pin 的取舍 map 挂载状态生命周期 = daemon 进程。代价:重启即重置(策略从配置重新灌入、临时放行丢失、需重新挂载治理目标);收益:无 bpffs 前提、无残留状态、排查时心智负担小。对单机治理场景是划算的。 ## 4. 途中 bug 修复 |症状|根因|修法| | --- | --- | --- | |冻结报"freezer 目标未设置",但治理目标明明挂着|我把 API 依赖里的 Freezer 漏接了(api.Deps 少一个字段)|补上接线;并让接口在 Freezer 为空时告警,防止再次静默失联| |sentinel-cli approve 22959 报 404|approve 要完整 request-id(形如 req-22959-1792977933120093361),PID 只是它的一段|说明用法;(提议加 PID 自动解析,被否决,不再动)| ## 5. 关键排障:污点链静默失效 改造完成后验证场景 6(污染进程连白名单目标)发现:直接放行,不冻结不出卡。此后多轮排障,两个问题互相掩护。 ### 5.1 分清"本来就不出声"和"坏了不出声" 内核对白名单放行是**不发事件不打日志**的——所以没有 `[connect]` 日志是正常的。真正异常的只有 `[taint] 标记污染` 缺失。这一步没走偏,省了大量时间。 ### 5.2 主因:内核参数位置错位 8 字节 排查路径(猜想 → 证据 → 结论): |猜想|证据|结论| | --- | --- | --- | |挂错容器|CLI 查治理目标正是 demo 所在容器|排除| |监控路径没写入内核|bpftool map dump name watch_map 全对|排除| |挂载"假成功"|bpftool perf show 显示链接活着|基本排除| |程序没被执行|开统计后 run_cnt 288→719 自涨|排除| |旧二进制|在二进制里搜诊断关键字 + md5 对比|排除| |参数位置错位|内核 format 文件:真实位置差 8 字节|确认| 根因因果链: ``` 代码以为 filename 在位置 16 → 实际那里是 dfd(值通常是 -100)→ 把 -100 当内存地址读字符串 → 每次读失败 → 静默返回 → 程序执行 719 次,全部无声空转 ``` 能潜伏是因为:加载成功、挂载成功、map 正确——三盏绿灯全亮,唯独数据是错的。 修复 + 防复发三层:**改对结构体**;**编译期断言**钉死关键位置;**启动时读内核 format 文件自检**,对不上就大声停用污点功能并打印真实位置(而不是默默空转);再用实测 format 原文做单测样本。布局由"long 类型多宽"决定,x86-64/arm64 一套通用;32 位内核会被启动自检显式拒绝。 ### 5.3 次因:这个内核拒绝给 fork 事件绑 BPF - 同一瞬间 openat/exit 挂载成功、仅 fork 被拒 → 排除权限类全局原因; - 报错文字说明"打开事件"成功、挂在"绑程序"一步; - 老式挂载通道(ioctl)**同样被拒** → 结论:6.18-WSL2 内核对 fork 事件的 BPF 绑定做了刻意限制。 解法:三层备胎——常规通道 → 老式 ioctl 通道 → **fexit/kernel_clone**(函数返回时拿子进程 PID,和 perf 子系统完全不沾边;kernel_clone 从5.10 起稳定存在;极老内核没 BTF 时自动剔除此程序重试,不强制依赖)。 副作用:分不清进程/协程创建,Go 起协程会各打一条传播日志(无害,判定永远看进程号,协程退出即清理)。 ### 5.4 附带收获:第三方库改名的应对 老式通道第一版用了 x/sys 的结构体,锁定的 v0.43.0 上字段名变了、编译失败。改为**按内核文档手工拼 64 字节**。 ## 6. 排障命令速查 ``` # 程序到底执行没有?(先开统计!) echo 1 > /proc/sys/kernel/bpf_stats_enabled bpftool prog show name sentinel_taint_openat # run_cnt 应该自己往上涨 # 确认挂载还活着 / 看内核里存了什么 bpftool perf show bpftool map dump name watch_map # 监控路径 bpftool map dump name taint_map # 被标记的进程号 # 内核真实传参布局(永远别信记忆里的"标准布局") cat /sys/kernel/tracing/events/syscalls/sys_enter_openat/format # 确认事件上报通路还通:连一个黑名单目标,应看到 [connect] 日志 ```

优秀的个人博客,低调大师

Muse Video API 与 Muse Image API 实战:一张设定图生成同一角色的系列竖屏短视频,视频每秒 $0.037

做系列短视频的团队,比如品牌吉祥物、固定出镜的虚拟主播、连续几集的小剧情,最头疼的是同一个角色每条视频长得都不一样。纯文生视频每次都会重新"想象"一张脸;用首帧图生视频能锁住长相,但每条视频都要从同一张图、同一个构图开始,换个场景就得先另做一张首帧。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册