diff options
-rw-r--r-- | util-linux/setpriv.c | 106 |
1 files changed, 95 insertions, 11 deletions
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c index 89fa2fc10..a1fa889e7 100644 --- a/util-linux/setpriv.c +++ b/util-linux/setpriv.c | |||
@@ -56,6 +56,9 @@ | |||
56 | //usage: "\n-d,--dump Show current capabilities" | 56 | //usage: "\n-d,--dump Show current capabilities" |
57 | //usage: ) | 57 | //usage: ) |
58 | //usage: "\n--nnp,--no-new-privs Ignore setuid/setgid bits and file capabilities" | 58 | //usage: "\n--nnp,--no-new-privs Ignore setuid/setgid bits and file capabilities" |
59 | //usage: IF_FEATURE_SETPRIV_CAPABILITIES( | ||
60 | //usage: "\n--inh-caps CAP[,CAP...] Set inheritable capabilities" | ||
61 | //usage: ) | ||
59 | 62 | ||
60 | //setpriv from util-linux 2.28: | 63 | //setpriv from util-linux 2.28: |
61 | // -d, --dump show current state (and do not exec anything) | 64 | // -d, --dump show current state (and do not exec anything) |
@@ -101,9 +104,11 @@ | |||
101 | 104 | ||
102 | enum { | 105 | enum { |
103 | IF_FEATURE_SETPRIV_DUMP(OPTBIT_DUMP,) | 106 | IF_FEATURE_SETPRIV_DUMP(OPTBIT_DUMP,) |
107 | IF_FEATURE_SETPRIV_CAPABILITIES(OPTBIT_INH,) | ||
104 | OPTBIT_NNP, | 108 | OPTBIT_NNP, |
105 | 109 | ||
106 | IF_FEATURE_SETPRIV_DUMP(OPT_DUMP = (1 << OPTBIT_DUMP),) | 110 | IF_FEATURE_SETPRIV_DUMP(OPT_DUMP = (1 << OPTBIT_DUMP),) |
111 | IF_FEATURE_SETPRIV_CAPABILITIES(OPT_INH = (1 << OPTBIT_INH),) | ||
107 | OPT_NNP = (1 << OPTBIT_NNP), | 112 | OPT_NNP = (1 << OPTBIT_NNP), |
108 | }; | 113 | }; |
109 | 114 | ||
@@ -159,8 +164,7 @@ static const char *const capabilities[] = { | |||
159 | 164 | ||
160 | #endif /* FEATURE_SETPRIV_CAPABILITIES */ | 165 | #endif /* FEATURE_SETPRIV_CAPABILITIES */ |
161 | 166 | ||
162 | #if ENABLE_FEATURE_SETPRIV_DUMP | 167 | #if ENABLE_FEATURE_SETPRIV_CAPABILITIES |
163 | # if ENABLE_FEATURE_SETPRIV_CAPABILITIES | ||
164 | static void getcaps(struct caps *caps) | 168 | static void getcaps(struct caps *caps) |
165 | { | 169 | { |
166 | int versions[] = { | 170 | int versions[] = { |
@@ -197,8 +201,9 @@ static void getcaps(struct caps *caps) | |||
197 | if (capget(&caps->header, caps->data) < 0) | 201 | if (capget(&caps->header, caps->data) < 0) |
198 | bb_simple_perror_msg_and_die("capget"); | 202 | bb_simple_perror_msg_and_die("capget"); |
199 | } | 203 | } |
200 | # endif /* FEATURE_SETPRIV_CAPABILITIES */ | 204 | #endif /* FEATURE_SETPRIV_CAPABILITIES */ |
201 | 205 | ||
206 | #if ENABLE_FEATURE_SETPRIV_DUMP | ||
202 | static int dump(void) | 207 | static int dump(void) |
203 | { | 208 | { |
204 | IF_FEATURE_SETPRIV_CAPABILITIES(struct caps caps;) | 209 | IF_FEATURE_SETPRIV_CAPABILITIES(struct caps caps;) |
@@ -215,7 +220,7 @@ static int dump(void) | |||
215 | 220 | ||
216 | nnp = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0); | 221 | nnp = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0); |
217 | if (nnp < 0) | 222 | if (nnp < 0) |
218 | bb_simple_perror_msg_and_die("prctl: GET_NO_NEW_PRIVS"); | 223 | bb_perror_msg_and_die("prctl: %s", "GET_NO_NEW_PRIVS"); |
219 | 224 | ||
220 | printf("uid: %u\n", (unsigned)ruid); | 225 | printf("uid: %u\n", (unsigned)ruid); |
221 | printf("euid: %u\n", (unsigned)euid); | 226 | printf("euid: %u\n", (unsigned)euid); |
@@ -262,7 +267,7 @@ static int dump(void) | |||
262 | for (i = 0; cap_valid(i); i++) { | 267 | for (i = 0; cap_valid(i); i++) { |
263 | int ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, (unsigned long) i, 0UL, 0UL); | 268 | int ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, (unsigned long) i, 0UL, 0UL); |
264 | if (ret < 0) | 269 | if (ret < 0) |
265 | bb_simple_perror_msg_and_die("prctl: CAP_AMBIENT_IS_SET"); | 270 | bb_perror_msg_and_die("prctl: %s", "CAP_AMBIENT_IS_SET"); |
266 | if (ret) { | 271 | if (ret) { |
267 | # if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES | 272 | # if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES |
268 | if (i < ARRAY_SIZE(capabilities)) | 273 | if (i < ARRAY_SIZE(capabilities)) |
@@ -283,7 +288,7 @@ static int dump(void) | |||
283 | for (i = 0; cap_valid(i); i++) { | 288 | for (i = 0; cap_valid(i); i++) { |
284 | int ret = prctl(PR_CAPBSET_READ, (unsigned long) i, 0UL, 0UL, 0UL); | 289 | int ret = prctl(PR_CAPBSET_READ, (unsigned long) i, 0UL, 0UL, 0UL); |
285 | if (ret < 0) | 290 | if (ret < 0) |
286 | bb_simple_perror_msg_and_die("prctl: CAPBSET_READ"); | 291 | bb_perror_msg_and_die("prctl: %s", "CAPBSET_READ"); |
287 | if (ret) { | 292 | if (ret) { |
288 | # if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES | 293 | # if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES |
289 | if (i < ARRAY_SIZE(capabilities)) | 294 | if (i < ARRAY_SIZE(capabilities)) |
@@ -307,20 +312,94 @@ static int dump(void) | |||
307 | } | 312 | } |
308 | #endif /* FEATURE_SETPRIV_DUMP */ | 313 | #endif /* FEATURE_SETPRIV_DUMP */ |
309 | 314 | ||
315 | #if ENABLE_FEATURE_SETPRIV_CAPABILITIES | ||
316 | static void parse_cap(unsigned long *index, int *add, const char *cap) | ||
317 | { | ||
318 | unsigned long i; | ||
319 | |||
320 | switch (cap[0]) { | ||
321 | case '-': | ||
322 | *add = 0; | ||
323 | break; | ||
324 | case '+': | ||
325 | *add = 1; | ||
326 | break; | ||
327 | default: | ||
328 | bb_error_msg_and_die("invalid capability '%s'", cap); | ||
329 | break; | ||
330 | } | ||
331 | |||
332 | cap++; | ||
333 | if ((sscanf(cap, "cap_%lu", &i)) == 1) { | ||
334 | if (!cap_valid(i)) | ||
335 | bb_error_msg_and_die("unsupported capability '%s'", cap); | ||
336 | *index = i; | ||
337 | return; | ||
338 | } | ||
339 | |||
340 | # if ENABLE_FEATURE_SETPRIV_CAPABILITY_NAMES | ||
341 | for (i = 0; i < ARRAY_SIZE(capabilities); i++) { | ||
342 | if (strcmp(capabilities[i], cap) != 0) | ||
343 | continue; | ||
344 | |||
345 | if (!cap_valid(i)) | ||
346 | bb_error_msg_and_die("unsupported capability '%s'", cap); | ||
347 | *index = i; | ||
348 | return; | ||
349 | } | ||
350 | # endif | ||
351 | |||
352 | bb_error_msg_and_die("unknown capability '%s'", cap); | ||
353 | } | ||
354 | |||
355 | static void set_inh_caps(char *capstring) | ||
356 | { | ||
357 | struct caps caps; | ||
358 | |||
359 | getcaps(&caps); | ||
360 | |||
361 | capstring = strtok(capstring, ","); | ||
362 | while (capstring) { | ||
363 | unsigned long cap; | ||
364 | int add; | ||
365 | |||
366 | parse_cap(&cap, &add, capstring); | ||
367 | if (CAP_TO_INDEX(cap) >= caps.u32s) | ||
368 | bb_error_msg_and_die("invalid capability cap"); | ||
369 | if (add) | ||
370 | caps.data[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap); | ||
371 | else | ||
372 | caps.data[CAP_TO_INDEX(cap)].inheritable &= ~CAP_TO_MASK(cap); | ||
373 | capstring = strtok(NULL, ","); | ||
374 | } | ||
375 | |||
376 | if ((capset(&caps.header, caps.data)) < 0) | ||
377 | bb_perror_msg_and_die("capset"); | ||
378 | |||
379 | if (ENABLE_FEATURE_CLEAN_UP) | ||
380 | free(caps.data); | ||
381 | } | ||
382 | #endif /* FEATURE_SETPRIV_CAPABILITIES */ | ||
383 | |||
310 | int setpriv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 384 | int setpriv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
311 | int setpriv_main(int argc UNUSED_PARAM, char **argv) | 385 | int setpriv_main(int argc UNUSED_PARAM, char **argv) |
312 | { | 386 | { |
313 | static const char setpriv_longopts[] ALIGN1 = | 387 | static const char setpriv_longopts[] ALIGN1 = |
314 | IF_FEATURE_SETPRIV_DUMP( | 388 | IF_FEATURE_SETPRIV_DUMP( |
315 | "dump\0" No_argument "d" | 389 | "dump\0" No_argument "d" |
390 | ) | ||
391 | "nnp\0" No_argument "\xff" | ||
392 | "no-new-privs\0" No_argument "\xff" | ||
393 | IF_FEATURE_SETPRIV_CAPABILITIES( | ||
394 | "inh-caps\0" Required_argument "\xfe" | ||
316 | ) | 395 | ) |
317 | "nnp\0" No_argument "\xff" | ||
318 | "no-new-privs\0" No_argument "\xff" | ||
319 | ; | 396 | ; |
320 | int opts; | 397 | int opts; |
398 | IF_FEATURE_SETPRIV_CAPABILITIES(char *inh_caps;) | ||
321 | 399 | ||
322 | applet_long_options = setpriv_longopts; | 400 | applet_long_options = setpriv_longopts; |
323 | opts = getopt32(argv, "+"IF_FEATURE_SETPRIV_DUMP("d")); | 401 | opts = getopt32(argv, "+"IF_FEATURE_SETPRIV_DUMP("d") |
402 | IF_FEATURE_SETPRIV_CAPABILITIES("\xfe:", &inh_caps)); | ||
324 | argv += optind; | 403 | argv += optind; |
325 | 404 | ||
326 | #if ENABLE_FEATURE_SETPRIV_DUMP | 405 | #if ENABLE_FEATURE_SETPRIV_DUMP |
@@ -332,9 +411,14 @@ int setpriv_main(int argc UNUSED_PARAM, char **argv) | |||
332 | #endif | 411 | #endif |
333 | if (opts & OPT_NNP) { | 412 | if (opts & OPT_NNP) { |
334 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) | 413 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) |
335 | bb_simple_perror_msg_and_die("prctl: NO_NEW_PRIVS"); | 414 | bb_perror_msg_and_die("prctl: %s", "SET_NO_NEW_PRIVS"); |
336 | } | 415 | } |
337 | 416 | ||
417 | #if ENABLE_FEATURE_SETPRIV_CAPABILITIES | ||
418 | if (opts & OPT_INH) | ||
419 | set_inh_caps(inh_caps); | ||
420 | #endif | ||
421 | |||
338 | if (!argv[0]) | 422 | if (!argv[0]) |
339 | bb_show_usage(); | 423 | bb_show_usage(); |
340 | BB_EXECVP_or_die(argv); | 424 | BB_EXECVP_or_die(argv); |