diff options
Diffstat (limited to 'util-linux/setpriv.c')
-rw-r--r-- | util-linux/setpriv.c | 152 |
1 files changed, 18 insertions, 134 deletions
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c index 0f85428ab..12ab1bd66 100644 --- a/util-linux/setpriv.c +++ b/util-linux/setpriv.c | |||
@@ -5,7 +5,6 @@ | |||
5 | * Copyright (C) 2017 by <assafgordon@gmail.com> | 5 | * Copyright (C) 2017 by <assafgordon@gmail.com> |
6 | * | 6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | * | ||
9 | */ | 8 | */ |
10 | //config:config SETPRIV | 9 | //config:config SETPRIV |
11 | //config: bool "setpriv (3.4 kb)" | 10 | //config: bool "setpriv (3.4 kb)" |
@@ -125,96 +124,10 @@ enum { | |||
125 | }; | 124 | }; |
126 | 125 | ||
127 | #if ENABLE_FEATURE_SETPRIV_CAPABILITIES | 126 | #if ENABLE_FEATURE_SETPRIV_CAPABILITIES |
128 | struct caps { | 127 | DEFINE_STRUCT_CAPS; |
129 | struct __user_cap_header_struct header; | ||
130 | cap_user_data_t data; | ||
131 | int u32s; | ||
132 | }; | ||
133 | |||
134 | # if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES | ||
135 | static const char *const capabilities[] = { | ||
136 | "chown", | ||
137 | "dac_override", | ||
138 | "dac_read_search", | ||
139 | "fowner", | ||
140 | "fsetid", | ||
141 | "kill", | ||
142 | "setgid", | ||
143 | "setuid", | ||
144 | "setpcap", | ||
145 | "linux_immutable", | ||
146 | "net_bind_service", | ||
147 | "net_broadcast", | ||
148 | "net_admin", | ||
149 | "net_raw", | ||
150 | "ipc_lock", | ||
151 | "ipc_owner", | ||
152 | "sys_module", | ||
153 | "sys_rawio", | ||
154 | "sys_chroot", | ||
155 | "sys_ptrace", | ||
156 | "sys_pacct", | ||
157 | "sys_admin", | ||
158 | "sys_boot", | ||
159 | "sys_nice", | ||
160 | "sys_resource", | ||
161 | "sys_time", | ||
162 | "sys_tty_config", | ||
163 | "mknod", | ||
164 | "lease", | ||
165 | "audit_write", | ||
166 | "audit_control", | ||
167 | "setfcap", | ||
168 | "mac_override", | ||
169 | "mac_admin", | ||
170 | "syslog", | ||
171 | "wake_alarm", | ||
172 | "block_suspend", | ||
173 | "audit_read", | ||
174 | }; | ||
175 | # endif /* FEATURE_SETPRIV_CAPABILITY_NAMES */ | ||
176 | 128 | ||
177 | static void getcaps(struct caps *caps) | 129 | static unsigned parse_cap(const char *cap) |
178 | { | 130 | { |
179 | static const uint8_t versions[] = { | ||
180 | _LINUX_CAPABILITY_U32S_3, /* = 2 (fits into byte) */ | ||
181 | _LINUX_CAPABILITY_U32S_2, /* = 2 */ | ||
182 | _LINUX_CAPABILITY_U32S_1, /* = 1 */ | ||
183 | }; | ||
184 | int i; | ||
185 | |||
186 | caps->header.pid = 0; | ||
187 | for (i = 0; i < ARRAY_SIZE(versions); i++) { | ||
188 | caps->header.version = versions[i]; | ||
189 | if (capget(&caps->header, NULL) == 0) | ||
190 | goto got_it; | ||
191 | } | ||
192 | bb_simple_perror_msg_and_die("capget"); | ||
193 | got_it: | ||
194 | |||
195 | switch (caps->header.version) { | ||
196 | case _LINUX_CAPABILITY_VERSION_1: | ||
197 | caps->u32s = _LINUX_CAPABILITY_U32S_1; | ||
198 | break; | ||
199 | case _LINUX_CAPABILITY_VERSION_2: | ||
200 | caps->u32s = _LINUX_CAPABILITY_U32S_2; | ||
201 | break; | ||
202 | case _LINUX_CAPABILITY_VERSION_3: | ||
203 | caps->u32s = _LINUX_CAPABILITY_U32S_3; | ||
204 | break; | ||
205 | default: | ||
206 | bb_error_msg_and_die("unsupported capability version"); | ||
207 | } | ||
208 | |||
209 | caps->data = xmalloc(sizeof(caps->data[0]) * caps->u32s); | ||
210 | if (capget(&caps->header, caps->data) < 0) | ||
211 | bb_simple_perror_msg_and_die("capget"); | ||
212 | } | ||
213 | |||
214 | static void parse_cap(unsigned long *index, const char *cap) | ||
215 | { | ||
216 | unsigned long i; | ||
217 | |||
218 | switch (cap[0]) { | 131 | switch (cap[0]) { |
219 | case '-': | 132 | case '-': |
220 | break; | 133 | break; |
@@ -226,26 +139,7 @@ static void parse_cap(unsigned long *index, const char *cap) | |||
226 | } | 139 | } |
227 | 140 | ||
228 | cap++; | 141 | cap++; |
229 | if ((sscanf(cap, "cap_%lu", &i)) == 1) { | 142 | return cap_name_to_number(cap); |
230 | if (!cap_valid(i)) | ||
231 | bb_error_msg_and_die("unsupported capability '%s'", cap); | ||
232 | *index = i; | ||
233 | return; | ||
234 | } | ||
235 | |||
236 | # if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES | ||
237 | for (i = 0; i < ARRAY_SIZE(capabilities); i++) { | ||
238 | if (strcmp(capabilities[i], cap) != 0) | ||
239 | continue; | ||
240 | |||
241 | if (!cap_valid(i)) | ||
242 | bb_error_msg_and_die("unsupported capability '%s'", cap); | ||
243 | *index = i; | ||
244 | return; | ||
245 | } | ||
246 | # endif | ||
247 | |||
248 | bb_error_msg_and_die("unknown capability '%s'", cap); | ||
249 | } | 143 | } |
250 | 144 | ||
251 | static void set_inh_caps(char *capstring) | 145 | static void set_inh_caps(char *capstring) |
@@ -256,11 +150,11 @@ static void set_inh_caps(char *capstring) | |||
256 | 150 | ||
257 | capstring = strtok(capstring, ","); | 151 | capstring = strtok(capstring, ","); |
258 | while (capstring) { | 152 | while (capstring) { |
259 | unsigned long cap; | 153 | unsigned cap; |
260 | 154 | ||
261 | parse_cap(&cap, capstring); | 155 | cap = parse_cap(capstring); |
262 | if (CAP_TO_INDEX(cap) >= caps.u32s) | 156 | if (CAP_TO_INDEX(cap) >= caps.u32s) |
263 | bb_error_msg_and_die("invalid capability cap"); | 157 | bb_error_msg_and_die("invalid capability '%s'", capstring); |
264 | 158 | ||
265 | if (capstring[0] == '+') | 159 | if (capstring[0] == '+') |
266 | caps.data[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap); | 160 | caps.data[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap); |
@@ -269,11 +163,8 @@ static void set_inh_caps(char *capstring) | |||
269 | capstring = strtok(NULL, ","); | 163 | capstring = strtok(NULL, ","); |
270 | } | 164 | } |
271 | 165 | ||
272 | if ((capset(&caps.header, caps.data)) < 0) | 166 | if (capset(&caps.header, caps.data) != 0) |
273 | bb_perror_msg_and_die("capset"); | 167 | bb_perror_msg_and_die("capset"); |
274 | |||
275 | if (ENABLE_FEATURE_CLEAN_UP) | ||
276 | free(caps.data); | ||
277 | } | 168 | } |
278 | 169 | ||
279 | static void set_ambient_caps(char *string) | 170 | static void set_ambient_caps(char *string) |
@@ -282,9 +173,9 @@ static void set_ambient_caps(char *string) | |||
282 | 173 | ||
283 | cap = strtok(string, ","); | 174 | cap = strtok(string, ","); |
284 | while (cap) { | 175 | while (cap) { |
285 | unsigned long index; | 176 | unsigned index; |
286 | 177 | ||
287 | parse_cap(&index, cap); | 178 | index = parse_cap(cap); |
288 | if (cap[0] == '+') { | 179 | if (cap[0] == '+') { |
289 | if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, index, 0, 0) < 0) | 180 | if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, index, 0, 0) < 0) |
290 | bb_perror_msg("cap_ambient_raise"); | 181 | bb_perror_msg("cap_ambient_raise"); |
@@ -298,16 +189,7 @@ static void set_ambient_caps(char *string) | |||
298 | #endif /* FEATURE_SETPRIV_CAPABILITIES */ | 189 | #endif /* FEATURE_SETPRIV_CAPABILITIES */ |
299 | 190 | ||
300 | #if ENABLE_FEATURE_SETPRIV_DUMP | 191 | #if ENABLE_FEATURE_SETPRIV_DUMP |
301 | # if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES | 192 | # if !ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES |
302 | static void printf_cap(const char *pfx, unsigned cap_no) | ||
303 | { | ||
304 | if (cap_no < ARRAY_SIZE(capabilities)) { | ||
305 | printf("%s%s", pfx, capabilities[cap_no]); | ||
306 | return; | ||
307 | } | ||
308 | printf("%scap_%u", pfx, cap_no); | ||
309 | } | ||
310 | # else | ||
311 | # define printf_cap(pfx, cap_no) printf("%scap_%u", (pfx), (cap_no)) | 193 | # define printf_cap(pfx, cap_no) printf("%scap_%u", (pfx), (cap_no)) |
312 | # endif | 194 | # endif |
313 | 195 | ||
@@ -396,10 +278,9 @@ static int dump(void) | |||
396 | bb_putchar('\n'); | 278 | bb_putchar('\n'); |
397 | # endif | 279 | # endif |
398 | 280 | ||
399 | if (ENABLE_FEATURE_CLEAN_UP) { | 281 | if (ENABLE_FEATURE_CLEAN_UP) |
400 | IF_FEATURE_SETPRIV_CAPABILITIES(free(caps.data);) | ||
401 | free(gids); | 282 | free(gids); |
402 | } | 283 | |
403 | return EXIT_SUCCESS; | 284 | return EXIT_SUCCESS; |
404 | } | 285 | } |
405 | #endif /* FEATURE_SETPRIV_DUMP */ | 286 | #endif /* FEATURE_SETPRIV_DUMP */ |
@@ -421,9 +302,12 @@ int setpriv_main(int argc UNUSED_PARAM, char **argv) | |||
421 | int opts; | 302 | int opts; |
422 | IF_FEATURE_SETPRIV_CAPABILITIES(char *inh_caps, *ambient_caps;) | 303 | IF_FEATURE_SETPRIV_CAPABILITIES(char *inh_caps, *ambient_caps;) |
423 | 304 | ||
424 | applet_long_options = setpriv_longopts; | 305 | opts = getopt32long(argv, "+" |
425 | opts = getopt32(argv, "+"IF_FEATURE_SETPRIV_DUMP("d") | 306 | IF_FEATURE_SETPRIV_DUMP("d") |
426 | IF_FEATURE_SETPRIV_CAPABILITIES("\xfe:\xfd:", &inh_caps, &ambient_caps)); | 307 | IF_FEATURE_SETPRIV_CAPABILITIES("\xfe:\xfd:"), |
308 | setpriv_longopts | ||
309 | IF_FEATURE_SETPRIV_CAPABILITIES(, &inh_caps, &ambient_caps) | ||
310 | ); | ||
427 | argv += optind; | 311 | argv += optind; |
428 | 312 | ||
429 | #if ENABLE_FEATURE_SETPRIV_DUMP | 313 | #if ENABLE_FEATURE_SETPRIV_DUMP |