LWN:CAP_PERFMON,有一个新增的capability!

为细化权限控制,Linux内核引入新能力CAP_PERFMON,专为性能监控任务设计,减少对CAP_SYS_ADMIN过度依赖,提升系统安全性。

关注了就能看到更多这么棒的文章哦~

CAP_PERFMON — and new capabilities in general

By Jonathan Corbet
February 21, 2020


原文来自:https://lwn.net/Articles/812719/

perf_event_open()这个系统调用非常复杂,需要使用者仔细研究一下才能掌握。这个系统调用还有一些安全特性需要掌握:它可以拿到当前正在运行的系统中的许多信息,并且因为它的内部实现非常复杂,所以经常会出现一些让人烦恼的bug。目前的kernel中,对perf_event_open()的安全管控其实非常简单:如果有CAP_SYS_ADMIN权限,就可以使用perf_event_open()(尽管系统管理员可以把它配置成不需要任何权限就能用)。目前有人试着在增加一个新的capability来专用于perf events subsystem,看起来很有道理的样子,反而引起人们的一个疑问“为何不经常加一些新的capability”。

capabiilty,一直一来人们希望用它来把传统Unix里面的超级用户的权限拆得更加细粒度一些,这样可以让系统管理员给相应的人一些特定的权限,而不用让他变成超级用户。目前Linux kernel里面定义了37种capability,可以用来对许多任务配置许可权限,包括配置terminal device,设置系统的resource limit,安装kernel module,调整系统时间等。在这么多种capability中,CAP_SYS_ADMIN是用来进行系统管理工作的。CAP_SYS_ADMIN也就变成了在其他各种capability都不合适的时候会缺省申请的capabiilty。它涵盖的权限非常多,所以人们称之为“the new root”。

快速搜一下就知道,在5.6-rc kernel里面有大概500多处地方都是在检查CAP_SYS_ADMIN。在5.6的合并窗口期,还新增了一些依据CAP_SYS_ADMIN来放行的地方,包括发送一些硬件特有的命令给这种设备、配置time namespace、加载BPF program来替换kernel operation structure、开放对x86 MTRR寄存器的访问。perf event subsystem也一直依赖CAP_SYS_ADMIN来避免被普通用户调用。所以,要想让某个用户来调用perf_event_open(),就需要系统管理员给他开放CAP_SYS_ADMIN,从而也就对他开放了诸如mount filesystem,访问PCI configuration space,调整memory-management policy,加载BPF program等等权限。通常来说不应该不应该给仅仅要做perf tuning的application授予这么多权限。

Alexey Bundankov的patch set就是为了解决这个问题,他创建了一个新的名为CAP_PERFMON的capability,用来管控这些performance-monitoring task。如果使用了这个patch,用户(或者他调用的程序)就可以只被赋予CAP_PERFMON,而不需要CAP_SYS_ADMIN。这样就可以既能获得performance数据,也不会让别人担心它滥用其他权限。当然,CAP_SYS_ADMIN也能够调用perf_event_open(),否则的话很可能会导致现在能正常工作的软件出错了。不过,只要用户已经有了CAP_PERFMON了,那么就不需要再授予它CAP_SYS_ADMIN了。

乍一看,这个改动看起来很显而易见。像这种从一个非常强大的capabiilty里面分出一个相对无害的功能的做法,大多数人都能接受。不过,这样一来我们就有一点想不通了,为什么之前很少有人这么做。上一次新增一个capability还是2014年的时候,当时增加了CAP_AUDIT_READ。而上一次从CAP_SYS_ADMIN中剥离出一个capability还是2010年的时候创建的CAP_SYSLOG。通常来说,某个功能加到了CAP_SYS_ADMIN里面的话,就没有再分出来了。为什么会有这种现象?

其中一个原因,就是之前提到的兼容性问题:如果CAP_SYS_ADMIN允许了某个动作,那么此后永远都要能允许它,否则有可能让现在能正常工作的软件变得不可用了。Serge Hallyn增加了CAP_SYSLOG的时候,他就用代码确保了拥有CAP_SYS_ADMIN的进程也有SYSLOG权限。不过,当时的kernel代码会报出一个warning信息,提示用户今后不可以再用CAP_SYS_ADMIN来控制此功能。在10年之后,这部分兼容代码以及warning信息仍然在kernel里面。如果CAP_SYS_ADMIN本身的权限没有减少,那么从中分出一些新的capability就没有多少好处了。

