Trying to set cap_setgid
,cap_setuid
,cap_setpcap
.
#include <sys/types.h>
#include <sys/capability.h>
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;
}
Execution is going under root user. Tracing the program shows this
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 +++
Privileges are set but do not work. Any suggestions how to solve this problem?
UPDATE: prctl
added to code
21a22
> prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
24a26
> cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET);
so now it is
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
setgid(65534);
setuid(65534);
cap_set_flag(caps, CAP_EFFECTIVE, 3, cap_list, CAP_SET);
Caps were inherited after setuid
, and caps that were set manually are still there, but it didn't solve the problem
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:
Can't understand it. Ive added 2strs after 1st setuid
, to check out for caps.
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));
it returned
catp set 0
=p cap_setgid,cap_setuid,cap_setpcap+i
Effective flag is not set, but cap_set_flag returned 0
I think you confused CAP_PERMITTED set with CAP_INHERITABLE, Unless you are using threads/exec , you want to use CAP_PERMITTED.
As for update2: try printing out
cap_to_text(cap_get_proc())
before/after and also consider what is the difference betweencap_set_flag
andcap_set_proc
.By default, capability sets are lost across an UID transition; use
to retain permitted capabilities (
cap_set_flag(caps, CAP_PERMITTED, ...)
). Note that the effective capability set will be reset, but can be re-established.The following works fine for me.