我想利用功能来运行一些带有perf的测试,而无需运行root
命令而不调整/proc/sys/kernel/perf_event_paranoid
。 perf的一些错误消息说:
You may not have permission to collect stats.
Consider tweaking /proc/sys/kernel/perf_event_paranoid,
which controls use of the performance events system by
unprivileged users (without CAP_SYS_ADMIN).
The current value is 2:
-1: Allow use of (almost) all events by all users
>= 0: Disallow raw tracepoint access by users without CAP_IPC_LOCK
>= 1: Disallow CPU event access by users without CAP_SYS_ADMIN
>= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN
所以我尝试用以下方式创建一些具有相同源但不同功能集的bash脚本:
wrapper_no_cap.sh -> no capabilities set
wrapper_cap_ipc_lock.sh -> setcap cap_ipc_lock+eip ./wrapper_cap_ipc_lock.sh
wrapper_cap_sys_admin.sh -> setcap cap_sys_admin+eip ./wrapper_cap_sys_admin.sh
每个脚本都有相同的来源,如下所示:
#!/bin/bash
perf stat -e L1-dcache-load-misses:k seq 1 10
但我运行的每个脚本都给我结果,好像我是一个普通用户(这意味着我无法计算内核事件或其他特权的东西)。当我调用脚本时,功能会被丢弃。 perf版本为4.11.ga351e9
。
这种方法有什么问题?
答案 0 :(得分:0)
脚本文件通常禁用它们的suid位(在内核和某些shell解释器中),似乎对功能有类似的影响(脚本文件实际上是使用git commit
等解释器启动的,所以脚本中的功能文件可能不会被进程继承):
使用小的简单编译程序用exec / execve调用perf并在二进制ELF上设置功能。</ p>
Linux内核中用于脚本启动的实际代码 -
http://elixir.free-electrons.com/linux/v4.10/source/fs/binfmt_script.c - 使用解释器二进制文件,而不是脚本文件(旧bash ./scriptfile
)来获取suid等权限
bprm->file
http://elixir.free-electrons.com/linux/v4.10/source/fs/exec.c#L1512
/*
* OK, now restart the process with the interpreter's dentry.
*/
file = open_exec(interp);
if (IS_ERR(file))
return PTR_ERR(file);
bprm->file = file;
retval = prepare_binprm(bprm);
答案 1 :(得分:-1)
我发现了利用@osgx建议的转变。
我写了这个包装perf的小C程序。这是:
#include <unistd.h>
#include <stdio.h>
#include <sys/capability.h>
#define MY_CAPABILIY "cap_sys_admin+eip"
int main(int argc, char * argv[], char * envp[])
{
cap_t old_cap=cap_get_proc(); //save current capabilities
//getting MY_CAPABILITY associated struct
cap_t csa = cap_from_text(MY_CAPABILIY);
//set capabilities
if(cap_set_proc(csa)<0) fprintf(stderr,"cannot set %s\n",MY_CAPABILIY);
execve("/usr/bin/perf",argv,envp); //exec perf
//restore capabilties
if(cap_set_proc(old_cap)<0) fprintf(stderr, "Error on capability restore\n" );
return 0;
}
让我们调用从perf_wrapper
上面的代码生成的可执行文件。它使用libcap编译(将选项-lcap
添加到gcc
)。可执行文件只是将MY_CAPABILITY设置为进程的功能,然后运行perf(或其他命令)。但这不足以使用CAP_SYS_ADMIN运行perf,因为perf
的可执行文件没有任何功能。为了让事情有效,还需要为perf可执行文件添加一些功能。
步骤如下:
sudo setcap cap_sys_admin+ei /usr/bin/perf
,这将CAP_SYS_ADMIN的perf功能设置为有效且可继承(也允许设置允许普通用户在没有功能的情况下运行perf)。sudo setcap cap_sys_admin+eip perf_wrapper
设置了perf_wrapper
现在可以通过执行perf_wrapper
并在正常的bash脚本中像perf一样传递params来使用perf和CAP_SYS_ADMIN。
注意:我不是能力方面的专家。我希望我没有犯很大的安全错误。