aboutsummaryrefslogtreecommitdiff
path: root/progs
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2021-03-27 13:59:26 -0700
committerAndrew G. Morgan <morgan@kernel.org>2021-03-27 14:07:50 -0700
commitcf6ddafe1d34d84e7a30b0b497c6174fc93ba074 (patch)
treeba8908474bf987ef0d86ba947553227f49e8e61e /progs
parentf38c190ceb6d3f0609b6cb4c295b9879eb599b21 (diff)
downloadlibcap-cf6ddafe1d34d84e7a30b0b497c6174fc93ba074.tar.gz
Add --explain=cap_foo support to capsh.
A convenience feature, so you don't have to grep the system header, and/or wade through a man page. This addresses: https://bugzilla.kernel.org/show_bug.cgi?id=212451 Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
Diffstat (limited to 'progs')
-rw-r--r--progs/Makefile18
-rw-r--r--progs/capsh.c40
-rw-r--r--progs/capshdoc.h408
-rwxr-xr-xprogs/mkcapshdoc.sh38
4 files changed, 496 insertions, 8 deletions
diff --git a/progs/Makefile b/progs/Makefile
index 1d7fc7a..289186e 100644
--- a/progs/Makefile
+++ b/progs/Makefile
@@ -4,11 +4,11 @@ include $(topdir)/Make.Rules
#
# Programs: all of the examples that we will compile
#
-PROGS=getpcaps capsh getcap setcap
+PROGS=getpcaps getcap setcap
BUILD=$(PROGS)
-all: $(BUILD)
+all: $(BUILD) capsh
ifeq ($(DYNAMIC),yes)
LDPATH = LD_LIBRARY_PATH=../libcap
@@ -28,7 +28,7 @@ $(BUILD): %: %.o $(DEPS)
$(CC) $(CFLAGS) -o $@ $< $(LIBCAPLIB) $(LDFLAGS)
%.o: %.c $(INCS)
- $(CC) $(IPATH) $(CAPSH_SHELL) $(CFLAGS) -c $< -o $@
+ $(CC) $(IPATH) $(CFLAGS) -c $< -o $@
install: all
mkdir -p -m 0755 $(FAKEROOT)$(SBINDIR)
@@ -41,7 +41,14 @@ endif
test: $(PROGS)
-tcapsh-static: capsh.c $(DEPS)
+capshdoc.h.cf: capshdoc.h ./mkcapshdoc.sh
+ ./mkcapshdoc.sh > $@
+ diff -u capshdoc.h $@ || (rm $@ ; exit 1)
+
+capsh: capsh.c capshdoc.h.cf $(DEPS)
+ $(CC) $(IPATH) $(CAPSH_SHELL) $(CFLAGS) -o $@ $< $(LIBCAPLIB) $(LDFLAGS)
+
+tcapsh-static: capsh.c capshdoc.h.cf $(DEPS)
$(CC) $(IPATH) $(CAPSH_SHELL) $(CFLAGS) -o $@ $< $(LIBCAPLIB) $(LDFLAGS) --static
sudotest: test tcapsh-static
@@ -49,4 +56,5 @@ sudotest: test tcapsh-static
clean:
$(LOCALCLEAN)
- rm -f *.o $(BUILD) tcapsh* privileged ping hack.sh compare-cap
+ rm -f *.o $(BUILD) privileged ping hack.sh compare-cap
+ rm -f capsh tcapsh* capshdoc.h.cf
diff --git a/progs/capsh.c b/progs/capsh.c
index f8e3f30..e3d8341 100644
--- a/progs/capsh.c
+++ b/progs/capsh.c
@@ -32,6 +32,8 @@
#define SHELL "/bin/bash"
#endif /* ndef SHELL */
+#include "./capshdoc.h"
+
#define MAX_GROUPS 100 /* max number of supplementary groups for user */
static char *binary(unsigned long value)
@@ -927,22 +929,54 @@ int main(int argc, char *argv[], char *envp[])
"Copyright (c) 2008-11,16,19-21 Andrew G. Morgan"
" <morgan@kernel.org>\n", argv[0]);
exit(0);
+ } else if (!strncmp("--explain=", argv[i], 10)) {
+ cap_value_t cap;
+ if (cap_from_name(argv[i]+10, &cap) != 0) {
+ fprintf(stderr, "unrecognised value '%s'\n", argv[i]+10);
+ exit(1);
+ }
+ if (cap < 0) {
+ fprintf(stderr, "negative capability (%d) invalid\n", cap);
+ exit(1);
+ }
+ if (cap < CAPSH_DOC_LIMIT) {
+ int j;
+ const char **lines = explanations[cap];
+ char *name = cap_to_name(cap);
+ if (cap < cap_max_bits()) {
+ printf("%s (%d)", name, cap);
+ } else {
+ printf("<reserved for> %s (%d)", name, cap);
+ }
+ cap_free(name);
+ printf(" [/proc/self/status:CapXXX: 0x%016llx]\n\n", 1ULL<<cap);
+ for (j=0; lines[j]; j++) {
+ printf(" %s\n", lines[j]);
+ }
+ continue;
+ } else if (cap < cap_max_bits()) {
+ printf("<unnamed in libcap> (%d)", cap);
+ } else {
+ printf("<unsupported> (%d)", cap);
+ }
+ printf(" [/proc/self/status:CapXXX: 0x%016llx]\n", 1ULL<<cap);
} else {
usage:
printf("usage: %s [args ...]\n"
- " --has-a=xxx exit 1 if capability xxx not ambient\n"
- " --has-ambient exit 1 unless ambient vector supported\n"
" --addamb=xxx add xxx,... capabilities to ambient set\n"
" --cap-uid=<n> use libcap cap_setuid() to change uid\n"
" --caps=xxx set caps as per cap_from_text()\n"
" --chroot=path chroot(2) to this path\n"
" --decode=xxx decode a hex string to a list of caps\n"
" --delamb=xxx remove xxx,... capabilities from ambient\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-p=xxx exit 1 if capability xxx not permitted\n"
+ " --has-a=xxx exit 1 if capability xxx not ambient\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"
" --has-no-new-privs exit 1 if privs not limited\n"
" --help, -h this message (or try 'man capsh')\n"
" --iab=... use cap_iab_from_text() to set iab\n"
diff --git a/progs/capshdoc.h b/progs/capshdoc.h
new file mode 100644
index 0000000..efe4797
--- /dev/null
+++ b/progs/capshdoc.h
@@ -0,0 +1,408 @@
+#ifdef CAPSHDOC
+#error "don't include this twice"
+#endif
+#define CAPSHDOC
+
+/*
+ * A line by line explanation of each named capability value
+ */
+static const char *explanation0[] = { /* cap_chown = 0 */
+ "Allows a process to arbitrarily change the user and",
+ "group ownership of a file.",
+ NULL
+};
+static const char *explanation1[] = { /* cap_dac_override = 1 */
+ "Allows a process to override of all Discretionary",
+ "Access Control (DAC) access, including ACL execute",
+ "access. That is read, write or execute files that the",
+ "process would otherwise not have access to. This",
+ "excludes DAC access covered by CAP_LINUX_IMMUTABLE.",
+ NULL
+};
+static const char *explanation2[] = { /* cap_dac_read_search = 2 */
+ "Allows a process to override all DAC restrictions",
+ "limiting the read and search of files and",
+ "directories. This excludes DAC access covered by",
+ "CAP_LINUX_IMMUTABLE.",
+ NULL
+};
+static const char *explanation3[] = { /* cap_fowner = 3 */
+ "Allows a process to perform operations on files, even",
+ "where file owner ID should otherwise need be equal to",
+ "the UID, except where CAP_FSETID is applicable. It",
+ "doesn't override MAC and DAC restrictions.",
+ NULL
+};
+static const char *explanation4[] = { /* cap_fsetid = 4 */
+ "Allows a process to set the S_ISUID and S_ISUID bits of",
+ "the file permissions, even when the process' effective",
+ "UID or GID/supplementary GIDs do not match that of the",
+ "file.",
+ NULL
+};
+static const char *explanation5[] = { /* cap_kill = 5 */
+ "Allows a process to sent a kill(2) signal to any other",
+ "process - overriding the limitation that there be a",
+ "[E]UID match between source and target process.",
+ NULL
+};
+static const char *explanation6[] = { /* cap_setgid = 6 */
+ "Allows a process to freely manipulate its own GIDs:",
+ " - arbitrarily set the GID, EGID, REGID, RESGID values",
+ " - arbitrarily set the supplementary GIDs",
+ " - allows the forging of GID credentials passed over a",
+ " socket",
+ NULL
+};
+static const char *explanation7[] = { /* cap_setuid = 7 */
+ "Allows a process to freely manipulate its own UIDs:",
+ " - arbitraily set the UID, EUID, REUID and RESUID",
+ " values",
+ " - allows the forging of UID credentials passed over a",
+ " socket",
+ NULL
+};
+static const char *explanation8[] = { /* cap_setpcap = 8 */
+ "Allows a process to freely manipulate its inheritable",
+ "capabilities. Linux supports the POSIX.1e Inheritable",
+ "set, as well as Bounding and Ambient Linux extension",
+ "vectors. This capability permits dropping bits from the",
+ "Bounding vector. It also permits the process to raise",
+ "Ambient vector bits that are both raised in the",
+ "Permitted and Inheritable sets of the process. This",
+ "capability cannot be used to raise Permitted bits, or",
+ "Effective bits beyond those already present in the",
+ "process' permitted set.",
+ "",
+ "[Historical note: prior to the advent of file",
+ "capabilities (2008), this capability was suppressed by",
+ "default, as its unsuppressed behavior was not",
+ "auditable: it could asynchronously grant its own",
+ "Permitted capabilities to and remove capabilities from",
+ "other processes arbitraily. The former leads to",
+ "undefined behavior, and the latter is better served by",
+ "the kill system call.]",
+ NULL
+};
+static const char *explanation9[] = { /* cap_linux_immutable = 9 */
+ "Allows a process to modify the S_IMMUTABLE and",
+ "S_APPEND file attributes.",
+ NULL
+};
+static const char *explanation10[] = { /* cap_net_bind_service = 10 */
+ "Allows a process to bind to privileged ports:",
+ " - TCP/UDP sockets below 1024",
+ " - ATM VCIs below 32",
+ NULL
+};
+static const char *explanation11[] = { /* cap_net_broadcast = 11 */
+ "Allows a process to broadcast to the network and to",
+ "listen to multicast.",
+ NULL
+};
+static const char *explanation12[] = { /* cap_net_admin = 12 */
+ "Allows a process to perform network configuration",
+ "operations:",
+ " - interface configuration",
+ " - administration of IP firewall, masquerading and",
+ " accounting",
+ " - setting debug options on sockets",
+ " - modification of routing tables",
+ " - setting arbitrary process, and process group",
+ " ownership on sockets",
+ " - binding to any address for transparent proxying",
+ " (this is also allowed via CAP_NET_RAW)",
+ " - setting TOS (Type of service)",
+ " - setting promiscuous mode",
+ " - clearing driver statistics",
+ " - multicasing",
+ " - read/write of device-specific registers",
+ " - activation of ATM control sockets",
+ NULL
+};
+static const char *explanation13[] = { /* cap_net_raw = 13 */
+ "Allows a process to use raw networking:",
+ " - RAW sockets",
+ " - PACKET sockets",
+ " - binding to any address for transparent proxying",
+ " (also permitted via CAP_NET_ADMIN)",
+ NULL
+};
+static const char *explanation14[] = { /* cap_ipc_lock = 14 */
+ "Allows a process to lock shared memory segments for IPC",
+ "purposes. Also enables mlock and mlockall system",
+ "calls.",
+ NULL
+};
+static const char *explanation15[] = { /* cap_ipc_owner = 15 */
+ "Allows a process to override IPC ownership checks.",
+ NULL
+};
+static const char *explanation16[] = { /* cap_sys_module = 16 */
+ "Allows a process to initiate the loading and unloading",
+ "of kernel modules. This capability can effectively",
+ "modify kernel without limit.",
+ NULL
+};
+static const char *explanation17[] = { /* cap_sys_rawio = 17 */
+ "Allows a process to perform raw IO:",
+ " - permit ioper/iopl access",
+ " - permit sending USB messages to any device via",
+ " /dev/bus/usb",
+ NULL
+};
+static const char *explanation18[] = { /* cap_sys_chroot = 18 */
+ "Allows a process to perform a chroot syscall to change",
+ "the effective root of the process' file system:",
+ "redirect to directory \"/\" to some other location.",
+ NULL
+};
+static const char *explanation19[] = { /* cap_sys_ptrace = 19 */
+ "Allows a process to perform a ptrace() of any other",
+ "process.",
+ NULL
+};
+static const char *explanation20[] = { /* cap_sys_pacct = 20 */
+ "Allows a process to configure process accounting.",
+ NULL
+};
+static const char *explanation21[] = { /* cap_sys_admin = 21 */
+ "Allows a process to perform a somewhat arbitrary",
+ "grab-bag of privileged operations. Over time, this",
+ "capability should weaken as specific capabilities are",
+ "created for subsets of CAP_SYS_ADMINs functionality:",
+ " - configuration of the secure attention key",
+ " - administration of the random device",
+ " - examination and configuration of disk quotas",
+ " - setting the domainname",
+ " - setting the hostname",
+ " - calling bdflush()",
+ " - mount() and umount(), setting up new SMB connection",
+ " - some autofs root ioctls",
+ " - nfsservctl",
+ " - VM86_REQUEST_IRQ",
+ " - to read/write pci config on alpha",
+ " - irix_prctl on mips (setstacksize)",
+ " - flushing all cache on m68k (sys_cacheflush)",
+ " - removing semaphores",
+ " - Used instead of CAP_CHOWN to \"chown\" IPC message",
+ " queues, semaphores and shared memory",
+ " - locking/unlocking of shared memory segment",
+ " - turning swap on/off",
+ " - forged pids on socket credentials passing",
+ " - setting readahead and flushing buffers on block",
+ " devices",
+ " - setting geometry in floppy driver",
+ " - turning DMA on/off in xd driver",
+ " - administration of md devices (mostly the above, but",
+ " some extra ioctls)",
+ " - tuning the ide driver",
+ " - access to the nvram device",
+ " - administration of apm_bios, serial and bttv (TV)",
+ " device",
+ " - manufacturer commands in isdn CAPI support driver",
+ " - reading non-standardized portions of PCI",
+ " configuration space",
+ " - DDI debug ioctl on sbpcd driver",
+ " - setting up serial ports",
+ " - sending raw qic-117 commands",
+ " - enabling/disabling tagged queuing on SCSI",
+ " controllers and sending arbitrary SCSI commands",
+ " - setting encryption key on loopback filesystem",
+ " - setting zone reclaim policy",
+ NULL
+};
+static const char *explanation22[] = { /* cap_sys_boot = 22 */
+ "Allows a process to initiate a reboot of the system.",
+ NULL
+};
+static const char *explanation23[] = { /* cap_sys_nice = 23 */
+ "Allows a process to maipulate the execution priorities",
+ "of arbitrary processes:",
+ " - those involving different UIDs",
+ " - setting their CPU affinity",
+ " - alter the FIFO vs. round-robin (realtime)",
+ " scheduling for itself and other processes.",
+ NULL
+};
+static const char *explanation24[] = { /* cap_sys_resource = 24 */
+ "Allows a process to adjust resource related parameters",
+ "of processes and the system:",
+ " - set and override resource limits",
+ " - override quota limits",
+ " - override the reserved space on ext2 filesystem",
+ " (this can also be achieved via CAP_FSETID)",
+ " - modify the data journaling mode on ext3 filesystem,",
+ " which uses journaling resources",
+ " - override size restrictions on IPC message queues",
+ " - configure more than 64Hz interrupts from the",
+ " real-time clock",
+ " - override the maximum number of consoles for console",
+ " allocation",
+ " - override the maximum number of keymaps",
+ NULL
+};
+static const char *explanation25[] = { /* cap_sys_time = 25 */
+ "Allows a process to perform time manipulation of clocks:",
+ " - alter the system clock",
+ " - enable irix_stime on MIPS",
+ " - set the real-time clock",
+ NULL
+};
+static const char *explanation26[] = { /* cap_sys_tty_config = 26 */
+ "Allows a process to manipulate tty devices:",
+ " - configure tty devices",
+ " - perform vhangup() of a tty",
+ NULL
+};
+static const char *explanation27[] = { /* cap_mknod = 27 */
+ "Allows a process to perform privileged operations with",
+ "the mknod() system call.",
+ NULL
+};
+static const char *explanation28[] = { /* cap_lease = 28 */
+ "Allows a process to take leases on files.",
+ NULL
+};
+static const char *explanation29[] = { /* cap_audit_write = 29 */
+ "Allows a process to write to the audit log via a",
+ "unicast netlink socket.",
+ NULL
+};
+static const char *explanation30[] = { /* cap_audit_control = 30 */
+ "Allows a process to configure audit logging via a",
+ "unicast netlink socket.",
+ NULL
+};
+static const char *explanation31[] = { /* cap_setfcap = 31 */
+ "Allows a process to set capabilities on files.",
+ NULL
+};
+static const char *explanation32[] = { /* cap_mac_override = 32 */
+ "Allows a process to override Manditory Access Control",
+ "(MAC) access. Not all kernels are configured with a MAC",
+ "mechanism, but this is the capability reserved for",
+ "overriding them.",
+ NULL
+};
+static const char *explanation33[] = { /* cap_mac_admin = 33 */
+ "Allows a process to configure the Mandatory Access",
+ "Control (MAC) policy. Not all kernels are configured",
+ "with a MAC enabled, but if they are this capability is",
+ "reserved for code to perform administration tasks.",
+ NULL
+};
+static const char *explanation34[] = { /* cap_syslog = 34 */
+ "Allows a process to configure the kernel's syslog",
+ "(printk) behavior.",
+ NULL
+};
+static const char *explanation35[] = { /* cap_wake_alarm = 35 */
+ "Allows a process to trigger something that can wake the",
+ "system up.",
+ NULL
+};
+static const char *explanation36[] = { /* cap_block_suspend = 36 */
+ "Allows a process to block system suspends - prevent the",
+ "system from entering a lower power state.",
+ NULL
+};
+static const char *explanation37[] = { /* cap_audit_read = 37 */
+ "Allows a process to read the audit log via a multicast",
+ "netlink socket.",
+ NULL
+};
+static const char *explanation38[] = { /* cap_perfmon = 38 */
+ "Allows a process to enable observability of privileged",
+ "operations related to performance. The mechanisms",
+ "include perf_events, i915_perf and other kernel",
+ "subsystems.",
+ NULL
+};
+static const char *explanation39[] = { /* cap_bpf = 39 */
+ "Allows a process to manipulate aspects of the kernel",
+ "enhanced Berkeley Packet Filter (BPF) system. This is",
+ "an execution subsystem of the kernel, that manages BPF",
+ "programs. CAP_BPF permits a process to:",
+ " - create all types of BPF maps",
+ " - advanced verifier features:",
+ " - indirect variable access",
+ " - bounded loops",
+ " - BPF to BPF function calls",
+ " - scalar precision tracking",
+ " - larger complexity limits",
+ " - dead code elimination",
+ " - potentially other features",
+ "",
+ "Other capabilities can be used together with CAP_BFP to",
+ "further manipulate the BPF system:",
+ " - CAP_PERFMON relaxes the verifier checks as follows:",
+ " - BPF programs can use pointer-to-integer",
+ " conversions",
+ " - speculation attack hardening measures can be",
+ " bypassed",
+ " - bpf_probe_read to read arbitrary kernel memory is",
+ " permitted",
+ " - bpf_trace_printk to print the content of kernel",
+ " memory",
+ " - CAP_SYS_ADMIN permits the following:",
+ " - use of bpf_probe_write_user",
+ " - iteration over the system-wide loaded programs,",
+ " maps, links BTFs and convert their IDs to file",
+ " descriptors.",
+ " - CAP_PERFMON is required to load tracing programs.",
+ " - CAP_NET_ADMIN is required to load networking",
+ " programs.",
+ NULL
+};
+static const char *explanation40[] = { /* cap_checkpoint_restore = 40 */
+ "Allows a process to perform checkpoint",
+ "and restore operations. Also permits",
+ "explicit PID control via clone3() and",
+ "also writing to ns_last_pid.",
+ NULL
+};
+static const char **explanations[] = {
+ explanation0,
+ explanation1,
+ explanation2,
+ explanation3,
+ explanation4,
+ explanation5,
+ explanation6,
+ explanation7,
+ explanation8,
+ explanation9,
+ explanation10,
+ explanation11,
+ explanation12,
+ explanation13,
+ explanation14,
+ explanation15,
+ explanation16,
+ explanation17,
+ explanation18,
+ explanation19,
+ explanation20,
+ explanation21,
+ explanation22,
+ explanation23,
+ explanation24,
+ explanation25,
+ explanation26,
+ explanation27,
+ explanation28,
+ explanation29,
+ explanation30,
+ explanation31,
+ explanation32,
+ explanation33,
+ explanation34,
+ explanation35,
+ explanation36,
+ explanation37,
+ explanation38,
+ explanation39,
+ explanation40,
+};
+#define CAPSH_DOC_LIMIT 41
diff --git a/progs/mkcapshdoc.sh b/progs/mkcapshdoc.sh
new file mode 100755
index 0000000..705d526
--- /dev/null
+++ b/progs/mkcapshdoc.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# This script generates some C code for inclusion in the capsh binary.
+# The Makefile generally only generates the .h code and compares it
+# with the checked in code in the progs directory.
+
+cat<<EOF
+#ifdef CAPSHDOC
+#error "don't include this twice"
+#endif
+#define CAPSHDOC
+
+/*
+ * A line by line explanation of each named capability value
+ */
+EOF
+
+let x=0
+while [ -f "../doc/values/${x}.txt" ]; do
+ name=$(fgrep ",${x}}" ../libcap/cap_names.list.h|sed -e 's/{"//' -e 's/",/ = /' -e 's/},//')
+ echo "static const char *explanation${x}[] = { /* ${name} */"
+ sed -e 's/"/\\"/g' -e 's/^/ "/' -e 's/$/",/' "../doc/values/${x}.txt"
+ let x=1+${x}
+ echo " NULL"
+ echo "};"
+done
+
+cat<<EOF
+static const char **explanations[] = {
+EOF
+let y=0
+while [ "${y}" -lt "${x}" ]; do
+ echo " explanation${y},"
+ let y=1+${y}
+done
+cat<<EOF
+};
+#define CAPSH_DOC_LIMIT ${x}
+EOF