aboutsummaryrefslogtreecommitdiffstats
path: root/run_with_inherited_caps.py
blob: 063860c82899c0d18c567fc8f62de89d35d1fa7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/python3

# resources for cffi:
# http://eli.thegreenplace.net/2013/03/09/python-ffi-with-ctypes-and-cffi

import cffi
import os
import time
import pwd

pid = os.getpid()
print('pid:', pid)

ffi = cffi.FFI()
libcap = ffi.dlopen('libcap.so.2')
ffi.cdef('''
typedef struct _cap_struct *cap_t;
typedef int cap_value_t;
typedef enum {
    CAP_EFFECTIVE=0,
    CAP_PERMITTED=1,
    CAP_INHERITABLE=2
} cap_flag_t;
typedef enum {
    CAP_CLEAR=0,
    CAP_SET=1
} cap_flag_value_t;

cap_t cap_get_proc(void);
int cap_set_flag(cap_t cap_p, cap_flag_t flag, int ncap,
                        const cap_value_t *caps, cap_flag_value_t value);
cap_t cap_init(void);
int cap_free(void *obj_d);
int cap_set_proc(cap_t cap_p);
''')

CAP_EFFECTIVE = 0
CAP_PERMITTED = 1
CAP_INHERITABLE = 2
CAP_CLEAR = 0
CAP_SET = 1

# generated list with command line below:
# sed -n 's/^#define \(CAP_.*\)\s\+\([0-9]\+\).*$/\1 = \2/p' /usr/include/linux/capability.h
CAP_CHOWN            = 0
CAP_DAC_OVERRIDE     = 1
CAP_DAC_READ_SEARCH  = 2
CAP_FOWNER           = 3
CAP_FSETID           = 4
CAP_KILL             = 5
CAP_SETGID           = 6
CAP_SETUID           = 7
CAP_SETPCAP          = 8
CAP_LINUX_IMMUTABLE  = 9
CAP_NET_BIND_SERVICE = 10
CAP_NET_BROADCAST    = 11
CAP_NET_ADMIN        = 12
CAP_NET_RAW          = 13
CAP_IPC_LOCK         = 14
CAP_IPC_OWNER        = 15
CAP_SYS_MODULE       = 16
CAP_SYS_RAWIO        = 17
CAP_SYS_CHROOT       = 18
CAP_SYS_PTRACE       = 19
CAP_SYS_PACCT        = 20
CAP_SYS_ADMIN        = 21
CAP_SYS_BOOT         = 22
CAP_SYS_NICE         = 23
CAP_SYS_RESOURCE     = 24
CAP_SYS_TIME         = 25
CAP_SYS_TTY_CONFIG   = 26
CAP_MKNOD            = 27
CAP_LEASE            = 28
CAP_AUDIT_WRITE      = 29
CAP_AUDIT_CONTROL    = 30
CAP_SETFCAP          = 31
CAP_MAC_OVERRIDE     = 32
CAP_MAC_ADMIN        = 33
CAP_SYSLOG           = 34
CAP_WAKE_ALARM       = 35
CAP_BLOCK_SUSPEND    = 36


uid, gid = 1000, 1000


print("before droping caps")
os.system("cat /proc/{}/status | grep Cap".format(pid))
os.system("cp /bin/sleep /tmp/sleep")
os.system("setcap cap_net_bind_service=ei /tmp/sleep")

cap_values = (CAP_NET_BIND_SERVICE, )
cap_values_temp = (CAP_SETUID, CAP_SETGID,)
ccap_values = ffi.new('cap_value_t[]', cap_values)
ccap_values_temp = ffi.new('cap_value_t[]', cap_values_temp)

print('len cap_values:', len(cap_values))
caps = libcap.cap_init()
libcap.cap_set_flag(caps, CAP_INHERITABLE, len(cap_values), ccap_values, CAP_SET)
libcap.cap_set_flag(caps, CAP_PERMITTED, len(cap_values_temp), ccap_values_temp, CAP_SET)
libcap.cap_set_flag(caps, CAP_EFFECTIVE, len(cap_values_temp), ccap_values_temp, CAP_SET)
libcap.cap_set_proc(caps)
libcap.cap_free(caps)

print("after dropping caps")
os.system("cat /proc/{}/status | grep Cap".format(pid))

os.setgroups(os.getgrouplist(pwd.getpwuid(uid)[0], gid))
os.setgid(gid)
os.setuid(uid)

print("after setgid/setuid/setgroups")
os.system("cat /proc/{}/status | grep Cap".format(pid))

os.execve("/tmp/sleep", ["/tmp/sleep", "9999"], {})