diff options
author | Andrew G. Morgan <morgan@kernel.org> | 2010-01-03 10:35:37 -0800 |
---|---|---|
committer | Andrew G. Morgan <morgan@kernel.org> | 2010-01-03 10:35:37 -0800 |
commit | 319cbc6501a0e78da9e2a2a608e7c4a14123594d (patch) | |
tree | 3950f0d5ae3dba31e88cae6d2621b59fdb6d1287 | |
parent | 35f5d10ab4c3aaa8ddfa88f81f9a8371faee430b (diff) | |
download | libcap-319cbc6501a0e78da9e2a2a608e7c4a14123594d.tar.gz |
Add a test for maximal lock-down.
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r-- | progs/capsh.c | 93 | ||||
-rwxr-xr-x | progs/quicktest.sh | 6 |
2 files changed, 70 insertions, 29 deletions
diff --git a/progs/capsh.c b/progs/capsh.c index 8f086db..9e8ea5a 100644 --- a/progs/capsh.c +++ b/progs/capsh.c @@ -35,6 +35,20 @@ static const cap_value_t raise_setpcap[1] = { CAP_SETPCAP }; static const cap_value_t raise_chroot[1] = { CAP_SYS_CHROOT }; +static char *binary(unsigned long value) +{ + static char string[8*sizeof(unsigned long) + 1]; + unsigned i; + + i = sizeof(string); + string[--i] = '\0'; + do { + string[--i] = (value & 1) ? '1' : '0'; + value >>= 1; + } while ((i > 0) && value); + return string + i; +} + int main(int argc, char *argv[], char *envp[]) { pid_t child; @@ -70,31 +84,44 @@ int main(int argc, char *argv[], char *envp[]) exit(1); } - for (ptr = argv[i]+7; (ptr = strtok(ptr, ",")); ptr = NULL) { - /* find name for token */ - cap_value_t cap; - int status; - - if (cap_from_name(ptr, &cap) != 0) { - 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 BSET changes"); - exit(1); - } - status = prctl(PR_CAPBSET_DROP, cap); - if (cap_set_proc(orig) != 0) { - perror("unable to lower CAP_SETPCAP post BSET change"); - exit(1); + if (strcmp("all", argv[i]+7) == 0) { + unsigned j = 0; + while (prctl(PR_CAPBSET_READ, j) >= 0) { + if (prctl(PR_CAPBSET_DROP, j) != 0) { + fprintf(stderr, + "Unable to drop bounding capability [%s]\n", + cap_to_name(j)); + exit(1); + } + j++; } - if (status) { - fprintf(stderr, "failed to drop [%s=%u]\n", ptr, cap); - exit(1); + } else { + for (ptr = argv[i]+7; (ptr = strtok(ptr, ",")); ptr = NULL) { + /* find name for token */ + cap_value_t cap; + int status; + + if (cap_from_name(ptr, &cap) != 0) { + 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 BSET changes"); + exit(1); + } + status = prctl(PR_CAPBSET_DROP, cap); + if (cap_set_proc(orig) != 0) { + perror("unable to lower CAP_SETPCAP post BSET change"); + exit(1); + } + if (status) { + fprintf(stderr, "failed to drop [%s=%u]\n", ptr, cap); + exit(1); + } } } - cap_free(raised_for_setpcap); cap_free(orig); } else if (!memcmp("--inh=", argv[i], 6)) { @@ -438,7 +465,10 @@ int main(int argc, char *argv[], char *envp[]) cap_t all; char *text; const char *sep; - gid_t groups[MAX_GROUPS]; + struct group *g; + gid_t groups[MAX_GROUPS], gid; + uid_t uid; + struct passwd *u; all = cap_get_proc(); text = cap_to_text(all, NULL); @@ -465,7 +495,9 @@ int main(int argc, char *argv[], char *envp[]) printf("\n"); set = prctl(PR_GET_SECUREBITS); if (set >= 0) { - printf("Securebits: 0%o/0x%x\n", set, set); + const char *b; + b = binary(set); /* use verilog convention for binary string */ + printf("Securebits: 0%o/0x%x/%u'b%s\n", set, set, strlen(b), b); printf(" secure-noroot: %s (%s)\n", (set & 1) ? "yes":"no", (set & 2) ? "locked":"unlocked"); @@ -485,14 +517,19 @@ int main(int argc, char *argv[], char *envp[]) printf("[Keepcaps ABI not supported]\n"); } } - printf("uid=%u\n", getuid()); - printf("gid=%u\n", getgid()); + uid = getuid(); + u = getpwuid(uid); + printf("uid=%u(%s)\n", getuid(), u ? u->pw_name : "???"); + gid = getgid(); + g = getgrgid(gid); + printf("gid=%u(%s)\n", gid, g ? g->gr_name : "???"); printf("groups="); status = getgroups(MAX_GROUPS, groups); sep = ""; for (j=0; j < status; j++) { - printf("%s%u", sep, groups[j]); - sep = ","; + g = getgrgid(groups[j]); + printf("%s%u(%s)", sep, groups[j], g ? g->gr_name : "???"); + sep = ","; } printf("\n"); } else if ((!strcmp("--", argv[i])) || (!strcmp("==", argv[i]))) { diff --git a/progs/quicktest.sh b/progs/quicktest.sh index bfe54c4..eda6d8a 100755 --- a/progs/quicktest.sh +++ b/progs/quicktest.sh @@ -121,10 +121,14 @@ fi exit 0 EOF chmod +xs hack.sh -capsh --uid=500 -- ./hack.sh +./capsh --uid=500 -- ./hack.sh status=$? rm -f ./hack.sh if [ $status -ne 0 ]; then echo "shell scripts can have capabilities (bug)" exit 1 fi + +# Max lockdown +pass_capsh --keep=1 --user=nobody --caps=cap_setpcap=ep \ + --drop=all --secbits=0xef --caps= --print |