Are there any way that I could run application with a special capabilities? I'm trying to set capabilities with function "cap_set_flag()", by setting flag "SET_CLEAR", to all "CAP_INHERITABLE" capabilities but it doesn't work. Child application still has all capabilities, but i expect it will have only "cap_dac_override". I also my app with sudo to change capabilities.
My app:
#include <sys/capability.h>
#include <stdio.h>
#include <unistd.h>
cap_value_t newcaps[1] = { CAP_DAC_OVERRIDE, };
cap_value_t cap_list_[33] = {
CAP_CHOWN,
CAP_DAC_READ_SEARCH,
CAP_FOWNER,
CAP_FSETID,
CAP_KILL,
CAP_SETGID,
CAP_SETUID,
CAP_SETPCAP,
CAP_LINUX_IMMUTABLE,
CAP_NET_BIND_SERVICE,
CAP_NET_BROADCAST,
CAP_NET_ADMIN,
CAP_NET_RAW,
CAP_IPC_LOCK,
CAP_IPC_OWNER,
CAP_SYS_MODULE,
CAP_SYS_RAWIO,
CAP_SYS_CHROOT,
CAP_SYS_PTRACE,
CAP_SYS_PACCT,
CAP_SYS_ADMIN,
CAP_SYS_BOOT,
CAP_SYS_NICE,
CAP_SYS_RESOURCE,
CAP_SYS_TIME,
CAP_SYS_TTY_CONFIG,
CAP_MKNOD,
CAP_LEASE,
CAP_AUDIT_WRITE,
CAP_AUDIT_CONTROL,
CAP_SETFCAP,
CAP_MAC_OVERRIDE,
CAP_MAC_ADMIN
};
void test() {
cap_value_t cap_list[35];
const char *cap_name[35] = {
"cap_chown",
"cap_dac_override",
"cap_dac_read_search",
"cap_fowner",
"cap_fsetid",
"cap_kill",
"cap_setgid",
"cap_setuid",
"cap_setpcap",
"cap_linux_immutable",
"cap_net_bind_service",
"cap_net_broadcast",
"cap_net_admin",
"cap_net_raw",
"cap_ipc_lock",
"cap_ipc_owner",
"cap_sys_module",
"cap_sys_rawio",
"cap_sys_chroot",
"cap_sys_ptrace",
"cap_sys_pacct",
"cap_sys_admin",
"cap_sys_boot",
"cap_sys_nice",
"cap_sys_resource",
"cap_sys_time",
"cap_sys_tty_config",
"cap_mknod",
"cap_lease",
"cap_audit_write",
"cap_audit_control",
"cap_setfcap",
"cap_mac_override",
"cap_mac_admin",
"cap_syslog"
};
int i;
pid_t pid = getpid();
cap_t cap = cap_get_pid(pid);
cap_flag_value_t cap_flags_value;
for (i=0; i < 34; i++) {
cap_from_name(cap_name[i], &cap_list[i]);
printf("%-20s %d\t\t", cap_name[i], cap_list[i]);
printf("flags: \t\t");
cap_get_flag(cap, cap_list[i], CAP_EFFECTIVE, &cap_flags_value);
printf(" EFFECTIVE %-4s ", (cap_flags_value == CAP_SET) ? "OK" : "NOK");
cap_get_flag(cap, cap_list[i], CAP_PERMITTED, &cap_flags_value);
printf(" PERMITTED %-4s ", (cap_flags_value == CAP_SET) ? "OK" : "NOK");
cap_get_flag(cap, cap_list[i], CAP_INHERITABLE, &cap_flags_value);
printf(" INHERITABLE %-4s ", (cap_flags_value == CAP_SET) ? "OK" : "NOK");
printf("\n");
}
}
int main(int argc, char **argv[]) {
cap_t caps = cap_get_proc();
printf("Capabilities: %s\n", cap_to_text(caps, NULL));
if (cap_set_flag(caps, CAP_INHERITABLE, 33, cap_list_, CAP_CLEAR)){
printf("ERROR");
return 0;}
if (cap_set_flag(caps, CAP_EFFECTIVE, 33, cap_list_, CAP_CLEAR)){
printf("ERROR");
return 0;}
if (cap_set_flag(caps, CAP_PERMITTED, 33, cap_list_, CAP_CLEAR)){
printf("ERROR");
return 0;}
cap_set_proc(caps);
if(cap_set_flag(caps, CAP_INHERITABLE, 1, newcaps, CAP_SET)){
printf("ERROR2");
return 0;
}
if(cap_set_flag(caps, CAP_INHERITABLE, 1, newcaps, CAP_SET)){
printf("ERROR2");
return 0;
}
if(cap_set_flag(caps, CAP_PERMITTED, 1, newcaps, CAP_SET)){
printf("ERROR2");
return 0;
}
cap_set_proc(caps);
printf("Capabilities: %s\n", cap_to_text(caps, NULL));
cap_free(caps);
printf("====================Cap====================\n");
test();
printf("====================Test====================\n");
return execl("/home/ilya/testSEM/test.o", NULL);
}
My test app:
#include <stdio.h>
#include <sys/capability.h>
int main(int argc, char **argv) {
cap_value_t cap_list[35];
const char *cap_name[35] = {
"cap_chown",
"cap_dac_override",
"cap_dac_read_search",
"cap_fowner",
"cap_fsetid",
"cap_kill",
"cap_setgid",
"cap_setuid",
"cap_setpcap",
"cap_linux_immutable",
"cap_net_bind_service",
"cap_net_broadcast",
"cap_net_admin",
"cap_net_raw",
"cap_ipc_lock",
"cap_ipc_owner",
"cap_sys_module",
"cap_sys_rawio",
"cap_sys_chroot",
"cap_sys_ptrace",
"cap_sys_pacct",
"cap_sys_admin",
"cap_sys_boot",
"cap_sys_nice",
"cap_sys_resource",
"cap_sys_time",
"cap_sys_tty_config",
"cap_mknod",
"cap_lease",
"cap_audit_write",
"cap_audit_control",
"cap_setfcap",
"cap_mac_override",
"cap_mac_admin",
"cap_syslog"
};
int i;
pid_t pid = getpid();
cap_t cap = cap_get_pid(pid);
cap_flag_value_t cap_flags_value;
for (i=0; i < 34 + 1; i++) {
cap_from_name(cap_name[i], &cap_list[i]);
printf("%-20s %d\t\t", cap_name[i], cap_list[i]);
printf("flags: \t\t");
cap_get_flag(cap, cap_list[i], CAP_EFFECTIVE, &cap_flags_value);
printf(" EFFECTIVE %-4s ", (cap_flags_value == CAP_SET) ? "OK" : "NOK");
cap_get_flag(cap, cap_list[i], CAP_PERMITTED, &cap_flags_value);
printf(" PERMITTED %-4s ", (cap_flags_value == CAP_SET) ? "OK" : "NOK");
cap_get_flag(cap, cap_list[i], CAP_INHERITABLE, &cap_flags_value);
printf(" INHERITABLE %-4s ", (cap_flags_value == CAP_SET) ? "OK" : "NOK");
printf("\n");
}
}
My results:
====================Cap====================
cap_chown 0 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_dac_override 1 flags: EFFECTIVE OK PERMITTED OK INHERITABLE OK
cap_dac_read_search 2 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_fowner 3 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_fsetid 4 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_kill 5 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_setgid 6 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_setuid 7 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_setpcap 8 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_linux_immutable 9 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_net_bind_service 10 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_net_broadcast 11 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_net_admin 12 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_net_raw 13 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_ipc_lock 14 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_ipc_owner 15 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_module 16 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_rawio 17 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_chroot 18 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_ptrace 19 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_pacct 20 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_admin 21 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_boot 22 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_nice 23 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_resource 24 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_time 25 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_sys_tty_config 26 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_mknod 27 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_lease 28 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_audit_write 29 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_audit_control 30 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_setfcap 31 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_mac_override 32 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
cap_mac_admin 33 flags: EFFECTIVE NOK PERMITTED NOK INHERITABLE NOK
====================Test====================
cap_chown 0 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_dac_override 1 flags: EFFECTIVE OK PERMITTED OK INHERITABLE OK
cap_dac_read_search 2 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_fowner 3 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_fsetid 4 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_kill 5 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_setgid 6 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_setuid 7 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_setpcap 8 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_linux_immutable 9 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_net_bind_service 10 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_net_broadcast 11 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_net_admin 12 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_net_raw 13 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_ipc_lock 14 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_ipc_owner 15 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_module 16 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_rawio 17 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_chroot 18 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_ptrace 19 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_pacct 20 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_admin 21 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_boot 22 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_nice 23 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_resource 24 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_time 25 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_sys_tty_config 26 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_mknod 27 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_lease 28 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_audit_write 29 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_audit_control 30 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_setfcap 31 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_mac_override 32 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_mac_admin 33 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
cap_syslog 34 flags: EFFECTIVE OK PERMITTED OK INHERITABLE NOK
Reading your program over you have two programs: app
and test
. The app
code you provide looks like it is invoking test.o
, but I'm going to refer to that program as test
in my explanation.
Try doing this:
$ sudo setcap cap_dac_override=ep app
$ sudo setcap cap_dac_override=ei test
If you run ./test
(as a regular user and not root
) it will be launched with no privilege at all. Confusing, but this is how things work by design.
INHERITABLE file capabilities (=ei
) are not privilege, but the potential for inheriting privilege. You can trigger that inheriting effect if you run ./app
(as a regular user) it will start with the single cap_dac_override
capability in its EFFECTIVE and PERMITTED sets (cap_dac_override=ep
). Your app
code will raise this single capability in the INHERITABLE process flag as well, to get a process with cap_dac_override=eip
.
When app
ends by executing ./test
, the raised process INHERITABLE flag will combine with the file INHERITABLE flag on the test
binary to run your code with privilege. Since it also has the EFFECTIVE file bit, this combination will cause the test
program to execute with cap_dac_override=eip
. Note, the =ep
process capabilities of app
are not inherited directly, but only =i
bits are passed on through execl()
and the rules for capability inheritance convert the file-I and the process-I into a post-execl()
process-IP.
For code like this, which knows how to get and set capabilities from code, you don't really need to include the '=e.' part when adding file capabilities. All that is doing is forcing the capabilities to be EFFECTIVE as the program starts running. This feature was included so programs that don't know about capabilities can be made to run with less than full root
privilege. It is good practice to use cap_set_flag()
and cap_set_proc()
to raise the EFFECTIVE capabilities you need only when you need them.