2012-08-27 78 views
4

嘗試設置cap_setgid,cap_setuid,cap_setpcapsetuid()後失去能力

#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; 
} 

執行在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: 看不懂。我在第一個setuid之後添加了2strs,以檢查上限。

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

+1

遺憾。通過添加cap_set_flag(caps,CAP_INHERITABLE,2,cap_list,CAP_SET)來解決 –

+2

將其作爲答案發布並接受它。如果你解決了你自己的問題,建議你這樣做。未來的程序員會很容易找到它。還要說明爲什麼需要它。 – Zagorax

+0

還有一些問題 –

回答

8

默認情況下,有能力集跨越UID過渡丟失;使用

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

保留允許能力(cap_set_flag(caps, CAP_PERMITTED, ...))。請注意,有效的能力集將被重置,但可以重新建立。


以下工作適合我。

#include <sys/capability.h> 
#include <sys/prctl.h> 
#include <unistd.h> 

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 
... 
+0

謝謝。我在你的帖子後對代碼進行了修改,但問題仍然存在。看問題更新,請致電 –

+0

@DmitryFedorov更新與工作代碼。 – ephemient

+0

在其他系統上奇怪一切都ok.thx –

相關問題