потеря способности после setuid ()

Попытка установить cap_setgid , cap_setuid , cap_setpcap .

 #include  #include  int main() { cap_t caps; caps = cap_get_proc(); cap_value_t cap_list[2]; cap_list[0] = CAP_SETUID; cap_list[1] = CAP_SETGID; cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_list, CAP_SET); cap_set_flag(caps, CAP_INHERITABLE, 2, cap_list, CAP_SET); cap_set_proc(caps); cap_free(caps); setgid(65534); setuid(65534); cap_get_proc(); setgid(0); setuid(0); return 0; } 

Выполнение происходит под пользователем root. Трассировка программы показывает это

 capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, {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_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, 0}) = 0 capset({_LINUX_CAPABILITY_VERSION_3, 0}, {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_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_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0 setgid(65534) = 0 setuid(65534) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, 0, CAP_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0 setgid(0) = -1 EPERM (Operation not permitted) setuid(0) = -1 EPERM (Operation not permitted) exit_group(0) = ? +++ exited with 0 +++ 

Привилегии устанавливаются, но не работают. Любые предложения по решению этой проблемы?

UPDATE: prctl добавлен в код

 21a22 > prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 24a26 > cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET); 

так что теперь это

 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); setgid(65534); setuid(65534); cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET); 

Шапки были унаследованы после setuid , и кепки, которые были установлены вручную, все еще существуют, но это не решило проблему

 setgid(65534) = 0 setuid(65534) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0 capget({_LINUX_CAPABILITY_VERSION_3, 0}, {0, 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_SETGID|CAP_SETUID|CAP_SETPCAP}) = 0 setgid(0) = -1 EPERM (Operation not permitted) setuid(0) = -1 EPERM (Operation not permitted) exit_group(0) = ? +++ exited with 0 +++ 

UPDATE2: Не могу понять. Ive добавил 2strs после 1-го setuid , чтобы проверить колпачки.

 printf("cape set %d\n", cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET)); printf("%s\n", cap_to_text(cap_get_proc(), NULL)); 

он вернулся

 catp set 0 =p cap_setgid,cap_setuid,cap_setpcap+i 

Эффективный флаг не установлен, но cap_set_flag возвращается 0

По умолчанию, наборы параметров теряются при переходе UID; использование

 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 

для сохранения разрешенных возможностей ( cap_set_flag(caps, CAP_PERMITTED, ...) ). Обратите внимание, что набор эффективных возможностей будет сброшен, но может быть восстановлен.


Следующие работы отлично подходят для меня.

 #include  #include  #include  int main(int argc, char **argv) { cap_value_t cap_values[] = {CAP_SETUID, CAP_SETGID}; cap_t caps; caps = cap_get_proc(); cap_set_flag(caps, CAP_PERMITTED, 2, cap_values, CAP_SET); cap_set_proc(caps); prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); cap_free(caps); setgid(65534); setuid(65534); caps = cap_get_proc(); cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_values, CAP_SET); cap_set_proc(caps); cap_free(caps); setgid(0); setuid(0); return 0; } 
 $ sudo strace ./a.out
 ...
 capget ({_ LINUX_CAPABILITY_VERSION_3, 0}, {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_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, 0}) = 0
 capset ({_ LINUX_CAPABILITY_VERSION_3, 0}, {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_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, 0}) = 0
 prctl (PR_SET_KEEPCAPS, 1) = 0
 setgid (65534) = 0
 setuid (65534) = 0
 capget ({_ LINUX_CAPABILITY_VERSION_3, 0}, NULL) = 0
 capget ({_ LINUX_CAPABILITY_VERSION_3, 0}, {0, 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, 0}) = 0
 capset ({_ LINUX_CAPABILITY_VERSION_3, 0}, {CAP_SETGID | разрешения CAP_SETUID, 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, 0}) = 0
 setgid (0) = 0
 setuid (0) = 0
 ...

Я думаю, вы путаете CAP_PERMITTED с CAP_INHERITABLE. Если вы не используете thread / exec, вы хотите использовать CAP_PERMITTED.

Наследуемый (ранее известный как разрешенный): этот набор имеет ANDed с наследуемым набором streamов, чтобы определить, какие наследуемые возможности включены в разрешенном наборе streamа после execve (2)

Что касается update2: попробуйте распечатать cap_to_text(cap_get_proc()) до / после, а также рассмотрите, какая разница между cap_set_flag и cap_set_proc .