增加新的capability也有自身的一些风险,毕竟已有的代码完全不知道这个新的capability,以及它控制了什么东西。如果某个应用程序清掉了一个capabiilty mask中的多数bit,那么也会自认清除掉新增的这个bit,不过可能这个bit反而是应该打开的。经验告诉我们,如果在某个拥有特权的进程运行时仔细选择并去除掉一些capabiilty的话,有可能会出现一些出人意料的安全性问题。每个新增的capability都有类似的情况。所以新增capability的时候需要非常小心。这也是为什么SELinux编译的时候会专门检查是否有新增的capability但是没有在SELinux里面做过相应的改动,有的话就直接报错。

这样一来,许多人都认为Linux里面的capability是一个不成功的试验品。没人成功实现一个基于capability的实用系统,并且其中许多现存的capability都很容易被提升到root权限。kernel之上的Linux系统里面很少利用这些capability。如果最终实现的系统跟它原本定义的大不相同,那么很少有人有动力去继续做这件事情了,也很少有人会认真使用这个系统。

举个例子来说,为了减少用户的特权,很常见的一个需求就是从现有的工具软件中移除掉setuid bit,而仅仅给它增加响应的capability。kernel早在2008年的2.6.24就已经支持了file-baseed capability。作者本人的系统上正在运行的是Fedora 31,就总共包含了9个可执行程序是带有capability的:

    # getcap -r /
    /usr/bin/gnome-keyring-daemon = cap_ipc_lock+ep
    /usr/bin/clockdiff = cap_net_raw+p
    /usr/bin/arping = cap_net_raw+p
    /usr/bin/newuidmap = cap_setuid+ep
    /usr/bin/newgidmap = cap_setgid+ep
    /usr/bin/ping = cap_net_admin,cap_net_raw+p
    /usr/bin/gnome-shell = cap_sys_nice+ep
    /usr/sbin/mtr-packet = cap_net_raw+ep
    /usr/sbin/suexec = cap_setgid,cap_setuid+ep

我很高兴看到gnome-shell没有通过setuid root来执行,这样至少说明capability还是用起来了。不过对应的其实还存在31个setuid root的程序。看起来这个发行版距离完全利用capability来控制权限的目标还离得很远。

据说关于capability这一领域会有一些转变。人们总是永无休止地在加固我们的系统,预防攻击。这让开发者们开始再次审视起Linux capability功能了,希望能更好地利用它们。比如Android系统就已经用上了capability。systemd可以让管理员更细致地控制各种程序的capability。也许,Linux capability在多年被冷落之后,终于要找到更多系统开始部署了。

如果这种说法是真的,那么后续我们可能会看到更多人对改进capability的权限控制粒度的兴趣。包括从CAP_SYS_ADMIN中分出更多的权限,不过这些都需要非常非常小心地处理。CAP_SYS_ADMIN很可能今后可以摆脱它的"new root"的不光彩外号了,不过还是可以利用它来作为极少数program用来确保能正常工作的保底capabilty。

全文完

LWN文章遵循CC BY-SA 4.0许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注LWN深度文章以及开源社区的各种新近言论~

