aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2017-07-07 02:14:23 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-07 02:14:23 +0200
commit6842d00cebef368a4ade9c9cd3dc92804b84c88d (patch)
tree351906ca680e575b7e3375a8c84f6757118c216d
parent0f49f6f9265ed339e69868708e4d303592a70507 (diff)
downloadbusybox-w32-6842d00cebef368a4ade9c9cd3dc92804b84c88d.tar.gz
busybox-w32-6842d00cebef368a4ade9c9cd3dc92804b84c88d.tar.bz2
busybox-w32-6842d00cebef368a4ade9c9cd3dc92804b84c88d.zip
setpriv: allow modifying ambient capabilities
With Linux 4.3, a new set of capabilities has been introduced with the ambient capabilities. These aim to solve the problem that it was impossible to grant run programs with elevated privileges across non-root users. Quoting from capabilities(7): This is a set of capabilities that are preserved across an execve(2) of a program that is not privileged. The ambient capability set obeys the invariant that no capability can ever be ambient if it is not both permitted and inheritable. With this new set of capabilities it is now possible to run an executable with elevated privileges as a different user, making it much easier to do proper privilege separation. Note though that the `--ambient-caps` switch is not part of any released version of util-linux, yet. It has been applied in 0c92194ee (setpriv: support modifying the set of ambient capabilities, 2017-06-24) and will probably be part of v2.31. function old new delta parse_cap - 174 +174 setpriv_main 1246 1301 +55 .rodata 146307 146347 +40 static.setpriv_longopts 40 55 +15 packed_usage 32092 32079 -13 Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--util-linux/setpriv.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c
index a1fa889e7..8d9c218a3 100644
--- a/util-linux/setpriv.c
+++ b/util-linux/setpriv.c
@@ -57,7 +57,8 @@
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( 59//usage: IF_FEATURE_SETPRIV_CAPABILITIES(
60//usage: "\n--inh-caps CAP[,CAP...] Set inheritable capabilities" 60//usage: "\n--inh-caps CAP,CAP Set inheritable capabilities"
61//usage: "\n--ambient-caps CAP,CAP Set ambient capabilities"
61//usage: ) 62//usage: )
62 63
63//setpriv from util-linux 2.28: 64//setpriv from util-linux 2.28:
@@ -100,15 +101,19 @@
100#ifndef PR_CAP_AMBIENT 101#ifndef PR_CAP_AMBIENT
101#define PR_CAP_AMBIENT 47 102#define PR_CAP_AMBIENT 47
102#define PR_CAP_AMBIENT_IS_SET 1 103#define PR_CAP_AMBIENT_IS_SET 1
104#define PR_CAP_AMBIENT_RAISE 2
105#define PR_CAP_AMBIENT_LOWER 3
103#endif 106#endif
104 107
105enum { 108enum {
106 IF_FEATURE_SETPRIV_DUMP(OPTBIT_DUMP,) 109 IF_FEATURE_SETPRIV_DUMP(OPTBIT_DUMP,)
107 IF_FEATURE_SETPRIV_CAPABILITIES(OPTBIT_INH,) 110 IF_FEATURE_SETPRIV_CAPABILITIES(OPTBIT_INH,)
111 IF_FEATURE_SETPRIV_CAPABILITIES(OPTBIT_AMB,)
108 OPTBIT_NNP, 112 OPTBIT_NNP,
109 113
110 IF_FEATURE_SETPRIV_DUMP(OPT_DUMP = (1 << OPTBIT_DUMP),) 114 IF_FEATURE_SETPRIV_DUMP(OPT_DUMP = (1 << OPTBIT_DUMP),)
111 IF_FEATURE_SETPRIV_CAPABILITIES(OPT_INH = (1 << OPTBIT_INH),) 115 IF_FEATURE_SETPRIV_CAPABILITIES(OPT_INH = (1 << OPTBIT_INH),)
116 IF_FEATURE_SETPRIV_CAPABILITIES(OPT_AMB = (1 << OPTBIT_AMB),)
112 OPT_NNP = (1 << OPTBIT_NNP), 117 OPT_NNP = (1 << OPTBIT_NNP),
113}; 118};
114 119
@@ -313,16 +318,14 @@ static int dump(void)
313#endif /* FEATURE_SETPRIV_DUMP */ 318#endif /* FEATURE_SETPRIV_DUMP */
314 319
315#if ENABLE_FEATURE_SETPRIV_CAPABILITIES 320#if ENABLE_FEATURE_SETPRIV_CAPABILITIES
316static void parse_cap(unsigned long *index, int *add, const char *cap) 321static void parse_cap(unsigned long *index, const char *cap)
317{ 322{
318 unsigned long i; 323 unsigned long i;
319 324
320 switch (cap[0]) { 325 switch (cap[0]) {
321 case '-': 326 case '-':
322 *add = 0;
323 break; 327 break;
324 case '+': 328 case '+':
325 *add = 1;
326 break; 329 break;
327 default: 330 default:
328 bb_error_msg_and_die("invalid capability '%s'", cap); 331 bb_error_msg_and_die("invalid capability '%s'", cap);
@@ -361,12 +364,12 @@ static void set_inh_caps(char *capstring)
361 capstring = strtok(capstring, ","); 364 capstring = strtok(capstring, ",");
362 while (capstring) { 365 while (capstring) {
363 unsigned long cap; 366 unsigned long cap;
364 int add;
365 367
366 parse_cap(&cap, &add, capstring); 368 parse_cap(&cap, capstring);
367 if (CAP_TO_INDEX(cap) >= caps.u32s) 369 if (CAP_TO_INDEX(cap) >= caps.u32s)
368 bb_error_msg_and_die("invalid capability cap"); 370 bb_error_msg_and_die("invalid capability cap");
369 if (add) 371
372 if (capstring[0] == '+')
370 caps.data[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap); 373 caps.data[CAP_TO_INDEX(cap)].inheritable |= CAP_TO_MASK(cap);
371 else 374 else
372 caps.data[CAP_TO_INDEX(cap)].inheritable &= ~CAP_TO_MASK(cap); 375 caps.data[CAP_TO_INDEX(cap)].inheritable &= ~CAP_TO_MASK(cap);
@@ -379,6 +382,26 @@ static void set_inh_caps(char *capstring)
379 if (ENABLE_FEATURE_CLEAN_UP) 382 if (ENABLE_FEATURE_CLEAN_UP)
380 free(caps.data); 383 free(caps.data);
381} 384}
385
386static void set_ambient_caps(char *string)
387{
388 char *cap;
389
390 cap = strtok(string, ",");
391 while (cap) {
392 unsigned long index;
393
394 parse_cap(&index, cap);
395 if (cap[0] == '+') {
396 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, index, 0, 0) < 0)
397 bb_perror_msg("cap_ambient_raise");
398 } else {
399 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, index, 0, 0) < 0)
400 bb_perror_msg("cap_ambient_lower");
401 }
402 cap = strtok(NULL, ",");
403 }
404}
382#endif /* FEATURE_SETPRIV_CAPABILITIES */ 405#endif /* FEATURE_SETPRIV_CAPABILITIES */
383 406
384int setpriv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 407int setpriv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -392,14 +415,15 @@ int setpriv_main(int argc UNUSED_PARAM, char **argv)
392 "no-new-privs\0" No_argument "\xff" 415 "no-new-privs\0" No_argument "\xff"
393 IF_FEATURE_SETPRIV_CAPABILITIES( 416 IF_FEATURE_SETPRIV_CAPABILITIES(
394 "inh-caps\0" Required_argument "\xfe" 417 "inh-caps\0" Required_argument "\xfe"
418 "ambient-caps\0" Required_argument "\xfd"
395 ) 419 )
396 ; 420 ;
397 int opts; 421 int opts;
398 IF_FEATURE_SETPRIV_CAPABILITIES(char *inh_caps;) 422 IF_FEATURE_SETPRIV_CAPABILITIES(char *inh_caps, *ambient_caps;)
399 423
400 applet_long_options = setpriv_longopts; 424 applet_long_options = setpriv_longopts;
401 opts = getopt32(argv, "+"IF_FEATURE_SETPRIV_DUMP("d") 425 opts = getopt32(argv, "+"IF_FEATURE_SETPRIV_DUMP("d")
402 IF_FEATURE_SETPRIV_CAPABILITIES("\xfe:", &inh_caps)); 426 IF_FEATURE_SETPRIV_CAPABILITIES("\xfe:\xfd:", &inh_caps, &ambient_caps));
403 argv += optind; 427 argv += optind;
404 428
405#if ENABLE_FEATURE_SETPRIV_DUMP 429#if ENABLE_FEATURE_SETPRIV_DUMP
@@ -417,6 +441,8 @@ int setpriv_main(int argc UNUSED_PARAM, char **argv)
417#if ENABLE_FEATURE_SETPRIV_CAPABILITIES 441#if ENABLE_FEATURE_SETPRIV_CAPABILITIES
418 if (opts & OPT_INH) 442 if (opts & OPT_INH)
419 set_inh_caps(inh_caps); 443 set_inh_caps(inh_caps);
444 if (opts & OPT_AMB)
445 set_ambient_caps(ambient_caps);
420#endif 446#endif
421 447
422 if (!argv[0]) 448 if (!argv[0])