当前位置:首页>Linux>Linux Security Modules(LSM) 模块 SELinux/AppArmor/eBPF-LSM 认知

Linux Security Modules(LSM) 模块 SELinux/AppArmor/eBPF-LSM 认知

  • 2026-04-02 05:45:47
Linux Security Modules(LSM) 模块 SELinux/AppArmor/eBPF-LSM 认知

写在前面


  • 博文内容为 Linux Security Modules(LSM)认知梳理,覆盖 LSM 的核心机制、发展脉络、6.x 内核阶段能力演进以及实战落地思路
  • 内容会重点介绍 SELinuxAppArmor 与 eBPF-LSM 的关系和使用边界
  • 文中包含常用排查命令与示例,方便快速上手验证
  • 理解不足小伙伴帮忙指正 :),生活加油

 我不再将这个世界与我所期待的、塑造的圆满世界比较,而是接受这个世界,爱它,属于它。---《悉达多》

持续分享技术干货,感兴趣小伙伴可以关注下 ^_^


在 Linux 安全生态中,Linux Security Modules(LSM)是贯穿内核与用户态、连接传统主机安全与云原生安全的核心框架。它打破了早期 Linux 单一安全模型的局限,通过模块化设计让不同安全策略按需集成,成为企业级安全防护的底层支柱。

在当前 AI agent 的场景里看,LSM 的价值会更直观。一个真正可用的 agent 往往不只是“会聊天”,而是具备读取文件、调用命令、访问网络、操作容器乃至连接集群控制面的能力。风险点也恰恰在这里:一旦 agent 进程被提示词绕过、插件被滥用、依赖链存在漏洞,问题很快就会从“模型输出不准”升级成“主机权限外溢”。

这时候,单靠应用层的参数校验、提示词约束或者业务代码里的 if/else 是不够的,因为这些限制都运行在同一个信任域里;而 LSM 能把约束下沉到内核对象访问层面,变成真正的“最后一道硬边界”。换句话说,哪怕 agent 已经拿到了某个 Linux 用户身份,SELinuxAppArmoreBPF-LSM 仍然可以继续裁决:它到底能读哪些目录、能执行哪些二进制、能连接哪些 socket、能不能碰 ssh key/var/run/docker.sockkubeconfig 这类高敏感资产。

从工程落地视角看,LSM 很适合给 AI agent 做“分层最小权限”设计:

  • 给不同类型的 agent 划分独立安全域,例如检索型 agent 只读知识库目录,运维型 agent 仅允许执行白名单命令
  • 把 agent 主进程与高风险工具执行器拆开,通过不同 SELinux type 或 AppArmor profile 做隔离,避免“一次越权,全盘通吃”
  • 限制 agent 对主机敏感文件、Unix Socket、挂载点和网络端口的访问,把能力收敛到任务所需的最小集合
  • 配合审计日志记录“哪一个 agent 在什么上下文下触发了哪次拒绝”,方便后续做策略收敛与攻击溯源

如果再往云原生方向延伸,这个思路会更重要。很多企业开始让 AI agent 直接参与 CI/CD、集群巡检、日志分析、自动化修复,这意味着它背后连接的是更高价值的基础设施。此时 LSM 不只是传统主机加固组件,更像是 agent runtime 的内核级权限闸门:它可以和 namespacecgroupcapabilitiesseccomp 一起组成分层防护,确保 agent 即便“能思考、会调用工具”,也依然只能在预先定义好的安全边界内行动。

因此,理解 LSM 的意义,已经不只是理解 SELinux/AppArmor 的配置语法,更是在理解一个越来越现实的问题:当 AI agent 开始具备执行能力时,我们如何用内核级机制把“可用的自动化”约束成“可控的自动化”。

LSM 和传统文件权限有什么区别

很多时候我们会把 LSM 和 Linux 原生文件权限(rwx)自主访问控制(DAC)混为一谈。两者都能做访问控制,但设计目标和控制能力并不一样。

  • 普通 Linux 用的是「自主访问控制(DAC)」—— 比如root权限最大,普通用户只能操作自己的文件;
  • SELinux/AppArmor 是「强制访问控制(MAC)」——不管你是 root 还是普通用户,程序能做什么、能访问哪些文件 / 端口,都被严格限制,哪怕程序被黑客控制,也干不了坏事。
对比维度
传统文件权限(DAC)
LSM(MAC 框架)
决策依据
用户/组 + 文件 rwx 位
安全策略 + 安全上下文(进程、文件、套接字等)
控制范围
主要是文件对象
文件、进程执行、网络、IPC、挂载等内核关键路径
权限继承
依赖用户身份,进程拿到权限后可继续扩散
可限制进程“即使有权限也不能做某些操作”
默认模型
“谁拥有资源谁决定”
“系统策略统一决定是否允许”
适用场景
日常权限管理、简单隔离
主机加固、容器隔离、零信任与高合规场景

可以简单记忆为:DAC 解决“谁可以访问文件”,LSM 解决“这个进程在当前策略下究竟能做什么”。

如果把 Linux 系统比作一栋办公楼:

  • DAC(传统权限)像门上的机械钥匙:你有钥匙就能开门,没有就进不去。
  • LSM 像楼里的安保系统:即使你有钥匙,也要看你是谁、什么时候来、要去哪个区域、当前规则是否允许。

也就是说,DAC 更像“静态门禁”,LSM 更像“动态风控”。

再举个常见例子:

  • 某进程运行用户是 root,按传统权限它几乎什么文件都能读。
  • 但如果启用了 SELinux/AppArmor,策略可以明确规定:这个进程只允许读 A 目录,访问 /etc/shadow 仍然会被拦截。

所以从结果上看,LSM 不是替代 rwx,而是在 rwx 之上再加一道更细的“安全裁决”。这也是为什么生产环境里常说:权限最小化 不只看 Linux 用户权限,还要看 LSM 策略是否收口。

为什么实验或生产里有人会选择先关闭 LSM

但是往往我们在做实验,或者一些生产环境的应急排障场景,会先选择关闭 LSM。这个决策通常不是“LSM 不好”,而是“当前场景下先保业务可用”。

常见原因:

  • 旧系统兼容性差:应用没有配套 SELinux/AppArmor 策略,启动就被拒绝
  • 故障定位提速:先排除“是否为策略拦截”这一变量
  • 发布窗口很短:来不及完整调策略,只能先临时放开

但代价也很明显:系统少了一层强制访问控制,越权访问和横向移动风险会变高。

更推荐的做法是“临时放松,不长期裸奔”:

  • SELinux 场景先用 permissive 收集日志,再切回 enforcing
  • AppArmor 场景先用 complain 观察行为,再切到 enforce
  • 优先做局部放行(单服务、单容器),避免全局关闭

可以临时关闭用来定位问题,但不建议把“关闭 LSM”当成长期方案。

一、认知 LSM:内核安全的可编程钩子框架

LSM 并非单一安全模块,而是 Linux 内核提供的一套通用安全扩展框架。核心目标是在最小化内核改动的前提下,支持多种强制访问控制(MAC)模型与安全策略的灵活集成。

核心定位:突破传统 DAC 模型局限