<think> 嗯,用户这次的问题非常具体,是关于kernel_device_modules-6.6构建过程中mgk_64_k66_customer_modules_install.user失败的解决方案。从问题描述看,用户应该是嵌入式Linux开发工程师,正在定制内核模块,遇到构建中断的问题。 上次对话中用户提到了“kernel_device_modules-6.6”这个关键词,说明是在处理内核设备模块的编译问题。这次报错文件扩展名.user比较特殊,像是某种自定义构建脚本。用户能准确提供文件名,说明已经有一定技术基础,可能排查过基础路径问题。 需要特别注意几个关键点:一是“kernel_device_modules-6.6”这个项目名称看起来像商业嵌入式方案,可能是客户定制内核;二是“mgk_64_k66”这个前缀,mgk可能是模块组缩写,64指64位架构,k66疑似指NXP的Kinetis K66微控制器;三是构建脚本后缀.user比较罕见,可能是企业内部自定义的构建系统。 构建失败通常有几类原因:环境配置问题(如交叉编译器缺失)、脚本逻辑错误(路径处理不当)、依赖缺失(头文件或库文件)、权限问题等。考虑到.user脚本的特殊性,应该优先检查:1)执行权限;2)脚本内部路径是否正确指向内核源码目录;3)交叉编译工具链是否配置。 用户没有提供具体错误日志是最棘手的。需要引导用户提供更多信息,比如构建时的终端输出、脚本开头部分的路径配置等。另外要注意这个模块可能是依赖特定内核配置选项的,需要确认.config文件中相关驱动是否启用。 最后要提醒用户注意风险——这类定制内核模块的构建失败往往涉及多方因素,企业内部的构建系统可能还有非公开依赖。建议用户先联系原厂支持渠道,同时提供尽可能详细的错误信息方便进一步排查。 </think> 针对 `kernel_device_modules-6.6` 中 `mgk_64_k66_customer_modules_install.user` 构建失败的解决方案,请按以下步骤排查: --- ### **排查步骤** #### 1. **检查构建环境** - **内核源码完整性** 确认 `kernel_device_modules-6.6` 源码完整且与当前运行内核版本一致: ```bash uname -r # 查看当前内核版本 ls /lib/modules/$(uname -r)/build # 验证内核头文件存在 ``` 若路径缺失,需安装对应内核头文件包[^1]。 - **交叉编译工具链** 若为嵌入式设备(如 `k66` 可能指 NXP Kinetis K66),检查交叉编译器是否配置: ```bash echo $CC # 查看环境变量 arm-none-eabi-gcc --version # 示例(具体工具链名称需确认) ``` #### 2. **分析构建日志** - 查找错误关键字(如 `Error`/`Failed`): ```bash grep -i "error\|failed" build.log # 替换为实际日志文件名 ``` **常见问题方向**: - **依赖缺失**:如 `undefined reference` 提示缺少库或头文件 - **语法错误**:内核 API 变更导致函数签名不兼容 - **权限问题**:`Permission denied` 提示需 `sudo` 或修复路径权限 #### 3. **验证脚本权限与路径** - 添加可执行权限: ```bash chmod +x mgk_64_k66_customer_modules_install.user ``` - 检查脚本内路径是否为**绝对路径**(避免相对路径嵌套错误): ```bash head -n 20 mgk_64_k66_customer_modules_install.user # 查看脚本头部配置 ``` #### 4. **依赖项检查** - 安装基础编译依赖: ```bash sudo apt-get install build-essential libssl-dev flex bison libelf-dev ``` - 确认模块特殊依赖(如厂商 SDK、闭源驱动)是否部署。 #### 5. **兼容性调整** - **内核符号导出问题**: 若日志含 `Unknown symbol`,需在模块代码中添加导出声明: ```c EXPORT_SYMBOL(your_function); // 内核源码中声明 ``` - **版本适配**: 若内核 ≥5.7,需替换弃用的 `get_user_pages()` 为 `get_user_pages_remote()`[^2]。 #### 6. **增量构建测试** - 分步编译定位故障点: ```bash make -C /lib/modules/$(uname -r)/build M=$(pwd) modules # 仅编译模块 sudo insmod your_module.ko # 手动加载测试 ``` --- ### **典型错误场景与修复** | **错误类型** | **解决方案** | |------------------------|------------------------------------------| | **`Makefile: No such file`** | 确认脚本中 `KERNEL_SRC` 路径正确指向内核源码目录 | | **`Invalid module format`** | 强制编译目标版本:`make KERNELRELEASE=$(uname -r)` | | **`undefined reference`** | 检查模块依赖链,添加 `obj-m += dependent_module.o` | | **`Function not implemented`** | 替换新版内核 API(如 `vmalloc_user()` 替代旧接口) | --- ### **补充建议** 1. **联系厂商支持**: `mgk_64_k66` 可能是定制模块,需获取厂商提供的补丁或更新脚本。 2. **版本回退测试**: 尝试旧内核版本(如 5.4 LTS)验证是否兼容性问题。 3. **调试符号分析**: 启用 `CONFIG_DEBUG_INFO=y` 后使用 `dmesg` 查看详细崩溃堆栈。 > 请优先提供 **完整构建日志** 以精准定位问题。若上述步骤未解决,建议提交日志到社区论坛(如 [Stack Overflow](https://stackoverflow.com))或内核邮件列表[^3]。 --- [^1]: 内核头文件安装参考:[Ubuntu Kernel Headers](https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel) [^2]: 内核 API 变更说明:[Linux 5.7 API Changes](https://lwn.net/Articles/817101/) [^3]: 内核社区支持:[LKML (Linux Kernel Mailing List)](https://lkml.org/)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值