diff options
author | Andrew G. Morgan <morgan@kernel.org> | 2009-11-22 21:57:18 -0800 |
---|---|---|
committer | Andrew G. Morgan <morgan@kernel.org> | 2009-11-22 22:00:53 -0800 |
commit | 7445469645b3587f0c8507504dc3889a013305e1 (patch) | |
tree | befa1fdbe4395f37b3f8edaf8d1042e8935d2934 | |
parent | b0135454ab5365ab284465e8ad2830f92b3ea74c (diff) | |
download | libcap-7445469645b3587f0c8507504dc3889a013305e1.tar.gz |
Checkpoint.
-rw-r--r-- | doc/Makefile | 6 | ||||
-rw-r--r-- | doc/capsh.1 | 78 | ||||
-rw-r--r-- | progs/capsh.c | 69 |
3 files changed, 149 insertions, 4 deletions
diff --git a/doc/Makefile b/doc/Makefile index ba5ee92..5fe2189 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -5,6 +5,7 @@ topdir=$(shell pwd)/.. include $(topdir)/Make.Rules +MAN1S = capsh.1 MAN3S = cap_init.3 cap_free.3 cap_dup.3 \ cap_clear.3 cap_clear_flag.3 cap_get_flag.3 cap_set_flag.3 \ cap_compare.3 cap_get_proc.3 cap_get_pid.3 cap_set_proc.3 \ @@ -14,7 +15,7 @@ MAN3S = cap_init.3 cap_free.3 cap_dup.3 \ capsetp.3 capgetp.3 libcap.3 MAN8S = getcap.8 setcap.8 -MANS = $(MAN3S) $(MAN8S) +MANS = $(MAN1S) $(MAN3S) $(MAN8S) all: $(MANS) @@ -28,8 +29,9 @@ html: done install: - mkdir -p -m 755 $(MANDIR)/man3 $(MANDIR)/man8 + mkdir -p -m 755 $(MANDIR)/man1 $(MANDIR)/man3 $(MANDIR)/man8 for man in \ + $(MANDIR)/man1 $(MAN1S) \ $(MANDIR)/man3 $(MAN3S) \ $(MANDIR)/man8 $(MAN8S) \ ; \ diff --git a/doc/capsh.1 b/doc/capsh.1 new file mode 100644 index 0000000..20973b5 --- /dev/null +++ b/doc/capsh.1 @@ -0,0 +1,78 @@ +.\" +.\" capsh.1 Man page added 2009-11-22 Andrew G. Morgan <morgan@kernel.org> +.\" +.TH CAPSH 1 "2009-11-22" "libcap 2" "User Commands" +.SH NAME +capsh \- capability shell wrapper +.SH SYNOPSIS +.B capsh +[\fIOPTION\fR]... +.SH DESCRIPTION +Linux capability support and use can be explored and constrained with +this tool. This tool provides a handy wrapper for certain types +of capability testing and environment creation. It also provides some +debugging features useful for summarizing capability state. +.SH OPTIONS +The tool takes a number of optional arguments, acting on them in the +order they are provided. They are as follows: +.TP 22 +.B --print +Display prevailing capability and related state. +.TP +.BI -- " [args]" +Execute +.B /bin/bash +with trailing arguments. Note, you can use +.B -c 'command to execute' +for commands. +.TP +.B == +Execute +.B capsh +again with remaining arguments. Useful for testing +.BR exec () +behavior. +.TP +.BI --caps= cap-set +Set the prevailing process capabilities to those specified by +.IR cap-set . +Where +.I cap-set +is a text-representation of capability state as per +.BR cap_from_text (3). +.TP +.BI --drop= <cap-list> +.TP +.BI --inh= <cap-list> +.TP +.BI --keep= <0|1> +.TP +.BI --chroot= <path> +.TP +.BI --secbits= <N> +.TP +.BI --forkfor= <sec> +.TP +.BI --killit= <sig> +.TP +.BI --uid= <id> +.TP +.BI --gid= <id> +.TP +.BI --groups= <gid-list> +.TP +.BI --user= <username> +.TP +.BI --decode= <N> +.SH "EXIT STATUS" +Following successful execution the tool exits with status 0. Following +an error, the tool immediately exits with status 1. +.SH AUTHOR +Written by Andrew G. Morgan <morgan@kernel.org>. +.SH "REPORTING BUGS" +Please report bugs to the author. +.SH "SEE ALSO" +.BR libcap (3), +.BR getcap (8), setcap (8) +and +.BR capabilities (7). diff --git a/progs/capsh.c b/progs/capsh.c index 40d632c..4cc3549 100644 --- a/progs/capsh.c +++ b/progs/capsh.c @@ -13,7 +13,10 @@ #include <string.h> #include <stdlib.h> #include <sys/prctl.h> +#include <sys/types.h> #include <unistd.h> +#include <pwd.h> +#include <grp.h> #include <errno.h> #include <sys/wait.h> #include <sys/capability.h> @@ -26,6 +29,8 @@ #define PR_GET_SECUREBITS 27 #define PR_SET_SECUREBITS 28 +#define MAX_GROUPS 100 /* max number of supplementary groups for user */ + static const cap_value_t raise_setpcap[1] = { CAP_SETPCAP }; static const cap_value_t raise_chroot[1] = { CAP_SYS_CHROOT }; @@ -311,6 +316,54 @@ int main(int argc, char *argv[], char *envp[]) value, strerror(errno)); exit(1); } + } else if (!memcmp("--gid=", argv[i], 6)) { + unsigned value; + int status; + + value = strtoul(argv[i]+6, NULL, 0); + status = setgid(value); + if (status < 0) { + fprintf(stderr, "Failed to set gid=%u: %s\n", + value, strerror(errno)); + exit(1); + } + } else if (!memcmp("--groups=", argv[i], 9)) { + exit(1); + } else if (!memcmp("--user=", argv[i], 7)) { + struct passwd *pwd; + const char *user; + gid_t groups[MAX_GROUPS]; + int status, ngroups; + + user = argv[i] + 7; + pwd = getpwnam(user); + if (pwd == NULL) { + fprintf(stderr, "User [%s] not known\n", user); + exit(1); + } + ngroups = MAX_GROUPS; + status = getgrouplist(user, pwd->pw_gid, groups, &ngroups); + if (status < 1) { + perror("Unable to get group list for user"); + exit(1); + } + status = setgroups(ngroups, groups); + if (status != 0) { + perror("Unable to set group list for user"); + exit(1); + } + status = setgid(pwd->pw_gid); + if (status < 0) { + fprintf(stderr, "Failed to set gid=%u(user=%s): %s\n", + pwd->pw_gid, user, strerror(errno)); + exit(1); + } + status = setuid(pwd->pw_uid); + if (status < 0) { + fprintf(stderr, "Failed to set uid=%u(user=%s): %s\n", + pwd->pw_uid, user, strerror(errno)); + exit(1); + } } else if (!memcmp("--decode=", argv[i], 9)) { unsigned long long value; unsigned cap; @@ -337,10 +390,11 @@ int main(int argc, char *argv[], char *envp[]) printf("\n"); } else if (!strcmp("--print", argv[i])) { unsigned cap; - int set; + int set, status; cap_t all; char *text; const char *sep; + gid_t groups[MAX_GROUPS]; all = cap_get_proc(); text = cap_to_text(all, NULL); @@ -388,6 +442,15 @@ int main(int argc, char *argv[], char *envp[]) } } printf("uid=%u\n", getuid()); + printf("gid=%u\n", getgid()); + printf("groups="); + status = getgroups(MAX_GROUPS, groups); + sep = ""; + for (i=0; i < status; i++) { + printf("%s%u", sep, groups[i]); + sep = ","; + } + printf("\n"); } else if ((!strcmp("--", argv[i])) || (!strcmp("==", argv[i]))) { argv[i] = strdup(argv[i][0] == '-' ? "/bin/bash" : argv[0]); argv[argc] = NULL; @@ -397,7 +460,7 @@ int main(int argc, char *argv[], char *envp[]) } else { usage: printf("usage: %s [args ...]\n" - " --help this message\n" + " --help this message (or try 'man capsh')\n" " --print display capability relevant state\n" " --decode=xxx decode a hex string to a list of caps\n" " --drop=xxx remove xxx,.. capabilities from bset\n" @@ -406,6 +469,8 @@ int main(int argc, char *argv[], char *envp[]) " --secbits=<n> write a new value for securebits\n" " --keep=<n> set keep-capabability bit to <n>\n" " --uid=<n> set uid to <n> (hint: id <username>)\n" + " --gid=<n> set gid to <n> (hint: id <username>)\n" + " --user=<name> set uid,gid and groups to that of user\n" " --chroot=path chroot(2) to this path to invoke bash\n" " --killit=<n> send signal(n) to child\n" " --forkfor=<n> fork and make child sleep for <n> sec\n" |