diff options
-rw-r--r-- | util-linux/setpriv.c | 151 |
1 files changed, 147 insertions, 4 deletions
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c index 8d3f25875..a509204a2 100644 --- a/util-linux/setpriv.c +++ b/util-linux/setpriv.c | |||
@@ -23,6 +23,26 @@ | |||
23 | //config: help | 23 | //config: help |
24 | //config: Enables the "--dump" switch to print out the current privilege | 24 | //config: Enables the "--dump" switch to print out the current privilege |
25 | //config: state. This is helpful for diagnosing problems. | 25 | //config: state. This is helpful for diagnosing problems. |
26 | //config: | ||
27 | //config:config FEATURE_SETPRIV_CAPABILITIES | ||
28 | //config: bool "Support capabilities" | ||
29 | //config: default y | ||
30 | //config: depends on SETPRIV | ||
31 | //config: help | ||
32 | //config: Capabilities can be used to grant processes additional rights | ||
33 | //config: without the necessity to always execute as the root user. | ||
34 | //config: Enabling this option enables "--dump" to show information on | ||
35 | //config: capabilities. | ||
36 | //config: | ||
37 | //config:config FEATURE_SETPRIV_CAPABILITY_NAMES | ||
38 | //config: bool "Support capability names" | ||
39 | //config: default y | ||
40 | //config: depends on SETPRIV && FEATURE_SETPRIV_CAPABILITIES | ||
41 | //config: help | ||
42 | //config: Capabilities can be either referenced via a human-readble name, | ||
43 | //config: e.g. "net_admin", or using their index, e.g. "cap_12". Enabling | ||
44 | //config: this option allows using the human-readable names in addition to | ||
45 | //config: the index-based names. | ||
26 | 46 | ||
27 | //applet:IF_SETPRIV(APPLET(setpriv, BB_DIR_BIN, BB_SUID_DROP)) | 47 | //applet:IF_SETPRIV(APPLET(setpriv, BB_DIR_BIN, BB_SUID_DROP)) |
28 | 48 | ||
@@ -55,6 +75,10 @@ | |||
55 | // --selinux-label <label> set SELinux label | 75 | // --selinux-label <label> set SELinux label |
56 | // --apparmor-profile <pr> set AppArmor profile | 76 | // --apparmor-profile <pr> set AppArmor profile |
57 | 77 | ||
78 | #if ENABLE_FEATURE_SETPRIV_CAPABILITIES | ||
79 | #include <linux/capability.h> | ||
80 | #include <sys/capability.h> | ||
81 | #endif | ||
58 | #include <sys/prctl.h> | 82 | #include <sys/prctl.h> |
59 | #include "libbb.h" | 83 | #include "libbb.h" |
60 | 84 | ||
@@ -74,13 +98,106 @@ enum { | |||
74 | OPT_NNP = (1 << OPTBIT_NNP), | 98 | OPT_NNP = (1 << OPTBIT_NNP), |
75 | }; | 99 | }; |
76 | 100 | ||
101 | #if ENABLE_FEATURE_SETPRIV_CAPABILITIES | ||
102 | struct caps { | ||
103 | struct __user_cap_header_struct header; | ||
104 | cap_user_data_t data; | ||
105 | int u32s; | ||
106 | }; | ||
107 | |||
108 | #if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES | ||
109 | static const char *const capabilities[] = { | ||
110 | "chown", | ||
111 | "dac_override", | ||
112 | "dac_read_search", | ||
113 | "fowner", | ||
114 | "fsetid", | ||
115 | "kill", | ||
116 | "setgid", | ||
117 | "setuid", | ||
118 | "setpcap", | ||
119 | "linux_immutable", | ||
120 | "net_bind_service", | ||
121 | "net_broadcast", | ||
122 | "net_admin", | ||
123 | "net_raw", | ||
124 | "ipc_lock", | ||
125 | "ipc_owner", | ||
126 | "sys_module", | ||
127 | "sys_rawio", | ||
128 | "sys_chroot", | ||
129 | "sys_ptrace", | ||
130 | "sys_pacct", | ||
131 | "sys_admin", | ||
132 | "sys_boot", | ||
133 | "sys_nice", | ||
134 | "sys_resource", | ||
135 | "sys_time", | ||
136 | "sys_tty_config", | ||
137 | "mknod", | ||
138 | "lease", | ||
139 | "audit_write", | ||
140 | "audit_control", | ||
141 | "setfcap", | ||
142 | "mac_override", | ||
143 | "mac_admin", | ||
144 | "syslog", | ||
145 | "wake_alarm", | ||
146 | "block_suspend", | ||
147 | "audit_read", | ||
148 | }; | ||
149 | #endif /* FEATURE_SETPRIV_CAPABILITY_NAMES */ | ||
150 | |||
151 | #endif /* FEATURE_SETPRIV_CAPABILITIES */ | ||
152 | |||
77 | #if ENABLE_FEATURE_SETPRIV_DUMP | 153 | #if ENABLE_FEATURE_SETPRIV_DUMP |
154 | # if ENABLE_FEATURE_SETPRIV_CAPABILITIES | ||
155 | static void getcaps(struct caps *caps) | ||
156 | { | ||
157 | int versions[] = { | ||
158 | _LINUX_CAPABILITY_U32S_3, | ||
159 | _LINUX_CAPABILITY_U32S_2, | ||
160 | _LINUX_CAPABILITY_U32S_1, | ||
161 | }; | ||
162 | int i; | ||
163 | |||
164 | caps->header.pid = 0; | ||
165 | for (i = 0; i < ARRAY_SIZE(versions); i++) { | ||
166 | caps->header.version = versions[i]; | ||
167 | if (capget(&caps->header, NULL) == 0) | ||
168 | goto got_it; | ||
169 | } | ||
170 | bb_simple_perror_msg_and_die("capget"); | ||
171 | got_it: | ||
172 | |||
173 | switch (caps->header.version) { | ||
174 | case _LINUX_CAPABILITY_VERSION_1: | ||
175 | caps->u32s = _LINUX_CAPABILITY_U32S_1; | ||
176 | break; | ||
177 | case _LINUX_CAPABILITY_VERSION_2: | ||
178 | caps->u32s = _LINUX_CAPABILITY_U32S_2; | ||
179 | break; | ||
180 | case _LINUX_CAPABILITY_VERSION_3: | ||
181 | caps->u32s = _LINUX_CAPABILITY_U32S_3; | ||
182 | break; | ||
183 | default: | ||
184 | bb_error_msg_and_die("unsupported capability version"); | ||
185 | } | ||
186 | |||
187 | caps->data = xmalloc(sizeof(caps->data[0]) * caps->u32s); | ||
188 | if (capget(&caps->header, caps->data) < 0) | ||
189 | bb_simple_perror_msg_and_die("capget"); | ||
190 | } | ||
191 | # endif /* FEATURE_SETPRIV_CAPABILITIES */ | ||
192 | |||
78 | static int dump(void) | 193 | static int dump(void) |
79 | { | 194 | { |
195 | IF_FEATURE_SETPRIV_CAPABILITIES(struct caps caps;) | ||
196 | const char *fmt; | ||
80 | uid_t ruid, euid, suid; | 197 | uid_t ruid, euid, suid; |
81 | gid_t rgid, egid, sgid; | 198 | gid_t rgid, egid, sgid; |
82 | gid_t *gids; | 199 | gid_t *gids; |
83 | int ngids, nnp; | 200 | int i, ngids, nnp; |
84 | 201 | ||
85 | getresuid(&ruid, &euid, &suid); /* never fails in Linux */ | 202 | getresuid(&ruid, &euid, &suid); /* never fails in Linux */ |
86 | getresgid(&rgid, &egid, &sgid); /* never fails in Linux */ | 203 | getresgid(&rgid, &egid, &sgid); /* never fails in Linux */ |
@@ -100,8 +217,7 @@ static int dump(void) | |||
100 | if (ngids == 0) { | 217 | if (ngids == 0) { |
101 | printf("[none]"); | 218 | printf("[none]"); |
102 | } else { | 219 | } else { |
103 | const char *fmt = ",%u" + 1; | 220 | fmt = ",%u" + 1; |
104 | int i; | ||
105 | for (i = 0; i < ngids; i++) { | 221 | for (i = 0; i < ngids; i++) { |
106 | printf(fmt, (unsigned)gids[i]); | 222 | printf(fmt, (unsigned)gids[i]); |
107 | fmt = ",%u"; | 223 | fmt = ",%u"; |
@@ -109,8 +225,35 @@ static int dump(void) | |||
109 | } | 225 | } |
110 | printf("\nno_new_privs: %d\n", nnp); | 226 | printf("\nno_new_privs: %d\n", nnp); |
111 | 227 | ||
112 | if (ENABLE_FEATURE_CLEAN_UP) | 228 | # if ENABLE_FEATURE_SETPRIV_CAPABILITIES |
229 | getcaps(&caps); | ||
230 | printf("Inheritable capabilities: "); | ||
231 | fmt = ""; | ||
232 | for (i = 0; cap_valid(i); i++) { | ||
233 | unsigned idx = CAP_TO_INDEX(i); | ||
234 | if (idx >= caps.u32s) { | ||
235 | printf("\nindex: %u u32s: %u capability: %u\n", idx, caps.u32s, i); | ||
236 | bb_error_msg_and_die("unsupported capability"); | ||
237 | } | ||
238 | if (caps.data[idx].inheritable & CAP_TO_MASK(i)) { | ||
239 | # if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES | ||
240 | if (i < ARRAY_SIZE(capabilities)) | ||
241 | printf("%s%s", fmt, capabilities[i]); | ||
242 | else | ||
243 | # endif | ||
244 | printf("%scap_%u", fmt, i); | ||
245 | fmt = ","; | ||
246 | } | ||
247 | } | ||
248 | if (!fmt[0]) | ||
249 | printf("[none]"); | ||
250 | bb_putchar('\n'); | ||
251 | # endif | ||
252 | |||
253 | if (ENABLE_FEATURE_CLEAN_UP) { | ||
254 | IF_FEATURE_SETPRIV_CAPABILITIES(free(caps.data);) | ||
113 | free(gids); | 255 | free(gids); |
256 | } | ||
114 | return EXIT_SUCCESS; | 257 | return EXIT_SUCCESS; |
115 | } | 258 | } |
116 | #endif /* FEATURE_SETPRIV_DUMP */ | 259 | #endif /* FEATURE_SETPRIV_DUMP */ |