4

作为构建过程的一部分,我想运行以下两个命令:

sudo chmod a+r /dev/cpu/*/msr
sudo setcap cap_sys_rawio=ep ./bench

这会将内核模块/dev/cpu/*/msr公开的文件设置为全球可读,并设置实际读取这些文件所需msr的二进制文件(作为构建的一部分生成)的附加权限。./bench

问题是这需要 root 权限,因此sudo.

我想要一个类似 setuid 根脚本的东西来完成这两个特定的事情,但是在现代 Linux 上不推荐和禁用setuid 根脚本。

对于一个简单的解决方案,我有哪些选择?

仅适用于第二行(setcap)的解决方案也很有趣,因为我需要这个来运行每个构建,而chmod每次启动只需要运行一次。

4

3 回答 3

5

通过实现同样的事情libcap实际上并没有那么多代码:

#include <stdio.h>
#include <sys/capability.h>

int main(int arc, char *argv[]) {
    cap_t c = cap_from_text("cap_sys_rawio=ep");
    int status = cap_set_file("./bench", c);
    cap_free(c);
    if (status)
        perror("attempt failed");
    return status != 0;
}

要编译它(在 debian 上,您需要sudo apt-get install libcap-dev; 在 fedora 上,sudo dnf install libcap-devel):

$ gcc -o mkcap mkcap.c -lcap

如果您只是按原样运行它,它将失败,因为程序需要具有足够的权限才能实际将功能添加到./bench

$ ./mkcap
attempt failed: Operation not permitted

因此,您需要使其本身具有足够的能力:

$ sudo /sbin/setcap cap_setfcap=ep ./mkcap
$ ./mkcap
$ echo $?
0
  • 您可能需要考虑更明确地使用"./bench"二进制文件的路径,因为根据您的环境,您可能会担心有人会滥用mkcapcap_sys_rawio其他程序。使用完整的路径名将不那么模棱两可。
  • 您还chmod go-x ./mkcap可以限制谁可以运行它。
  • 您还可以考虑对所有这些使用可继承的功能:
basic $ sudo setcap cap_setfcap=ei ./mkcap
basic $ ./mkcap
attempt failed: Operation not permitted
basic $ sudo capsh --inh=cap_setfcap --user=$(whoami) --
enhanced $ ./mkcap
enhanced $ echo $?
0

enhanced(capsh shell)层中,您可以在设置了文件可继承位的二进制文件上提高该功能。这样,默认basic层 shell 无法从mkcap. 在所有其他方面,enhanced外壳层与层相同basic。例如,您可以执行构建并且几乎可以正常做事。(exit用于离开enhanced外壳。)

有一个pam_cap模块还可以在登录等时向特定用户的所有 shell 添加一个可继承位。

于 2021-04-10T16:09:51.353 回答
4

您可以构建一个简单的 C 程序来代替 shell 脚本:

#include <stdio.h>
#include <unistd.h>

int main(void) {
    char *const envp[] = {NULL};
    execle("/sbin/setcap", "setcap", "cap_sys_rawio=ep", "./bench", NULL, envp);
    perror("execle");
    return 1;
}

笔记:

  • 这是安全的,因为它忽略了它的环境(包括 PATH)并且不调用 shell,但它仍然可以从任何地方运行,所以不能保证到底是什么./bench。您可能想要硬编码绝对路径。
  • 您可以使用相同的技巧来运行多个命令,但是您必须进入forkand wait。(不要使用system,因为这会调用 shell 并违背禁止 setuid 脚本的目的!)
  • 您可以使用函数代替调用 setcap 二进制文件,但这libcap有点复杂。
  • 如果你想做第一部分,你可以像 shell 一样使用glob扩展,然后避免不得不./dev/cpu/*/msrstatchownexec
于 2020-01-13T22:37:23.480 回答
1

正如已经建议的那样,使用 libcap 是设置功能的一个不错的选择。要访问没有 sudo 权限的 MSR,我建议使用msr-safe。它已经为 Intel 实现了,但是我也成功地为 AMD 测试了它。加载 msr_safe 内核模块后,会有一些新文件。而不是通过/dev/cpu/*/msr您访问 msrs 将使用/dev/cpu/*/msr_safe. 它将向您公开/dev/cpu/msr_allowlist(以前msr_whitelist)中列出的寄存器。您还可以通过文件中的掩码来控制这些寄存器的哪些位是可写的。

此外,可以准备一个批处理 ( /dev/cpu/msr_batch) - 您将重复访问的寄存器列表,这样可以减少开销。此功能在libmsr中实现。

于 2021-07-09T08:45:03.997 回答