我试图了解Linux功能如何传递给另一个进程的exec().从我读过的内容来看,为了在exec之后保留一个功能,它必须在可继承的集合中.但是,我不确定的是这个集合是如何填充的.
我的目标是能够以通常需要root的常规用户身份运行程序.它需要的功能是cap_dac_override,因此它可以读取私有文件.我不想给它任何其他能力.
这是我的包装:
#include
int main(int argc, char *argv[]) {
return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL);
}
这在我对生成的可执行文件设置setuid权限时有效:
~ $sudo chown root: ./registerdns
~ $sudo chmod u+s ./registerdns
~ $./registerdns
Successfully registered hostname with DNS
不过,我想使用功能而不是setuid.我已经尝试在包装器上设置cap_dac_override功能:
~ $sudo setcap cap_dac_override=eip ./registerdns
~ $./registerdns
Failed to open /var/lib/samba/private/secrets.tdb
ERROR: Unable to open secrets database
我还尝试在net_dac_override功能上为net可执行文件本身设置可继承标志:
~ $sudo setcap cap_dac_override=eip ./registerdns
~ $sudo setcap cap_dac_override=i /usr/bin/net
~ $./registerdns
Failed to open /var/lib/samba/private/secrets.tdb
ERROR: Unable to open secrets database
我需要使用包装器来确保只有在使用那组精确的参数时才能使用该功能.网络程序会做一些其他可能会给用户提供过多权限的危险.
我显然误解了继承是如何工作的.我似乎无法弄清楚如何设置包装器以将其功能传递给替换过程,以便它可以使用它们.我已经阅读了手册页,以及无数其他文档应该如何工作,我以为我正在做它描述的内容.
解决方法:
事实证明,在包装器上设置i不会为包装器进程添加CAP_INHERITABLE集的功能,因此它不会通过exec传递.因此,我必须在调用execl之前手动将CAP_DAC_OVERRIDE添加到CAP_INHERITABLE:
#include
#include
#include
int main(int argc, char **argv[]) {
cap_t caps = cap_get_proc();
printf("Capabilities: %s\n", cap_to_text(caps, NULL));
cap_value_t newcaps[1] = { CAP_DAC_OVERRIDE, };
cap_set_flag(caps, CAP_INHERITABLE, 1, newcaps, CAP_SET);
cap_set_proc(caps);
printf("Capabilities: %s\n", cap_to_text(caps, NULL));
cap_free(caps);
return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL);
}
另外,我必须将cap_dac_override添加到/usr/bin/net上设置的允许文件功能中并设置有效位:
~ $sudo setcap cap_dac_override=p ./registerdns
~ $sudo setcap cap_dac_override=ei /usr/bin/net
~ $./registerdns
Capabilities = cap_dac_override+p
Capabilities = cap_dac_override+ip
Successfully registered hostname with DNS
我想我现在完全明白发生了什么:
>包装器在其允许的集合中需要CAP_DAC_OVERRIDE,因此它可以将其添加到其可继承的集合中.
>包装器的进程可继承集与其文件可继承集不同,因此在文件上设置i是无用的;包装器必须使用cap_set_flag / cap_set_proc显式地将CAP_DAC_OVERRIDE添加到CAP_INHERITABLE.
>网络文件需要在其可继承集中具有CAP_DAC_OVERRIDE,以便它实际上可以将包装器中的功能继承到其CAP_PERMITTED集中.它还需要设置有效位,以便它自动提升为CAP_EFFECTIVE.
标签:linux,capabilities,setcap
来源: https://codeday.me/bug/20190810/1637101.html