diff options
author | Jorge Lucangeli Obes <jorgelo@google.com> | 2016-11-10 22:12:48 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-11-10 22:12:48 +0000 |
commit | 0a972d8f9984f519ae05bea92ad1ad34b9485921 (patch) | |
tree | bb1f11259d81b794c3f5d0dcdfc7aff04e35d936 | |
parent | c590c72c39c09c5bde7d22c75f4062aedc761ac8 (diff) | |
parent | b562e4e37c8b0bca6789f05da1f5ac508cc08a97 (diff) | |
download | libcap-0a972d8f9984f519ae05bea92ad1ad34b9485921.tar.gz |
Update our copy of libcap. am: 02403a9504
am: b562e4e37c
Change-Id: Id47b57b6a81377d40b80d88da1b5b56fa5fe5cd1
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Make.Rules | 5 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | kdebug/Makefile | 14 | ||||
-rw-r--r-- | kdebug/test-bash.sh | 4 | ||||
-rw-r--r-- | kdebug/test-init.sh | 14 | ||||
-rwxr-xr-x | kdebug/test-kernel.sh | 67 | ||||
-rw-r--r-- | kdebug/test-passwd | 2 | ||||
-rw-r--r-- | kdebug/test-prompt.sh | 2 | ||||
-rw-r--r-- | libcap/Makefile | 10 | ||||
-rw-r--r-- | libcap/cap_file.c | 17 | ||||
-rw-r--r-- | libcap/include/uapi/linux/capability.h | 11 | ||||
-rw-r--r-- | libcap/include/uapi/linux/securebits.h | 11 | ||||
-rw-r--r-- | progs/Makefile | 5 | ||||
-rwxr-xr-x | progs/quicktest.sh | 19 | ||||
-rw-r--r-- | progs/setcap.c | 3 |
16 files changed, 157 insertions, 31 deletions
@@ -1,2 +1,3 @@ +patches/ *.o *~ @@ -40,7 +40,7 @@ PKGCONFIGDIR=$(prefix)/$(lib)/pkgconfig # common defines for libcap LIBTITLE=libcap VERSION=2 -MINOR=24 +MINOR=25 # # Compilation specifics @@ -70,7 +70,6 @@ CFLAGS += -Dlinux $(WARNINGS) $(DEBUG) PAM_CAP := $(shell if [ -f /usr/include/security/pam_modules.h ]; then echo yes ; else echo no ; fi) INDENT := $(shell if [ -n "$$(which indent 2>/dev/null)" ]; then echo "| indent -kr" ; fi) DYNAMIC := $(shell if [ ! -d "$(topdir)/.git" ]; then echo yes; fi) -LIBATTR := yes # When installing setcap, set its inheritable bit to be able to place # capabilities on files. It can be used in conjunction with pam_cap @@ -80,7 +79,7 @@ LIBATTR := yes # # make RAISE_SETFCAP=no install # -RAISE_SETFCAP := $(LIBATTR) +RAISE_SETFCAP := yes # Global cleanup stuff @@ -8,13 +8,14 @@ include Make.Rules # flags # -all install clean: %: %-here +all install clean kdebug: %: %-here $(MAKE) -C libcap $@ ifneq ($(PAM_CAP),no) $(MAKE) -C pam_cap $@ endif $(MAKE) -C progs $@ $(MAKE) -C doc $@ + $(MAKE) -C kdebug $@ all-here: diff --git a/kdebug/Makefile b/kdebug/Makefile new file mode 100644 index 0000000..c710050 --- /dev/null +++ b/kdebug/Makefile @@ -0,0 +1,14 @@ +topdir=$(shell pwd)/.. +include ../Make.Rules + +test: + ./test-kernel.sh + +all: + @echo cd to kdebug to test a kernel build + +install: + +clean: + $(LOCALCLEAN) + rm -f fs.conf initramfs.img diff --git a/kdebug/test-bash.sh b/kdebug/test-bash.sh new file mode 100644 index 0000000..2777b21 --- /dev/null +++ b/kdebug/test-bash.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# bash is used in various headers so we need a wrapper to invoke sh +# instead. +exec sh "$@" diff --git a/kdebug/test-init.sh b/kdebug/test-init.sh new file mode 100644 index 0000000..4b55b51 --- /dev/null +++ b/kdebug/test-init.sh @@ -0,0 +1,14 @@ +#!/bin/sh +PATH=/bin + +echo -n "Mounting filesystems ... " +mount -t proc proc /proc +mount -t devtmpfs dev /dev +mount -t sysfs sys /sys +mount -t devpts pts /dev/pts +echo done + +echo Hello, World +cd /root +./quicktest.sh +sh -i diff --git a/kdebug/test-kernel.sh b/kdebug/test-kernel.sh new file mode 100755 index 0000000..c8ce144 --- /dev/null +++ b/kdebug/test-kernel.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# The following is a synthesis of info in: +# +# http://vmsplice.net/~stefan/stefanha-kernel-recipes-2015.pdf +# http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/README +# +KBASE=../../linux +#APPEND="console=ttyS0" + +function die { + echo "$*" + exit 1 +} + +pushd .. +make || die "failed to make libcap tree" +popd + +# Assumes desired make *config (eg. make defconfig) is already done. +pushd $KBASE +pwd +make V=1 all || die "failed to build kernel: $0" +popd + +HERE=$(/bin/pwd) + +cat > fs.conf <<EOF +file /init test-init.sh 0755 0 0 +dir /etc 0755 0 0 +file /etc/passwd test-passwd 0444 0 0 +dir /lib 0755 0 0 +dir /proc 0755 0 0 +dir /dev 0755 0 0 +dir /sys 0755 0 0 +dir /sbin 0755 0 0 +file /sbin/busybox /usr/sbin/busybox 0755 0 0 +dir /bin 0755 0 0 +file /bin/myprompt test-prompt.sh 0755 0 0 +file /bin/bash test-bash.sh 0755 0 0 +dir /usr 0755 0 0 +dir /usr/bin 0755 0 0 +dir /root 0755 0 0 +file /root/quicktest.sh $HERE/../progs/quicktest.sh 0755 0 0 +file /root/setcap $HERE/../progs/setcap 0755 0 0 +file /root/getcap $HERE/../progs/getcap 0755 0 0 +file /root/capsh $HERE/../progs/capsh 0755 0 0 +file /root/getpcaps $HERE/../progs/getpcaps 0755 0 0 +EOF + +COMMANDS="ls ln cp id pwd mkdir rmdir cat rm sh mount umount chmod less" +for f in $COMMANDS; do + echo slink /bin/$f /sbin/busybox 0755 0 0 >> fs.conf +done + +UCOMMANDS="id cut" +for f in $UCOMMANDS; do + echo slink /usr/bin/$f /sbin/busybox 0755 0 0 >> fs.conf +done + +$KBASE/usr/gen_init_cpio fs.conf | gzip -9 > initramfs.img + +KERNEL=$KBASE/arch/x86_64/boot/bzImage + +qemu-system-$(uname -m) -m 1024 \ + -kernel $KERNEL \ + -initrd initramfs.img \ + -append "$APPEND" diff --git a/kdebug/test-passwd b/kdebug/test-passwd new file mode 100644 index 0000000..4fa92a4 --- /dev/null +++ b/kdebug/test-passwd @@ -0,0 +1,2 @@ +root:x:0:0:root:/root:/bin/bash +nobody:x:99:99:Nobody:/:/sbin/nologin diff --git a/kdebug/test-prompt.sh b/kdebug/test-prompt.sh new file mode 100644 index 0000000..1c19c16 --- /dev/null +++ b/kdebug/test-prompt.sh @@ -0,0 +1,2 @@ +#!/bin/sh +echo -n "$(pwd)# " diff --git a/libcap/Makefile b/libcap/Makefile index 0ccd2e7..d189777 100644 --- a/libcap/Makefile +++ b/libcap/Makefile @@ -10,15 +10,7 @@ LIBNAME=$(LIBTITLE).so STALIBNAME=$(LIBTITLE).a # -FILES=cap_alloc cap_proc cap_extint cap_flag cap_text - -# make including file support something you can override (no libattr -# no support). -ifeq ($(LIBATTR),yes) -FILES += cap_file -LDFLAGS += -lattr -DEPS = -lattr -endif +FILES=cap_alloc cap_proc cap_extint cap_flag cap_text cap_file INCLS=libcap.h cap_names.h $(INCS) OBJS=$(addsuffix .o, $(FILES)) diff --git a/libcap/cap_file.c b/libcap/cap_file.c index 553c2d2..76aac8c 100644 --- a/libcap/cap_file.c +++ b/libcap/cap_file.c @@ -1,18 +1,27 @@ /* - * Copyright (c) 1997,2007 Andrew G Morgan <morgan@kernel.org> + * Copyright (c) 1997,2007,2016 Andrew G Morgan <morgan@kernel.org> * * This file deals with setting capabilities on files. */ #include <sys/types.h> -#include <sys/xattr.h> #include <byteswap.h> #include <sys/stat.h> #include <unistd.h> - #include <linux/xattr.h> -#define XATTR_SECURITY_PREFIX "security." +/* + * We hardcode the prototypes for the Linux system calls here since + * there are no libcap library APIs that expose the user to these + * details, and that way we don't need to force clients to link any + * other libraries to access them. + */ +extern ssize_t getxattr(const char *, const char *, void *, size_t); +extern ssize_t fgetxattr(int, const char *, void *, size_t); +extern int setxattr(const char *, const char *, const void *, size_t, int); +extern int fsetxattr(int, const char *, const void *, size_t, int); +extern int removexattr(const char *, const char *); +extern int fremovexattr(int, const char *); #include "libcap.h" diff --git a/libcap/include/uapi/linux/capability.h b/libcap/include/uapi/linux/capability.h index a4b907f..432e023 100644 --- a/libcap/include/uapi/linux/capability.h +++ b/libcap/include/uapi/linux/capability.h @@ -308,8 +308,12 @@ struct vfs_cap_data { #define CAP_LEASE 28 +/* Allow writing the audit log via unicast netlink socket */ + #define CAP_AUDIT_WRITE 29 +/* Allow configuration of audit via unicast netlink socket */ + #define CAP_AUDIT_CONTROL 30 #define CAP_SETFCAP 31 @@ -343,7 +347,12 @@ struct vfs_cap_data { #define CAP_BLOCK_SUSPEND 36 -#define CAP_LAST_CAP CAP_BLOCK_SUSPEND +/* Allow reading the audit log via multicast netlink socket */ + +#define CAP_AUDIT_READ 37 + + +#define CAP_LAST_CAP CAP_AUDIT_READ #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) diff --git a/libcap/include/uapi/linux/securebits.h b/libcap/include/uapi/linux/securebits.h index 985aac9..35ac35c 100644 --- a/libcap/include/uapi/linux/securebits.h +++ b/libcap/include/uapi/linux/securebits.h @@ -43,9 +43,18 @@ #define SECBIT_KEEP_CAPS (issecure_mask(SECURE_KEEP_CAPS)) #define SECBIT_KEEP_CAPS_LOCKED (issecure_mask(SECURE_KEEP_CAPS_LOCKED)) +/* When set, a process cannot add new capabilities to its ambient set. */ +#define SECURE_NO_CAP_AMBIENT_RAISE 6 +#define SECURE_NO_CAP_AMBIENT_RAISE_LOCKED 7 /* make bit-6 immutable */ + +#define SECBIT_NO_CAP_AMBIENT_RAISE (issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE)) +#define SECBIT_NO_CAP_AMBIENT_RAISE_LOCKED \ + (issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE_LOCKED)) + #define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \ issecure_mask(SECURE_NO_SETUID_FIXUP) | \ - issecure_mask(SECURE_KEEP_CAPS)) + issecure_mask(SECURE_KEEP_CAPS) | \ + issecure_mask(SECURE_NO_CAP_AMBIENT_RAISE)) #define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1) #endif /* _UAPI_LINUX_SECUREBITS_H */ diff --git a/progs/Makefile b/progs/Makefile index 778149e..c094a24 100644 --- a/progs/Makefile +++ b/progs/Makefile @@ -4,10 +4,7 @@ include $(topdir)/Make.Rules # # Programs: all of the examples that we will compile # -PROGS=getpcaps capsh -ifeq ($(LIBATTR),yes) -PROGS += getcap setcap -endif +PROGS=getpcaps capsh getcap setcap BUILD=$(PROGS) diff --git a/progs/quicktest.sh b/progs/quicktest.sh index ca6bf1e..e8b2c8e 100755 --- a/progs/quicktest.sh +++ b/progs/quicktest.sh @@ -89,21 +89,25 @@ if [ $? -ne 0 ]; then exit 0 fi +# nobody's uid. Static compilation of the capsh binary can disable pwd +# info discovery. +nouid=$(/usr/bin/id nobody -u) + pass_capsh --secbits=42 --print fail_capsh --secbits=32 --keep=1 --keep=0 --print pass_capsh --secbits=10 --keep=0 --keep=1 --print -fail_capsh --secbits=47 -- -c "./tcapsh --user=nobody" +fail_capsh --secbits=47 -- -c "./tcapsh --uid=$nouid" rm -f tcapsh # Suppress uid=0 privilege -fail_capsh --secbits=47 --print -- -c "./capsh --user=nobody" +fail_capsh --secbits=47 --print -- -c "./capsh --uid=$nouid" # suppress uid=0 privilege and test this privileged -pass_capsh --secbits=0x2f --print -- -c "./privileged --user=nobody" +pass_capsh --secbits=0x2f --print -- -c "./privileged --uid=$nouid" # observe that the bounding set can be used to suppress this forced capability -fail_capsh --drop=cap_setuid --secbits=0x2f --print -- -c "./privileged --user=nobody" +fail_capsh --drop=cap_setuid --secbits=0x2f --print -- -c "./privileged --uid=$nouid" # change the way the capability is obtained (make it inheritable) ./setcap cap_setuid,cap_setgid=ei ./privileged @@ -111,15 +115,16 @@ fail_capsh --drop=cap_setuid --secbits=0x2f --print -- -c "./privileged --user=n # Note, the bounding set (edited with --drop) only limits p # capabilities, not i's. pass_capsh --secbits=47 --inh=cap_setuid,cap_setgid --drop=cap_setuid \ - --uid=500 --print -- -c "./privileged --user=nobody" + --uid=500 --print -- -c "./privileged --uid=$nouid" rm -f ./privileged # test that we do not support capabilities on setuid shell-scripts cat > hack.sh <<EOF #!/bin/bash +/usr/bin/id mypid=\$\$ -caps=\$(./getpcaps \$mypid 2>&1 | cut -d: -f2) +caps=\$(./getpcaps \$mypid 2>&1 | /usr/bin/cut -d: -f2) if [ "\$caps" != " =" ]; then echo "Shell script got [\$caps] - you should upgrade your kernel" exit 1 @@ -139,7 +144,7 @@ if [ $status -ne 0 ]; then fi # Max lockdown -pass_capsh --keep=1 --user=nobody --caps=cap_setpcap=ep \ +pass_capsh --keep=1 --uid=$nouid --caps=cap_setpcap=ep \ --drop=all --secbits=0x2f --caps= --print # Verify we can chroot diff --git a/progs/setcap.c b/progs/setcap.c index 83090ae..7304343 100644 --- a/progs/setcap.c +++ b/progs/setcap.c @@ -171,6 +171,7 @@ int main(int argc, char **argv) retval = cap_set_file(*++argv, cap_d); if (retval != 0) { int explained = 0; + int oerrno = errno; #ifdef linux cap_value_t cap; cap_flag_value_t per_state; @@ -193,7 +194,7 @@ int main(int argc, char **argv) fprintf(stderr, "Failed to set capabilities on file `%s' (%s)\n", - argv[0], strerror(errno)); + argv[0], strerror(oerrno)); if (!explained) { usage(); } |