我有一个包装器程序,它只用于向nodejs脚本添加CAP_NET_RAW
功能。二进制文件已将功能设置为cap_net_raw+eip
,但进程未获取它们,设置它们会导致EPERM (Operation not permitted)
。从Debian 9升级到10后,包装器停止工作。将功能添加到nodejs二进制文件可以工作,nodejs脚本运行良好,但不希望允许任何nodejs脚本原始访问网络适配器。
下面是包装器的源代码:
#include <sys/capability.h>
#include <unistd.h>
void main() {
cap_t caps = cap_get_proc();
cap_value_t newcaps[1] = { CAP_NET_RAW, };
cap_set_flag(caps, CAP_INHERITABLE, 1, newcaps, CAP_SET);
cap_set_proc(caps);
cap_free(caps);
execl("/usr/bin/node", "node", "/opt/sitemp/sitemp.js", NULL);
}
在strace下运行它会产生以下结果:
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = 0
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=0, inheritable=0}) = 0
capset({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=0, inheritable=1<<CAP_NET_RAW}) = -1 EPERM (Operation not permitted)
发布于 2021-05-28 05:12:09
评论太长了,这里有一个更完整的解释。
首先,文件功能仅适用于二进制文件。
让我们调用您的包装器程序wrapper.c
(编译为wrapper
)。它被编码的目的是提升一个可继承的能力。可继承功能可以使后续执行的程序具有特权的方式是它们与可执行文件上的“文件可继承”功能。
也就是说,你可以这样做:
$ sudo setcap cap_net_raw=p ./wrapper
$ sudo setcap cap_net_raw=ie /usr/bin/node
现在,当您执行./wrapper
时,它将引发一个可继承的能力,并且当它允许有效时,该组合将在运行的/usr/bin/node
程序的允许和有效标志中继承并提高允许的能力。
如果不使用./wrapper
,就不会拥有进程可继承功能,/usr/bin/node
也不会继承任何权限。
或者,您可以清除这些功能并修改您的wrapper.c
,使其如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <sys/capability.h>
#include <unistd.h>
void main() {
cap_iab_t iab = cap_iab_from_text("^cap_net_raw");
if (iab == NULL) {
perror("iab not parsed");
exit(1);
}
if (cap_iab_set_proc(iab)) {
perror("unable to set iab");
exit(1);
}
cap_free(iab);
execl("/usr/bin/node", "node", "/opt/sitemp/sitemp.js", NULL);
perror("execl failed");
}
您需要编译并设置此版本的wrapper
,如下所示:
$ sudo setcap -r /usr/bin/node
$ cc -o wrapper wrapper.c -lcap
$ sudo setcap cap_net_raw,cap_setpcap=p ./wrapper
现在,当您运行./wrapper
时,它将同时引发环境和可继承功能,并且两者的组合将导致/usr/bin/node
直接从./wrapper
继承某些特权。
https://stackoverflow.com/questions/65729446
复制