当我具有正确的功能时,无法打开/ proc / self / oom_score_adj
我试图为一个过程设置OOM杀手分数调整,受到oom_adjust_setup in OpenSSH’s port_linux.c的启发.为此,我打开/ proc / self / oom_score_adj,读取旧值,并写入一个新值.显然,我的进程需要是root或具有CAP_SYS_RESOURCE能力才能做到这一点.
我得到了一个我无法解释的结果.当我的进程没有该功能时,我能够打开该文件并读取和写入值,尽管我写的值没有生效(足够公平):
$./a.out
CAP_SYS_RESOURCE: not effective, not permitted, not inheritable
oom_score_adj value: 0
wrote 5 bytes
oom_score_adj value: 0
但是当我的进程确实具有该功能时,我甚至无法打开该文件:它与EACCES失败:
$sudo setcap CAP_SYS_RESOURCE+eip a.out
$./a.out
CAP_SYS_RESOURCE: effective, permitted, not inheritable
failed to open /proc/self/oom_score_adj: Permission denied
为什么这样做?我错过了什么?
一些进一步的谷歌搜索引导我到this lkml post by Azat Khuzhin on 20 Oct 2013.显然CAP_SYS_RESOURCE允许您更改任何进程的oom_score_adj,但你自己.要更改自己的分数调整,您需要将其与CAP_DAC_OVERRIDE结合使用 – 即禁用所有文件的访问控制. (如果我想要的话,我会把这个程序设为setuid root.)
所以我的问题是,如果没有CAP_DAC_OVERRIDE,我怎样才能做到这一点?
我正在运行Ubuntu xenial 16.04.4,内核版本4.13.0-45-generic.我的问题类似但与this question不同:这是关于写入时的错误,当没有能力时.
我的示例程序:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/capability.h>
void read_value(FILE *fp)
{
int value;
rewind(fp);
if (fscanf(fp, "%d", &value) != 1) {
fprintf(stderr, "read failed: %s\n", ferror(fp) ? strerror(errno) : "cannot parse");
}
else {
fprintf(stderr, "oom_score_adj value: %d\n", value);
}
}
void write_value(FILE *fp)
{
int result;
rewind(fp);
result = fprintf(fp, "-1000");
if (result < 0) {
fprintf(stderr, "write failed: %s\n", strerror(errno));
}
else {
fprintf(stderr, "wrote %d bytes\n", result);
}
}
int main()
{
FILE *fp;
struct __user_cap_header_struct h;
struct __user_cap_data_struct d;
h.version = _LINUX_CAPABILITY_VERSION_3;
h.pid = 0;
if (0 != capget(&h, &d)) {
fprintf(stderr, "capget failed: %s\n", strerror(errno));
}
else {
fprintf(stderr, "CAP_SYS_RESOURCE: %s, %s, %s\n",
d.effective & (1 << CAP_SYS_RESOURCE) ? "effective" : "not effective",
d.permitted & (1 << CAP_SYS_RESOURCE) ? "permitted" : "not permitted",
d.inheritable & (1 << CAP_SYS_RESOURCE) ? "inheritable" : "not inheritable");
}
fp = fopen("/proc/self/oom_score_adj", "r+");
if (!fp) {
fprintf(stderr, "failed to open /proc/self/oom_score_adj: %s\n", strerror(errno));
return 1;
}
else {
read_value(fp);
write_value(fp);
read_value(fp);
fclose(fp);
}
return 0;
}