diff options
author | Sadaf Ebrahimi <sadafebrahimi@google.com> | 2023-08-24 01:50:07 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-08-24 01:50:07 +0000 |
commit | d7d1a0a38c5be06a7e7d6391d140b54878836f48 (patch) | |
tree | 14cfbb9d58780e8b97fa7ed642ea8b7dc1233c6c /progs/capsh.c | |
parent | bff7ee0debce60af18a069d107327bad351e41e8 (diff) | |
parent | 9577b17009379649c9220edca7d0077311445b95 (diff) | |
download | libcap-d7d1a0a38c5be06a7e7d6391d140b54878836f48.tar.gz |
Upgrade libcap to libcap-2.69 am: 3620cbbd3a am: 73ad227596 am: 8a1cf2a372 am: bed57b7ffc am: 9577b17009android-wear-14.0.0-gpl_r1android-14.0.0_r51android-14.0.0_r50android14-qpr3-release
Original change: https://android-review.googlesource.com/c/platform/external/libcap/+/2724494
Change-Id: I4ea4e156399ef29965e8ef1e5ce85c0fb0a969db
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'progs/capsh.c')
-rw-r--r-- | progs/capsh.c | 385 |
1 files changed, 254 insertions, 131 deletions
diff --git a/progs/capsh.c b/progs/capsh.c index 50c2c99..f753291 100644 --- a/progs/capsh.c +++ b/progs/capsh.c @@ -40,6 +40,35 @@ #define MAX_GROUPS 100 /* max number of supplementary groups for user */ +/* parse a non-negative integer with some error handling */ +static unsigned long nonneg_uint(const char *text, const char *prefix, int *ok) +{ + char *remains; + unsigned long value; + ssize_t len = strlen(text); + + if (len == 0 || *text == '-') { + goto fail; + } + value = strtoul(text, &remains, 0); + if (*remains) { + goto fail; + } + if (ok != NULL) { + *ok = 1; + } + return value; + +fail: + if (ok == NULL) { + fprintf(stderr, "%s: want non-negative integer, got \"%s\"\n", + prefix, text); + exit(1); + } + *ok = 0; + return 0; +} + static char *binary(unsigned long value) { static char string[8*sizeof(unsigned long) + 1]; @@ -89,6 +118,10 @@ static void display_current(void) char *text; all = cap_get_proc(); + if (all == NULL) { + perror("failed to get process capabilities"); + exit(1); + } text = cap_to_text(all, NULL); printf("Current: %s\n", text); cap_free(text); @@ -101,7 +134,16 @@ static void display_current_iab(void) char *text; iab = cap_iab_get_proc(); + if (iab == NULL) { + perror("failed to get IAB for process"); + exit(1); + } text = cap_iab_to_text(iab); + if (text == NULL) { + perror("failed to obtain text for IAB"); + cap_free(iab); + exit(1); + } printf("Current IAB: %s\n", text); cap_free(text); cap_free(iab); @@ -178,29 +220,42 @@ static void arg_print(void) static const cap_value_t raise_setpcap[1] = { CAP_SETPCAP }; static const cap_value_t raise_chroot[1] = { CAP_SYS_CHROOT }; -static void push_pcap(cap_t *orig_p, cap_t *raised_for_setpcap_p) +static cap_t will_need_setpcap(int strict) { - /* - * We need to do this here because --inh=XXX may have reset - * orig and it isn't until we are within the --drop code that - * we know what the prevailing (orig) pI value is. - */ - *orig_p = cap_get_proc(); - if (NULL == *orig_p) { + cap_flag_value_t enabled; + cap_t raised = NULL; + + if (strict) { + return NULL; + } + + raised = cap_get_proc(); + if (raised == NULL) { perror("Capabilities not available"); exit(1); } - - *raised_for_setpcap_p = cap_dup(*orig_p); - if (NULL == *raised_for_setpcap_p) { - fprintf(stderr, "modification requires CAP_SETPCAP\n"); + if (cap_get_flag(raised, CAP_SETPCAP, CAP_EFFECTIVE, &enabled) != 0) { + perror("Unable to check CAP_EFFECTIVE CAP_SETPCAP value"); exit(1); } - if (cap_set_flag(*raised_for_setpcap_p, CAP_EFFECTIVE, 1, - raise_setpcap, CAP_SET) != 0) { - perror("unable to select CAP_SETPCAP"); + if (enabled != CAP_SET) { + cap_set_flag(raised, CAP_EFFECTIVE, 1, raise_setpcap, CAP_SET); + } else { + /* no need to raise - since already raised */ + cap_free(raised); + raised = NULL; + } + return raised; +} + +static void push_pcap(int strict, cap_t *orig_p, cap_t *raised_for_setpcap_p) +{ + *orig_p = cap_get_proc(); + if (NULL == *orig_p) { + perror("Capabilities not available"); exit(1); } + *raised_for_setpcap_p = will_need_setpcap(strict); } static void pop_pcap(cap_t orig, cap_t raised_for_setpcap) @@ -209,23 +264,24 @@ static void pop_pcap(cap_t orig, cap_t raised_for_setpcap) cap_free(orig); } -static void arg_drop(const char *arg_names) +static void arg_drop(int strict, const char *arg_names) { char *ptr; cap_t orig, raised_for_setpcap; char *names; - push_pcap(&orig, &raised_for_setpcap); + push_pcap(strict, &orig, &raised_for_setpcap); if (strcmp("all", arg_names) == 0) { unsigned j = 0; while (CAP_IS_SUPPORTED(j)) { int status; - if (cap_set_proc(raised_for_setpcap) != 0) { + if (raised_for_setpcap != NULL && + cap_set_proc(raised_for_setpcap) != 0) { perror("unable to raise CAP_SETPCAP for BSET changes"); exit(1); } status = cap_drop_bound(j); - if (cap_set_proc(orig) != 0) { + if (raised_for_setpcap != NULL && cap_set_proc(orig) != 0) { perror("unable to lower CAP_SETPCAP post BSET change"); exit(1); } @@ -258,12 +314,13 @@ static void arg_drop(const char *arg_names) fprintf(stderr, "capability [%s] is unknown to libcap\n", ptr); exit(1); } - if (cap_set_proc(raised_for_setpcap) != 0) { + if (raised_for_setpcap != NULL && + cap_set_proc(raised_for_setpcap) != 0) { perror("unable to raise CAP_SETPCAP for BSET changes"); exit(1); } status = cap_drop_bound(cap); - if (cap_set_proc(orig) != 0) { + if (raised_for_setpcap != NULL && cap_set_proc(orig) != 0) { perror("unable to lower CAP_SETPCAP post BSET change"); exit(1); } @@ -279,23 +336,15 @@ static void arg_drop(const char *arg_names) static void arg_change_amb(const char *arg_names, cap_flag_value_t set) { char *ptr; - cap_t orig, raised_for_setpcap; + cap_t orig; char *names; - push_pcap(&orig, &raised_for_setpcap); + orig = cap_get_proc(); if (strcmp("all", arg_names) == 0) { unsigned j = 0; while (CAP_IS_SUPPORTED(j)) { int status; - if (cap_set_proc(raised_for_setpcap) != 0) { - perror("unable to raise CAP_SETPCAP for AMBIENT changes"); - exit(1); - } status = cap_set_ambient(j, set); - if (cap_set_proc(orig) != 0) { - perror("unable to lower CAP_SETPCAP post AMBIENT change"); - exit(1); - } if (status != 0) { char *name_ptr; @@ -307,7 +356,7 @@ static void arg_change_amb(const char *arg_names, cap_flag_value_t set) } j++; } - pop_pcap(orig, raised_for_setpcap); + cap_free(orig); return; } @@ -325,22 +374,14 @@ static void arg_change_amb(const char *arg_names, cap_flag_value_t set) fprintf(stderr, "capability [%s] is unknown to libcap\n", ptr); exit(1); } - if (cap_set_proc(raised_for_setpcap) != 0) { - perror("unable to raise CAP_SETPCAP for AMBIENT changes"); - exit(1); - } status = cap_set_ambient(cap, set); - if (cap_set_proc(orig) != 0) { - perror("unable to lower CAP_SETPCAP post AMBIENT change"); - exit(1); - } if (status != 0) { fprintf(stderr, "failed to %s ambient [%s=%u]\n", set == CAP_CLEAR ? "clear":"raise", ptr, cap); exit(1); } } - pop_pcap(orig, raised_for_setpcap); + cap_free(orig); free(names); } @@ -427,24 +468,70 @@ static void describe(cap_value_t cap) { } } -int main(int argc, char *argv[], char *envp[]) +__attribute__ ((noreturn)) +static void do_launch(char *args[], char *envp[]) { + cap_launch_t lau; pid_t child; - unsigned i; - const char *shell = SHELL; + int ret, result; - child = 0; - - char *temp_name = cap_to_name(cap_max_bits() - 1); - if (temp_name[0] != 'c') { - printf("WARNING: libcap needs an update (cap=%d should have a name).\n", - cap_max_bits() - 1); + lau = cap_new_launcher(args[0], (void *) args, (void *) envp); + if (lau == NULL) { + perror("failed to create launcher"); + exit(1); + } + child = cap_launch(lau, NULL); + if (child <= 0) { + perror("child failed to start"); + exit(1); } - cap_free(temp_name); + cap_free(lau); + ret = waitpid(child, &result, 0); + if (ret != child) { + fprintf(stderr, "failed to wait for PID=%d, result=%x: ", + child, result); + perror(""); + exit(1); + } + if (WIFEXITED(result)) { + exit(WEXITSTATUS(result)); + } + if (WIFSIGNALED(result)) { + fprintf(stderr, "child PID=%d terminated by signo=%d\n", + child, WTERMSIG(result)); + exit(1); + } + fprintf(stderr, "child PID=%d generated result=%0x\n", child, result); + exit(1); +} + +int main(int argc, char *argv[], char *envp[]) +{ + pid_t child = 0; + unsigned i; + int strict = 0, quiet_start = 0, dont_set_env = 0; + const char *shell = SHELL; for (i=1; i<argc; ++i) { + if (!strcmp("--quiet", argv[i])) { + quiet_start = 1; + continue; + } + if (i == 1) { + char *temp_name = cap_to_name(cap_max_bits() - 1); + if (temp_name == NULL) { + perror("obtaining highest capability name"); + exit(1); + } + if (temp_name[0] != 'c') { + printf("WARNING: libcap needs an update" + " (cap=%d should have a name).\n", + cap_max_bits() - 1); + } + cap_free(temp_name); + } if (!strncmp("--drop=", argv[i], 7)) { - arg_drop(argv[i]+7); + arg_drop(strict, argv[i]+7); } else if (!strncmp("--dropped=", argv[i], 10)) { cap_value_t cap; if (cap_from_name(argv[i]+10, &cap) < 0) { @@ -459,7 +546,7 @@ int main(int argc, char *argv[], char *envp[]) } } else if (!strcmp("--has-ambient", argv[i])) { if (!CAP_AMBIENT_SUPPORTED()) { - fprintf(stderr, "ambient set not supported\n"); + perror("ambient set not supported"); exit(1); } } else if (!strncmp("--addamb=", argv[i], 9)) { @@ -468,32 +555,21 @@ int main(int argc, char *argv[], char *envp[]) arg_change_amb(argv[i]+9, CAP_CLEAR); } else if (!strncmp("--noamb", argv[i], 7)) { if (cap_reset_ambient() != 0) { - fprintf(stderr, "failed to reset ambient set\n"); + perror("failed to reset ambient set"); exit(1); } + } else if (!strcmp("--noenv", argv[i])) { + dont_set_env = 1; } else if (!strncmp("--inh=", argv[i], 6)) { cap_t all, raised_for_setpcap; char *text; char *ptr; - all = cap_get_proc(); - if (all == NULL) { - perror("Capabilities not available"); - exit(1); - } + push_pcap(strict, &all, &raised_for_setpcap); if (cap_clear_flag(all, CAP_INHERITABLE) != 0) { perror("libcap:cap_clear_flag() internal error"); exit(1); } - - raised_for_setpcap = cap_dup(all); - if ((raised_for_setpcap != NULL) - && (cap_set_flag(raised_for_setpcap, CAP_EFFECTIVE, 1, - raise_setpcap, CAP_SET) != 0)) { - cap_free(raised_for_setpcap); - raised_for_setpcap = NULL; - } - text = cap_to_text(all, NULL); cap_free(all); if (text == NULL) { @@ -510,13 +586,13 @@ int main(int argc, char *argv[], char *envp[]) } else { strcpy(ptr, text); } + cap_free(text); all = cap_from_text(ptr); if (all == NULL) { perror("Fatal error internalizing capabilities"); exit(1); } - cap_free(text); free(ptr); if (raised_for_setpcap != NULL) { @@ -534,45 +610,29 @@ int main(int argc, char *argv[], char *envp[]) perror("Unable to set inheritable capabilities"); exit(1); } - /* - * Since status is based on orig, we don't want to restore - * the previous value of 'all' again here! - */ - cap_free(all); + } else if (!strcmp("--strict", argv[i])) { + strict = !strict; } else if (!strncmp("--caps=", argv[i], 7)) { cap_t all, raised_for_setpcap; - raised_for_setpcap = cap_get_proc(); - if (raised_for_setpcap == NULL) { - perror("Capabilities not available"); - exit(1); - } - - if ((raised_for_setpcap != NULL) - && (cap_set_flag(raised_for_setpcap, CAP_EFFECTIVE, 1, - raise_setpcap, CAP_SET) != 0)) { - cap_free(raised_for_setpcap); - raised_for_setpcap = NULL; - } - + raised_for_setpcap = will_need_setpcap(strict); all = cap_from_text(argv[i]+7); if (all == NULL) { fprintf(stderr, "unable to interpret [%s]\n", argv[i]); exit(1); } - if (raised_for_setpcap != NULL) { /* - * This is only for the case that pP does not contain - * the requested change to pI.. Failing here is not - * indicative of the cap_set_proc(all) failing (always). + * This is actually only for the case that pP does not + * contain the requested change to pI.. Failing here + * is not always indicative of the cap_set_proc(all) + * failing. */ (void) cap_set_proc(raised_for_setpcap); cap_free(raised_for_setpcap); raised_for_setpcap = NULL; } - if (cap_set_proc(all) != 0) { fprintf(stderr, "Unable to set capabilities [%s]\n", argv[i]); exit(1); @@ -581,7 +641,6 @@ int main(int argc, char *argv[], char *envp[]) * Since status is based on orig, we don't want to restore * the previous value of 'all' again here! */ - cap_free(all); } else if (!strcmp("--modes", argv[i])) { cap_mode_t c; @@ -594,30 +653,38 @@ int main(int argc, char *argv[], char *envp[]) printf(" %s", m); } printf("\n"); - } else if (!strncmp("--mode=", argv[i], 7)) { - const char *target = argv[i]+7; - cap_mode_t c; - int found = 0; - for (c = 1; ; c++) { - const char *m = cap_mode_name(c); - if (!strcmp("UNKNOWN", m)) { - found = 0; - break; + } else if (!strncmp("--mode", argv[i], 6)) { + if (argv[i][6] == '=') { + const char *target = argv[i]+7; + cap_mode_t c; + int found = 0; + for (c = 1; ; c++) { + const char *m = cap_mode_name(c); + if (!strcmp("UNKNOWN", m)) { + found = 0; + break; + } + if (!strcmp(m, target)) { + found = 1; + break; + } } - if (!strcmp(m, target)) { - found = 1; - break; + if (!found) { + printf("unsupported mode: %s\n", target); + exit(1); } - } - if (!found) { - printf("unsupported mode: %s\n", target); - exit(1); - } - int ret = cap_set_mode(c); - if (ret != 0) { - printf("failed to set mode [%s]: %s\n", - target, strerror(errno)); - exit(1); + int ret = cap_set_mode(c); + if (ret != 0) { + printf("failed to set mode [%s]: %s\n", + target, strerror(errno)); + exit(1); + } + } else if (argv[i][6]) { + printf("unrecognized command [%s]\n", argv[i]); + goto usage; + } else { + cap_mode_t m = cap_get_mode(); + printf("Mode: %s\n", cap_mode_name(m)); } } else if (!strncmp("--inmode=", argv[i], 9)) { const char *target = argv[i]+9; @@ -631,7 +698,7 @@ int main(int argc, char *argv[], char *envp[]) unsigned value; int set; - value = strtoul(argv[i]+7, NULL, 0); + value = nonneg_uint(argv[i]+7, "invalid --keep value", NULL); set = prctl(PR_SET_KEEPCAPS, value); if (set < 0) { fprintf(stderr, "prctl(PR_SET_KEEPCAPS, %u) failed: %s\n", @@ -688,7 +755,7 @@ int main(int argc, char *argv[], char *envp[]) } else if (!strncmp("--secbits=", argv[i], 10)) { unsigned value; int status; - value = strtoul(argv[i]+10, NULL, 0); + value = nonneg_uint(argv[i]+10, "invalid --secbits value", NULL); status = cap_set_secbits(value); if (status < 0) { fprintf(stderr, "failed to set securebits to 0%o/0x%x\n", @@ -701,8 +768,9 @@ int main(int argc, char *argv[], char *envp[]) fprintf(stderr, "already forked\n"); exit(1); } - value = strtoul(argv[i]+10, NULL, 0); + value = nonneg_uint(argv[i]+10, "invalid --forkfor value", NULL); if (value == 0) { + fprintf(stderr, "require non-zero --forkfor value\n"); goto usage; } child = fork(); @@ -717,7 +785,8 @@ int main(int argc, char *argv[], char *envp[]) pid_t result; unsigned value; - value = strtoul(argv[i]+9, NULL, 0); + value = nonneg_uint(argv[i]+9, "invalid --killit signo value", + NULL); if (!child) { fprintf(stderr, "no forked process to kill\n"); exit(1); @@ -743,7 +812,7 @@ int main(int argc, char *argv[], char *envp[]) unsigned value; int status; - value = strtoul(argv[i]+6, NULL, 0); + value = nonneg_uint(argv[i]+6, "invalid --uid value", NULL); status = setuid(value); if (status < 0) { fprintf(stderr, "Failed to set uid=%u: %s\n", @@ -754,7 +823,7 @@ int main(int argc, char *argv[], char *envp[]) unsigned value; int status; - value = strtoul(argv[i]+10, NULL, 0); + value = nonneg_uint(argv[i]+10, "invalid --cap-uid value", NULL); status = cap_setuid(value); if (status < 0) { fprintf(stderr, "Failed to cap_setuid(%u): %s\n", @@ -765,7 +834,7 @@ int main(int argc, char *argv[], char *envp[]) unsigned value; int status; - value = strtoul(argv[i]+6, NULL, 0); + value = nonneg_uint(argv[i]+6, "invalid --gid value", NULL); status = setgid(value); if (status < 0) { fprintf(stderr, "Failed to set gid=%u: %s\n", @@ -845,6 +914,20 @@ int main(int argc, char *argv[], char *envp[]) pwd->pw_uid, user, strerror(errno)); exit(1); } + if (!dont_set_env) { + /* + * not setting this confuses bash at start up, but use + * --noenv to preserve the HOME etc values instead. + */ + if (setenv("HOME", pwd->pw_dir, 1) != 0) { + perror("unable to set HOME"); + exit(1); + } + if (setenv("USER", user, 1) != 0) { + perror("unable to set USER"); + exit(1); + } + } } else if (!strncmp("--decode=", argv[i], 9)) { unsigned long long value; unsigned cap; @@ -885,13 +968,22 @@ int main(int argc, char *argv[], char *envp[]) } } else if (!strcmp("--print", argv[i])) { arg_print(); - } else if ((!strcmp("--", argv[i])) || (!strcmp("==", argv[i]))) { + } else if ((!strcmp("--", argv[i])) || (!strcmp("==", argv[i])) + || (!strcmp("-+", argv[i])) || (!strcmp("=+", argv[i]))) { + int launch = argv[i][1] == '+'; if (argv[i][0] == '=') { + if (quiet_start) { + argv[i--] = strdup("--quiet"); + } argv[i] = find_self(argv[0]); } else { argv[i] = strdup(shell); } argv[argc] = NULL; + /* Two ways to chain load - use cap_launch() or execve() */ + if (launch) { + do_launch(argv+i, envp); + } execve(argv[i], argv+i, envp); fprintf(stderr, "execve '%s' failed!\n", argv[i]); free(argv[i]); @@ -909,6 +1001,10 @@ int main(int argc, char *argv[], char *envp[]) exit(1); } orig = cap_get_proc(); + if (orig == NULL) { + perror("failed to get process capabilities"); + exit(1); + } if (cap_get_flag(orig, cap, CAP_PERMITTED, &enabled) || !enabled) { fprintf(stderr, "cap[%s] not permitted\n", argv[i]+8); exit(1); @@ -925,6 +1021,10 @@ int main(int argc, char *argv[], char *envp[]) exit(1); } orig = cap_get_proc(); + if (orig == NULL) { + perror("failed to get process capabilities"); + exit(1); + } if (cap_get_flag(orig, cap, CAP_INHERITABLE, &enabled) || !enabled) { fprintf(stderr, "cap[%s] not inheritable\n", argv[i]+8); @@ -942,10 +1042,21 @@ int main(int argc, char *argv[], char *envp[]) fprintf(stderr, "cap[%s] not in ambient vector\n", argv[i]+8); exit(1); } + } else if (!strncmp("--has-b=", argv[i], 8)) { + cap_value_t cap; + if (cap_from_name(argv[i]+8, &cap) < 0) { + fprintf(stderr, "cap[%s] not recognized by library\n", + argv[i] + 8); + exit(1); + } + if (!cap_get_bound(cap)) { + fprintf(stderr, "cap[%s] not in bounding vector\n", argv[i]+8); + exit(1); + } } else if (!strncmp("--is-uid=", argv[i], 9)) { unsigned value; uid_t uid; - value = strtoul(argv[i]+9, NULL, 0); + value = nonneg_uint(argv[i]+9, "invalid --is-uid value", NULL); uid = getuid(); if (uid != value) { fprintf(stderr, "uid: got=%d, want=%d\n", uid, value); @@ -954,7 +1065,7 @@ int main(int argc, char *argv[], char *envp[]) } else if (!strncmp("--is-gid=", argv[i], 9)) { unsigned value; gid_t gid; - value = strtoul(argv[i]+9, NULL, 0); + value = nonneg_uint(argv[i]+9, "invalid --is-gid value", NULL); gid = getgid(); if (gid != value) { fprintf(stderr, "gid: got=%d, want=%d\n", gid, value); @@ -967,7 +1078,7 @@ int main(int argc, char *argv[], char *envp[]) exit(1); } if (cap_iab_set_proc(iab)) { - perror("unable to set IAP vectors"); + perror("unable to set IAB tuple"); exit(1); } cap_free(iab); @@ -983,7 +1094,7 @@ int main(int argc, char *argv[], char *envp[]) } } else if (!strcmp("--license", argv[i])) { printf( - "%s see LICENSE file for details.\n" + "%s see License file for details.\n" "Copyright (c) 2008-11,16,19-21 Andrew G. Morgan" " <morgan@kernel.org>\n", argv[0]); exit(0); @@ -997,7 +1108,7 @@ int main(int argc, char *argv[], char *envp[]) fprintf(stderr, "negative capability (%d) invalid\n", cap); exit(1); } - if (cap < CAPSH_DOC_LIMIT) { + if (cap < capsh_doc_limit) { describe(cap); continue; } @@ -1010,10 +1121,14 @@ int main(int argc, char *argv[], char *envp[]) } else if (!strncmp("--suggest=", argv[i], 10)) { cap_value_t cap; int hits = 0; - for (cap=0; cap < CAPSH_DOC_LIMIT; cap++) { + for (cap=0; cap < capsh_doc_limit; cap++) { const char **lines = explanations[cap]; int j; char *name = cap_to_name(cap); + if (name == NULL) { + perror("invalid named cap"); + exit(1); + } char *match = strcasestr(name, argv[i]+10); cap_free(name); if (match != NULL) { @@ -1046,11 +1161,13 @@ int main(int argc, char *argv[], char *envp[]) " --current show current caps and IAB vectors\n" " --decode=xxx decode a hex string to a list of caps\n" " --delamb=xxx remove xxx,... capabilities from ambient\n" + " --drop=xxx drop xxx,... caps from bounding set\n" " --explain=xxx explain what capability xxx permits\n" " --forkfor=<n> fork and make child sleep for <n> sec\n" " --gid=<n> set gid to <n> (hint: id <username>)\n" " --groups=g,... set the supplemental groups\n" " --has-a=xxx exit 1 if capability xxx not ambient\n" + " --has-b=xxx exit 1 if capability xxx not dropped\n" " --has-ambient exit 1 unless ambient vector supported\n" " --has-i=xxx exit 1 if capability xxx not inheritable\n" " --has-p=xxx exit 1 if capability xxx not permitted\n" @@ -1064,19 +1181,25 @@ int main(int argc, char *argv[], char *envp[]) " --keep=<n> set keep-capability bit to <n>\n" " --killit=<n> send signal(n) to child\n" " --license display license info\n" - " --modes list libcap named capability modes\n" - " --mode=<xxx> set capability mode to <xxx>\n" + " --mode display current libcap mode\n" + " --mode=<xxx> set libcap mode to <xxx>\n" + " --modes list libcap named modes\n" " --no-new-privs set sticky process privilege limiter\n" " --noamb reset (drop) all ambient capabilities\n" + " --noenv no fixup of env vars (for --user)\n" " --print display capability relevant state\n" + " --quiet if first argument skip max cap check\n" " --secbits=<n> write a new value for securebits\n" " --shell=/xx/yy use /xx/yy instead of " SHELL " for --\n" + " --strict toggle --caps, --drop and --inh fixups\n" " --suggest=text search cap descriptions for text\n" " --supports=xxx exit 1 if capability xxx unsupported\n" " --uid=<n> set uid to <n> (hint: id <username>)\n" " --user=<name> set uid,gid and groups to that of user\n" " == re-exec(capsh) with args as for --\n" + " =+ cap_launch capsh with args as for -+\n" " -- remaining arguments are for " SHELL "\n" + " -+ cap_launch " SHELL " with remaining args\n" " (without -- [%s] will simply exit(0))\n", argv[0], argv[0]); if (strcmp("--help", argv[1]) && strcmp("-h", argv[1])) { |