Linux 程序启动时清除了可继承的能力
Linux inheritable capability cleared on program start
我正在尝试启动一个具有网络权限的程序,以便它可以执行 iptables
而无需成为 root 用户。我需要 CAP_NET_ADMIN
才能继承和允许。可执行文件启动时似乎清除了可继承标志,但无效或不允许:
Script started on Thu 25 Oct 2018 11:09:45 PM UTC
[ec2-user@ip-172-31-16-197 cap_question]$ cat caps.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/capability.h>
int main(int argc, char **argv) {
cap_t caps = cap_get_proc();
printf("Inside the executable [%s]\n", argv[0]);
char *cap_text = cap_to_text(caps, NULL);
printf("capabilities %s\n", cap_text);
cap_free(cap_text);
cap_free(caps);
}
[ec2-user@ip-172-31-16-197 cap_question]$ cc caps.c -o caps -lcap
[ec2-user@ip-172-31-16-197 cap_question]$ sudo setcap cap_net_admin=eip caps
[ec2-user@ip-172-31-16-197 cap_question]$ getcap caps
caps = cap_net_admin+eip
[ec2-user@ip-172-31-16-197 cap_question]$ ./caps
Inside the executable [./caps]
capabilities = cap_net_admin+ep
[ec2-user@ip-172-31-16-197 cap_question]$ exit
Script done on Thu 25 Oct 2018 11:10:25 PM UTC
可以看到,可执行文件为cap_net_admin=eip
。但是当我实际运行的时候,权限集是cap_net_admin=ep
。我不明白为什么可执行文件在启动时会失去可继承性。如果我要 fork
/exec
iptables,它不会获得这些权限。
我已经读过 threads like these 和 man capabilities
很多遍了,我能想到的最好的解释是我的 shell 没有 cap_net_admin=i
,所以子进程没有。如何根据需要设置可继承标志来启动进程?
During an execve(2)
, the kernel calculates the new capabilities of the process using the following algorithm:
P'(permitted) = (P(inheritable) & F(inheritable)) |
(F(permitted) & cap_bset)
P'(effective) = F(effective) ? P'(permitted) : 0
P'(inheritable) = P(inheritable) [i.e., unchanged]
P(inheritable)
表示进程中的可继承位,F(inheritable)
是正在执行的文件的可继承位。可以看到,F(inheritable)
只是用来判断进程允许的capabilities,并没有用来判断可继承的capabilities。
文件的可继承功能与进程的可继承功能进行“与”运算——这允许您使用此标志防止在新进程中设置某些功能, 它不用于向新进程添加任何内容。
如果你想让你的进程继承能力,你可以调用cap_set_proc()
。当允许一项功能时,您可以将其设置为可继承。
我正在尝试启动一个具有网络权限的程序,以便它可以执行 iptables
而无需成为 root 用户。我需要 CAP_NET_ADMIN
才能继承和允许。可执行文件启动时似乎清除了可继承标志,但无效或不允许:
Script started on Thu 25 Oct 2018 11:09:45 PM UTC
[ec2-user@ip-172-31-16-197 cap_question]$ cat caps.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/capability.h>
int main(int argc, char **argv) {
cap_t caps = cap_get_proc();
printf("Inside the executable [%s]\n", argv[0]);
char *cap_text = cap_to_text(caps, NULL);
printf("capabilities %s\n", cap_text);
cap_free(cap_text);
cap_free(caps);
}
[ec2-user@ip-172-31-16-197 cap_question]$ cc caps.c -o caps -lcap
[ec2-user@ip-172-31-16-197 cap_question]$ sudo setcap cap_net_admin=eip caps
[ec2-user@ip-172-31-16-197 cap_question]$ getcap caps
caps = cap_net_admin+eip
[ec2-user@ip-172-31-16-197 cap_question]$ ./caps
Inside the executable [./caps]
capabilities = cap_net_admin+ep
[ec2-user@ip-172-31-16-197 cap_question]$ exit
Script done on Thu 25 Oct 2018 11:10:25 PM UTC
可以看到,可执行文件为cap_net_admin=eip
。但是当我实际运行的时候,权限集是cap_net_admin=ep
。我不明白为什么可执行文件在启动时会失去可继承性。如果我要 fork
/exec
iptables,它不会获得这些权限。
我已经读过 threads like these 和 man capabilities
很多遍了,我能想到的最好的解释是我的 shell 没有 cap_net_admin=i
,所以子进程没有。如何根据需要设置可继承标志来启动进程?
During an
execve(2)
, the kernel calculates the new capabilities of the process using the following algorithm:P'(permitted) = (P(inheritable) & F(inheritable)) | (F(permitted) & cap_bset) P'(effective) = F(effective) ? P'(permitted) : 0 P'(inheritable) = P(inheritable) [i.e., unchanged]
P(inheritable)
表示进程中的可继承位,F(inheritable)
是正在执行的文件的可继承位。可以看到,F(inheritable)
只是用来判断进程允许的capabilities,并没有用来判断可继承的capabilities。
文件的可继承功能与进程的可继承功能进行“与”运算——这允许您使用此标志防止在新进程中设置某些功能, 它不用于向新进程添加任何内容。
如果你想让你的进程继承能力,你可以调用cap_set_proc()
。当允许一项功能时,您可以将其设置为可继承。