早期 Linux 主要依赖自主访问控制(DAC,例如文件权限 rwx),安全性在很大程度上依赖进程行为自律,难以抵御恶意进程越权访问。LSM 通过在关键访问路径(文件读写、网络连接、进程创建、IPC 通信等)插入钩子,提供了统一的安全决策入口。

通过这些钩子,不同安全模块可按策略对访问行为做“允许/拒绝”判定,弥补 DAC 对强制隔离能力不足的问题。

核心原理:钩子机制 + 安全上下文

用一句话讲 LSM = 在内核关键对象访问路径上埋入统一安全钩子,再基于安全上下文做最终裁决。

它不是简单地“在系统调用入口拦一下”,而是把检查点嵌进 VFS、进程管理、网络栈、IPC、挂载、凭据变更等真实执行路径里。所以 LSM 的价值不只是能拒绝访问,更在于它能在对象已经解析、身份已经明确、内核语义已经收敛的阶段做决策,这比很多用户态包装式防护更接近真实执行面。

钩子机制到底钩在哪里

LSM 的基础是内核在大量关键路径上预留的 hook。这些钩子并不直接实现安全策略,而是提供统一“插槽”,让 SELinuxAppArmorSmackYamaBPF LSM 等模块把自己的检查逻辑挂进去。

