summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2009-11-23 00:43:10 -0800
committerAndrew G. Morgan <morgan@kernel.org>2009-11-23 00:43:10 -0800
commit9c49729624b1a9c2c48d43929a4cbb2ce3c8db06 (patch)
tree8ce5b407332553a2d36f3553f9fbdf78717e2c67
parent7445469645b3587f0c8507504dc3889a013305e1 (diff)
downloadlibcap2-9c49729624b1a9c2c48d43929a4cbb2ce3c8db06.tar.gz
New features (setting user and groups)
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r--doc/capsh.1116
-rw-r--r--progs/capsh.c51
2 files changed, 149 insertions, 18 deletions
diff --git a/doc/capsh.1 b/doc/capsh.1
index 20973b5..4f9273d 100644
--- a/doc/capsh.1
+++ b/doc/capsh.1
@@ -1,7 +1,7 @@
.\"
-.\" capsh.1 Man page added 2009-11-22 Andrew G. Morgan <morgan@kernel.org>
+.\" capsh.1 Man page added 2009-12-23 Andrew G. Morgan <morgan@kernel.org>
.\"
-.TH CAPSH 1 "2009-11-22" "libcap 2" "User Commands"
+.TH CAPSH 1 "2009-12-24" "libcap 2" "User Commands"
.SH NAME
capsh \- capability shell wrapper
.SH SYNOPSIS
@@ -24,7 +24,7 @@ Execute
.B /bin/bash
with trailing arguments. Note, you can use
.B -c 'command to execute'
-for commands.
+for specific commands.
.TP
.B ==
Execute
@@ -41,29 +41,115 @@ Where
is a text-representation of capability state as per
.BR cap_from_text (3).
.TP
-.BI --drop= <cap-list>
+.BI --drop= cap-list
+Remove the listed capabilities from the prevailing bounding set. The
+capabilites are a comma separated list of capabilities as recognized
+by the
+.BR cap_from_name (3)
+function. Use of this feature requires that the capsh program is
+operating with
+.B CAP_SETPCAP
+in its effective set.
.TP
-.BI --inh= <cap-list>
+.BI --inh= cap-list
+Set the inheritable set of capabilities for the current process to
+equal those provided in the comma separated list. For this action to
+succeed, the prevailing process should already have each of these
+capabilities in the union of the current inheritable and permitted
+capability sets, or the capsh program is operating with
+.B CAP_SETPCAP
+in its effective set.
.TP
-.BI --keep= <0|1>
+.BI --user= username
+Assume the identity of the named user. That is, look up the user's
+.IR uid " and " gid
+with
+.BR getpwuid (3)
+and their group memberships with
+.BR getgrouplist (3)
+and set them all.
.TP
-.BI --chroot= <path>
+.BI --uid= id
+Force all
+.B uid
+values to equal
+.I id
+using the
+.BR setuid (2)
+system call.
.TP
-.BI --secbits= <N>
+.BI --gid= <id>
+Force all
+.B gid
+values to equal
+.I id
+using the
+.BR setgid (2)
+system call.
.TP
-.BI --forkfor= <sec>
+.BI --groups= <id-list>
+Set the supplementary groups to the numerical list provided. The
+groups are set with the
+.BR setgroups (2)
+system call.
.TP
-.BI --killit= <sig>
+.BI --keep= <0|1>
+In a non-pure capability mode, the kernel provides liberal privilege
+to the super-user. However, it is normally the case that when the
+super-user changes
+.I uid
+to some lesser user, then capabilities are dropped. For these
+situations, the kernel can permit the process to retain its
+capabilities after a
+.BR setuid (2)
+system call. This feature is known as
+.I keep-caps
+support. The way to activate it using this script is with this
+argument. Setting the value to 1 will cause
+.I keep-caps
+to be active. Setting it to 0 will cause keep-caps to deactivate for
+the current process. In all cases,
+.I keep-caps
+is deactivated when an
+.BR exec ()
+is performed. See
+.B --secbits
+for ways to disable this feature.
.TP
-.BI --uid= <id>
+.BI --secbits= N
+XXX - need to document this feature.
.TP
-.BI --gid= <id>
+.BI --chroot= path
+Execute the
+.BR chroot (2)
+system call with the new root-directory (/) equal to
+.IR path .
+This operation requires
+.B CAP_SYS_CHROOT
+to be in effect.
.TP
-.BI --groups= <gid-list>
+.BI --forkfor= sec
.TP
-.BI --user= <username>
+.BI --killit= sig
.TP
-.BI --decode= <N>
+.BI --decode= N
+This is a convenience feature. If you look at
+.B /proc/1/status
+there are some capability related fields of the following form:
+
+ CapInh: 0000000000000000
+ CapPrm: ffffffffffffffff
+ CapEff: fffffffffffffeff
+ CapBnd: ffffffffffffffff
+
+This option provides a quick way to decode a capability vector
+represented in this form. For example, the missing capability from
+this effective set is 0x0100. By running:
+
+ capsh --decode=0x0100
+
+we observe that the missing capability is:
+.BR cap_setpcap .
.SH "EXIT STATUS"
Following successful execution the tool exits with status 0. Following
an error, the tool immediately exits with status 1.
diff --git a/progs/capsh.c b/progs/capsh.c
index 4cc3549..10aecf4 100644
--- a/progs/capsh.c
+++ b/progs/capsh.c
@@ -18,6 +18,7 @@
#include <pwd.h>
#include <grp.h>
#include <errno.h>
+#include <ctype.h>
#include <sys/wait.h>
#include <sys/capability.h>
@@ -328,7 +329,50 @@ int main(int argc, char *argv[], char *envp[])
exit(1);
}
} else if (!memcmp("--groups=", argv[i], 9)) {
- exit(1);
+ char *ptr, *buf;
+ long length, max_groups;
+ gid_t *group_list;
+ int g_count;
+
+ length = sysconf(_SC_GETGR_R_SIZE_MAX);
+ buf = calloc(1, length);
+ if (NULL == buf) {
+ fprintf(stderr, "No memory for [%s] operation\n", argv[i]);
+ exit(1);
+ }
+
+ max_groups = sysconf(_SC_NGROUPS_MAX);
+ group_list = calloc(max_groups, sizeof(gid_t));
+ if (NULL == group_list) {
+ fprintf(stderr, "No memory for gid list\n");
+ exit(1);
+ }
+
+ g_count = 0;
+ for (ptr = argv[i] + 9; (ptr = strtok(ptr, ","));
+ ptr = NULL, g_count++) {
+ if (max_groups <= g_count) {
+ fprintf(stderr, "Too many groups specified (%d)\n", g_count);
+ exit(1);
+ }
+ if (!isdigit(*ptr)) {
+ struct group *g, grp;
+ getgrnam_r(ptr, &grp, buf, length, &g);
+ if (NULL == g) {
+ fprintf(stderr, "Failed to identify gid for group [%s]\n", ptr);
+ exit(1);
+ }
+ group_list[g_count] = g->gr_gid;
+ } else {
+ group_list[g_count] = strtoul(ptr, NULL, 0);
+ }
+ }
+ free(buf);
+ if (setgroups(g_count, group_list) != 0) {
+ fprintf(stderr, "Failed to setgroups.\n");
+ exit(1);
+ }
+ free(group_list);
} else if (!memcmp("--user=", argv[i], 7)) {
struct passwd *pwd;
const char *user;
@@ -374,7 +418,7 @@ int main(int argc, char *argv[], char *envp[])
value = strtoull(argv[i]+9, NULL, 16);
printf("0x%016llx=", value);
- for (cap=0; value >> cap; ++cap) {
+ for (cap=0; (cap < 64) && (value >> cap); ++cap) {
if (value & (1ULL << cap)) {
const char *ptr;
@@ -470,8 +514,9 @@ int main(int argc, char *argv[], char *envp[])
" --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"
+ " --groups=g,... set the supplemental groups\n"
" --user=<name> set uid,gid and groups to that of user\n"
- " --chroot=path chroot(2) to this path to invoke bash\n"
+ " --chroot=path chroot(2) to this path\n"
" --killit=<n> send signal(n) to child\n"
" --forkfor=<n> fork and make child sleep for <n> sec\n"
" == re-exec(capsh) with args as for --\n"