aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util-linux/setpriv.c106
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
102enum { 105enum {
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
164static void getcaps(struct caps *caps) 168static 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
202static int dump(void) 207static 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
316static 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
355static 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
310int setpriv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 384int setpriv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
311int setpriv_main(int argc UNUSED_PARAM, char **argv) 385int 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);