clinuxinheritancelinux-capabilities

Changing capabilities of the process


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  

Solution

  • 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.