尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Linux 内核 Perf 事件安全指南:基于 CAP_PERFMON 的监控权限控制与资源管理

Linux 内核 Perf 事件安全指南:基于 CAP_PERFMON 的监控权限控制与资源管理 Linux 内核 Perf 事件安全指南基于 CAP_PERFMON 的监控权限控制与资源管理【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux导读本文基于 Linux 内核官方文档 Documentation/admin-guide/perf-security.rst 编写系统讲解内核 perf_events 子系统即perf_event_open()系统调用及 Perf 用户态工具所依赖的底层机制在权限访问控制与资源管理方面的完整安全模型。你将掌握为何 perf 监控会带来敏感数据泄露风险、内核如何通过CAP_PERFMON能力capability落实最小权限原则、如何用 group setcap sudo 搭建特权 Perf 用户组、perf_event_paranoid各级别对监控范围的具体限制以及文件描述符与内存这两类核心资源的配额机制。文中所有权限判定逻辑均可在当前内核源码中直接定位验证。perf_events 监控为何存在数据泄露风险Performance Counters for Linuxperf_events在提供强大可观测性的同时也可能泄露被监控进程访问的敏感数据。这种泄露既可能发生在直接使用perf_event_open()系统调用 API 的场景也可能发生在 Perf 用户态工具生成的数据文件中。风险高低取决于 perf_events 性能监控单元PMU与 Perf 工具所收集数据的性质。内核文档将收集到的系统与性能数据划分为四个类别系统软硬件配置数据如 CPU 型号与缓存配置、可用内存数量与拓扑、所用内核与 Perf 版本、性能监控配置实验时间、事件配置、Perf 命令行参数等。模块与进程标识数据用户与内核模块路径及其加载地址和大小、进程与线程名称及其 PID/TID、硬件与软件事件捕获的时间戳。计数器执行指标数据内核软件计数器上下文切换、缺页、CPU 迁移等、架构硬件性能计数器PMC与机器特定寄存器MSR的内容它们提供系统各部分的执行指标如内存控制器 IMC、互连 QPI/UPI、外设 PCIe uncore 计数器但不直接归属到任何执行上下文状态。执行上下文寄存器与内存数据架构执行上下文寄存器内容x86_64 上的 RIP、RSP、RBP 等、进程用户与内核空间内存地址和数据、各类可捕获此类数据的架构 MSR 内容。其中第四类数据可能包含敏感进程数据。如果 PMU 在某些监控模式下捕获了执行上下文寄存器或进程内存数据那么对这些监控模式的访问必须被妥善地有序化和安全化。因此perf_events 的性能监控与可观测操作成为内核安全访问控制管理的对象。perf_events 的访问控制模型特权进程与非特权进程为了执行安全检查Linux 实现将进程划分为两类特权进程有效用户 ID 为 0即超级用户 root。特权进程绕过内核所有安全权限检查perf_events 性能监控对特权进程完全开放不受访问范围scope与资源resource限制。非特权进程有效 UID 非零。非特权进程必须通过基于进程凭据通常为有效 UID、有效 GID 和补充组列表的完整安全权限检查。Linux 将传统上与超级用户关联的权限拆分为独立单元——能力capabilities可按线程粒度对非特权用户的进程与文件独立地启用和禁用。CAP_PERFMON最小权限原则的实现拥有CAP_PERFMON能力的非特权进程在 perf_events 性能监控与可观测操作方面被等同于特权进程对待从而在内核中绕过范围scope权限检查。CAP_PERFMON在内核中实现了性能监控与可观测操作的最小权限原则least privilegePOSIX 1003.1e: 2.2.2.39为系统提供了安全的性能监控与可观测途径。在内核源码中CAP_PERFMON的能力编号为 38定义于 include/uapi/linux/capability.h#define CAP_PERFMON 38向后兼容CAP_SYS_ADMIN 与 CAP_SYS_PTRACECAP_SYS_ADMIN出于向后兼容原因访问 perf_events 监控与可观测操作的通道对CAP_SYS_ADMIN特权进程同样开放。但在安全监控与可观测场景下内核文档明确不鼓励使用CAP_SYS_ADMIN而推荐CAP_PERFMON。如果系统审计记录显示某进程在调用 perf_events 系统调用 API 时因同时缺失CAP_PERFMON与CAP_SYS_ADMIN而产生双重拒绝记录则建议仅授予该进程CAP_PERFMON以此消除与性能监控和可观测性使用相关的双重访问拒绝日志。CAP_SYS_PTRACE在 Linux v5.9 之前非特权进程使用 perf_events 系统调用 API 还需要通过PTRACE_MODE_READ_REALCREDSptrace 访问模式检查其结果决定监控是否被允许。因此被授予CAP_SYS_PTRACE能力的非特权进程可有效通过该检查。从 Linux v5.9 起不再要求CAP_SYS_PTRACE只需为进程提供CAP_PERFMON即可执行性能监控与可观测操作。CAP_SYSLOG授予非特权进程的其他能力可能有效启用捕获后续性能分析所需的额外数据。例如CAP_SYSLOG能力允许从/proc/kallsyms文件读取内核空间内存地址。内核源码中的权限判定实现perf_event_paranoid与能力检查的结合逻辑集中体现在 kernel/events/core.c 的三个导出函数中int perf_allow_kernel(void) { if (sysctl_perf_event_paranoid 1 !perfmon_capable()) return -EACCES; return security_perf_event_open(PERF_SECURITY_KERNEL); } EXPORT_SYMBOL_GPL(perf_allow_kernel); int perf_allow_cpu(void) { if (sysctl_perf_event_paranoid 0 !perfmon_capable()) return -EACCES; return security_perf_event_open(PERF_SECURITY_CPU); } EXPORT_SYMBOL_GPL(perf_allow_cpu); int perf_allow_tracepoint(void) { if (sysctl_perf_event_paranoid -1 !perfmon_capable()) return -EPERM; return security_perf_event_open(PERF_SECURITY_TRACEPOINT); } EXPORT_SYMBOL_GPL(perf_allow_tracepoint);可以清楚看到每当 sysctl 阈值被超过且进程不具备perfmon_capable()即拥有CAP_PERFMON时对应操作会被拒绝。这三个函数分别管控内核空间事件kernel、CPU 级事件cpu与 tracepoint 事件的开放程度其声明位于 include/linux/perf_event.h并在配置了 CONFIG_PERF_EVENTS 的内核中由 security 层进一步兜底security_perf_event_open。此外kernel/events/core.c 等处的perfmon_capable()调用还用于内核栈回溯、事件采样等其他权限敏感的路径印证了CAP_PERFMON在整个 perf_events 子系统中的核心地位。创建特权 Perf 用户组借助能力capabilities、特权能力二进制文件、文件系统 ACL以及sudo工具可以创建专属的特权 Perf 用户组组内成员被允许无限制地执行性能监控与可观测操作。具体分两种方案。方案一为 Perf 可执行文件赋予能力第 1 步创建 perf_users 组并将 Perf 可执行文件归属于该组同时限制其他用户访问# groupadd perf_users # ls -alhF -rwxr-xr-x 2 root root 11M Oct 19 15:12 perf # chgrp perf_users perf # ls -alhF -rwxr-xr-x 2 root perf_users 11M Oct 19 15:12 perf # chmod o-rwx perf # ls -alhF -rwxr-x--- 2 root perf_users 11M Oct 19 15:12 perf最终权限变为-rwxr-x---即只有 root 与perf_users组成员可以执行该 Perf 二进制。第 2 步为 Perf 可执行文件赋予所需能力使 perf_users 组成员获得监控与可观测特权# setcap cap_perfmon,cap_sys_ptrace,cap_syslogep perf # setcap -v cap_perfmon,cap_sys_ptrace,cap_syslogep perf perf: OK # getcap perf perf cap_sys_ptrace,cap_syslog,cap_perfmonepcap_perfmon授予 perf_events 监控与可观测操作权限核心能力。cap_sys_ptrace兼容旧内核v5.9 之前的 ptrace 访问模式检查并支持对目标进程的附加观测能力。cap_syslog允许读取/proc/kallsyms中的内核空间地址用于符号解析。libcap 不支持 cap_perfmon 时的回退写法如果系统安装的 libcap 尚不支持cap_perfmon名称可使用其数值编号38代替# setcap 38,cap_ipc_lock,cap_sys_ptrace,cap_syslogep perf注意对于perf top这类工具可能需要将cap_ipc_lock一并加入组合或者改用perf top -m N来减少其用于 perf ring buffer 的内存详见下文内存分配小节。另外使用不支持CAP_PERFMON的 libcap 时cap_get_flag(caps, 38, CAP_EFFECTIVE, val)会失败导致默认事件退化为cycles:u作为变通可显式指定cycles事件让仅带CAP_PERFMON的 perf 二进制同时获得内核与用户态采样# perf top -e cycles最终效果perf_users组成员能够通过执行配置好的 Perf 工具进行性能监控与可观测操作该可执行文件运行时会通过 perf_events 子系统的范围scope检查。方案二通过 capsh 构建特权 Shell 环境当 Perf 可执行文件无法被赋予所需能力时例如文件系统以 nosuid 挂载或文件系统不支持扩展属性可以创建能力特权环境——即一个特权 Shell。该 Shell 为派生进程天然携带CAP_PERFMON及其他所需能力使性能监控与可观测操作在该环境中无限制可用并可通过 sudo 仅向 perf_users 组成员开放。第 1 步创建使用 capsh 的 Shell 脚本将CAP_PERFMON及其他所需能力加入 Shell 进程的 ambient 能力集在启用SECBIT_NO_SETUID_FIXUP、SECBIT_NOROOT、SECBIT_NO_CAP_AMBIENT_RAISE位后锁定进程安全位然后将进程身份切换为 sudo 调用者即 perf_users 组成员# ls -alh /usr/local/bin/perf.shell -rwxr-xr-x. 1 root root 83 Oct 13 23:57 /usr/local/bin/perf.shell # cat /usr/local/bin/perf.shell exec /usr/sbin/capsh --iab^cap_perfmon --secbits239 --user$SUDO_USER -- -l其中--iab^cap_perfmon设置 inherited/ambient/bounding 能力集--secbits239锁定位对应 8 个安全位的组合239 0xEF--user$SUDO_USER将身份切回 sudo 调用者。第 2 步在 /etc/sudoers 中为 perf_users 组扩展 sudo 策略# grep perf_users /etc/sudoers %perf_users ALL/usr/local/bin/perf.shell第 3 步验证 perf_users 组成员能够进入特权 Shell且派生进程的 permitted、effective 与 ambient 能力集中包含CAP_PERFMON$ id uid1003(capsh_test) gid1004(capsh_test) groups1004(capsh_test),1000(perf_users) contextunconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 $ sudo perf.shell [sudo] password for capsh_test: $ grep Cap /proc/self/status CapInh: 0000004000000000 CapPrm: 0000004000000000 CapEff: 0000004000000000 CapBnd: 000000ffffffffff CapAmb: 0000004000000000 $ capsh --decode0000004000000000 0x0000004000000000cap_perfmoncapsh --decode将十六进制位图还原为能力名0x0000004000000000恰好对应cap_perfmon能力编号 38即 1 38。此后 perf_users 组成员即可进入该特权环境使用受CAP_PERFMON能力管辖的性能监控 API 工具。需要特别说明这种访问控制管理方式仅对超级用户root或具备CAP_SETPCAP、CAP_SETFCAP能力的进程可用因为创建能力环境本身需要设置进程能力与文件能力。非特权用户的访问控制perf_event_paranoid非特权进程的 perf_events范围scope与访问access控制由perf_event_paranoid设置决定。该 sysctl 文件位于/proc/sys/kernel/perf_event_paranoid其默认值为 2定义于 kernel/events/core.c并与其他 perf 相关 sysctl 一起注册在 events_core_sysctl_table 中kernel/events/core.c包括perf_event_mlock_kb、perf_event_max_sample_rate等。各级别的具体语义如下值监控范围scope可监控的事件perf_event_mlock_kb 内存锁定限制-1不施加任何 scope 与 access 限制最大化允许的监控范围忽略——分配性能数据存储缓冲区时不应用 per-user per-cpu 锁定限制。这是最不安全的模式因为允许的监控范围最大且对监控资源不施加任何 perf_events 特定限制0每进程 系统级监控排除裸 tracepoint 与 ftrace 函数 tracepoint用户态与内核态执行期间发生的 CPU 与系统事件均可监控施加限制但对拥有CAP_IPC_LOCK能力的非特权进程忽略1仅每进程监控排除系统级监控用户态与内核态执行期间发生的 CPU 与系统事件均可监控施加限制但对拥有CAP_IPC_LOCK能力的非特权进程忽略2仅每进程监控仅限用户态执行期间发生的 CPU 与系统事件可被监控施加限制但对拥有CAP_IPC_LOCK能力的非特权进程忽略结合上文源码可以建立清晰的对应关系perf_allow_kernel()在paranoid 1时拒绝非CAP_PERFMON进程对应级别 2 排除内核态事件、perf_allow_cpu()在paranoid 0时拒绝对应级别 1 排除系统级监控、perf_allow_tracepoint()在paranoid -1时拒绝对应级别 0 排除裸 tracepoint。因此调低perf_event_paranoid会依次开放 tracepoint、系统级监控、内核态事件而最严格的默认值 2 意味着普通用户只能做用户态、每进程的监控。资源控制打开的文件描述符RLIMIT_NOFILEperf_events 系统调用 API 会为每一个配置的 PMU 事件分配一个文件描述符。打开的文件描述符是按进程计账的资源受RLIMIT_NOFILE限制即ulimit -n通常继承自登录 Shell 进程。在大型服务器上为长事件列表配置 Perf 采集时很容易触及该限制导致所需监控配置无法完成。RLIMIT_NOFILE可按用户修改limits.conf文件提升。通常一次 Perf 采样会话perf record所需打开的 perf_event 文件描述符数量不少于监控事件数 × 被监控 CPU 数——例如在 8 核机器上监控 10 个事件就可能需要约 80 个描述符如果还涉及系统级监控请据此评估ulimit -n是否充足。内存分配perf_event_mlock_kb用户进程可用于捕获性能监控数据的内存量由perf_event_mlock_kb设置即/proc/sys/kernel/perf_event_mlock_kb管控。这一 perf 事件专属资源设置定义了用户进程允许映射以执行性能监控的每 CPU 内存总量上限。它本质上是扩展了RLIMIT_MEMLOCKulimit -l限制但仅针对专门用于捕获被监控性能事件及相关数据的 mmap 内存区域。示例若机器有 8 个核、perf_event_mlock_kb设置为 516 KiB则用户进程在RLIMIT_MEMLOCK之上额外获得516 KiB × 8 4128 KiB内存用于 perf_event mmap 缓冲区。这意味着如果用户想同时启动两个或更多性能监控进程必须手动在监控进程之间分配这 4128 KiB例如使用 Perf record 模式的--mmap-pages选项。否则第一个启动的监控进程会占满全部 4128 KiB后续进程将因内存不足而无法继续。CAP_IPC_LOCK 的豁免RLIMIT_MEMLOCK与perf_event_mlock_kb资源约束对拥有CAP_IPC_LOCK能力的进程被忽略。因此可以通过为 Perf 可执行文件赋予CAP_IPC_LOCK能力为 perf_events/Perf 特权用户提供超出上述约束的监控内存——这正是前文特权组配置中将cap_ipc_lock纳入setcap组合、以及perf top -m N减少 ring buffer 内存占用的原因所在。总结Linux 内核通过能力 sysctl 阈值的组合为 perf_events 构建了层次化的安全模型CAP_PERFMON是推荐的监控特权能力配合CAP_SYSLOG、CAP_IPC_LOCK等能力可覆盖符号解析与内存豁免需求perf_event_paranoid则从 -1 到 2 提供从完全开放到仅用户态每进程监控的弹性收紧梯度RLIMIT_NOFILE与perf_event_mlock_kb分别从描述符与内存两个维度约束资源消耗。运维人员既可通过 group setcap 直接赋予 Perf 二进制能力也可通过 capsh sudo 搭建受限特权 Shell。所有关键判定逻辑均可在 kernel/events/core.c 与 include/uapi/linux/capability.h 中直接查阅验证是理解 perf 安全配置与排查EACCES权限问题的第一手依据。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表