常见的钩子大致分几类:

  • 文件与目录访问:inode_permissionfile_openpath_unlinksb_mount
  • 进程与执行控制:bprm_check_securitytask_fix_setuidtask_kill
  • 网络相关:socket_createsocket_connectsocket_bindsocket_listen
  • 凭据与对象初始化:cred_preparecred_transferinode_init_security
  • 审计与运行时扩展:BPF LSM 可以在对应 lsm/* hook 点上动态挂程序

从实现视角看,LSM 并不是“每个模块各改各的内核代码”,而是:

  1. 内核在公共路径调用统一的 security_*() 包装函数
  2. 包装函数内部遍历已注册的 LSM hook 链
  3. 每个安全模块按自己的策略做判定
  4. 如果是访问控制型 hook,通常任一模块返回拒绝,内核就会终止后续敏感操作

这个模型很像网络栈里的“统一分发入口 + 不同协议处理器”,只不过这里分发的不是数据包,而是安全决策。

安全上下文存放在哪里

只有钩子还不够,内核还需要知道“谁在访问谁”。这就是安全上下文(security context)的作用。

在 LSM 体系里,主体和客体都可以带有额外的安全属性,常见对象包括:

  • task_struct / cred:进程身份、安全域、能力集等
  • inode / file / super_block:文件、目录、挂载点的安全属性
  • socket:网络对象的访问控制属性
  • msg_msgipckey:消息队列、共享内存、密钥对象等

内核不会把这些对象都改成某个安全模块私有结构,而是预留 security blob 指针或相关扩展区,供各个 LSM 附加自己的元数据。

这也是为什么不同 LSM 的“上下文表达”不一样:

  • SELinux 更偏向标签化,典型是 user:role:type:level
  • AppArmor 更偏向 profile 和路径匹配
  • Smack 也是标签模型,但语义更轻量
  • BPF LSM 往往不自带长期标签体系,而是读取内核对象状态、cgroup、comm、uid、inode 等字段进行动态判定

所以从本质上说,LSM 自己不定义唯一的安全模型,它定义的是安全决策框架;至于“上下文长什么样、策略怎么写、拒绝条件是什么”,由具体模块决定。

一次文件访问是怎么经过 LSM 的

这个过程非常值得展开,因为它最能体现 LSM 不是“粗暴拦系统调用”,而是沿着内核真实路径做检查。

以应用执行下面这个动作举例:

cat /etc/shadow

从概念路径上看,大致会经过下面几个阶段:

  1. 用户态调用 open/openat/openat2
  2. 内核进入 VFS 路径解析,找到目标 dentry/inode
  3. VFS 在关键节点调用如 inode_permissionfile_open 这类安全检查
  4. security_inode_permission() / security_file_open() 分发给各个已注册 LSM
  5. 任一 LSM 返回拒绝,最终系统调用向用户态返回 -EACCES 或 -EPERM

也就是说,真正决定“能不能读”的,不只是传统 rwx 位,还包括访问路径上叠加的 LSM 判断。

一个更接近内核思维的认知是:

  • DAC 先回答:从 Unix 用户权限看,这个动作是否基础可行
  • LSM 再回答:即使基础可行,在当前安全域下是否仍然允许

这也是为什么很多场景下,进程明明是 root,但依然会被 SELinux/AppArmor 拒绝。

执行与网络路径里的 LSM 更关键

除了文件访问,exec 和 socket 往往是主机安全里最敏感的两条链路。

1.exec 链路

一个程序从 fork 到 execve,LSM 不只是检查“能不能执行这个文件”,还会参与:

  • 新执行镜像的安全检查
  • 凭据切换是否合法
  • setuid/setgid 后的安全域变化
  • 执行后的进程是否需要进入新 profile / type

典型相关 hook 包括:

  • bprm_set_creds
  • bprm_check_security
  • bprm_committing_creds
  • bprm_committed_creds

这也是为什么 SELinux 能基于 domain transition 做“执行某个二进制后进入新域”,而不是简单沿用原来权限。

2.socket 链路

网络路径则更多体现在:

  • 谁可以创建什么类型的 socket
  • 谁可以 bind 某个端口
  • 谁可以 connect 到某个地址
  • 谁可以收发特定协议族的数据

典型 hook 包括:

  • socket_create
  • socket_bind
  • socket_connect
  • socket_sendmsg
  • socket_recvmsg

这在云原生和 AI agent 场景很有价值,因为它不只是限制“能不能联网”,还能继续约束“能连什么、从哪个上下文连、是不是能碰控制面端口或敏感 Unix Socket”。

多个 LSM 同时启用时,内核怎么裁决

现代内核经常不是只跑一个 LSM,而是多模块协同,例如:

  • capability
  • yama
  • apparmor 或 selinux
  • bpf

可以先看系统当前启用顺序:

# 查看当前启用的 LSM 模块cat /sys/kernel/security/lsm

输出可能类似:

capability,landlock,lockdown,yama,integrity,apparmor,bpf

这里有两个关键认知:

  • capability 本身也是 LSM 体系的一部分,负责 Linux capability 相关裁决
  • 对很多“返回 int 的访问控制型 hook”来说,拒绝优先于允许,任一模块返回错误码,操作通常就会被终止

因此多 LSM 协同的本质不是“谁最后说了算”,而是“多个安全模块共同收紧边界”。这和很多中间件责任链不同,它更偏向“并联审核,任一票否决”。

1.2.6 为什么说 LSM 比用户态拦截更靠近真实执行面

很多人做安全控制时,习惯在用户态包一层,比如:

  • 命令执行框架里做白名单判断
  • SDK 层限制某些 API 不让调用
  • 在 shell wrapper 里禁止访问特定路径

这些方法不是没用,但它们最大的问题是:检查点离真实资源访问点太远。

而 LSM 的优势在于它工作的时机更晚、更贴近对象:

  • 路径已经解析完成,避免很多“字符串路径”和真实 inode 不一致的问题
  • 进程凭据已经确定,减少用户态 TOCTOU 风险
  • 网络对象已经创建,协议族和地址族语义更明确
  • 最终是否允许由内核决定,不依赖应用自己“自觉守规矩”

所以对于高风险场景,常见做法不是“只做用户态控制”,而是:

业务白名单 + 容器隔离 + seccomp + capabilities + LSM

这里的 LSM 负责的是最后的内核对象裁决。

1.2.7 Demo 1:直接观察 LSM hook 是否在触发

如果系统开启了 tracing/debugfs,可以先看看当前支持哪些 LSM tracepoint:

# 查看 LSM 相关 tracepointsudo cat /sys/kernel/debug/tracing/available_events | grep '^lsm:'

如果能看到类似 lsm_inode_permissionlsm_socket_connect 之类事件,说明内核已经把对应 hook 暴露给 tracing 体系。

接下来可以做一个最直接的观察实验:

# 开一个终端观察 inode 权限检查sudo bpftrace -e 'tracepoint:lsm:inode_permission { printf("comm=%s pid=%d mask=%d inode=%llu\n", comm, pid, args->mask, args->inode); }'

另开一个终端执行:

cat /etc/hosts >/dev/nullcat /etc/passwd >/dev/null

如果你的内核和 bpftrace 环境支持该 tracepoint,就能看到文件访问时 LSM 检查在持续触发。这个实验的重点不是“看见 deny”,而是建立认知:哪怕只是一次普通读文件,LSM 检查也真实地位于内核访问路径中。

1.2.8 Demo 2:观察执行链路里的安全裁决

执行链路也可以做一个轻量观察。先看系统中和 exec 相关的 LSM 事件:

sudo cat /sys/kernel/debug/tracing/available_events | grep -E '^lsm:.*bprm|^lsm:.*task'

如果有对应事件,可以直接追踪:

sudo bpftrace -e 'tracepoint:lsm:bprm_check_security { printf("exec-check comm=%s pid=%d\n", comm, pid); }'

然后执行:

/bin/true/usr/bin/id

如果环境支持,你会看到每次 execve 前都经过了对应安全检查点。理解这个实验的价值很重要:LSM 不只是保护“文件读写”,它还深度参与“进程要不要获得新的执行映像和凭据”。

1.2.9 Demo 3:用 eBPF-LSM 做一个最小 deny 示例

如果系统支持 BPF LSM,可以进一步理解“LSM 不只是静态模块,还能程序化扩展”。

一个最小化思路是:在 file_open 或 socket_connect hook 上挂一个 eBPF 程序,当命中某个进程名或目标对象时返回负错误码,直接拒绝访问。

例如下面这个示意逻辑:

SEC("lsm/file_open")intBPF_PROG(block_bad_reader, struct file *file, int mask, int ret){char comm[16];if (ret != 0) {return ret;    }    bpf_get_current_comm(comm, sizeof(comm));if (__builtin_memcmp(comm, "cat"3) == 0) {return -EACCES;    }return0;}

它表达的语义非常直接:

  • 如果前面的 LSM 已经拒绝,优先透传已有 ret
  • 返回 0:允许继续
  • 返回负错误码:拒绝本次访问

当然,生产里不能真按 comm=cat 这么粗糙地做,但这个 Demo 很适合建立 eBPF-LSM 的第一层认知:安全逻辑已经从“静态配置”扩展成“可编程裁决”。

可以用下面命令确认环境能力:

# 查看当前内核支持的 LSM/BPF 相关能力bpftool feature probe | grep -i lsm# 查看已加载的 eBPF LSM 程序bpftool prog show --type lsm

1.2.10 几个容易混淆但必须说明白的点

1.LSM 不是替代 DAC,而是叠加在 DAC 之上

大部分访问会先经过 Unix 传统权限,再经过 LSM。不是有了 SELinux/AppArmor 就可以不关心文件属主和 rwx

2.LSM 不等于 SELinux

SELinux 只是 LSM 之上的一个具体实现;AppArmorSmackLandlockBPF LSM 都是同一框架里的不同策略模型。

3.路径控制和对象控制不是一回事

AppArmor 更偏路径语义,SELinux 更偏 inode/label 语义。两者都能做强控制,但底层依赖对象模型不同,这决定了它们在重命名、挂载、硬链接等场景下的策略表达方式和维护体验也不同。

4.eBPF-LSM 很灵活,但不是“万能替代品”

它适合做运行时补强、细粒度审计、快速试验和特定场景防护;但在大规模长期治理里,成熟的 SELinux/AppArmor 仍然更适合承接稳定基线策略。

下面是常见的检查命令,可以先建立一个“系统当前 LSM 状态”的基础认知:

# 查看当前启用的 LSM 模块(顺序也很关键)cat /sys/kernel/security/lsm# 查看当前内核支持的 LSM 能力(部分发行版输出格式略有差异)bpftool feature probe | grep -i lsm# 查看已加载的 eBPF LSM 程序bpftool prog show --type lsm# 查看 LSM 相关 tracepoint(需要开启 tracing/debugfs)sudo cat /sys/kernel/debug/tracing/available_events | grep '^lsm:'
# SELinux:查看文件安全上下文ls -Z /etc/passwd# SELinux:查看进程安全上下文ps -eZ | head# AppArmor:查看 profile 执行状态aa-status

与用户态系统调用拦截相比,LSM 钩子在内核对象访问流程中做决策,更贴近内核真实执行路径,能有效减少 TOCTOU 类绕过风险。这也是它能长期成为 Linux 主机安全、容器安全、AI agent runtime 权限约束底座的根本原因。

1.3 主流 LSM 模块生态

理解 LSM 生态时,一个很容易踩的坑是把它简单理解成“SELinux 和 AppArmor 二选一”。实际上,Linux 现在的安全模块已经形成了一个分层体系:

  • 有的模块负责主访问控制基线,比如 SELinuxAppArmor
  • 有的模块负责特定风险面的补强,比如 YamaLockdown
  • 有的模块更适合做开发者侧沙箱或运行时编程扩展,比如 LandlockBPF LSM

所以这一节更推荐按“能力定位”来理解各个模块,而不是只按历史知名度排序。

1.3.1 SELinux:标签化 MAC 的代表

SELinux 是最典型、也最成熟的 LSM 实现之一。它的核心思想不是“按文件路径做判断”,而是给主体和客体打上安全标签,再按策略决定“某类主体能否对某类客体执行某种操作”。

其常见决策模型可以概括成:

主体 domain/type + 客体 type/class + 操作 perm -> allow/deny

例如:

  • httpd_t 是否允许读取 httpd_sys_content_t
  • container_t 是否允许连接某类端口
  • init_t 执行某个二进制后是否发生 domain transition

SELinux 的核心特点:

  • 标签驱动:更接近内核对象本身,而不是依赖字符串路径
  • 策略细粒度:文件、进程、socket、端口、能力、IPC 都能精细控制
  • 支持域切换:一个进程执行不同程序后,可以进入新的安全域
  • 审计能力强:拒绝日志信息完整,适合合规和取证

它的典型优势是:

  • 强隔离能力非常强,适合多租户、政企、金融、高合规环境
  • 对容器、系统服务、守护进程等长期运行对象治理效果好
  • 能把“root 也不能随意越权”这件事落到内核级

它的典型成本也要说清楚:

  • 策略体系复杂,学习曲线明显高于 AppArmor
  • 策略调试、label 维护、文件重标记等工作有一定运维门槛
  • 一旦系统对象和策略不匹配,容易出现“服务明明有权限但仍被拒绝”的排障成本

常见场景:

  • RHEL/CentOS/Fedora 体系主机加固
  • Kubernetes/OpenShift 容器隔离
  • 面向审计与等保合规的生产环境

快速观察命令:

# 查看 SELinux 当前模式getenforce# 查看进程安全上下文ps -eZ | head# 查看文件安全标签ls -Z /etc/passwd

如果用一句话总结:SELinux 更像一套“内核级对象标签治理系统”,而不只是“更严格的权限管理”。

1.3.2 AppArmor:以路径为中心的轻量 MAC

和 SELinux 相比,AppArmor 的认知门槛通常更低。它更强调“给某个程序绑定 profile,然后按路径规则限制它能访问什么、执行什么、联网做什么”。

典型策略关注点包括:

  • 允许读写哪些路径
  • 是否允许执行某些二进制
  • 是否允许网络访问
  • 是否允许访问 capability、mount、ptrace 等能力

AppArmor 的核心特点:

  • 路径导向:策略和文件路径强相关,可读性通常较好
  • profile 模型清晰:每个程序/服务可以绑定独立 profile
  • 学习和维护成本低于 SELinux
  • complain/enforce 模式切换友好,比较适合逐步收敛策略

它的典型优势:

  • 对 Ubuntu/Debian 体系用户更友好
  • 适合以“服务”为单位做隔离治理
  • 对很多工程团队来说,上手更快、策略更容易读懂

它的边界也很明确:

  • 路径语义意味着在重命名、链接、挂载这类场景下,思维模型和标签型方案不同
  • 做极复杂对象关系治理时,表达能力通常不如 SELinux 那么强势

常见场景:

  • Ubuntu/Debian/SUSE 体系默认或常见主机防护
  • Web 服务、数据库、系统守护进程隔离
  • 对可维护性要求高于极致细粒度的团队环境

快速观察命令:

# 查看 profile 状态aa-status# 查看某个程序是否有 profileapparmor_status | grep nginx

如果用一句话概括:AppArmor 更像“面向程序路径和运行画像的安全外壳”。

1.3.3 Smack:更简化的标签模型

Smack(Simplified Mandatory Access Control Kernel)也是标签型 MAC,但它的目标不是像 SELinux 一样把策略做得非常庞大,而是提供一个更简单直接的标签访问模型。

其基本思路是:

  • 主体和客体都有标签
  • 标签之间通过简单规则定义读、写、执行等权限关系

它的特点是:

  • 策略模型相对简洁
  • 适合资源受限或安全模型相对稳定的环境
  • 常见于某些嵌入式或特定定制发行版

相比 SELinuxSmack 的优势在于轻量、规则更直接;但在通用企业 Linux 生态里,它的普及度和工具链成熟度通常不如 SELinux/AppArmor

可以把它理解成:如果 SELinux 像一套大型安全治理系统,Smack 更像一个收敛后的简化标签控制器。

1.3.4 TOMOYO:偏学习模式的路径安全控制

TOMOYO 也是比较有代表性的 LSM,但它的思路和 AppArmor 有点像,同样关注路径和程序行为,只是它更强调从运行行为中学习、再逐步固化策略。

它比较适合用于:

  • 先观察程序真实访问路径
  • 再根据学习结果生成限制策略
  • 最终切换到强约束模式

这个思路很适合历史系统改造,因为很多老应用很难一开始就人工写出完整安全策略。

不过从今天的主流企业落地看,TOMOYO 的声量明显低于 SELinux/AppArmor,更多是特定场景或研究型认知里会接触到。

1.3.5 Yama:聚焦 ptrace 等高风险行为的补强模块

Yama 的定位和前面几个不一样,它不是全量 MAC 框架替代者,而是一个“补强型 LSM”。

它最常被提到的能力是限制 ptrace 行为,例如:

  • 限制任意进程互相调试
  • 收紧跨进程内存观察与注入能力
  • 降低本地提权和信息窃取风险

很多发行版会通过:

cat /proc/sys/kernel/yama/ptrace_scope

来控制其行为级别。

它的价值在于:哪怕系统没有启用特别复杂的 MAC 策略,也可以先把高风险调试类能力收紧,降低本地横向利用面。

所以 Yama 更像是“针对攻击链关键动作的专项闸门”。

1.3.6 Landlock:面向非特权应用的沙箱 LSM

Landlock 是近几年非常值得关注的模块,因为它代表了另一个方向:不是只让系统管理员写内核级安全策略,而是让普通应用也能主动给自己加沙箱。

它的关键价值在于:

  • 面向非特权进程
  • 允许应用在运行时主动声明自己后续允许访问的文件系统范围等
  • 更适合做“应用自我收权”

这和传统 SELinux/AppArmor 的运维视角不完全一样。Landlock 更像给开发者提供一个“用户态自助式最小权限”接口。

典型适用场景:

  • 下载器、文档解析器、浏览器插件等不可信输入处理程序
  • 开发者希望在应用内部主动降低后续文件系统访问面
  • 桌面端或开发工具侧的轻量沙箱

它的边界是:

  • 更适合做附加限制,而不是替代成熟的系统级 MAC 治理
  • 策略能力和覆盖对象面相对聚焦,不像 SELinux 那么全能

如果用一句话概括:Landlock 是把 LSM 能力部分下放给应用开发者的尝试。

1.3.7 Lockdown 与 Integrity:偏平台完整性和内核自保护

很多人在看 /sys/kernel/security/lsm 时会发现除了熟悉的 selinux/apparmor/bpf,还会看到 lockdownintegrity 这类模块。

这两个模块更偏“平台完整性”和“内核自保护”:

  • Lockdown:限制即使是 root 也不能随意做某些会破坏内核信任边界的操作,比如直接访问内核内存、篡改某些底层接口
  • Integrity:为完整性度量、文件签名、可信启动链等能力提供基础支撑,常和 IMA/EVM 这类机制相关

它们和 SELinux/AppArmor 的区别在于:

  • 后者更关注“进程能不能访问对象”
  • 前者更关注“系统信任根和平台完整性是否被破坏”

在安全启动、受监管环境、机密计算、固件到内核的可信链路治理里,这类模块很重要。

1.3.8 eBPF-LSM:把安全策略变成可编程逻辑

eBPF-LSM 是现代 Linux 安全体系里非常关键的变化点。它并不试图完全替代 SELinux/AppArmor,而是让开发者可以在 LSM hook 上动态加载 eBPF 程序,把安全检查逻辑写成代码。

它带来的变化主要有三点:

  • 运行时可编程:不必每次改内核或重写大型静态策略
  • 更适合高变化场景:比如容器、云原生、临时实验、运行时审计
  • 和可观测体系天然结合:易于把检测、审计、拦截串成一体

典型应用方式:

  • 对特定进程的文件访问做额外 deny
  • 拦截某些网络连接行为
  • 把 cgroup、uid、comm、namespace、inode 等条件组合成动态策略
  • 快速验证一条安全规则,再决定是否固化到 SELinux/AppArmor

它的优势很明显:

  • 灵活
  • 迭代快
  • 便于和现代运行时平台集成

但它也有明确边界:

  • 需要较新的内核能力和 eBPF 工具链
  • 程序编写、验证器限制、兼容性调试有一定门槛
  • 不适合把所有长期基线治理都改写成 BPF 逻辑

更合理的工程思路通常是:

  • SELinux/AppArmor 负责长期稳定基线
  • eBPF-LSM 负责运行时补强、灰度试验、快速响应和深度审计

快速观察命令:

# 查看内核是否支持 LSM 相关 BPF 能力bpftool feature probe | grep -i lsm# 查看已加载的 BPF LSM 程序bpftool prog show --type lsm

1.3.9 capability:最容易被忽略,但几乎一定存在的基础 LSM

严格说,capability 也属于 LSM 生态的一部分,而且很多系统里它几乎一定会启用。它负责的是 Linux capability 相关的权限裁决,例如:

  • 是否允许 CAP_SYS_ADMIN
  • 是否允许 CAP_NET_ADMIN
  • 是否允许 CAP_SYS_PTRACE

它的价值在于把传统“root 全有、非 root 全无”的粗粒度权限拆成可组合能力位。

不过 capability 解决的是“超权能力拆分”问题,不等价于完整的 MAC 体系。它通常是所有安全方案里的基础层,而不是最终层。

1.3.10 怎么选择:不要问谁最好,要问谁适合你的治理目标

如果从工程视角给一个简单判断:

  • 要强隔离、强合规、深度对象治理,优先看 SELinux
  • 要快速落地、策略可读、维护成本可控,优先看 AppArmor
  • 要做开发者自收权沙箱,重点看 Landlock
  • 要做运行时动态补强和高变化场景控制,重点看 eBPF-LSM
  • 要做特定攻击面补强,不要忽略 YamaLockdownIntegrity

真正成熟的生产环境,往往不是只靠某一个模块,而是多 LSM 与其他机制一起协同:

capabilities + seccomp + namespace/cgroup + SELinux/AppArmor + eBPF-LSM

这才是现代 Linux 主机和云原生安全生态更真实的样子。

二、LSM 发展脉络:从单模块到多模块协同

LSM 的演进可以粗略分为三个阶段:

2.1 基础建设期:框架确立

如果回头看这段历史,LSM 出现并不是因为社区一开始就想清楚了“要做一个完美安全框架”,而是因为 Linux 安全扩展长期处于“每家都改自己 patch”的割裂状态。

早期多个安全项目都在尝试把自己的访问控制模型塞进内核:

  • 有的项目强调强制访问控制
  • 有的项目强调细粒度对象标签
  • 有的项目强调路径约束或专有安全模型

问题在于,这些能力大多以“内核补丁集”的方式存在,彼此之间很难共存,也很难进入主线长期维护。

根据 Linux Kernel 官方文档中的历史说明,2001 年 3 月,NSA 在 2.5 Linux Kernel Summit 上介绍了 SELinux;随后社区讨论逐渐收敛到一个更现实的方向:不要把某一个安全模型直接主线化,而是先把“安全钩子框架”主线化。 官方文档同时指出,LSM 项目随后启动,并在 2003 年 12 月 合入主线内核。

这个决策非常关键,它本质上做了两件事:

  1. 把“安全模型之争”转换成“统一 hook 框架 + 各模块自行实现”
  2. 把 capabilities 这类原本散落在核心逻辑中的权限判断,也逐步纳入 LSM 语义体系

从内核设计角度看,这是一种非常典型的主线化妥协:

  • 内核主线不直接站队某一种 MAC 模型
  • 但主线负责提供足够稳定的扩展点和对象安全字段
  • 真正的策略竞争放到 LSM 模块层

也正是因为这个架构选择,Linux 才没有把“安全”固化成单一答案,而是给后续 SELinuxSmackTOMOYOAppArmorYama 乃至后来的 LandlockBPF LSM 留出了演进空间。

如果想从运行系统角度感受这套设计现在的落点,可以先看两个基本事实:

# 当前系统启用了哪些 LSMcat /sys/kernel/security/lsm# 当前内核默认的 LSM 顺序(部分系统可直接读取)grep '^CONFIG_LSM=' /boot/config-$(uname -r) 2>/dev/null

这两个文件本身就体现了 LSM 的核心思想:内核负责框架与顺序,具体安全语义由各模块定义。

2.1.1 这个阶段真正解决了什么问题

基础建设期最重要的成果,不是“某个安全模块更强了”,而是 Linux 内核第一次对安全扩展给出了统一工程接口:

  • 关键对象里有了可挂接安全元数据的位置
  • 关键执行路径里有了可复用 hook
  • 模块注册有了统一入口
  • 安全策略不再必须通过长期维护 out-of-tree patch 才能生存

这使得 LSM 从一开始就是“框架先行”,而不是“策略先行”。

2.2 机制完善期:可用性与兼容性提升

框架进入主线之后,第二个问题马上出现了:有了 hook,不代表就能稳定落地。真正困难的是下面这些工程问题:

  • 安全上下文怎么挂到越来越多的内核对象上
  • 不同模块怎么在不互相踩踏的前提下共享 blob
  • 用户态怎么查看、切换、审计安全上下文
  • 发行版如何把安全模块默认启用而不把用户体验彻底搞坏

这一阶段的关键词其实不是“发明新模型”,而是“把模型做成可运营系统”。

从官方文档可以看到,LSM 后来逐渐形成了一套更清晰的对象承载方式:

  • 进程与执行信息挂到 task_structcred
  • 文件系统信息挂到 super_block
  • 文件、管道、socket 信息挂到 inodefile
  • IPC 信息挂到 kern_ipc_permmsg_msg

这一步的价值很大,因为它意味着 LSM 不再只是一堆零散 hook,而是逐渐形成“对象生命周期 + 安全属性生命周期”协同的能力。

与此同时,社区也长期面对一个现实限制:早期和相当长一段时间里,LSM 更偏向“一个 major 模块 + 若干 minor 模块”的模式。

Linux Kernel 文档里对这一点有比较明确的表述:

  • capability 总会存在
  • 可以叠加若干 minor 模块,例如 Yama
  • 但 major 模块通常只有一个,比如 SELinux 或 AppArmor

这背后的原因并不神秘,主要是三个层面的复杂度:

  1. 多个强 MAC 同时裁决时,语义组合非常难定义
  2. 多模块都要占用和管理 security blob,内核对象布局和生命周期会更复杂
  3. 工具链、审计、策略调试都需要知道“到底是谁拒绝了这次访问”

所以这个阶段的 LSM,本质上完成的是“从理论可扩展到可工程部署”的过渡。很多今天看起来理所当然的能力,其实都来自这一时期的打磨:

  • /proc/.../attr 这类进程安全属性接口逐渐稳定
  • /sys/kernel/security/lsm 这种运行时可观察入口越来越清晰
  • 发行版开始围绕 SELinux/AppArmor 建立更成熟的策略包、审计工具和排障流程

从工程角度说,这个阶段最大的贡献是:LSM 不再只是内核安全研究者能用的东西,而开始变成发行版、运维团队、平台团队可以真正接住的能力。

可以用下面命令感受一下这些“工程化接口”:

# 查看运行中的 LSM 顺序cat /sys/kernel/security/lsm# 查看当前进程可见的 attr 接口ls /proc/self/attr# SELinux 体系下查看审计告警sudo ausearch -m AVC -ts recent 2>/dev/null | head

2.2.1 这一阶段的核心矛盾:安全强度和可维护性的平衡

很多团队第一次接触 LSM,都会把问题理解成“功能够不够强”。但进入生产后真正的挑战往往是:

  • 策略能不能持续维护
  • 升级内核和发行版之后会不会大面积误杀
  • 故障时能不能快速判断是 DAC、capability、seccomp 还是 LSM 拒绝
  • 容器和传统系统服务能不能共用一套治理思路

这也是为什么 SELinux 和 AppArmor 会在不同发行版生态里走出不同路线。它们不只是“技术实现不同”,更是对“安全强度 vs 运维复杂度”给出了不同平衡点。

2.3 现代化转型期:与 eBPF 和云原生深度融合

真正推动 LSM 再次“进化”的,不只是内核技术本身,而是工作负载形态变了。

传统主机时代,很多进程是长期稳定运行的:

  • 服务名稳定
  • 文件布局稳定
  • 端口稳定
  • 部署方式稳定

这使得静态策略虽然麻烦,但还能维护。

到了容器和云原生时代,情况明显变了:

  • 工作负载生命周期更短
  • 镜像与进程名变化更快
  • Pod、容器、sidecar、构建任务会持续出现和消失
  • 策略需要和编排系统、镜像、命名空间、cgroup、审计链路联动

于是 LSM 进入了一个新的阶段:不再只是“给系统服务写静态 MAC 策略”,而是要和现代运行时协同,支持更动态的约束方式。

这一阶段最关键的两个变化是:

1.多模块协同开始成为常态

今天的系统里,更常见的不是“只启一个大模块”,而是多种机制共同工作:

  • capability 提供基础能力位裁决
  • YamaLockdownIntegrity 提供特定攻击面补强
  • SELinux 或 AppArmor 提供主基线 MAC
  • Landlock 提供应用自收权
  • BPF LSM 提供运行时动态补强与审计

虽然不同模块在“major/minor”上的角色划分仍然存在,但从治理视角看,现代 Linux 已经明显从“单安全模块中心化”转向“多层安全机制协作化”。

2.可编程安全成为现实

BPF LSM 的出现非常关键。根据内核官方 LSM BPF Programs 文档,eBPF 程序可以直接附着到 LSM hook 上,实现系统级 MAC 与审计策略。

这意味着安全逻辑第一次真正具备了下面这些特性:

  • 不改内核源码即可扩展安全逻辑
  • 可以按进程、cgroup、namespace、inode、socket 等动态组合条件
  • 能和 tracing、metrics、审计平台天然联动
  • 非常适合灰度实验、快速响应和高变化环境

另外,Landlock 也代表了另一条现代化路线。内核官方文档指出,Landlock 首次在 Linux 5.13 引入,它允许非特权进程主动收缩自己的环境权限。这说明 LSM 的角色已经不再局限于“管理员给系统上锁”,而开始支持“应用自己给自己上锁”。

这两条线叠加起来,LSM 的定位就发生了变化:

  • 过去更像“系统管理员写给整台机器的安全策略”
  • 现在更像“主机、容器、应用、运行时共同参与的权限控制平面”

2.3.1 对云原生和 AI agent 场景意味着什么

到了今天,很多企业已经不满足于“保护主机上的传统服务”,而是要保护:

  • 容器运行时
  • CI/CD 任务
  • 集群组件
  • 自动化修复脚本
  • 具备工具调用和执行能力的 AI agent

这时 LSM 的意义明显扩大了。它不只是一个传统 Linux 安全名词,而是在回答一个现代问题:

当工作负载越来越短命、越来越自动化、越来越具备执行能力时,谁来提供最后的内核级权限边界?

答案通常不是某一个单独机制,而是一组机制叠加,其中 LSM 负责最贴近内核对象的那一层:

namespace/cgroup + seccomp + capabilities + LSM + eBPF observability

对于 AI agent 尤其如此。agent 一旦能读文件、起进程、连网络、调容器接口,它就不再只是一个聊天程序,而是一个高自动化执行体。此时:

  • SELinux/AppArmor 负责稳定基线
  • BPF LSM 负责快速补强和运行时策略实验
  • Landlock 适合部分应用自我收权场景

这也解释了为什么今天重新学习 LSM,不应该只停留在“SELinux 配置很麻烦”这一层,而要把它放进现代运行时安全体系里看。

三、Linux 6.x 阶段的 LSM 能力变化

在 6.x 内核阶段,LSM 相关能力的重点可归纳为三类:

3.1 eBPF-LSM 工程化能力增强

  • LSM 挂载点可用性增强,便于把安全逻辑做成程序化策略
  • BPF 验证器与运行时能力持续优化,提升策略可控性与稳定性
  • 与可观测工具链衔接更顺畅,便于“防护+审计”联动

3.2 多模块共存与分工更清晰

多 LSM 协同已是常见部署方式。典型组合是:

  • SELinux/AppArmor:负责稳定的强制访问控制基线
  • eBPF-LSM:负责高变化场景下的运行时检测与快速策略实验

3.3 容器与云原生场景适配持续推进

面向 K8s 场景,策略下发、命名空间隔离、工作负载标签化治理需求越来越强,LSM 正在和容器运行时、网络策略组件、审计平台形成更紧密协同。

四、SELinux、AppArmor 与 eBPF-LSM 的关系和使用边界

很多同学会把三者理解成“互相替代”。更准确的说法是:SELinuxAppArmoreBPF-LSM 都是基于 LSM 框架工作的不同实现形态,侧重点不同,常见是叠加而不是二选一。

4.1 三者关系:同框架下的不同策略引擎

  • LSM:内核统一安全钩子框架,负责“在哪里检查”
  • SELinux/AppArmor:传统 MAC 引擎,负责“按既定策略做强约束”
  • eBPF-LSM:可编程策略引擎,负责“按运行时逻辑做动态判定”

可以理解为:

  • SELinux/AppArmor 偏“稳定基线”,适合长期、可审计、可复用的安全边界
  • eBPF-LSM 偏“动态补位”,适合快速响应新行为、新风险和新业务模式

4.2 使用边界:该用谁、谁来兜底

维度
SELinux
AppArmor
eBPF-LSM
策略模型
标签/类型(TE)
路径规则
程序逻辑(BPF)
稳定性
高,适合长期基线
高,易在 Debian/Ubuntu 体系落地
依赖内核能力与工程实现
上手成本
相对高
相对低
中高(需 BPF/内核知识)
变更速度
高(可快速迭代)
典型价值
高合规、强隔离
快速收口、易维护
运行时检测、精细化拦截
不适合单独承担
高频动态策略试验
复杂标签级合规诉求
全量替代成熟基线策略

落地原则建议:

  • 要“长期稳态合规”:优先 SELinux(RHEL/Fedora 生态)或 AppArmor(Ubuntu/SUSE 生态)
  • 要“快速试验与动态防护”:在基线策略上叠加 eBPF-LSM
  • 不建议仅靠 eBPF-LSM 裸跑生产,缺少成熟基线时治理成本会明显上升

4.3 典型组合方式(推荐)

  • 组合 A:SELinux + eBPF-LSM

  • 适用:金融、政企、强审计场景

  • 思路:SELinux 兜底关键访问边界,eBPF-LSM 补充运行时异常行为检测

  • 组合 B:AppArmor + eBPF-LSM

  • 适用:云原生平台、迭代快的业务团队

  • 思路:AppArmor 快速建立基础隔离,eBPF-LSM 处理短周期风险规则

  • 组合 C:仅 SELinux 或仅 AppArmor

  • 适用:安全边界较稳定、变更频率低的传统业务

  • 风险:对突发新型行为的响应速度通常弱于“基线 + 动态”双层方案

4.4 一个常见误区

误区:启用 eBPF-LSM 后可以完全替代 SELinux/AppArmor。更合理的工程结论是:eBPF-LSM 更像“高机动策略层”,而 SELinux/AppArmor 是“稳定底盘”。两者分层协作,通常比单栈方案更稳、更快、更易审计。

五、实战落地:典型场景与操作示例

5.1 场景一:主机级文件与进程防护

以 AppArmor 为例,为 /usr/bin/cat 配置最小权限,限制其访问敏感文件:

# /etc/apparmor.d/usr.bin.cat#include <tunables/global>/usr/bin/cat {#include <abstractions/base>  deny /etc/shadow rw,  /usr/* r,}# 重载并启用sudo apparmor_parser -r /etc/apparmor.d/usr.bin.catsudo aa-enforce /usr/bin/cat

验证策略:

aa-status | grep /usr/bin/catcat /etc/shadowsudo grep DENIED /var/log/audit/audit.log | tail

如果是 SELinux 场景,通常通过标签与策略模块控制访问边界:

getenforcels -Z /etc/shadowsudo ausearch -m AVC -ts recent

5.2 场景二:容器运行时安全

在容器环境中,常见做法是“容器隔离 + LSM 策略 + 审计联动”:

  • 隔离层:运行时隔离(如 Kata 容器)降低逃逸风险
  • 控制层:对接 LSM 钩子约束关键行为(文件、网络、进程执行)
  • 管理层:集中下发策略并汇聚审计日志

在 K8s 中可先做基础核查:

# 查看 Pod 安全上下文kubectl get pod <pod-name> -o jsonpath='{.spec.securityContext}'# AppArmor 注解示例kubectl annotate pod <pod-name> \container.apparmor.security.beta.kubernetes.io/<container-name>=localhost/<profile-name># 进入容器后检查 LSM 状态(视镜像能力而定)aa-statusgetenforce

5.3 场景三:eBPF-LSM 动态行为拦截

下面示例是“思路代码”,用于说明 eBPF-LSM 工作方式:在 file_permission 钩子中识别访问行为并返回拒绝。实际生产实现需按内核版本和 helper 能力调整。

// lsm_nginx.c (示意)SEC("lsm/file_permission")intBPF_PROG(check_file_permission, struct file *file, int mask){// 1. 获取当前进程信息// 2. 解析目标路径// 3. 按策略判定是否允许// 4. return 0 允许 / return -EPERM 拒绝return0;}

常用验证命令:

# 查看 LSM 类型的 eBPF 程序bpftool prog show --type lsm# 观察运行日志(需开启 tracing)sudo cat /sys/kernel/debug/tracing/trace_pipe

5.4 实战注意事项

  • 内核版本:eBPF-LSM 依赖较新内核能力,生产建议优先选择稳定的 LTS 内核
  • 灰度策略:先审计、后阻断,避免策略误杀影响业务
  • 性能观测:持续监控热点钩子开销,避免复杂策略叠加导致尾延迟抖动
  • 变更治理:策略发布纳入 CI/CD,做到可回滚、可审计、可追溯

六、排障认知:如何判断问题是不是 LSM 导致

很多线上问题最终并不是“程序真的坏了”,而是“程序被 LSM 拦了”。如果排障时没有先确认这一层,就很容易把时间浪费在错误方向上。

一个比较稳妥的思路是:

  1. 先确认系统到底启用了哪些 LSM;
  2. 再看当前服务是否真的命中了拒绝日志;
  3. 最后决定是调策略、切审计模式,还是临时放宽。

6.1 主机通用排查:先确认 LSM 栈和系统状态

无论是 SELinux、AppArmor 还是 eBPF-LSM,第一步都应该先确认宿主机当前到底启用了什么。

# 查看当前激活的 LSM 顺序cat /sys/kernel/security/lsm# 查看内核启动参数里是否显式指定了 lsm 顺序cat /proc/cmdline# 查看 securityfs 是否已挂载mount | grep securityfs# 查看当前系统内核版本uname -r

如果这里连 selinuxapparmorbpf 都不在激活列表里,那后面的很多排查动作就没有意义了。

6.2 SELinux 排障:先看模式,再看 AVC 拒绝

SELinux 场景下,最常见的问题并不是“服务起不来”,而是“服务起得来但某个动作被悄悄拒绝”。所以排查顺序通常是:模式 -> 上下文 -> AVC 日志。

# 查看 SELinux 当前模式getenforce# 查看 SELinux 全量状态sestatus# 查看目标进程的安全上下文ps -eZ | grep nginx# 查看目标文件或目录的安全上下文ls -lZ /var/www/html# 查询最近的 AVC 拒绝sudo ausearch -m AVC -ts recent# 将审计日志转换成人类可读建议sudo ausearch -m AVC -ts recent | audit2why

如果想临时确认“问题是否就是 SELinux 引起”,更稳妥的方式不是直接禁用,而是先切到宽容模式观察:

# 临时切到 permissive,只审计不阻断sudo setenforce 0getenforce# 复现问题后查看 AVCsudo ausearch -m AVC -ts recent# 验证结束后切回 enforcingsudo setenforce 1getenforce

6.3 AppArmor 排障:围绕 profile、模式和拒绝日志来查

AppArmor 的排查一般更直观,因为它以 profile 和路径规则为中心。工程里最常用的判断方式就是:当前 profile 是否生效、是否处于 complain 模式、内核日志里有没有 DENIED。

# 查看 AppArmor 总体状态sudo aa-status# 查看某个进程当前使用的 profileps auxZ | grep nginx# 查看已加载 profile 文件sudo find /etc/apparmor.d -maxdepth 1 -type f | sort | head# 查询最近的 AppArmor 拒绝日志sudo journalctl -k | grep -i apparmor | tail -n 20

如果怀疑是 AppArmor 拦截,可以先把单个 profile 切到 complain 模式,只记录不拦截:

# 将指定 profile 切到 complain 模式sudo aa-complain /etc/apparmor.d/usr.bin.cat# 验证状态sudo aa-status | grep /usr/bin/cat# 复现业务动作后查看日志sudo journalctl -k | grep -i apparmor | tail -n 20# 确认规则无误后切回 enforcesudo aa-enforce /etc/apparmor.d/usr.bin.cat

6.4 eBPF-LSM 排障:重点看程序是否真的挂上了钩子

eBPF-LSM 排障和 SELinux / AppArmor 最大的不同在于:问题不只是“策略对不对”,还包括“程序有没有成功加载、有没有成功附着、有没有被 verifier 拒绝”。

# 查看系统是否支持 BPF LSMbpftool feature probe | grep -i lsm# 查看当前已加载的 LSM 类型 BPF 程序sudo bpftool prog show --type lsm# 查看某个程序的详细信息sudo bpftool prog show --type lsm -j# 观察 BPF/LSM 相关内核日志sudo journalctl -k | grep -Ei 'bpf|lsm' | tail -n 50# 如启用了 tracing,可观察运行时输出sudo cat /sys/kernel/debug/tracing/trace_pipe

如果 bpftool prog show --type lsm 看不到任何程序,而你又确信已经部署过 eBPF-LSM,那么优先检查加载流程和内核能力,不要先怀疑业务代码。

七、灰度验证:从“只审计”到“真阻断”的最小闭环

LSM 最容易出事故的阶段,不是长期运行,而是第一次上策略。所以更推荐的方式不是“一次性全量 enforce”,而是先做最小闭环验证:先能看到、再能解释、最后才真正阻断。

7.1 SELinux:先收集 AVC,再决定是否放行

SELinux 最经典的灰度方式就是 permissive -> 分析 AVC -> 调整上下文/策略 -> enforcing

# 1. 临时宽容模式sudo setenforce 0# 2. 触发一次目标业务访问curl http://127.0.0.1/# 3. 查看最近拒绝并分析原因sudo ausearch -m AVC -ts recent | audit2why# 4. 如需修复文件上下文,可先查看默认映射sudo semanage fcontext -l | grep httpd | head# 5. 恢复目录默认标签并重试sudo restorecon -Rv /var/www/html# 6. 验证后切回强制模式sudo setenforce 1

这类流程的价值在于:你不是“拍脑袋关掉 SELinux”,而是先用审计模式拿证据,再决定怎么修。

7.2 AppArmor:先 complain 学习,再 enforce 收口

AppArmor 更适合做“小步快跑”的 profile 收敛,因为它支持先观察行为,再回收权限。

# 1. 将 profile 切到 complainsudo aa-complain /etc/apparmor.d/usr.bin.cat# 2. 执行一次目标命令cat /etc/passwd >/dev/null# 3. 查看拒绝/学习日志sudo journalctl -k | grep -i apparmor | tail -n 20# 4. 重新加载 profilesudo apparmor_parser -r /etc/apparmor.d/usr.bin.cat# 5. 切回 enforcesudo aa-enforce /etc/apparmor.d/usr.bin.cat# 6. 再次验证sudo aa-status | grep /usr/bin/cat

如果团队还不熟悉 AppArmor,建议先从单一二进制、单一目录的最小 profile 开始,不要一上来就做全业务覆盖。

7.3 eBPF-LSM:先做 observe-only,再做 deny

eBPF-LSM 的优势是快,但风险也在于快。 更稳妥的做法是先把程序写成“只记录、不阻断”,确认命中条件正确后,再把 return 0 改成 return -EPERM 一类拒绝动作。

# 查看当前 LSM BPF 程序sudo bpftool prog show --type lsm# 查看 BPF map,确认命中计数或事件缓冲区是否在增长sudo bpftool map show# 如果你的程序通过 ringbuf/perf event 上报事件,可在用户态读取sudo journalctl -kf# 观察 trace_pipe 中的调试输出sudo cat /sys/kernel/debug/tracing/trace_pipe

在生产里,eBPF-LSM 更适合作为“快速响应层”而不是“第一次就全量阻断层”。先确认规则命中质量,再决定是否真正拒绝,是比较稳的做法。

7.4 容器场景:先看节点,再看 Pod,再看运行时

容器里看到“Permission denied”时,很多人第一反应是镜像权限问题,但真实原因可能是节点上的 AppArmor / SELinux / seccomp / 运行时策略共同作用。

# 节点侧:查看 LSM 状态cat /sys/kernel/security/lsm# 节点侧:检查容器运行时crictl info | head# Pod 侧:查看安全上下文kubectl get pod <pod-name> -o yaml | grep -A20 securityContext# Pod 侧:查看注解中的 AppArmor 信息kubectl get pod <pod-name> -o yaml | grep -i apparmor# 节点侧:查看最近内核拒绝日志sudo journalctl -k | grep -Ei 'apparmor|avc|seccomp' | tail -n 50

在 K8s 里,LSM 排障一定要把“节点视角”和“工作负载视角”放在一起看,只盯着容器内部往往不够。

八、总结

LSM 是 Linux 安全能力的底座,不是某一个具体产品。它的核心价值在于:为不同安全模型提供统一内核接入点,并在传统主机与云原生场景中持续演进。

在工程落地上,建议采用“基线策略 + 动态策略 + 可观测审计”三层体系:用 SELinux/AppArmor 稳定兜底,用 eBPF-LSM 快速响应新风险,用审计链路验证策略效果与性能影响。

博文部分内容参考

© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知 :)


https://docs.kernel.org/security/lsm.html

https://docs.kernel.org/bpf/prog_lsm.html

https://www.kernel.org/doc/html/latest/admin-guide/LSM/index.html


© 2018-至今 liruilonger@gmail.com, 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-04-04 04:14:51 HTTP/2.0 GET : https://f.mffb.com.cn/a/483959.html
  2. 运行时间 : 0.251235s [ 吞吐率:3.98req/s ] 内存消耗:4,862.37kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=6e42e94f05c98a443a6ceebf5f87ce9d
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000583s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000620s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.004030s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.004736s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000743s ]
  6. SELECT * FROM `set` [ RunTime:0.006020s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000739s ]
  8. SELECT * FROM `article` WHERE `id` = 483959 LIMIT 1 [ RunTime:0.020946s ]
  9. UPDATE `article` SET `lasttime` = 1775247292 WHERE `id` = 483959 [ RunTime:0.019302s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.001885s ]
  11. SELECT * FROM `article` WHERE `id` < 483959 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.022151s ]
  12. SELECT * FROM `article` WHERE `id` > 483959 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.025259s ]
  13. SELECT * FROM `article` WHERE `id` < 483959 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.053578s ]
  14. SELECT * FROM `article` WHERE `id` < 483959 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.010300s ]
  15. SELECT * FROM `article` WHERE `id` < 483959 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.010891s ]
0.252922s